int optimus_verify_partition(const char* partName, HIMAGE hImg, char* _errInfo) { #define MaxSz (64 - 7) //verify file to at most 64B to corresponding to USB burn, strlen("verify ") == 7 char* argv[4]; int ret = 0; HIMAGEITEM hImgItem = NULL; int imgItemSz = 0; char CmdVerify[MaxSz + 7] = {0}; hImgItem = image_item_open(hImg, "VERIFY", partName); if (!hImgItem) { DWN_ERR("Fail to open verify file for part (%s)\n", partName); return ITEM_NOT_EXIST; } imgItemSz = (int)image_item_get_size(hImgItem); if (imgItemSz > MaxSz || !imgItemSz) { DWN_ERR("verify file size %d for part %s invalid, max is %d\n", imgItemSz, partName, MaxSz); ret = __LINE__; goto _finish; } DWN_DBG("item sz %u\n", imgItemSz); ret = image_item_read(hImg, hImgItem, CmdVerify, imgItemSz); if (ret) { DWN_ERR("Fail to read verify item for part %s\n", partName); goto _finish; } CmdVerify[imgItemSz] = 0; DWN_DBG("verify[%s]\n", CmdVerify); argv[0] = "verify"; ret = cli_simple_parse_line(CmdVerify, argv + 1); if (ret != 2) { DWN_ERR("verify cmd argc must be 2, but %d\n", ret); return __LINE__; } ret = optimus_media_download_verify(3, argv, _errInfo); if (ret) { DWN_ERR("Fail when verify\n"); return __LINE__; } _finish: image_item_close(hImgItem); return ret; }
//return value is the size actual write to media //Paras: const char* partName, const char* imgType, const char* verifyAlgorithm static u32 optimus_func_download_image(struct ImgBurnInfo* pDownInfo, u32 dataSz, const u8* data, char* errInfo) { int burnSz = 0; int ret = 0; u64 nextMediaOffset = pDownInfo->nextMediaOffset; DWN_DBG("data=0x%p, sz=0x%x, offset=%llx\n", data, dataSz, nextMediaOffset); ret = optimus_storage_open(pDownInfo, data, dataSz); if(OPT_DOWN_OK != ret){ sprintf(errInfo, "Fail to open stoarge\n"); DWN_ERR(errInfo); return 0; } burnSz = optimus_storage_write(pDownInfo, nextMediaOffset, dataSz, data, errInfo); if(!burnSz){ DWN_ERR("Fail in optimus_storage_write, data 0x%p, wantSz 0x%x\n", data, dataSz); goto _err; } pDownInfo->imgSzDisposed += burnSz; ret = optimus_storage_close(pDownInfo); if(ret){ DWN_ERR("Fail to close media\n"); return 0; } return burnSz; _err: optimus_storage_close(pDownInfo); pDownInfo->imgBurnSta = OPTIMUS_IMG_STA_BURN_FAILED;//// return 0; }
int do_sdc_burn(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int rcode = 0; const char* sdc_cfg_file = argv[1]; if (argc < 2 ) { return CMD_RET_USAGE; } if ( !aml_check_is_ready_for_sdc_produce() ) { DWN_DBG("Not ready\n"); return __LINE__; } optimus_work_mode_set(OPTIMUS_WORK_MODE_SDC_UPDATE); show_logo_to_report_burning();//indicate enter flow of burning! when 'run update' if (optimus_led_open(LED_TYPE_PWM)) { DWN_ERR("Fail to open led for burn\n"); return __LINE__; } optimus_led_show_in_process_of_burning(); rcode = optimus_burn_package_in_sdmmc(sdc_cfg_file); return rcode; }
//Normal image can write directly to NAND, best aligned to 16K when write //FIXME: check it aligned to 16K when called //1, write to media 2 -- save the verify info static u32 optimus_download_normal_image(struct ImgBurnInfo* pDownInfo, u32 dataSz, const u8* data) { int ret = 0; u64 addrOrOffsetInBy = pDownInfo->nextMediaOffset; DWN_DBG("addrOffset=0x%x, dataSz=0x%x, data = 0x%x\n", addrOffset, dataSz, data); //FIXME:why dirty value if not convert to u64 ret = store_write_ops((u8*)pDownInfo->partName, (u8*)data, addrOrOffsetInBy, (u64)dataSz); if(ret){ DWN_ERR("Fail to write to media\n"); return 0; } pDownInfo->nextMediaOffset += dataSz; return dataSz; }
int optimus_progress_init(const unsigned itemSzHigh, const unsigned itemSzLow, const u32 startStep, const u32 endStep) { _progressInfo.itemSzLow = itemSzLow; _progressInfo.itemSzHigh = itemSzHigh; _progressInfo.startStep = startStep; _progressInfo.endStep = endStep; _progressInfo.currentStep = startStep; _progressInfo.totalStepNum = endStep - startStep; _progressInfo.unReportSzInByte = 0;//clear it //ATTENTION: as divisor / is lossy, _progressInfo.bytesToIncOneStep * _progressInfo.totalStepNum <= item size, so 100% is sometimes not exactly Burn Completed!! _progressInfo.bytesToIncOneStep = ((((u64)itemSzHigh)<<32) + itemSzLow) / _progressInfo.totalStepNum; _progressInfo.bytesToUpdateStep = (OPTIMUS_PROMPT_SIZE_MIN > _progressInfo.bytesToIncOneStep) ? OPTIMUS_PROMPT_SIZE_MIN : _progressInfo.bytesToIncOneStep; DWN_DBG("item size 0x[%x, %x], currentStep %d, totalStepNum %d, bytesToIncOneStep 0x%x\n", itemSzHigh, itemSzLow, _progressInfo.currentStep, _progressInfo.totalStepNum, _progressInfo.bytesToIncOneStep); return 0; }
int optimus_sdc_burn_partitions(ConfigPara_t* pCfgPara, HIMAGE hImg, __hdle hUiProgress, int NeedVerify) { BurnParts_t* cfgParts = &pCfgPara->burnParts; int burnNum = cfgParts->burn_num; int i = 0; int rcode = 0; //update burn_parts para if burnNum is 0, i.e, not configured if (!burnNum) { rcode = get_burn_parts_from_img(hImg, pCfgPara); if (rcode) { DWN_ERR("Fail to get burn parts from image\n"); return __LINE__; } burnNum = cfgParts->burn_num; DWN_DBG("Data part num %d\n", burnNum); } if (!burnNum) { DWN_ERR("Data part num is 0!!\n"); return __LINE__; } for (i = 0; i < burnNum; i++) { const char* partName = cfgParts->burnParts[i]; rcode = optimus_burn_one_partition(partName, hImg, hUiProgress, NeedVerify); if (rcode) { DWN_ERR("Fail in burn part %s\n", partName); return __LINE__; } } return rcode; }
//return value is the data size that actual dealed static u32 optimus_storage_write(struct ImgBurnInfo* pDownInfo, u64 addrOrOffsetInBy, unsigned dataSz, const u8* data, char* errInfo) { u32 burnSz = 0; const u32 imgType = pDownInfo->imgType; const int MediaType = pDownInfo->storageMediaType; addrOrOffsetInBy += pDownInfo->partBaseOffset; DWN_DBG("[0x]Data %p, addrOrOffsetInBy %llx, dataSzInBy %x\n", data, addrOrOffsetInBy, dataSz); if(OPTIMUS_IMG_STA_BURN_ING != pDownInfo->imgBurnSta) { sprintf(errInfo, "Error burn sta %d\n", pDownInfo->imgBurnSta); DWN_ERR(errInfo); return 0; } switch(MediaType) { case OPTIMUS_MEDIA_TYPE_NAND: case OPTIMUS_MEDIA_TYPE_SDMMC: case OPTIMUS_MEDIA_TYPE_STORE: { switch(imgType) { case IMG_TYPE_NORMAL: burnSz = optimus_download_normal_image(pDownInfo, dataSz, data); break; case IMG_TYPE_BOOTLOADER: burnSz = optimus_download_bootloader_image(pDownInfo, dataSz, data); break; case IMG_TYPE_SPARSE: burnSz = optimus_download_sparse_image(pDownInfo, dataSz, data); break; default: DWN_ERR("error image type %d\n", imgType); } } break; case OPTIMUS_MEDIA_TYPE_KEY_UNIFY: { burnSz = v2_key_burn(pDownInfo->partName, data, dataSz, errInfo); if(burnSz != dataSz){//return value is write size DWN_ERR("burn key failed\n"); return 0; } } break; case OPTIMUS_MEDIA_TYPE_MEM: { u8* buf = (u8*)(unsigned)addrOrOffsetInBy; if(buf != data){ DWN_ERR("buf(%llx) != data(%p)\n", addrOrOffsetInBy, data); return 0; } if(!strcmp("dtb", pDownInfo->partName))//as memory write back size = min[fileSz, 2G], so reach here if downloaded ok! { int rc = 0; char* dtbLoadAddr = (char*)CONFIG_DTB_LOAD_ADDR; const int DtbMaxSz = (2U<<20); unsigned fdtSz = 0; unsigned char* destDtb = (unsigned char*)data; //Make sure flash already inited before 'run aml_dt' //old tool will download dtb before 'disk_initial', but new tool will 'disk_initial' first if(is_optimus_storage_inited() || (OPTIMUS_WORK_MODE_USB_PRODUCE != optimus_work_mode_get())) { destDtb = (unsigned char*)get_multi_dt_entry((unsigned int)data); } rc = fdt_check_header(destDtb); if(rc){ sprintf(errInfo, "failed at fdt_check_header\n"); DWN_ERR(errInfo); return 0; } fdtSz = fdt_totalsize(destDtb); if(DtbMaxSz <= fdtSz){ sprintf(errInfo, "failed: fdt header ok but sz 0%x > max 0x%x\n", fdtSz, DtbMaxSz); DWN_ERR(errInfo); return 0; } DWN_MSG("load dtb to 0x%p\n", dtbLoadAddr); memcpy(dtbLoadAddr, destDtb, fdtSz); } burnSz = dataSz; } break; default: sprintf(errInfo, "Error MediaType %d\n", MediaType); DWN_ERR(errInfo); } return burnSz; }
static int _check_partition_table_consistency(const unsigned uboot_bin) { int rc = 0; unsigned partitionTableSz = 0; const int acsOffsetInSpl = START_ADDR - AHB_SRAM_BASE; const int addrMapFromAhb2Bin = AHB_SRAM_BASE - uboot_bin; const struct acs_setting* acsSettingInBin = NULL; unsigned partTabAddrInBin = 0; const struct partitions* partsTabInBin = NULL; const struct acs_setting* acsSettingInSram = NULL; const struct partitions* partsTabInSram = NULL; DWN_DBG("uboot_bin 0x%p, acsOffsetInSpl 0x%x, addrMapFromAhb2Bin 0x%x\n", uboot_bin, acsOffsetInSpl, addrMapFromAhb2Bin); acsSettingInBin = (struct acs_setting*)(*(unsigned*)(uboot_bin + acsOffsetInSpl) - addrMapFromAhb2Bin); partitionTableSz = acsSettingInBin->partition_table_length; DWN_MSG("acsSettingInBin=0x%x, partTabSz=0x%x\n", (unsigned int)acsSettingInBin, partitionTableSz); if( (unsigned)acsSettingInBin >= uboot_bin + 64*1024 || (unsigned)acsSettingInBin <= uboot_bin){//acs not in the spl DWN_MSG("Acs not in the spl of uboot_bin\n"); return 0; } if(memcmp(MAGIC_ACS, acsSettingInBin->acs_magic, strlen(MAGIC_ACS)) || memcmp(TABLE_MAGIC_NAME, acsSettingInBin->partition_table_magic, strlen(TABLE_MAGIC_NAME))) { DWN_MSG("acs magic OR part magic in ubootin not match\n"); return 0;//Not to check partTable as acs magic or part magic not match in u-boot.bin, maybe encrypted by AMLETOOL } partTabAddrInBin = acsSettingInBin->partition_table_addr - addrMapFromAhb2Bin; partsTabInBin = (const struct partitions*)partTabAddrInBin; #ifndef CONFIG_MESON_TRUSTZONE acsSettingInSram = (struct acs_setting*)(*(unsigned*)START_ADDR); #else //twice eget value at sram address and copy 1K to memory acsSettingInSram = (struct acs_setting*)meson_trustzone_acs_addr(START_ADDR); DWN_MSG("[Trust]acsSettingInSram=0x%p\n", acsSettingInSram); #endif// #ifndef CONFIG_MESON_TRUSTZONE partsTabInSram = (const struct partitions*)acsSettingInSram->partition_table_addr; DWN_MSG("partsTabInSram=0x%p\n", partsTabInSram); if(memcmp(MAGIC_ACS, acsSettingInSram->acs_magic, strlen(MAGIC_ACS)) || memcmp(TABLE_MAGIC_NAME, acsSettingInSram->partition_table_magic, strlen(TABLE_MAGIC_NAME))) { DWN_MSG("acs magic OR part magic in SPL not match\n"); return __LINE__;//Not to check partTable as acs magic or part magic not match in SRAM, assert this!! } #ifdef CONFIG_MESON_TRUSTZONE partsTabInSram = (const struct partitions*)meson_trustzone_acs_addr((unsigned)&acsSettingInSram->partition_table_addr); #endif// #ifndef CONFIG_MESON_TRUSTZONE rc = memcmp(partsTabInSram, partsTabInBin, partitionTableSz); DWN_MSG("Check parts table %s\n", !rc ? "OK." : "FAILED!"); #if 0//I comment print as str-prefix function (strcmp, strcmp, and .etc) are all not reliable in uboot if(rc) { DWN_MSG("acs_setting 0x%p, 0x%p\n", acsSettingInBin, acsSettingInSram); DWN_MSG("partitions 0x%08x, 0x%p\n", partTabAddrInBin, partsTabInSram); DWN_MSG("partition_table_addr 0x%x, 0x%x\n", acsSettingInSram->partition_table_addr, acsSettingInBin->partition_table_addr); DWN_MSG("part in ubootbin:\n"); _show_partition_table(partsTabInBin); DWN_MSG("part in spl:\n"); _show_partition_table(partsTabInSram); return __LINE__; } #endif//#if 0 return rc; }
//.NeedVerify: Try to get verify file if .NeedVerify == 1 static int optimus_burn_one_partition(const char* partName, HIMAGE hImg, __hdle hUiProgress, int NeedVerify) { int rcode = 0; s64 imgItemSz = 0; s64 leftItemSz = 0; u32 thisReadLen = 0; __hdle hImgItem = NULL; char* downTransBuf = NULL;//get buffer from optimus_buffer_manager const unsigned ItemReadBufSz = OPTIMUS_DOWNLOAD_SLOT_SZ;//read this size from image item each time unsigned sequenceNo = 0; const char* fileFmt = NULL; /*static */char _errInfo[512]; unsigned itemSizeNotAligned = 0; printf("\n"); DWN_MSG("=====>To burn part [%s]\n", partName); optimus_progress_ui_printf("Burning part[%s]\n", partName); hImgItem = image_item_open(hImg, "PARTITION", partName); if (!hImgItem) { DWN_ERR("Fail to open item for part (%s)\n", partName); return __LINE__; } imgItemSz = leftItemSz = image_item_get_size(hImgItem); if (!imgItemSz) { DWN_ERR("image size is 0 , image of part (%s) not exist ?\n", partName); return __LINE__; } fileFmt = (IMAGE_ITEM_TYPE_SPARSE == image_item_get_type(hImgItem)) ? "sparse" : "normal"; itemSizeNotAligned = image_item_get_first_cluster_size(hImg, hImgItem); leftItemSz -= itemSizeNotAligned; rcode = sdc_burn_buf_manager_init(partName, imgItemSz, fileFmt, itemSizeNotAligned); if (rcode) { DWN_ERR("fail in sdc_burn_buf_manager_init, rcode %d\n", rcode); return __LINE__; } //for each loop: //1, get buffer from buffer_manager, //2, read item data to buffer, //3, report data ready to buffer_manager for (; leftItemSz > 0; leftItemSz -= thisReadLen, sequenceNo++) { thisReadLen = leftItemSz > ItemReadBufSz ? ItemReadBufSz: (u32)leftItemSz; rcode = optimus_buf_manager_get_buf_for_bulk_transfer(&downTransBuf, thisReadLen, sequenceNo, _errInfo); if (rcode) { DWN_ERR("fail in get buf, msg[%s]\n", _errInfo); goto _finish; } //If the item head is not alinged to FAT cluster, Read it firstly to speed up mmc read if (itemSizeNotAligned && !sequenceNo) { DWN_MSG("itemSizeNotAligned 0x%x\n", itemSizeNotAligned); rcode = image_item_read(hImg, hImgItem, downTransBuf - itemSizeNotAligned, itemSizeNotAligned); if (rcode) { DWN_ERR("fail in read data from item,rcode %d, len 0x%x, sequenceNo %d\n", rcode, itemSizeNotAligned, sequenceNo); goto _finish; } } rcode = image_item_read(hImg, hImgItem, downTransBuf, thisReadLen); if (rcode) { DWN_ERR("fail in read data from item,rcode %d\n", rcode); goto _finish; } rcode = optimus_buf_manager_report_transfer_complete(thisReadLen, _errInfo); if (rcode) { DWN_ERR("fail in report data ready, rcode %d\n", rcode); goto _finish; } if (hUiProgress)optimus_progress_ui_update_by_bytes(hUiProgress, thisReadLen) ; } DWN_DBG("BURN part %s %s!\n", partName, leftItemSz ? "FAILED" : "SUCCESS"); _finish: image_item_close(hImgItem); if (rcode) { DWN_ERR("Fail to burn part(%s) with in format (%s) before verify\n", partName, fileFmt); optimus_progress_ui_printf("Failed at burn part[%s] befor VERIFY\n", partName); return rcode; } #if 1 if (!NeedVerify) { return rcode; } rcode = optimus_verify_partition(partName, hImg, _errInfo); if (ITEM_NOT_EXIST == rcode) { printf("WRN:part(%s) NOT verified\n", partName); return 0; } if (rcode) { printf("Fail in verify part(%s)\n", partName); optimus_progress_ui_printf("Failed at VERIFY part[%s]\n", partName); return __LINE__; } #endif//#fi 0 return rcode; }