//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; }
//store dtb read/write buff size static int do_store_dtb_ops(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { int ret = 0; char _cmdBuf[128]; char* ops = argv[2]; const unsigned maxDtbSz = 256 * 1024; unsigned actualDtbSz = 0; char* devCmd = NULL; char* dtbLoadaddr = argv[3]; if (argc < 4) return CMD_RET_USAGE; const int is_write = !strcmp("write", ops); if (!is_write) { ret = !strcmp("read", ops) || !strcmp("iread", ops);//must be 0 if (!ret) return CMD_RET_USAGE; } actualDtbSz = maxDtbSz; if (argc > 4) { const unsigned bufSz = simple_strtoul(argv[4], NULL, 0); if (bufSz > maxDtbSz) { ErrP("bufSz (%s) > max 0x%x\n", argv[4], maxDtbSz); return CMD_RET_FAILURE; } } ops = is_write ? "dtb_write" : "dtb_read"; switch (device_boot_flag) { case NAND_BOOT_FLAG: case SPI_NAND_FLAG: { devCmd = "amlnf"; } break; case EMMC_BOOT_FLAG: case SPI_EMMC_FLAG: { devCmd = "emmc"; } break; default: ErrP("device_boot_flag=0x%x err\n", device_boot_flag); return CMD_RET_FAILURE; } sprintf(_cmdBuf, "%s %s %s 0x%x", devCmd, ops, dtbLoadaddr, actualDtbSz); MsgP("To run cmd[%s]\n", _cmdBuf); ret = run_command(_cmdBuf, 0); #ifdef CONFIG_MULTI_DTB if (!is_write && strcmp("iread", ops)) { extern unsigned long get_multi_dt_entry(unsigned long fdt_addr); unsigned long dtImgAddr = simple_strtoul(dtbLoadaddr, NULL, 16); unsigned long fdtAddr = get_multi_dt_entry(dtImgAddr); ret = fdt_check_header((char*)fdtAddr); if (ret) { ErrP("Fail in fdt check header\n"); return CMD_RET_FAILURE; } unsigned fdtsz = fdt_totalsize((char*)fdtAddr); memmove((char*)dtImgAddr, (char*)fdtAddr, fdtsz); } #endif// #ifdef CONFIG_MULTI_DTB return ret; }
static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { void *os_hdr; int ret; #if defined(CONFIG_ANDROID_IMG) void *temp_os_hdr = NULL; boot_img_hdr *temp_android_hdr = NULL; #endif memset ((void *)&images, 0, sizeof (images)); images.verify = getenv_yesno ("verify"); bootm_start_lmb(); /* get kernel image header, start address and length */ os_hdr = boot_get_kernel (cmdtp, flag, argc, argv, &images, &images.os.image_start, &images.os.image_len); if (images.os.image_len == 0) { puts ("ERROR: can't get kernel image!\n"); return 1; } /* get image parameters */ switch (genimg_get_format (os_hdr)) { case IMAGE_FORMAT_LEGACY: images.os.type = image_get_type (os_hdr); images.os.comp = image_get_comp (os_hdr); images.os.os = image_get_os (os_hdr); images.os.end = image_get_image_end (os_hdr); images.os.load = image_get_load (os_hdr); break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: if (fit_image_get_type (images.fit_hdr_os, images.fit_noffset_os, &images.os.type)) { puts ("Can't get image type!\n"); show_boot_progress (-109); return 1; } if (fit_image_get_comp (images.fit_hdr_os, images.fit_noffset_os, &images.os.comp)) { puts ("Can't get image compression!\n"); show_boot_progress (-110); return 1; } if (fit_image_get_os (images.fit_hdr_os, images.fit_noffset_os, &images.os.os)) { puts ("Can't get image OS!\n"); show_boot_progress (-111); return 1; } images.os.end = fit_get_end (images.fit_hdr_os); if (fit_image_get_load (images.fit_hdr_os, images.fit_noffset_os, &images.os.load)) { puts ("Can't get image load address!\n"); show_boot_progress (-112); return 1; } break; #endif #if defined(CONFIG_ANDROID_IMG) case IMAGE_FORMAT_ANDROID: temp_os_hdr = os_hdr + 0x800;//shift 0x800 Android format head temp_android_hdr = (void *) os_hdr; images.os.type = image_get_type (temp_os_hdr); images.os.comp = image_get_comp (temp_os_hdr); images.os.os = image_get_os (temp_os_hdr); images.os.end = image_get_image_end (temp_os_hdr); images.os.load = image_get_load (temp_os_hdr); images.rd_start = ((ulong)temp_android_hdr->kernel_size + 0x800 + (ulong)os_hdr + ((ulong)temp_android_hdr->page_size - 1)) & (~((ulong)temp_android_hdr->page_size - 1)); images.rd_end = images.rd_start + (ulong)temp_android_hdr->ramdisk_size; printf(" Ramdisk start addr = 0x%x, len = 0x%x\n",images.rd_start,temp_android_hdr->ramdisk_size ); #if defined(CONFIG_OF_LIBFDT) if(images.ft_len = (ulong)temp_android_hdr->second_size) { fdt_addr = (images.rd_end + ((ulong)temp_android_hdr->page_size - 1)) & (~((ulong)temp_android_hdr->page_size - 1)); /*get_multi_dt_entry, compatible with single dt*/ fdt_addr = get_multi_dt_entry(fdt_addr); images.ft_addr = (char *)fdt_addr; images.ft_len = fdt_totalsize(fdt_addr); printf(" Flat device tree start addr = 0x%x, len = 0x%x magic=0x%x\n", (int *)images.ft_addr,images.ft_len,*(unsigned int*)images.ft_addr); } #endif break; #endif default: puts ("ERROR: unknown image format type!\n"); return 1; } /* find kernel entry point */ if (images.legacy_hdr_valid) { images.ep = image_get_ep (&images.legacy_hdr_os_copy); #if defined(CONFIG_FIT) } else if (images.fit_uname_os) { ret = fit_image_get_entry (images.fit_hdr_os, images.fit_noffset_os, &images.ep); if (ret) { puts ("Can't get entry point property!\n"); return 1; } #endif } else { puts ("Could not find kernel entry point!\n"); return 1; } if (((images.os.type == IH_TYPE_KERNEL) || (images.os.type == IH_TYPE_MULTI)) && (images.os.os == IH_OS_LINUX)) { /* find ramdisk */ #ifndef CONFIG_ANDROID_IMG #if defined(CONFIG_AML_MESON_FIT) //call boot_get_ramdisk() here for get ramdisk start addr boot_get_ramdisk (argc, argv, &images, IH_INITRD_ARCH, &images.rd_start, &images.rd_end); #endif #endif #if defined(CONFIG_ANDROID_IMG) if(!images.rd_start) #endif { ret = boot_get_ramdisk (argc, argv, &images, IH_INITRD_ARCH, &images.rd_start, &images.rd_end); if (ret) { puts ("Ramdisk image is corrupt or invalid\n"); return 1; } } #if defined(CONFIG_OF_LIBFDT) /* find flattened device tree */ #if defined(CONFIG_ANDROID_IMG) if(!images.ft_addr) #endif { ret = boot_get_fdt (flag, argc, argv, &images, &images.ft_addr, &images.ft_len); if (ret) { puts ("Could not find a valid device tree\n"); return 1; } } set_working_fdt_addr(images.ft_addr); #endif } #if defined(CONFIG_ANDROID_IMG) images.os.start = (ulong)temp_os_hdr; #else images.os.start = (ulong)os_hdr; #endif images.state = BOOTM_STATE_START; return 0; }