113c5d8ecSJoseph Chen // SPDX-License-Identifier: GPL-2.0 213c5d8ecSJoseph Chen /* 313c5d8ecSJoseph Chen * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd 413c5d8ecSJoseph Chen */ 513c5d8ecSJoseph Chen 613c5d8ecSJoseph Chen #include <common.h> 7e3460df7SJason Zhu #include <android_image.h> 8e3460df7SJason Zhu #include <errno.h> 913c5d8ecSJoseph Chen #include <malloc.h> 10*6177e32dSJason Zhu #include <misc_decompress.h> 11aa415ed9SJoseph Chen #include <spl.h> 1213c5d8ecSJoseph Chen #include <spl_rkfw.h> 13e3460df7SJason Zhu #include <linux/kernel.h> 142241fc0fSJason Zhu #include <asm/arch/spl_resource_img.h> 1513c5d8ecSJoseph Chen 161cb393f1SJason Zhu #ifdef CONFIG_SPL_ATF 1713c5d8ecSJoseph Chen static const __aligned(16) struct s_fip_name_id fip_name_id[] = { 1813c5d8ecSJoseph Chen { BL30_IMAGE_NAME, UUID_SCP_FIRMWARE_BL30 }, /* optional */ 1913c5d8ecSJoseph Chen { BL31_IMAGE_NAME, UUID_EL3_RUNTIME_FIRMWARE_BL31 }, /* mandatory */ 2013c5d8ecSJoseph Chen { BL32_IMAGE_NAME, UUID_SECURE_PAYLOAD_BL32 }, /* optional */ 2113c5d8ecSJoseph Chen }; 2213c5d8ecSJoseph Chen 2313c5d8ecSJoseph Chen static int file2comp_id(const char *file_name, u32 *comp_id) 2413c5d8ecSJoseph Chen { 2513c5d8ecSJoseph Chen int i; 2613c5d8ecSJoseph Chen 2713c5d8ecSJoseph Chen for (i = 0; i < ARRAY_SIZE(fip_name_id); i++) { 2813c5d8ecSJoseph Chen if (!strcmp(file_name, fip_name_id[i].name)) { 2913c5d8ecSJoseph Chen *comp_id = fip_name_id[i].id; 3013c5d8ecSJoseph Chen return 0; 3113c5d8ecSJoseph Chen } 3213c5d8ecSJoseph Chen } 3313c5d8ecSJoseph Chen 3413c5d8ecSJoseph Chen return -ENOENT; 3513c5d8ecSJoseph Chen } 3613c5d8ecSJoseph Chen 3713c5d8ecSJoseph Chen static int open_image(const char *image_name, tboot_entry *entry, 3813c5d8ecSJoseph Chen struct tag_tboot_header_2k *hdr) 3913c5d8ecSJoseph Chen { 4013c5d8ecSJoseph Chen u32 i, component_num, sign_offset; 4113c5d8ecSJoseph Chen component_data *pcompdata; 4213c5d8ecSJoseph Chen boot_component *pcomp; 4313c5d8ecSJoseph Chen int n_found = 0; 4413c5d8ecSJoseph Chen u32 comp_id; 4513c5d8ecSJoseph Chen int ret; 4613c5d8ecSJoseph Chen 4713c5d8ecSJoseph Chen ret = file2comp_id(image_name, &comp_id); 4813c5d8ecSJoseph Chen if (ret) { 4913c5d8ecSJoseph Chen printf("Can't find unknown image: %s\n", image_name); 5013c5d8ecSJoseph Chen return ret; 5113c5d8ecSJoseph Chen } 5213c5d8ecSJoseph Chen 5313c5d8ecSJoseph Chen component_num = (hdr->size >> 16) & 0xffff; 5413c5d8ecSJoseph Chen sign_offset = (hdr->size & 0xffff) << 2; 5513c5d8ecSJoseph Chen pcompdata = (component_data *)((char *)hdr + sizeof(tboot_header)); 5613c5d8ecSJoseph Chen pcomp = (boot_component *)((char *)hdr + sign_offset + SIGNATURE_SIZE); 5713c5d8ecSJoseph Chen 5813c5d8ecSJoseph Chen for (i = 0; i < component_num; i++) { 5913c5d8ecSJoseph Chen if (comp_id == pcomp->component_id) { 6013c5d8ecSJoseph Chen if (n_found < MAX_BL_CODE_NUM) { 6113c5d8ecSJoseph Chen memcpy(&entry[n_found].component, pcomp, 6213c5d8ecSJoseph Chen sizeof(boot_component)); 6313c5d8ecSJoseph Chen memcpy(&entry[n_found].compdata, pcompdata, 6413c5d8ecSJoseph Chen sizeof(component_data)); 6513c5d8ecSJoseph Chen n_found++; 6613c5d8ecSJoseph Chen } else { 6713c5d8ecSJoseph Chen printf("Image num excess max: %d!\n", 6813c5d8ecSJoseph Chen MAX_BL_CODE_NUM); 6913c5d8ecSJoseph Chen return -EINVAL; 7013c5d8ecSJoseph Chen } 7113c5d8ecSJoseph Chen } else { 7213c5d8ecSJoseph Chen if (n_found > 0) 7313c5d8ecSJoseph Chen break; 7413c5d8ecSJoseph Chen } 7513c5d8ecSJoseph Chen 7613c5d8ecSJoseph Chen pcomp++; 7713c5d8ecSJoseph Chen pcompdata++; 7813c5d8ecSJoseph Chen } 7913c5d8ecSJoseph Chen 8013c5d8ecSJoseph Chen if (!n_found) { 8113c5d8ecSJoseph Chen printf("No find %s\n", image_name); 8213c5d8ecSJoseph Chen return -ENONET; 8313c5d8ecSJoseph Chen } 8413c5d8ecSJoseph Chen 8513c5d8ecSJoseph Chen return n_found; 8613c5d8ecSJoseph Chen } 8713c5d8ecSJoseph Chen 8813c5d8ecSJoseph Chen static int check_image(struct tag_tboot_header_2k *hdr) 8913c5d8ecSJoseph Chen { 9013c5d8ecSJoseph Chen u32 hash_format[] = { 0, 160, 256, 256 }; 9113c5d8ecSJoseph Chen 9213c5d8ecSJoseph Chen /* HASH format identifier */ 9313c5d8ecSJoseph Chen return (hash_format[hdr->flags & 0x3] == 0) ? -EINVAL : 0; 9413c5d8ecSJoseph Chen } 9513c5d8ecSJoseph Chen 9613c5d8ecSJoseph Chen static int load_image(struct spl_load_info *info, 9713c5d8ecSJoseph Chen struct tag_tboot_header_2k *hdr, 9813c5d8ecSJoseph Chen u32 image_sector, 9913c5d8ecSJoseph Chen const char *image_name, 10013c5d8ecSJoseph Chen uintptr_t *entry_point) 10113c5d8ecSJoseph Chen { 10213c5d8ecSJoseph Chen tboot_entry entry[MAX_BL_CODE_NUM]; 10313c5d8ecSJoseph Chen void *image_buf = NULL; 10413c5d8ecSJoseph Chen ulong load_addr; 10513c5d8ecSJoseph Chen u32 sect_off; 10613c5d8ecSJoseph Chen u32 sect_cnt; 10713c5d8ecSJoseph Chen int image_num; 10813c5d8ecSJoseph Chen int i, ret; 10913c5d8ecSJoseph Chen 11013c5d8ecSJoseph Chen /* Parse components from image header */ 11113c5d8ecSJoseph Chen image_num = open_image(image_name, entry, hdr); 11213c5d8ecSJoseph Chen if (image_num < 0) 11313c5d8ecSJoseph Chen return image_num; 11413c5d8ecSJoseph Chen 11513c5d8ecSJoseph Chen /* Get all component */ 11613c5d8ecSJoseph Chen for (i = 0; i < image_num; i++) { 11713c5d8ecSJoseph Chen load_addr = entry[i].compdata.load_addr; 11813c5d8ecSJoseph Chen sect_cnt = entry[i].component.image_size; 11913c5d8ecSJoseph Chen sect_off = entry[i].component.storage_addr; 12013c5d8ecSJoseph Chen 12113c5d8ecSJoseph Chen printf("%s[%d]: addr=0x%lx, size=0x%lx\n", 12213c5d8ecSJoseph Chen image_name, i, load_addr, (ulong)sect_cnt * 512); 12313c5d8ecSJoseph Chen 12413c5d8ecSJoseph Chen /* 12513c5d8ecSJoseph Chen * MMC/NAND controller DMA can't access sram region, so: 12613c5d8ecSJoseph Chen * data -> ddr buffer -> memcpy to sram region. 12713c5d8ecSJoseph Chen */ 128b35a1137SJoseph Chen if (load_addr < CONFIG_SYS_SDRAM_BASE || 129b35a1137SJoseph Chen load_addr >= CONFIG_SYS_SDRAM_BASE + SDRAM_MAX_SIZE) { 13013c5d8ecSJoseph Chen image_buf = memalign(ARCH_DMA_MINALIGN, sect_cnt * 512); 13113c5d8ecSJoseph Chen if (!image_buf) { 13213c5d8ecSJoseph Chen printf("%s: malloc failed\n", __func__); 13313c5d8ecSJoseph Chen return -ENOMEM; 13413c5d8ecSJoseph Chen } 13513c5d8ecSJoseph Chen } else { 13613c5d8ecSJoseph Chen image_buf = (void *)load_addr; 13713c5d8ecSJoseph Chen } 13813c5d8ecSJoseph Chen 13913c5d8ecSJoseph Chen ret = info->read(info, image_sector + sect_off, 14013c5d8ecSJoseph Chen sect_cnt, image_buf); 14113c5d8ecSJoseph Chen if (ret != sect_cnt) { 14213c5d8ecSJoseph Chen printf("Read '%s' failed at sector: %ld, ret=%d\n", 14313c5d8ecSJoseph Chen image_name, (ulong)image_sector + sect_off, ret); 14413c5d8ecSJoseph Chen return -EIO; 14513c5d8ecSJoseph Chen } 14613c5d8ecSJoseph Chen 14713c5d8ecSJoseph Chen /* Verify component */ 14813c5d8ecSJoseph Chen ret = check_image(hdr); 14913c5d8ecSJoseph Chen if (ret) { 15013c5d8ecSJoseph Chen printf("%s[%d]: verify image fail!\n", image_name, i); 15113c5d8ecSJoseph Chen return ret; 15213c5d8ecSJoseph Chen } 15313c5d8ecSJoseph Chen 15413c5d8ecSJoseph Chen /* Handle sram region */ 15513c5d8ecSJoseph Chen if ((ulong)image_buf != load_addr) { 15613c5d8ecSJoseph Chen memcpy((void *)load_addr, image_buf, sect_cnt << 9); 15713c5d8ecSJoseph Chen free(image_buf); 15813c5d8ecSJoseph Chen } 15913c5d8ecSJoseph Chen 16013c5d8ecSJoseph Chen /* Fill entry_point by first component */ 16113c5d8ecSJoseph Chen if (i == 0) 16213c5d8ecSJoseph Chen *entry_point = (uintptr_t)load_addr; 16313c5d8ecSJoseph Chen } 16413c5d8ecSJoseph Chen 16513c5d8ecSJoseph Chen return ret; 16613c5d8ecSJoseph Chen } 16713c5d8ecSJoseph Chen 16813c5d8ecSJoseph Chen static int rkfw_load_trust(struct spl_load_info *info, u32 image_sector, 1691cb393f1SJason Zhu struct spl_image_info *spl_image, 17013c5d8ecSJoseph Chen int *found_rkfw, u32 try_count) 17113c5d8ecSJoseph Chen { 17213c5d8ecSJoseph Chen struct tag_tboot_header_2k hdr; 17313c5d8ecSJoseph Chen u32 sect_addr = image_sector; 17413c5d8ecSJoseph Chen int blkcnt = 4; /* header sectors, 2KB */ 17513c5d8ecSJoseph Chen int i, ret = 0; 17613c5d8ecSJoseph Chen 17713c5d8ecSJoseph Chen /* Find valid image header */ 17813c5d8ecSJoseph Chen for (i = 0; i < try_count; i++) { 17913c5d8ecSJoseph Chen sect_addr = image_sector + (i * RKFW_RETRY_SECTOR_SIZE); 18013c5d8ecSJoseph Chen if (blkcnt != info->read(info, sect_addr, blkcnt, &hdr)) 18113c5d8ecSJoseph Chen continue; 18213c5d8ecSJoseph Chen 18313c5d8ecSJoseph Chen if (hdr.tag == TBOOT_HEAD_TAG) { 18413c5d8ecSJoseph Chen /* Mark it */ 18513c5d8ecSJoseph Chen *found_rkfw = 1; 18613c5d8ecSJoseph Chen 18713c5d8ecSJoseph Chen /* bl31 is mandatory */ 18813c5d8ecSJoseph Chen ret = load_image(info, &hdr, sect_addr, 1891cb393f1SJason Zhu BL31_IMAGE_NAME, &spl_image->entry_point); 19013c5d8ecSJoseph Chen if (ret) 19113c5d8ecSJoseph Chen continue; 19213c5d8ecSJoseph Chen 19313c5d8ecSJoseph Chen /* bl32 is optional */ 19413c5d8ecSJoseph Chen ret = load_image(info, &hdr, sect_addr, 1951cb393f1SJason Zhu BL32_IMAGE_NAME, &spl_image->entry_point_bl32); 19613c5d8ecSJoseph Chen if (ret) { 19713c5d8ecSJoseph Chen if (ret == -ENONET) { 1981cb393f1SJason Zhu spl_image->entry_point_bl32 = -1; /* Not exist */ 19913c5d8ecSJoseph Chen ret = 0; 20013c5d8ecSJoseph Chen } else { 20113c5d8ecSJoseph Chen continue; 20213c5d8ecSJoseph Chen } 20313c5d8ecSJoseph Chen } 20413c5d8ecSJoseph Chen break; 20513c5d8ecSJoseph Chen } 20613c5d8ecSJoseph Chen } 20713c5d8ecSJoseph Chen 20813c5d8ecSJoseph Chen return ret; 20913c5d8ecSJoseph Chen } 2101cb393f1SJason Zhu #else 2111cb393f1SJason Zhu static int rkfw_load_trust(struct spl_load_info *info, u32 image_sector, 2121cb393f1SJason Zhu struct spl_image_info *spl_image, 2131cb393f1SJason Zhu int *found_rkfw, u32 try_count) 2141cb393f1SJason Zhu { 2151cb393f1SJason Zhu struct tag_second_loader_hdr hdr; 2161cb393f1SJason Zhu int i, ret, blkcnt = 4; /* header sectors, 2KB */ 2171cb393f1SJason Zhu char *load_addr; 2181cb393f1SJason Zhu u32 sect_addr; 2191cb393f1SJason Zhu 2201cb393f1SJason Zhu /* Detect valid image header */ 2211cb393f1SJason Zhu for (i = 0; i < try_count; i++) { 2221cb393f1SJason Zhu sect_addr = image_sector + (i * RKFW_RETRY_SECTOR_SIZE); 2231cb393f1SJason Zhu ret = info->read(info, sect_addr, blkcnt, &hdr); 2241cb393f1SJason Zhu if (ret != blkcnt) 2251cb393f1SJason Zhu continue; 2261cb393f1SJason Zhu 2271cb393f1SJason Zhu if (!memcmp(hdr.magic, TBOOT_HEAD_TAG, 6)) { 2281cb393f1SJason Zhu *found_rkfw = 1; 2291cb393f1SJason Zhu spl_image->entry_point = (uintptr_t)hdr.loader_load_addr; 2301cb393f1SJason Zhu /* Load full binary image(right behind header) */ 2311cb393f1SJason Zhu sect_addr += blkcnt; 2321cb393f1SJason Zhu load_addr = (char *)((size_t)hdr.loader_load_addr); 2331cb393f1SJason Zhu blkcnt = DIV_ROUND_UP(hdr.loader_load_size, 512); 2341cb393f1SJason Zhu 2351cb393f1SJason Zhu printf("tee.bin: addr=0x%lx, size=0x%lx\n", 2361cb393f1SJason Zhu (ulong)load_addr, (ulong)blkcnt * 512); 2371cb393f1SJason Zhu ret = info->read(info, sect_addr, blkcnt, load_addr); 2381cb393f1SJason Zhu if (ret != blkcnt) 2391cb393f1SJason Zhu continue; 2401cb393f1SJason Zhu 2411cb393f1SJason Zhu break; 2421cb393f1SJason Zhu } 2431cb393f1SJason Zhu } 2441cb393f1SJason Zhu 2451cb393f1SJason Zhu if (i == try_count) { 2461cb393f1SJason Zhu printf("Can not find usable uboot\n"); 2471cb393f1SJason Zhu return -ENONET; 2481cb393f1SJason Zhu } 2491cb393f1SJason Zhu 2501cb393f1SJason Zhu return 0; 2511cb393f1SJason Zhu } 2521cb393f1SJason Zhu #endif 25313c5d8ecSJoseph Chen 25413c5d8ecSJoseph Chen static int rkfw_load_uboot(struct spl_load_info *info, u32 image_sector, 2551cb393f1SJason Zhu struct spl_image_info *spl_image, u32 try_count) 25613c5d8ecSJoseph Chen { 25713c5d8ecSJoseph Chen struct tag_second_loader_hdr hdr; 25813c5d8ecSJoseph Chen int i, ret, blkcnt = 4; /* header sectors, 2KB */ 25913c5d8ecSJoseph Chen char *load_addr; 26013c5d8ecSJoseph Chen u32 sect_addr; 26113c5d8ecSJoseph Chen 26213c5d8ecSJoseph Chen /* Detect valid image header */ 26313c5d8ecSJoseph Chen for (i = 0; i < try_count; i++) { 26413c5d8ecSJoseph Chen sect_addr = image_sector + (i * RKFW_RETRY_SECTOR_SIZE); 26513c5d8ecSJoseph Chen ret = info->read(info, sect_addr, blkcnt, &hdr); 26613c5d8ecSJoseph Chen if (ret != blkcnt) 26713c5d8ecSJoseph Chen continue; 26813c5d8ecSJoseph Chen 26913c5d8ecSJoseph Chen if (!memcmp(hdr.magic, LOADER_HARD_STR, 6)) { 27013c5d8ecSJoseph Chen /* Load full binary image(right behind header) */ 27113c5d8ecSJoseph Chen sect_addr += blkcnt; 27213c5d8ecSJoseph Chen load_addr = (char *)((size_t)hdr.loader_load_addr); 27313c5d8ecSJoseph Chen blkcnt = DIV_ROUND_UP(hdr.loader_load_size, 512); 27413c5d8ecSJoseph Chen 27513c5d8ecSJoseph Chen printf("u-boot.bin: addr=0x%lx, size=0x%lx\n", 27613c5d8ecSJoseph Chen (ulong)load_addr, (ulong)blkcnt * 512); 27713c5d8ecSJoseph Chen ret = info->read(info, sect_addr, blkcnt, load_addr); 27813c5d8ecSJoseph Chen if (ret != blkcnt) 27913c5d8ecSJoseph Chen continue; 28013c5d8ecSJoseph Chen 28113c5d8ecSJoseph Chen break; 28213c5d8ecSJoseph Chen } 28313c5d8ecSJoseph Chen } 28413c5d8ecSJoseph Chen 28513c5d8ecSJoseph Chen if (i == try_count) { 28613c5d8ecSJoseph Chen printf("Can not find usable uboot\n"); 28713c5d8ecSJoseph Chen return -ENONET; 28813c5d8ecSJoseph Chen } 28913c5d8ecSJoseph Chen 29013c5d8ecSJoseph Chen /* Fill entry point */ 2911cb393f1SJason Zhu #ifdef CONFIG_SPL_ATF 2921cb393f1SJason Zhu spl_image->entry_point_bl33 = (uintptr_t)hdr.loader_load_addr; 2931cb393f1SJason Zhu #endif 2941cb393f1SJason Zhu #ifdef CONFIG_SPL_OPTEE 2951cb393f1SJason Zhu spl_image->entry_point_os = (uintptr_t)hdr.loader_load_addr; 2961cb393f1SJason Zhu #endif 29713c5d8ecSJoseph Chen return 0; 29813c5d8ecSJoseph Chen } 29913c5d8ecSJoseph Chen 300e3460df7SJason Zhu static int rkfw_load_kernel(struct spl_load_info *info, u32 image_sector, 3011cb393f1SJason Zhu struct spl_image_info *spl_image, u32 try_count) 302e3460df7SJason Zhu { 303e3460df7SJason Zhu struct andr_img_hdr *hdr; 304e3460df7SJason Zhu int ret, cnt; 3052241fc0fSJason Zhu int dtb_sector, ramdisk_sector, resource_sector; 306e3460df7SJason Zhu 307e3460df7SJason Zhu cnt = ALIGN(sizeof(struct andr_img_hdr), 512) >> 9; 308e3460df7SJason Zhu hdr = malloc(cnt * 512); 309e3460df7SJason Zhu if (!hdr) 310e3460df7SJason Zhu return -ENOMEM; 311e3460df7SJason Zhu 312e3460df7SJason Zhu ret = info->read(info, image_sector, cnt, (void *)hdr); 313e3460df7SJason Zhu if (ret != cnt) { 314e3460df7SJason Zhu ret = -EIO; 315e3460df7SJason Zhu goto out; 316e3460df7SJason Zhu } 317e3460df7SJason Zhu 318e3460df7SJason Zhu if (memcmp(hdr->magic, ANDR_BOOT_MAGIC, strlen(ANDR_BOOT_MAGIC)) != 0) { 319e3460df7SJason Zhu printf("SPL: boot image head magic error\n"); 320e3460df7SJason Zhu ret = -EINVAL; 321e3460df7SJason Zhu goto out; 322e3460df7SJason Zhu } 323e3460df7SJason Zhu 324e3460df7SJason Zhu ramdisk_sector = ALIGN(hdr->kernel_size, hdr->page_size); 3252241fc0fSJason Zhu resource_sector = ALIGN(hdr->kernel_size, hdr->page_size) 3262241fc0fSJason Zhu + ALIGN(hdr->ramdisk_size, hdr->page_size); 327e3460df7SJason Zhu dtb_sector = ALIGN(hdr->kernel_size, hdr->page_size) 328e3460df7SJason Zhu + ALIGN(hdr->ramdisk_size, hdr->page_size) 329e3460df7SJason Zhu + ALIGN(hdr->second_size, hdr->page_size); 330e3460df7SJason Zhu image_sector = image_sector + cnt; 331e3460df7SJason Zhu cnt = ALIGN(hdr->kernel_size, hdr->page_size) >> 9; 332e3460df7SJason Zhu 333e3460df7SJason Zhu /* Load kernel image */ 334*6177e32dSJason Zhu #ifdef CONFIG_SPL_ROCKCHIP_HW_DECOMPRESS 335*6177e32dSJason Zhu ret = info->read(info, image_sector, cnt, 336*6177e32dSJason Zhu (void *)CONFIG_SPL_KERNEL_COMPRESS_ADDR); 337*6177e32dSJason Zhu #else 338e3460df7SJason Zhu ret = info->read(info, image_sector, cnt, (void *)CONFIG_SPL_KERNEL_ADDR); 339*6177e32dSJason Zhu #endif 340e3460df7SJason Zhu if (ret != cnt) { 341e3460df7SJason Zhu ret = -EIO; 342e3460df7SJason Zhu goto out; 343e3460df7SJason Zhu } 344*6177e32dSJason Zhu #ifdef CONFIG_SPL_ROCKCHIP_HW_DECOMPRESS 345*6177e32dSJason Zhu struct udevice *dev; 346*6177e32dSJason Zhu u32 cap = GZIP_MOD; 347*6177e32dSJason Zhu 348*6177e32dSJason Zhu dev = misc_decompress_get_device(cap); 349*6177e32dSJason Zhu 350*6177e32dSJason Zhu if (!dev) 351*6177e32dSJason Zhu goto out; 352*6177e32dSJason Zhu 353*6177e32dSJason Zhu ret = misc_decompress_start(dev, CONFIG_SPL_KERNEL_COMPRESS_ADDR, 354*6177e32dSJason Zhu CONFIG_SPL_KERNEL_ADDR, hdr->kernel_size); 355*6177e32dSJason Zhu if (ret) 356*6177e32dSJason Zhu goto out; 357*6177e32dSJason Zhu 358*6177e32dSJason Zhu #endif 359e3460df7SJason Zhu 360e3460df7SJason Zhu /* Load ramdisk image */ 361e3460df7SJason Zhu if (hdr->ramdisk_size) { 362*6177e32dSJason Zhu #ifdef CONFIG_SPL_ROCKCHIP_HW_DECOMPRESS 363*6177e32dSJason Zhu ret = info->read(info, (ramdisk_sector >> 9) + image_sector, 364*6177e32dSJason Zhu ALIGN(hdr->ramdisk_size, hdr->page_size) >> 9, 365*6177e32dSJason Zhu (void *)CONFIG_SPL_RAMDISK_COMPRESS_ADDR); 366*6177e32dSJason Zhu #else 367e3460df7SJason Zhu ret = info->read(info, (ramdisk_sector >> 9) + image_sector, 368e3460df7SJason Zhu ALIGN(hdr->ramdisk_size, hdr->page_size) >> 9, 369e3460df7SJason Zhu (void *)CONFIG_SPL_RAMDISK_ADDR); 370*6177e32dSJason Zhu #endif 371e3460df7SJason Zhu if (ret != (ALIGN(hdr->ramdisk_size, hdr->page_size) >> 9)) { 372e3460df7SJason Zhu ret = -EIO; 373e3460df7SJason Zhu goto out; 374e3460df7SJason Zhu } 375*6177e32dSJason Zhu #ifdef CONFIG_SPL_ROCKCHIP_HW_DECOMPRESS 376*6177e32dSJason Zhu int timeout = 10000; 377*6177e32dSJason Zhu 378*6177e32dSJason Zhu while (misc_decompress_is_complete(dev)) { 379*6177e32dSJason Zhu if (timeout < 0) { 380*6177e32dSJason Zhu ret = -EIO; 381*6177e32dSJason Zhu goto out; 382*6177e32dSJason Zhu } 383*6177e32dSJason Zhu 384*6177e32dSJason Zhu timeout--; 385*6177e32dSJason Zhu udelay(10); 386*6177e32dSJason Zhu } 387*6177e32dSJason Zhu 388*6177e32dSJason Zhu ret = misc_decompress_start(dev, 389*6177e32dSJason Zhu CONFIG_SPL_RAMDISK_COMPRESS_ADDR, 390*6177e32dSJason Zhu CONFIG_SPL_RAMDISK_ADDR, 391*6177e32dSJason Zhu hdr->kernel_size); 392*6177e32dSJason Zhu if (ret) 393*6177e32dSJason Zhu goto out; 394*6177e32dSJason Zhu #endif 395e3460df7SJason Zhu } 396e3460df7SJason Zhu 3972241fc0fSJason Zhu /* Load resource, and checkout the dtb */ 3982241fc0fSJason Zhu if (hdr->second_size) { 3992241fc0fSJason Zhu struct resource_img_hdr *head = 4002241fc0fSJason Zhu (struct resource_img_hdr *)(CONFIG_SPL_FDT_ADDR + 0x100000); 4012241fc0fSJason Zhu 4022241fc0fSJason Zhu ret = info->read(info, (resource_sector >> 9) + image_sector, 4032241fc0fSJason Zhu ALIGN(hdr->second_size, hdr->page_size) >> 9, 4042241fc0fSJason Zhu (void *)head); 4052241fc0fSJason Zhu if (ret != (ALIGN(hdr->second_size, hdr->page_size) >> 9)) { 4062241fc0fSJason Zhu ret = -EIO; 4072241fc0fSJason Zhu goto out; 4082241fc0fSJason Zhu } 4091cb393f1SJason Zhu #ifdef CONFIG_SPL_KERNEL_BOOT 4102241fc0fSJason Zhu if (spl_resource_image_check_header(head)) { 4112241fc0fSJason Zhu printf("Can't find kernel dtb in spl."); 4122241fc0fSJason Zhu } else { 4132241fc0fSJason Zhu struct resource_entry *entry; 4142241fc0fSJason Zhu char *dtb_temp; 4152241fc0fSJason Zhu 4162241fc0fSJason Zhu entry = spl_resource_image_get_dtb_entry(head); 4172241fc0fSJason Zhu if (!entry) { 4182241fc0fSJason Zhu ret = -EIO; 4192241fc0fSJason Zhu goto out; 4202241fc0fSJason Zhu } 4212241fc0fSJason Zhu 4222241fc0fSJason Zhu dtb_temp = (char *)((char *)head + entry->f_offset * 512); 4232241fc0fSJason Zhu memcpy((char *)CONFIG_SPL_FDT_ADDR, dtb_temp, 4242241fc0fSJason Zhu entry->f_size); 4252241fc0fSJason Zhu } 4261cb393f1SJason Zhu #endif 4272241fc0fSJason Zhu } else { 428e3460df7SJason Zhu /* Load dtb image */ 429e3460df7SJason Zhu ret = info->read(info, (dtb_sector >> 9) + image_sector, 430e3460df7SJason Zhu ALIGN(hdr->dtb_size, hdr->page_size) >> 9, 431e3460df7SJason Zhu (void *)CONFIG_SPL_FDT_ADDR); 432e3460df7SJason Zhu if (ret != (ALIGN(hdr->dtb_size, hdr->page_size) >> 9)) { 433e3460df7SJason Zhu ret = -EIO; 434e3460df7SJason Zhu goto out; 435e3460df7SJason Zhu } 4362241fc0fSJason Zhu } 437e3460df7SJason Zhu 4381cb393f1SJason Zhu spl_image->fdt_addr = (void *)CONFIG_SPL_FDT_ADDR; 4391cb393f1SJason Zhu #ifdef CONFIG_SPL_OPTEE 4401cb393f1SJason Zhu spl_image->entry_point_os = (uintptr_t)CONFIG_SPL_KERNEL_ADDR; 4411cb393f1SJason Zhu #endif 4421cb393f1SJason Zhu #ifdef CONFIG_SPL_ATF 4431cb393f1SJason Zhu spl_image->entry_point_bl33 = CONFIG_SPL_KERNEL_ADDR; 4441cb393f1SJason Zhu #endif 445e3460df7SJason Zhu ret = 0; 446e3460df7SJason Zhu out: 447e3460df7SJason Zhu free(hdr); 448e3460df7SJason Zhu 449e3460df7SJason Zhu return ret; 450e3460df7SJason Zhu } 451e3460df7SJason Zhu 45213c5d8ecSJoseph Chen int spl_load_rkfw_image(struct spl_image_info *spl_image, 45313c5d8ecSJoseph Chen struct spl_load_info *info, 454aa415ed9SJoseph Chen u32 trust_sector, u32 uboot_sector, 455aa415ed9SJoseph Chen u32 boot_sector) 45613c5d8ecSJoseph Chen { 45713c5d8ecSJoseph Chen int ret, try_count = RKFW_RETRY_SECTOR_TIMES; 45813c5d8ecSJoseph Chen int found_rkfw = 0; 45913c5d8ecSJoseph Chen 4601cb393f1SJason Zhu ret = rkfw_load_trust(info, trust_sector, spl_image, 46113c5d8ecSJoseph Chen &found_rkfw, try_count); 46213c5d8ecSJoseph Chen if (ret) { 46313c5d8ecSJoseph Chen printf("Load trust image failed! ret=%d\n", ret); 46413c5d8ecSJoseph Chen goto out; 46513c5d8ecSJoseph Chen } 466aa415ed9SJoseph Chen #ifdef CONFIG_SPL_KERNEL_BOOT 467aa415ed9SJoseph Chen if (spl_image->next_stage == SPL_NEXT_STAGE_UBOOT) { 468aa415ed9SJoseph Chen #endif 469aa415ed9SJoseph Chen ret = rkfw_load_uboot(info, uboot_sector, spl_image, try_count); 470e3460df7SJason Zhu if (ret) 47113c5d8ecSJoseph Chen printf("Load uboot image failed! ret=%d\n", ret); 4724ef4c8bfSJason Zhu else 4734ef4c8bfSJason Zhu goto boot; 474aa415ed9SJoseph Chen #ifdef CONFIG_SPL_KERNEL_BOOT 475aa415ed9SJoseph Chen } else if (spl_image->next_stage == SPL_NEXT_STAGE_KERNEL) { 476aa415ed9SJoseph Chen #endif 477aa415ed9SJoseph Chen ret = rkfw_load_kernel(info, boot_sector, spl_image, try_count); 478e3460df7SJason Zhu if (ret) { 479e3460df7SJason Zhu printf("Load kernel image failed! ret=%d\n", ret); 48013c5d8ecSJoseph Chen goto out; 48113c5d8ecSJoseph Chen } 482aa415ed9SJoseph Chen #ifdef CONFIG_SPL_KERNEL_BOOT 483aa415ed9SJoseph Chen } 484aa415ed9SJoseph Chen #endif 48513c5d8ecSJoseph Chen 4864ef4c8bfSJason Zhu boot: 48713c5d8ecSJoseph Chen #if CONFIG_IS_ENABLED(LOAD_FIT) 48813c5d8ecSJoseph Chen spl_image->fdt_addr = 0; 48913c5d8ecSJoseph Chen #endif 4901cb393f1SJason Zhu #ifdef CONFIG_SPL_ATF 49113c5d8ecSJoseph Chen spl_image->os = IH_OS_ARM_TRUSTED_FIRMWARE; 4921cb393f1SJason Zhu #else 4931cb393f1SJason Zhu spl_image->os = IH_OS_OP_TEE; 4941cb393f1SJason Zhu #endif 49513c5d8ecSJoseph Chen 49613c5d8ecSJoseph Chen out: 49713c5d8ecSJoseph Chen /* If not found rockchip firmware, try others outside */ 49813c5d8ecSJoseph Chen return found_rkfw ? ret : -EAGAIN; 49913c5d8ecSJoseph Chen } 500