//check key is burned yet --> need keyOverWrite -->can_write static int sdc_check_key_need_to_burn(const char* keyName, const int keyOverWrite) { int rc = 0; char _cmd[96]; sprintf(_cmd, "aml_key_burn misc is_burned %s", keyName); rc = run_command(_cmd, 0); if (rc < 0) { DWN_ERR("Fail in check key is_burned\n"); return -__LINE__; } DWN_MSG("key[%s] is %s burned\n", keyName, rc ? "NOT" : "DO"); if (rc) {//not success return 1;//need burn as not burned yet. } if (!keyOverWrite) { DWN_MSG("User choose not to overwrite the key\n"); return 0; } sprintf(_cmd, "aml_key_burn misc can_write %s", keyName); rc = run_command(_cmd, 0); if (rc) { DWN_ERR("Fail in check key[%s] is_burned\n", keyName); return -__LINE__; } DWN_MSG("key[%s] is %s can_write\n", keyName, rc ? "NOT" : "DO"); return !rc; }
//return value is the actual size it write static int optimus_download_bootloader_image(struct ImgBurnInfo* pDownInfo, u32 dataSzReceived, const u8* data) { int ret = OPT_DOWN_OK; uint64_t size = dataSzReceived; if(dataSzReceived < pDownInfo->imgPktSz){ DWN_ERR("please write back bootloader after all data rx end.0x(%x, %x)\n", dataSzReceived, (u32)pDownInfo->imgPktSz); return 0; } ret = _check_partition_table_consistency((unsigned)data); if(ret){ DWN_ERR("Fail in _check_partition_table_consistency\n"); return 0; } if(size > (1U<<20)){ DWN_ERR("uboot.bin size 0x%llx > 1M unsupported\n", size); return 0; } size = size <= 0x60000 ? 0x60000 : (1U<<20);//384K when non-secure_os, 1M when secure_os ret = store_boot_write((unsigned char*)data, 0, size); return ret ? 0 : dataSzReceived; }
//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 optimus_sdc_burn_dtb_load(HIMAGE hImg) { s64 itemSz = 0; HIMAGEITEM hImgItem = NULL; int rc = 0; const char* partName = "dtb"; u64 partBaseOffset = OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR; unsigned char* dtbTransferBuf = (unsigned char*)partBaseOffset; //meson1.dtb but not meson.dtb for m8 compatible if (_check_if_secureboot_enabled()) { DWN_MSG("SecureEnabled, use meson1_ENC\n"); hImgItem = image_item_open(hImg, partName, "meson1_ENC"); } else { hImgItem = image_item_open(hImg, partName, "meson1"); } if (!hImgItem) { DWN_WRN("Fail to open item [meson1,%s]\n", partName); return ITEM_NOT_EXIST; } itemSz = image_item_get_size(hImgItem); if (!itemSz) { DWN_ERR("Item size 0\n"); image_item_close(hImgItem); return __LINE__; } #if 1 const unsigned itemSzNotAligned = image_item_get_first_cluster_size(hImg, hImgItem); if (itemSzNotAligned /*& 0x7*/) {//Not Aligned 8bytes/64bits, mmc dma read will failed DWN_MSG("align 4 mmc read...\t");//Assert Make 'DDR' buffer addr align 8 dtbTransferBuf += image_get_cluster_size(hImg) - itemSzNotAligned; partBaseOffset += image_get_cluster_size(hImg) - itemSzNotAligned; } #endif rc = image_item_read(hImg, hImgItem, dtbTransferBuf, (unsigned)itemSz); if (rc) { DWN_ERR("Failed at item read, rc = %d\n", rc); image_item_close(hImgItem); return __LINE__; } image_item_close(hImgItem); rc = optimus_parse_img_download_info(partName, itemSz, "normal", "mem", partBaseOffset); if (rc) { DWN_ERR("Failed in init down info\n"); return __LINE__; } { unsigned wrLen = 0; char errInfo[512]; wrLen = optimus_download_img_data(dtbTransferBuf, (unsigned)itemSz, errInfo); rc = (wrLen == itemSz) ? 0 : __LINE__; } return rc; }
//fetch the keys names which need be burned from item[conf, keys] static int sdc_burn_get_user_key_names(HIMAGE hImg, const char* **pKeysName, unsigned* keysNum) { int rc = 0; HIMAGEITEM hImgItem = NULL; unsigned itemSz = 0; unsigned char* thisReadBuf = (unsigned char*)OPTIMUS_SPARSE_IMG_FILL_VAL_BUF;//This buf is not used and not need reuse when burning keys const unsigned thisReadBufSz = (OPTIMUS_SPARSE_IMG_FILL_BUF_SZ >> 1); const char* *keysName = (const char**)(thisReadBuf + thisReadBufSz); hImgItem = image_item_open(hImg, "conf", "keys"); if (!hImgItem) { DWN_ERR("Fail to open keys.conf\n"); return ITEM_NOT_EXIST; } itemSz = (unsigned)image_item_get_size(hImgItem); if (!itemSz) { DWN_ERR("Item size 0\n"); image_item_close(hImgItem); return __LINE__; } const unsigned itemSzNotAligned = image_item_get_first_cluster_size(hImg, hImgItem); if (itemSzNotAligned /*& 0x7*/) {//Not Aligned 8bytes/64bits, mmc dma read will failed DWN_MSG("align 4 mmc read...\t");//Assert Make 'DDR' buffer addr align 8 thisReadBuf += image_get_cluster_size(hImg); thisReadBuf -= itemSzNotAligned; } rc = image_item_read(hImg, hImgItem, thisReadBuf, itemSz); if (rc) { DWN_ERR("Failed at item read, rc = %d\n", rc); image_item_close(hImgItem); return __LINE__; } image_item_close(hImgItem); if (itemSz >= thisReadBufSz) { DWN_ERR("itemSz(0x%x) of keys.conf too large, > max 0x%x.\n", itemSz, thisReadBufSz); return __LINE__; } rc = _optimus_parse_buf_2_lines((char*)thisReadBuf, itemSz, keysName, keysNum, 16); if (rc) { DWN_ERR("Fail in parse buf_2_lines\n"); return __LINE__; } rc = _optimus_abandon_ini_comment_lines((char**)keysName, *keysNum); *pKeysName = keysName; return rc; }
int get_burn_parts_from_img(HIMAGE hImg, ConfigPara_t* pcfgPara) { BurnParts_t* pburnPartsCfg = &pcfgPara->burnParts; int i = 0; int ret = 0; int burnNum = 0; const int totalItemNum = get_total_itemnr(hImg); for (i = 0; i < totalItemNum; i++) { const char* main_type = NULL; const char* sub_type = NULL; ret = get_item_name(hImg, i, &main_type, &sub_type); if (ret) { DWN_ERR("Exception:fail to get item name!\n"); return __LINE__; } if (!strcmp("PARTITION", main_type)) { char* partName = pburnPartsCfg->burnParts[burnNum]; if (!strcmp("bootloader", sub_type)) continue; if (!strcmp(AML_SYS_RECOVERY_PART, sub_type)) { if (OPTIMUS_WORK_MODE_SYS_RECOVERY == optimus_work_mode_get()) continue; } strcpy(partName, sub_type); pburnPartsCfg->bitsMap4BurnParts |= 1U<<burnNum; burnNum += 1; } } if (burnNum) { pburnPartsCfg->burn_num = burnNum; ret = check_cfg_burn_parts(pcfgPara); if (ret) { DWN_ERR("Fail in check burn parts\n"); return __LINE__; } print_burn_parts_para(pburnPartsCfg); } return OPT_DOWN_OK; }
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; }
int optimus_burn_package_in_sdmmc(const char* sdc_cfg_file) { int rcode = 0; #if defined(CONFIG_AML_MESON_8) AML_WATCH_DOG_DISABLE(); //disable watchdog #endif//#ifdef CONFIG_AML_MESON_8 DWN_MSG("mmcinfo\n"); rcode = run_command("mmcinfo", 0); if(rcode){ DWN_ERR("Fail in init mmc, Does sdcard not plugged in?\n"); return __LINE__; } #if 0//this asserted by 'run update' and 'aml_check_is_ready_for_sdc_produce' rcode = do_fat_get_fileSz(sdc_cfg_file); if(!rcode){ printf("The [%s] not exist in bootable mmc card\n", sdc_cfg_file); return __LINE__; } #endif//#if 0 rcode = optimus_burn_with_cfg_file(sdc_cfg_file); return rcode; }
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; }
int check_cfg_burn_parts(const ConfigPara_t* burnPara) { const BurnParts_t* pBurnParts = &burnPara->burnParts; const int cfgBurnNum = pBurnParts->burn_num; const unsigned bitsMap = pBurnParts->bitsMap4BurnParts; int mediaPathHasCfg = burnPara->burnEx.bitsMap.mediaPath; int i = 0; for (i = 0; i < cfgBurnNum; i++) { int b = bitsMap & (1U<<i); if(!b){ err("Please cfg burn_part%d\n", i); return __LINE__; } if(mediaPathHasCfg) { if(!strcmp(pBurnParts->burnParts[i], "media")) { DWN_ERR("media can't cfg in both media_path and burn_parts\n"); return __LINE__; } } } return 0; }
//fetch the keys names which need be burned from item[conf, keys] static int sdc_burn_get_user_key_names(HIMAGE hImg, const char* **pKeysName, unsigned* keysNum) { int rc = 0; HIMAGEITEM hImgItem = NULL; unsigned itemSz = 0; unsigned char* thisReadBuf = (unsigned char*)OPTIMUS_SPARSE_IMG_FILL_VAL_BUF;//This buf is not used and not need reuse when burning keys const unsigned thisReadBufSz = (OPTIMUS_SPARSE_IMG_FILL_BUF_SZ >> 1); const char* *keysName = (const char**)(thisReadBuf + thisReadBufSz); hImgItem = image_item_open(hImg, "conf", "keys"); if(!hImgItem){ DWN_ERR("Fail to open keys.conf\n"); return ITEM_NOT_EXIST; } itemSz = (unsigned)image_item_get_size(hImgItem); if(!itemSz){ DWN_ERR("Item size 0\n"); image_item_close(hImgItem); return __LINE__; } rc = image_item_read(hImg, hImgItem, thisReadBuf, itemSz); if(rc){ DWN_ERR("Failed at item read, rc = %d\n", rc); image_item_close(hImgItem); return __LINE__; } image_item_close(hImgItem); if(itemSz >= thisReadBufSz){ DWN_ERR("itemSz(0x%x) of keys.conf too large, > max 0x%x.\n", itemSz, thisReadBufSz); return __LINE__; } rc = _optimus_parse_buf_2_lines((char*)thisReadBuf, itemSz, keysName, keysNum, 16); if(rc){ DWN_ERR("Fail in parse buf_2_lines\n"); return __LINE__; } rc = _optimus_abandon_ini_comment_lines((char**)keysName, *keysNum); *pKeysName = keysName; return rc; }
static int sdc_burn_dtb_load(HIMAGE hImg) { s64 itemSz = 0; HIMAGEITEM hImgItem = NULL; int rc = 0; const char* partName = "dtb"; const u64 partBaseOffset = OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR; unsigned char* dtbTransferBuf = (unsigned char*)(unsigned)partBaseOffset; hImgItem = image_item_open(hImg, partName, "meson"); if(!hImgItem){ DWN_ERR("Fail to open verify file for part (%s)\n", partName); return ITEM_NOT_EXIST; } itemSz = image_item_get_size(hImgItem); if(!itemSz){ DWN_ERR("Item size 0\n"); image_item_close(hImgItem); return __LINE__; } rc = image_item_read(hImg, hImgItem, dtbTransferBuf, (unsigned)itemSz); if(rc){ DWN_ERR("Failed at item read, rc = %d\n", rc); image_item_close(hImgItem); return __LINE__; } image_item_close(hImgItem); rc = optimus_parse_img_download_info(partName, itemSz, "normal", "mem", partBaseOffset); if(rc){ DWN_ERR("Failed in init down info\n"); return __LINE__; } { unsigned wrLen = 0; char errInfo[512]; wrLen = optimus_download_img_data(dtbTransferBuf, (unsigned)itemSz, errInfo); rc = (wrLen == itemSz) ? 0 : wrLen; } return rc; }
u32 optimus_cb_simg_write_media(const unsigned destAddrInSec, const unsigned dataSzInBy, const char* data) { int ret = OPT_DOWN_OK; unsigned char* partName = (unsigned char*)OptimusImgBurnInfo.partName; if(OPTIMUS_MEDIA_TYPE_STORE < OptimusImgBurnInfo.storageMediaType){ DWN_ERR("storage type %d not supported yet!\n", OptimusImgBurnInfo.storageMediaType); return OPT_DOWN_FAIL; } //FIXME:why dirty value if not convert to u64 ret = store_write_ops(partName, (u8*)data, (((u64)destAddrInSec)<<9), (u64)dataSzInBy); if(ret){ DWN_ERR("Fail to write to media, ret = %d\n", ret); return 0; } return dataSzInBy; }
static int optimus_read_keyfile_2_mem(const char* filePath, u8* buf, unsigned* keyValLen) { int rc = 0; unsigned keySz = 0; if(DEV_FILE_FMT_VFAT == _optKeyInfo.fileFmt) { long hFile = -1; unsigned readSz = 0; #if 1//FIXME: remove this mmcinfo /*rc = run_command("mmcinfo 0", 0);*/ rc = optimus_sdc_burn_switch_to_extmmc(); if(rc){ DWN_ERR("Fail in mmcinfo\n"); return __LINE__; } #endif// keySz = (unsigned)do_fat_get_fileSz(filePath);//can support both sdc and udisk if(!keySz){ DWN_ERR("size is 0 of file [%s]\n", filePath); return __LINE__; } hFile = do_fat_fopen(filePath); if(hFile < 0){ DWN_ERR("Fail to open file[%s]\n", filePath); return __LINE__; } readSz = do_fat_fread(hFile, buf, keySz); if(readSz != keySz){ DWN_ERR("Want read %d bytes, but %d\n", keySz, readSz); return __LINE__; } do_fat_fclose(hFile); } *keyValLen = keySz; return rc; }
static int do_opt_keysburn_uninit(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int rc = 0; rc = v2_key_command(argc, argv, _errInfo); if(rc){ DWN_ERR("Fail to init key driver.\n"); return -__LINE__; } return rc; }
int optimus_burn_bootlader(HIMAGE hImg) { int rcode = 0; int NeedVerify = 1; rcode = optimus_burn_one_partition("bootloader", hImg, NULL, NeedVerify); if (rcode) { DWN_ERR("Fail when burn bootloader\n"); return __LINE__; } return rcode; }
static int do_aml_key_burn(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int rc = 0; cmd_tbl_t *c; sprintf(_errInfo, "success"); c = find_cmd_tbl(argv[1], cmd_opt_key_burn, ARRAY_SIZE(cmd_opt_key_burn)); if(!c){ DWN_ERR("Can't find subcmd[%s]\n", argv[1]); return 1; } rc = c->cmd(cmdtp, flag, argc, argv); DWN_MSG("[key]%s\n", _errInfo); if(rc < 0){ DWN_ERR("Fail in cmd[%s %s].ret=%d\n", argv[1], argv[2], rc); return -__LINE__; } rc = strncmp("success", _errInfo, 7); return rc; }
//return value: the data size disposed static u32 optimus_download_sparse_image(struct ImgBurnInfo* pDownInfo, u32 dataSz, const u8* data) { u32 unParsedDataLen = 0; int flashOffset = 0; const u64 addrOffset = pDownInfo->nextMediaOffset; flashOffset = optimus_simg_to_media((char*)data, dataSz, &unParsedDataLen, ((u32)(addrOffset>>9))); if(flashOffset < 0){ DWN_ERR("Fail in parse simg. src 0x%p, size 0x%x, unParsedDataLen 0x%x, ret %d\n", data, dataSz, unParsedDataLen, flashOffset); return 0; } pDownInfo->nextMediaOffset += ((u64)flashOffset)<<9; return dataSz - unParsedDataLen; }
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; }
//outStr will be null-terminater after format int optimus_hex_data_2_ascii_str(const unsigned char* hexData, const unsigned nBytes, char* outStr, const unsigned strSz) { int i = 1; if (strSz < 2 * nBytes + 1) { DWN_ERR("strSz(%d) > 2 * nBytes(%d)\n", strSz, nBytes); return __LINE__; } sprintf(outStr, "%02x", hexData[0]); for (; i < nBytes; ++i) { sprintf(outStr, "%s%02x", outStr, hexData[i]); } return 0; }
//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; }
static int optimus_verify_bootloader(struct ImgBurnInfo* pDownInfo, u8* genSum) { int ret = OPT_DOWN_OK; unsigned char* pBuf = (unsigned char*)OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR; uint64_t size = 0; /*size = 0x60000;////////////TODO:hardcode len!!*/ size=pDownInfo->imgPktSz; ret = store_boot_read(pBuf, (u64)0, size); if(ret){ DWN_ERR("Fail to read bootloader\n"); return __LINE__; } sha1_csum(pBuf, (u32)pDownInfo->imgPktSz, genSum); return ret; }
//asset nand logical partition size equals CFG size in storage.c //nand often make mistake this size, emmc should always ok static int _assert_logic_partition_cap(const char* thePartName, const uint64_t nandPartCap) { extern struct partitions * part_table; struct partitions * thePart = NULL; for(thePart = part_table; NAND_PART_SIZE_FULL != thePart->size; ++thePart) { const uint64_t partSzInBytes = thePart->size; if(strcmp(thePartName, thePart->name))continue; if(partSzInBytes != nandPartCap){ DWN_ERR("partSz in ACS %llx != flash Sz %llx\n", partSzInBytes, nandPartCap); return __LINE__; } break; } return 0; }
int optimus_burn_package_in_sdmmc(const char* sdc_cfg_file) { int rcode = 0; #if 0//this asserted by 'run update' and 'aml_check_is_ready_for_sdc_produce' rcode = do_fat_get_fileSz(sdc_cfg_file); if (!rcode) { printf("The [%s] not exist in bootable mmc card\n", sdc_cfg_file); return __LINE__; } #endif//#if 0 rcode = optimus_device_probe("mmc", "0"); if (rcode) { DWN_ERR("Fail to detect device mmc 0\n"); return __LINE__; } setenv("usb_update","0"); rcode = optimus_burn_with_cfg_file(sdc_cfg_file); return rcode; }
static int optimus_sha1sum_verify_partition(const char* partName, const u64 verifyLen, const u8 imgType, u8* genSum) { int ret = 0; u8* buff = (u8*) OPTIMUS_SHA1SUM_BUFFER_ADDR; const u32 buffSz = OPTIMUS_SHA1SUM_BUFFER_LEN; sha1_context ctx; u64 leftLen = verifyLen; if(strcmp(partName, OptimusImgBurnInfo.partName)){ DWN_ERR("partName %s err, must %s\n", partName, OptimusImgBurnInfo.partName); return OPT_DOWN_FAIL; } if(!is_optimus_burn_complete()){ return OPT_DOWN_FAIL; } memset(buff, 0xde, 1024);//clear 1kb data before verfiy, in case read buffer not overlapped if(IMG_TYPE_BOOTLOADER == imgType) { return optimus_verify_bootloader(&OptimusImgBurnInfo, genSum); } else if(IMG_TYPE_SPARSE == imgType)//sparse image { ret = optimus_sparse_back_info_probe(); if(OPT_DOWN_TRUE != ret){ DWN_ERR("Fail to probe back sparse info\n"); return OPT_DOWN_FAIL; } } ret = optimus_storage_open(&OptimusImgBurnInfo, NULL, 0); if(ret){ DWN_ERR("Fail to open storage for read\n"); return OPT_DOWN_FAIL; } sha1_starts(&ctx); DWN_MSG("To verify part %s in fmt %s\n", partName, (IMG_TYPE_SPARSE == imgType) ? "sparse": "normal"); if(IMG_TYPE_SPARSE == imgType)//sparse image { for(; leftLen;) { u32 spHeadSz = 0; u32 chunkDataLen = 0; u64 chunkDataOffset = 0; u8* head = NULL; ret = optimus_sparse_get_chunk_data(&head, &spHeadSz, &chunkDataLen, &chunkDataOffset); if(ret){ DWN_ERR("Fail to get chunk data\n"); goto _finish; } sha1_update(&ctx, head, spHeadSz); leftLen -= spHeadSz + chunkDataLen;//update image read info for(;chunkDataLen;) { const int thisReadLen = (chunkDataLen > buffSz) ? buffSz : chunkDataLen; ret = optimus_storage_read(&OptimusImgBurnInfo, chunkDataOffset, thisReadLen, buff, NULL); if(ret){ DWN_ERR("Fail to read at offset 0x[%x, %8x], len=0x%8x\n", ((u32)(chunkDataOffset>>32)), (u32)chunkDataOffset, thisReadLen); goto _finish; } sha1_update(&ctx, buff, thisReadLen); chunkDataLen -= thisReadLen; chunkDataOffset += thisReadLen; } if(leftLen && !spHeadSz) { DWN_ERR("Fail to read when pkt len left 0x%x\n", (u32)leftLen); break; } } } else//normal image { for(; leftLen;)
int optimus_storage_init(int toErase) { int ret = 0; char* cmd = NULL; if(_disk_intialed_ok){//To assert only actual disk intialed once DWN_MSG("Disk inited again.\n"); return 0; } if(OPTIMUS_WORK_MODE_USB_PRODUCE != optimus_work_mode_get())//Already inited in other work mode { DWN_MSG("Exit before re-init\n"); store_exit(); } switch(toErase) { case 0://NO erase ret = store_init(1); break; case 3://erase all(with key) { cmd = "store disprotect key"; DWN_MSG("run cmd [%s]\n", cmd); ret = run_command(cmd, 0); if(ret){ DWN_ERR("Fail when run cmd[%s], ret %d\n", cmd, ret); break; } } case 1://normal erase, store init 3 ret = store_init(3); break; case 4://force erase all { cmd = "store disprotect key; store disprotect fbbt; store disprotect hynix"; DWN_MSG("run cmd [%s]\n", cmd); ret = run_command(cmd, 0); if(ret){ DWN_ERR("Fail when run cmd[%s], ret %d\n", cmd, ret); break; } } case 2: ret = store_init(4); break; default: DWN_ERR("Unsupported erase flag %d\n", toErase); ret = -__LINE__; break; } if(!ret) { _disk_intialed_ok = 1; if(OPTIMUS_WORK_MODE_USB_PRODUCE == optimus_work_mode_get())//env not relocated in this case { DWN_MSG("usb producing env_relocate\n"); env_relocate(); } } return ret; }
//TODO: add _errInfo as argument to pass more info static int _parse_img_download_info(struct ImgBurnInfo* pDownInfo, const char* partName, const u64 imgSz, const char* imgType, const char* mediaType, const u64 partBaseOffset) { u64 partCap = 0; int ret = 0; memset(pDownInfo, 0, sizeof(struct ImgBurnInfo));//clear burnning info //TODO: check format is normal/bootloader if upload!! if(!strcmp("sparse", imgType)) { pDownInfo->imgType = IMG_TYPE_SPARSE; } else if(!strcmp("bootloader", partName)) { pDownInfo->imgType = IMG_TYPE_BOOTLOADER; } else if(!strcmp("normal", imgType)) { pDownInfo->imgType = IMG_TYPE_NORMAL; } else{ DWN_ERR("err image type %s\n", imgType); return __LINE__; } if(!strcmp("store", mediaType)) { pDownInfo->storageMediaType = OPTIMUS_MEDIA_TYPE_STORE; } else if(!strcmp("nand", mediaType)) { pDownInfo->storageMediaType = OPTIMUS_MEDIA_TYPE_NAND; } else if(!strcmp("sdmmc", mediaType)) { pDownInfo->storageMediaType = OPTIMUS_MEDIA_TYPE_SDMMC; } else if(!strcmp("spiflash", mediaType)) { pDownInfo->storageMediaType = OPTIMUS_MEDIA_TYPE_SPIFLASH; } else if(!strcmp("key", mediaType)) { pDownInfo->storageMediaType = OPTIMUS_MEDIA_TYPE_KEY_UNIFY; if(OPTIMUS_DOWNLOAD_SLOT_SZ <= imgSz){ DWN_ERR("size (0x%llx) for key %s invalid!!\n", imgSz, partName); return __LINE__; } } else if(!strcmp("mem", mediaType)) { pDownInfo->storageMediaType = OPTIMUS_MEDIA_TYPE_MEM; } else{ DWN_ERR("error mediaType %s\n", mediaType); return __LINE__; } pDownInfo->partBaseOffset = partBaseOffset; memcpy(pDownInfo->partName, partName, strlen(partName)); if(OPTIMUS_MEDIA_TYPE_MEM > pDownInfo->storageMediaType)//if command for burning partition { if(strcmp("bootloader", partName))//get size if not bootloader { ret = store_get_partititon_size((u8*)partName, &partCap); if(ret){ DWN_ERR("Fail to get size for part %s\n", partName); return __LINE__; } partCap <<= 9;//trans sector to byte DWN_MSG("flash LOGIC partCap 0x%llxB\n", partCap); if(imgSz > partCap) { DWN_ERR("imgSz 0x%llx out of cap 0x%llx\n", imgSz, partCap); return __LINE__; } ret = _assert_logic_partition_cap(partName, partCap); if(ret){ DWN_ERR("Fail in _assert_logic_partition_cap\n"); return __LINE__; } } } pDownInfo->nextMediaOffset = pDownInfo->imgSzDisposed = 0; pDownInfo->imgPktSz = imgSz; pDownInfo->imgBurnSta = OPTIMUS_IMG_STA_PRE_BURN; DWN_MSG("Down(%s) part(%s) sz(0x%llx) fmt(%s)\n", mediaType, partName, pDownInfo->imgPktSz, imgType); return 0; }
//TODO: to consist with optimus_storage_write, return value should be readSzInBy static int optimus_storage_read(struct ImgBurnInfo* pDownInfo, u64 addrOrOffsetInBy, unsigned readSzInBy, unsigned char* buff, char* errInfo) { int ret = 0; const int MediaType = pDownInfo->storageMediaType; unsigned char* partName = (unsigned char*)pDownInfo->partName; addrOrOffsetInBy += pDownInfo->partBaseOffset; switch(MediaType) { case OPTIMUS_MEDIA_TYPE_NAND: case OPTIMUS_MEDIA_TYPE_SDMMC: case OPTIMUS_MEDIA_TYPE_STORE: { if(IMG_TYPE_BOOTLOADER == pDownInfo->imgType) { ret = store_boot_read(buff, addrOrOffsetInBy, (u64)readSzInBy); } else { ret = store_read_ops(partName, buff, addrOrOffsetInBy, (u64)readSzInBy); } if(ret){ if(errInfo) sprintf(errInfo, "Read failed\n"); DWN_ERR("Read failed\n"); return OPT_DOWN_FAIL; } } break; case OPTIMUS_MEDIA_TYPE_KEY_UNIFY: { unsigned fmtLen = 0; if(addrOrOffsetInBy){ DWN_ERR("OH NO, IS key len > 64K!!? addrOrOffsetInBy is 0x%llx not 0\n", addrOrOffsetInBy); return OPT_DOWN_FAIL; } ret = v2_key_read(pDownInfo->partName, buff, readSzInBy, errInfo, &fmtLen); } break; case OPTIMUS_MEDIA_TYPE_MEM: { u8* buf = (u8*)(unsigned)addrOrOffsetInBy; if(addrOrOffsetInBy >> 32){ DWN_ERR("mem addr 0x%llx too large\n", addrOrOffsetInBy); } if(buf != buff){ DWN_ERR("buf(%llx) != buff(%p)\n", addrOrOffsetInBy, buff); } } break; default: DWN_MSG("Error MediaType %d\n", MediaType); return OPT_DOWN_FAIL; } return ret; }
//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 optimus_storage_open(struct ImgBurnInfo* pDownInfo, const u8* data, const u32 dataSz) { int ret = OPT_DOWN_OK; const char* partName = (const char*)pDownInfo->partName; const int imgType = pDownInfo->imgType; const int MediaType = pDownInfo->storageMediaType; if(!pDownInfo->imgSzDisposed && OPTIMUS_IMG_STA_PRE_BURN == pDownInfo->imgBurnSta) { DWN_MSG("Burn Start...\n"); pDownInfo->imgBurnSta = OPTIMUS_IMG_STA_BURN_ING; } else if(pDownInfo->imgSzDisposed == pDownInfo->imgPktSz && OPTIMUS_IMG_STA_BURN_COMPLETE == pDownInfo->imgBurnSta) { DWN_MSG("Verify Start...\n"); pDownInfo->imgBurnSta = OPTIMUS_IMG_STA_VERIFY_ING; } switch(MediaType) { case OPTIMUS_MEDIA_TYPE_NAND: case OPTIMUS_MEDIA_TYPE_SDMMC: case OPTIMUS_MEDIA_TYPE_STORE: { if(IMG_TYPE_BOOTLOADER != pDownInfo->imgType && !pDownInfo->devHdle)//if not bootloader and device not open { /*pDownInfo->devHdle = aml_nftl_get_dev(partName);*/ pDownInfo->devHdle = (void*)1; if(!pDownInfo->devHdle) { DWN_ERR("Fail to open nand part %s\n", partName); return OPT_DOWN_FAIL; } if(IMG_TYPE_SPARSE == imgType) { ret = optimus_simg_probe(data, dataSz); if(!ret){ DWN_ERR("Fail in sparse format probe,ret=%d\n", ret); return OPT_DOWN_FAIL; } return optimus_simg_parser_init(data); } } else//is bootloader, than do nothing { return OPT_DOWN_OK; } } break; case OPTIMUS_MEDIA_TYPE_KEY_UNIFY: break; case OPTIMUS_MEDIA_TYPE_MEM: break; default: DWN_MSG("Error MediaType %d\n", MediaType); return OPT_DOWN_FAIL; } return ret; }