/* * (C) Copyright 2007-2013 * Allwinner Technology Co., Ltd. * Char * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include #include #include #include #include "sprite_card.h" #include "sprite_download.h" #include "./firmware/imgdecode.h" #include "./firmware/imagefile_new.h" #include #include #include "./cartoon/sprite_cartoon.h" #include extern uint img_file_start; extern int sunxi_sprite_deal_part_from_sysrevoery(sunxi_download_info *dl_map); extern int __imagehd(HIMAGE tmp_himage); extern int char8_char16_compare(const char *char8, const efi_char16_t *char16, size_t char16_len); typedef struct tag_IMAGE_HANDLE { ImageHead_t ImageHead; ImageItem_t *ItemTable; } IMAGE_HANDLE; static HIMAGE Img_Open_from_sysrecovery(__u32 start) { IMAGE_HANDLE *pImage = NULL; uint ItemTableSize; img_file_start = start; if (!img_file_start) { pr_err("sunxi sprite error: unable to get firmware start position\n"); return NULL; } debug("img start = 0x%x\n", img_file_start); pImage = (IMAGE_HANDLE *)malloc(sizeof(IMAGE_HANDLE)); if (NULL == pImage) { pr_err("sunxi sprite error: fail to malloc memory for img head\n"); return NULL; } memset(pImage, 0, sizeof(IMAGE_HANDLE)); //debug("try to read mmc start %d\n", img_file_start); if (!sunxi_flash_read(img_file_start, IMAGE_HEAD_SIZE / 512, &pImage->ImageHead)) { pr_err("sunxi sprite error: read iamge head fail\n"); goto _img_open_fail_; } debug("read mmc ok\n"); if (memcmp(pImage->ImageHead.magic, IMAGE_MAGIC, 8) != 0) { pr_err("sunxi sprite error: iamge magic is bad\n"); goto _img_open_fail_; } ItemTableSize = pImage->ImageHead.itemcount * sizeof(ImageItem_t); pImage->ItemTable = (ImageItem_t *)malloc(ItemTableSize); if (NULL == pImage->ItemTable) { pr_err("sunxi sprite error: fail to malloc memory for item table\n"); goto _img_open_fail_; } if (!sunxi_flash_read(img_file_start + (IMAGE_HEAD_SIZE / 512), ItemTableSize / 512, pImage->ItemTable)) { pr_err("sunxi sprite error: read iamge item table fail\n"); goto _img_open_fail_; } return pImage; _img_open_fail_: if (pImage->ItemTable) { free(pImage->ItemTable); } if (pImage) { free(pImage); } return NULL; } static int sprite_erase_partition_by_name(char *part_name) { int ret = -1; __u32 img_start; __u32 part_size; ret = sunxi_partition_get_info_byname(part_name, &img_start, &part_size); if (ret) { pr_msg("sprite update error: no %s found\n", part_name); if (!strcmp(part_name, "data")) { ret = sunxi_partition_get_info_byname( "UDISK", &img_start, &part_size); if (ret) { pr_err("sprite update error: no udisk partition\n"); } ret = sunxi_partition_get_info_byname( "userdata", &img_start, &part_size); if (ret) { pr_err("sprite update error: no userdata partition\n"); return -1; } } } if (!ret) { __u32 tmp_size; __u32 tmp_start; char *src_buf = NULL; src_buf = (char *)malloc(1024 * 1024); if (!src_buf) { pr_err("sprite erase error: fail to get memory for tmpdata\n"); return -1; } tmp_start = img_start; tmp_size = part_size; pr_msg("data part size=%d\n", tmp_size); tick_printf("begin erase part %s\n", part_name); memset(src_buf, 0xff, 1024 * 1024); sunxi_flash_write(tmp_start, 1024 * 1024 / 512, src_buf); if (src_buf) { free(src_buf); } tick_printf("finish erase part\n"); } return 0; } /* * pms id:79675 * DragonSN tool usage * 1. Destroy the data of metadata partition and UserData partition. * When Android starts, it recognizes that the partition is damaged, * which will trigger Android erasure * 2. Speed up the production line */ int sprite_erase_for_androidrecovery(void) { int ret; ret = sprite_erase_partition_by_name("data"); if (ret) { pr_err("sprite update error: fail to erase data\n"); return -1; } ret = sprite_erase_partition_by_name("meta"); if (ret) { pr_err("sprite update error: fail to erase data\n"); return -1; } return 0; } static int sprite_erase_in_sysrecovery(void) { int ret; ret = sprite_erase_partition_by_name("data"); if (ret) { pr_err("sprite update error: fail to erase data\n"); return -1; } ret = sprite_erase_partition_by_name("cache"); if (ret) { pr_err("sprite update error: fail to erase cache\n"); return -1; } ret = sprite_erase_partition_by_name("Reserve0"); if (ret) { pr_err("sprite update error: fail to erase cache\n"); return -1; } ret = sprite_erase_partition_by_name("Reserve1"); if (ret) { pr_err("sprite update error: fail to erase cache\n"); return -1; } ret = sprite_erase_partition_by_name("Reserve2"); if (ret) { pr_err("sprite update error: fail to erase cache\n"); return -1; } return 0; } int sprite_form_sysrecovery(void) { HIMAGEITEM imghd = 0; __u32 part_size; __u32 img_start; sunxi_download_info *dl_info = NULL; char *src_buf = NULL; int ret = -1; int production_media = get_boot_storage_type(); #ifdef CONFIG_SUNXI_SPRITE_CARTOON int nodeoffset; int processbar_direct = 0; ; nodeoffset = fdt_path_offset(working_fdt, FDT_PATH_CARD_BOOT); if (nodeoffset >= 0) { if (fdt_getprop_u32(working_fdt, nodeoffset, "processbar_direct", (uint32_t *)&processbar_direct) < 0) processbar_direct = 0; } sprite_cartoon_create(processbar_direct); #endif tick_printf("sunxi sprite begin\n"); src_buf = (char *)malloc(1024 * 1024); if (!src_buf) { pr_err("sprite update error: fail to get memory for tmpdata\n"); goto _update_error_; } ret = sunxi_partition_get_info_byname("sysrecovery", &img_start, &part_size); if (ret) { pr_err("sprite update error: read image start error\n"); goto _update_error_; } tick_printf("part start = %d\n", img_start); imghd = Img_Open_from_sysrecovery(img_start); if (!imghd) { pr_err("sprite update error: fail to open img\n"); goto _update_error_; } __imagehd(imghd); #ifdef CONFIG_SUNXI_SPRITE_CARTOON sprite_cartoon_upgrade(10); #endif //erase the data partition. ret = sprite_erase_in_sysrecovery(); if (ret) { goto _update_error_; } dl_info = (sunxi_download_info *)malloc(sizeof(sunxi_download_info)); if (!dl_info) { pr_err("sprite update error: fail to get memory for download map\n"); goto _update_error_; } memset(dl_info, 0, sizeof(sunxi_download_info)); ret = sprite_card_fetch_download_map(dl_info); if (ret) { pr_err("sunxi sprite error: donn't download dl_map\n"); goto _update_error_; } #ifdef CONFIG_SUNXI_SPRITE_CARTOON sprite_cartoon_upgrade(20); #endif if (sunxi_sprite_deal_part_from_sysrevoery(dl_info)) { pr_err("sunxi sprite error : download part error\n"); goto _update_error_; } if (sunxi_sprite_deal_recorvery_boot(production_media)) { pr_err("recovery error : download uboot or boot0 error!\n"); goto _update_error_; } tick_printf("successed in downloading uboot and boot0\n"); #ifdef CONFIG_SUNXI_SPRITE_CARTOON sprite_cartoon_upgrade(100); #endif mdelay(3000); Img_Close(imghd); if (dl_info) { free(dl_info); } if (src_buf) { free(src_buf); } sunxi_board_restart(0); return 0; _update_error_: if (dl_info) { free(dl_info); } if (src_buf) { free(src_buf); } pr_err("sprite update error: current card sprite failed\n"); pr_err("now hold the machine\n"); return -1; }