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*aa415ed9SJoseph Chen #include <spl.h> 1113c5d8ecSJoseph Chen #include <spl_rkfw.h> 12e3460df7SJason Zhu #include <linux/kernel.h> 132241fc0fSJason Zhu #include <asm/arch/spl_resource_img.h> 1413c5d8ecSJoseph Chen 151cb393f1SJason Zhu #ifdef CONFIG_SPL_ATF 1613c5d8ecSJoseph Chen static const __aligned(16) struct s_fip_name_id fip_name_id[] = { 1713c5d8ecSJoseph Chen { BL30_IMAGE_NAME, UUID_SCP_FIRMWARE_BL30 }, /* optional */ 1813c5d8ecSJoseph Chen { BL31_IMAGE_NAME, UUID_EL3_RUNTIME_FIRMWARE_BL31 }, /* mandatory */ 1913c5d8ecSJoseph Chen { BL32_IMAGE_NAME, UUID_SECURE_PAYLOAD_BL32 }, /* optional */ 2013c5d8ecSJoseph Chen }; 2113c5d8ecSJoseph Chen 2213c5d8ecSJoseph Chen static int file2comp_id(const char *file_name, u32 *comp_id) 2313c5d8ecSJoseph Chen { 2413c5d8ecSJoseph Chen int i; 2513c5d8ecSJoseph Chen 2613c5d8ecSJoseph Chen for (i = 0; i < ARRAY_SIZE(fip_name_id); i++) { 2713c5d8ecSJoseph Chen if (!strcmp(file_name, fip_name_id[i].name)) { 2813c5d8ecSJoseph Chen *comp_id = fip_name_id[i].id; 2913c5d8ecSJoseph Chen return 0; 3013c5d8ecSJoseph Chen } 3113c5d8ecSJoseph Chen } 3213c5d8ecSJoseph Chen 3313c5d8ecSJoseph Chen return -ENOENT; 3413c5d8ecSJoseph Chen } 3513c5d8ecSJoseph Chen 3613c5d8ecSJoseph Chen static int open_image(const char *image_name, tboot_entry *entry, 3713c5d8ecSJoseph Chen struct tag_tboot_header_2k *hdr) 3813c5d8ecSJoseph Chen { 3913c5d8ecSJoseph Chen u32 i, component_num, sign_offset; 4013c5d8ecSJoseph Chen component_data *pcompdata; 4113c5d8ecSJoseph Chen boot_component *pcomp; 4213c5d8ecSJoseph Chen int n_found = 0; 4313c5d8ecSJoseph Chen u32 comp_id; 4413c5d8ecSJoseph Chen int ret; 4513c5d8ecSJoseph Chen 4613c5d8ecSJoseph Chen ret = file2comp_id(image_name, &comp_id); 4713c5d8ecSJoseph Chen if (ret) { 4813c5d8ecSJoseph Chen printf("Can't find unknown image: %s\n", image_name); 4913c5d8ecSJoseph Chen return ret; 5013c5d8ecSJoseph Chen } 5113c5d8ecSJoseph Chen 5213c5d8ecSJoseph Chen component_num = (hdr->size >> 16) & 0xffff; 5313c5d8ecSJoseph Chen sign_offset = (hdr->size & 0xffff) << 2; 5413c5d8ecSJoseph Chen pcompdata = (component_data *)((char *)hdr + sizeof(tboot_header)); 5513c5d8ecSJoseph Chen pcomp = (boot_component *)((char *)hdr + sign_offset + SIGNATURE_SIZE); 5613c5d8ecSJoseph Chen 5713c5d8ecSJoseph Chen for (i = 0; i < component_num; i++) { 5813c5d8ecSJoseph Chen if (comp_id == pcomp->component_id) { 5913c5d8ecSJoseph Chen if (n_found < MAX_BL_CODE_NUM) { 6013c5d8ecSJoseph Chen memcpy(&entry[n_found].component, pcomp, 6113c5d8ecSJoseph Chen sizeof(boot_component)); 6213c5d8ecSJoseph Chen memcpy(&entry[n_found].compdata, pcompdata, 6313c5d8ecSJoseph Chen sizeof(component_data)); 6413c5d8ecSJoseph Chen n_found++; 6513c5d8ecSJoseph Chen } else { 6613c5d8ecSJoseph Chen printf("Image num excess max: %d!\n", 6713c5d8ecSJoseph Chen MAX_BL_CODE_NUM); 6813c5d8ecSJoseph Chen return -EINVAL; 6913c5d8ecSJoseph Chen } 7013c5d8ecSJoseph Chen } else { 7113c5d8ecSJoseph Chen if (n_found > 0) 7213c5d8ecSJoseph Chen break; 7313c5d8ecSJoseph Chen } 7413c5d8ecSJoseph Chen 7513c5d8ecSJoseph Chen pcomp++; 7613c5d8ecSJoseph Chen pcompdata++; 7713c5d8ecSJoseph Chen } 7813c5d8ecSJoseph Chen 7913c5d8ecSJoseph Chen if (!n_found) { 8013c5d8ecSJoseph Chen printf("No find %s\n", image_name); 8113c5d8ecSJoseph Chen return -ENONET; 8213c5d8ecSJoseph Chen } 8313c5d8ecSJoseph Chen 8413c5d8ecSJoseph Chen return n_found; 8513c5d8ecSJoseph Chen } 8613c5d8ecSJoseph Chen 8713c5d8ecSJoseph Chen static int check_image(struct tag_tboot_header_2k *hdr) 8813c5d8ecSJoseph Chen { 8913c5d8ecSJoseph Chen u32 hash_format[] = { 0, 160, 256, 256 }; 9013c5d8ecSJoseph Chen 9113c5d8ecSJoseph Chen /* HASH format identifier */ 9213c5d8ecSJoseph Chen return (hash_format[hdr->flags & 0x3] == 0) ? -EINVAL : 0; 9313c5d8ecSJoseph Chen } 9413c5d8ecSJoseph Chen 9513c5d8ecSJoseph Chen static int load_image(struct spl_load_info *info, 9613c5d8ecSJoseph Chen struct tag_tboot_header_2k *hdr, 9713c5d8ecSJoseph Chen u32 image_sector, 9813c5d8ecSJoseph Chen const char *image_name, 9913c5d8ecSJoseph Chen uintptr_t *entry_point) 10013c5d8ecSJoseph Chen { 10113c5d8ecSJoseph Chen tboot_entry entry[MAX_BL_CODE_NUM]; 10213c5d8ecSJoseph Chen void *image_buf = NULL; 10313c5d8ecSJoseph Chen ulong load_addr; 10413c5d8ecSJoseph Chen u32 sect_off; 10513c5d8ecSJoseph Chen u32 sect_cnt; 10613c5d8ecSJoseph Chen int image_num; 10713c5d8ecSJoseph Chen int i, ret; 10813c5d8ecSJoseph Chen 10913c5d8ecSJoseph Chen /* Parse components from image header */ 11013c5d8ecSJoseph Chen image_num = open_image(image_name, entry, hdr); 11113c5d8ecSJoseph Chen if (image_num < 0) 11213c5d8ecSJoseph Chen return image_num; 11313c5d8ecSJoseph Chen 11413c5d8ecSJoseph Chen /* Get all component */ 11513c5d8ecSJoseph Chen for (i = 0; i < image_num; i++) { 11613c5d8ecSJoseph Chen load_addr = entry[i].compdata.load_addr; 11713c5d8ecSJoseph Chen sect_cnt = entry[i].component.image_size; 11813c5d8ecSJoseph Chen sect_off = entry[i].component.storage_addr; 11913c5d8ecSJoseph Chen 12013c5d8ecSJoseph Chen printf("%s[%d]: addr=0x%lx, size=0x%lx\n", 12113c5d8ecSJoseph Chen image_name, i, load_addr, (ulong)sect_cnt * 512); 12213c5d8ecSJoseph Chen 12313c5d8ecSJoseph Chen /* 12413c5d8ecSJoseph Chen * MMC/NAND controller DMA can't access sram region, so: 12513c5d8ecSJoseph Chen * data -> ddr buffer -> memcpy to sram region. 12613c5d8ecSJoseph Chen */ 127b35a1137SJoseph Chen if (load_addr < CONFIG_SYS_SDRAM_BASE || 128b35a1137SJoseph Chen load_addr >= CONFIG_SYS_SDRAM_BASE + SDRAM_MAX_SIZE) { 12913c5d8ecSJoseph Chen image_buf = memalign(ARCH_DMA_MINALIGN, sect_cnt * 512); 13013c5d8ecSJoseph Chen if (!image_buf) { 13113c5d8ecSJoseph Chen printf("%s: malloc failed\n", __func__); 13213c5d8ecSJoseph Chen return -ENOMEM; 13313c5d8ecSJoseph Chen } 13413c5d8ecSJoseph Chen } else { 13513c5d8ecSJoseph Chen image_buf = (void *)load_addr; 13613c5d8ecSJoseph Chen } 13713c5d8ecSJoseph Chen 13813c5d8ecSJoseph Chen ret = info->read(info, image_sector + sect_off, 13913c5d8ecSJoseph Chen sect_cnt, image_buf); 14013c5d8ecSJoseph Chen if (ret != sect_cnt) { 14113c5d8ecSJoseph Chen printf("Read '%s' failed at sector: %ld, ret=%d\n", 14213c5d8ecSJoseph Chen image_name, (ulong)image_sector + sect_off, ret); 14313c5d8ecSJoseph Chen return -EIO; 14413c5d8ecSJoseph Chen } 14513c5d8ecSJoseph Chen 14613c5d8ecSJoseph Chen /* Verify component */ 14713c5d8ecSJoseph Chen ret = check_image(hdr); 14813c5d8ecSJoseph Chen if (ret) { 14913c5d8ecSJoseph Chen printf("%s[%d]: verify image fail!\n", image_name, i); 15013c5d8ecSJoseph Chen return ret; 15113c5d8ecSJoseph Chen } 15213c5d8ecSJoseph Chen 15313c5d8ecSJoseph Chen /* Handle sram region */ 15413c5d8ecSJoseph Chen if ((ulong)image_buf != load_addr) { 15513c5d8ecSJoseph Chen memcpy((void *)load_addr, image_buf, sect_cnt << 9); 15613c5d8ecSJoseph Chen free(image_buf); 15713c5d8ecSJoseph Chen } 15813c5d8ecSJoseph Chen 15913c5d8ecSJoseph Chen /* Fill entry_point by first component */ 16013c5d8ecSJoseph Chen if (i == 0) 16113c5d8ecSJoseph Chen *entry_point = (uintptr_t)load_addr; 16213c5d8ecSJoseph Chen } 16313c5d8ecSJoseph Chen 16413c5d8ecSJoseph Chen return ret; 16513c5d8ecSJoseph Chen } 16613c5d8ecSJoseph Chen 16713c5d8ecSJoseph Chen static int rkfw_load_trust(struct spl_load_info *info, u32 image_sector, 1681cb393f1SJason Zhu struct spl_image_info *spl_image, 16913c5d8ecSJoseph Chen int *found_rkfw, u32 try_count) 17013c5d8ecSJoseph Chen { 17113c5d8ecSJoseph Chen struct tag_tboot_header_2k hdr; 17213c5d8ecSJoseph Chen u32 sect_addr = image_sector; 17313c5d8ecSJoseph Chen int blkcnt = 4; /* header sectors, 2KB */ 17413c5d8ecSJoseph Chen int i, ret = 0; 17513c5d8ecSJoseph Chen 17613c5d8ecSJoseph Chen /* Find valid image header */ 17713c5d8ecSJoseph Chen for (i = 0; i < try_count; i++) { 17813c5d8ecSJoseph Chen sect_addr = image_sector + (i * RKFW_RETRY_SECTOR_SIZE); 17913c5d8ecSJoseph Chen if (blkcnt != info->read(info, sect_addr, blkcnt, &hdr)) 18013c5d8ecSJoseph Chen continue; 18113c5d8ecSJoseph Chen 18213c5d8ecSJoseph Chen if (hdr.tag == TBOOT_HEAD_TAG) { 18313c5d8ecSJoseph Chen /* Mark it */ 18413c5d8ecSJoseph Chen *found_rkfw = 1; 18513c5d8ecSJoseph Chen 18613c5d8ecSJoseph Chen /* bl31 is mandatory */ 18713c5d8ecSJoseph Chen ret = load_image(info, &hdr, sect_addr, 1881cb393f1SJason Zhu BL31_IMAGE_NAME, &spl_image->entry_point); 18913c5d8ecSJoseph Chen if (ret) 19013c5d8ecSJoseph Chen continue; 19113c5d8ecSJoseph Chen 19213c5d8ecSJoseph Chen /* bl32 is optional */ 19313c5d8ecSJoseph Chen ret = load_image(info, &hdr, sect_addr, 1941cb393f1SJason Zhu BL32_IMAGE_NAME, &spl_image->entry_point_bl32); 19513c5d8ecSJoseph Chen if (ret) { 19613c5d8ecSJoseph Chen if (ret == -ENONET) { 1971cb393f1SJason Zhu spl_image->entry_point_bl32 = -1; /* Not exist */ 19813c5d8ecSJoseph Chen ret = 0; 19913c5d8ecSJoseph Chen } else { 20013c5d8ecSJoseph Chen continue; 20113c5d8ecSJoseph Chen } 20213c5d8ecSJoseph Chen } 20313c5d8ecSJoseph Chen break; 20413c5d8ecSJoseph Chen } 20513c5d8ecSJoseph Chen } 20613c5d8ecSJoseph Chen 20713c5d8ecSJoseph Chen return ret; 20813c5d8ecSJoseph Chen } 2091cb393f1SJason Zhu #else 2101cb393f1SJason Zhu static int rkfw_load_trust(struct spl_load_info *info, u32 image_sector, 2111cb393f1SJason Zhu struct spl_image_info *spl_image, 2121cb393f1SJason Zhu int *found_rkfw, u32 try_count) 2131cb393f1SJason Zhu { 2141cb393f1SJason Zhu struct tag_second_loader_hdr hdr; 2151cb393f1SJason Zhu int i, ret, blkcnt = 4; /* header sectors, 2KB */ 2161cb393f1SJason Zhu char *load_addr; 2171cb393f1SJason Zhu u32 sect_addr; 2181cb393f1SJason Zhu 2191cb393f1SJason Zhu /* Detect valid image header */ 2201cb393f1SJason Zhu for (i = 0; i < try_count; i++) { 2211cb393f1SJason Zhu sect_addr = image_sector + (i * RKFW_RETRY_SECTOR_SIZE); 2221cb393f1SJason Zhu ret = info->read(info, sect_addr, blkcnt, &hdr); 2231cb393f1SJason Zhu if (ret != blkcnt) 2241cb393f1SJason Zhu continue; 2251cb393f1SJason Zhu 2261cb393f1SJason Zhu if (!memcmp(hdr.magic, TBOOT_HEAD_TAG, 6)) { 2271cb393f1SJason Zhu *found_rkfw = 1; 2281cb393f1SJason Zhu spl_image->entry_point = (uintptr_t)hdr.loader_load_addr; 2291cb393f1SJason Zhu /* Load full binary image(right behind header) */ 2301cb393f1SJason Zhu sect_addr += blkcnt; 2311cb393f1SJason Zhu load_addr = (char *)((size_t)hdr.loader_load_addr); 2321cb393f1SJason Zhu blkcnt = DIV_ROUND_UP(hdr.loader_load_size, 512); 2331cb393f1SJason Zhu 2341cb393f1SJason Zhu printf("tee.bin: addr=0x%lx, size=0x%lx\n", 2351cb393f1SJason Zhu (ulong)load_addr, (ulong)blkcnt * 512); 2361cb393f1SJason Zhu ret = info->read(info, sect_addr, blkcnt, load_addr); 2371cb393f1SJason Zhu if (ret != blkcnt) 2381cb393f1SJason Zhu continue; 2391cb393f1SJason Zhu 2401cb393f1SJason Zhu break; 2411cb393f1SJason Zhu } 2421cb393f1SJason Zhu } 2431cb393f1SJason Zhu 2441cb393f1SJason Zhu if (i == try_count) { 2451cb393f1SJason Zhu printf("Can not find usable uboot\n"); 2461cb393f1SJason Zhu return -ENONET; 2471cb393f1SJason Zhu } 2481cb393f1SJason Zhu 2491cb393f1SJason Zhu return 0; 2501cb393f1SJason Zhu } 2511cb393f1SJason Zhu #endif 25213c5d8ecSJoseph Chen 25313c5d8ecSJoseph Chen static int rkfw_load_uboot(struct spl_load_info *info, u32 image_sector, 2541cb393f1SJason Zhu struct spl_image_info *spl_image, u32 try_count) 25513c5d8ecSJoseph Chen { 25613c5d8ecSJoseph Chen struct tag_second_loader_hdr hdr; 25713c5d8ecSJoseph Chen int i, ret, blkcnt = 4; /* header sectors, 2KB */ 25813c5d8ecSJoseph Chen char *load_addr; 25913c5d8ecSJoseph Chen u32 sect_addr; 26013c5d8ecSJoseph Chen 26113c5d8ecSJoseph Chen /* Detect valid image header */ 26213c5d8ecSJoseph Chen for (i = 0; i < try_count; i++) { 26313c5d8ecSJoseph Chen sect_addr = image_sector + (i * RKFW_RETRY_SECTOR_SIZE); 26413c5d8ecSJoseph Chen ret = info->read(info, sect_addr, blkcnt, &hdr); 26513c5d8ecSJoseph Chen if (ret != blkcnt) 26613c5d8ecSJoseph Chen continue; 26713c5d8ecSJoseph Chen 26813c5d8ecSJoseph Chen if (!memcmp(hdr.magic, LOADER_HARD_STR, 6)) { 26913c5d8ecSJoseph Chen /* Load full binary image(right behind header) */ 27013c5d8ecSJoseph Chen sect_addr += blkcnt; 27113c5d8ecSJoseph Chen load_addr = (char *)((size_t)hdr.loader_load_addr); 27213c5d8ecSJoseph Chen blkcnt = DIV_ROUND_UP(hdr.loader_load_size, 512); 27313c5d8ecSJoseph Chen 27413c5d8ecSJoseph Chen printf("u-boot.bin: addr=0x%lx, size=0x%lx\n", 27513c5d8ecSJoseph Chen (ulong)load_addr, (ulong)blkcnt * 512); 27613c5d8ecSJoseph Chen ret = info->read(info, sect_addr, blkcnt, load_addr); 27713c5d8ecSJoseph Chen if (ret != blkcnt) 27813c5d8ecSJoseph Chen continue; 27913c5d8ecSJoseph Chen 28013c5d8ecSJoseph Chen break; 28113c5d8ecSJoseph Chen } 28213c5d8ecSJoseph Chen } 28313c5d8ecSJoseph Chen 28413c5d8ecSJoseph Chen if (i == try_count) { 28513c5d8ecSJoseph Chen printf("Can not find usable uboot\n"); 28613c5d8ecSJoseph Chen return -ENONET; 28713c5d8ecSJoseph Chen } 28813c5d8ecSJoseph Chen 28913c5d8ecSJoseph Chen /* Fill entry point */ 2901cb393f1SJason Zhu #ifdef CONFIG_SPL_ATF 2911cb393f1SJason Zhu spl_image->entry_point_bl33 = (uintptr_t)hdr.loader_load_addr; 2921cb393f1SJason Zhu #endif 2931cb393f1SJason Zhu #ifdef CONFIG_SPL_OPTEE 2941cb393f1SJason Zhu spl_image->entry_point_os = (uintptr_t)hdr.loader_load_addr; 2951cb393f1SJason Zhu #endif 29613c5d8ecSJoseph Chen return 0; 29713c5d8ecSJoseph Chen } 29813c5d8ecSJoseph Chen 299e3460df7SJason Zhu static int rkfw_load_kernel(struct spl_load_info *info, u32 image_sector, 3001cb393f1SJason Zhu struct spl_image_info *spl_image, u32 try_count) 301e3460df7SJason Zhu { 302e3460df7SJason Zhu struct andr_img_hdr *hdr; 303e3460df7SJason Zhu int ret, cnt; 3042241fc0fSJason Zhu int dtb_sector, ramdisk_sector, resource_sector; 305e3460df7SJason Zhu 306e3460df7SJason Zhu cnt = ALIGN(sizeof(struct andr_img_hdr), 512) >> 9; 307e3460df7SJason Zhu hdr = malloc(cnt * 512); 308e3460df7SJason Zhu if (!hdr) 309e3460df7SJason Zhu return -ENOMEM; 310e3460df7SJason Zhu 311e3460df7SJason Zhu ret = info->read(info, image_sector, cnt, (void *)hdr); 312e3460df7SJason Zhu if (ret != cnt) { 313e3460df7SJason Zhu ret = -EIO; 314e3460df7SJason Zhu goto out; 315e3460df7SJason Zhu } 316e3460df7SJason Zhu 317e3460df7SJason Zhu if (memcmp(hdr->magic, ANDR_BOOT_MAGIC, strlen(ANDR_BOOT_MAGIC)) != 0) { 318e3460df7SJason Zhu printf("SPL: boot image head magic error\n"); 319e3460df7SJason Zhu ret = -EINVAL; 320e3460df7SJason Zhu goto out; 321e3460df7SJason Zhu } 322e3460df7SJason Zhu 323e3460df7SJason Zhu ramdisk_sector = ALIGN(hdr->kernel_size, hdr->page_size); 3242241fc0fSJason Zhu resource_sector = ALIGN(hdr->kernel_size, hdr->page_size) 3252241fc0fSJason Zhu + ALIGN(hdr->ramdisk_size, hdr->page_size); 326e3460df7SJason Zhu dtb_sector = ALIGN(hdr->kernel_size, hdr->page_size) 327e3460df7SJason Zhu + ALIGN(hdr->ramdisk_size, hdr->page_size) 328e3460df7SJason Zhu + ALIGN(hdr->second_size, hdr->page_size); 329e3460df7SJason Zhu image_sector = image_sector + cnt; 330e3460df7SJason Zhu cnt = ALIGN(hdr->kernel_size, hdr->page_size) >> 9; 331e3460df7SJason Zhu 332e3460df7SJason Zhu /* Load kernel image */ 333e3460df7SJason Zhu ret = info->read(info, image_sector, cnt, (void *)CONFIG_SPL_KERNEL_ADDR); 334e3460df7SJason Zhu if (ret != cnt) { 335e3460df7SJason Zhu ret = -EIO; 336e3460df7SJason Zhu goto out; 337e3460df7SJason Zhu } 338e3460df7SJason Zhu 339e3460df7SJason Zhu /* Load ramdisk image */ 340e3460df7SJason Zhu if (hdr->ramdisk_size) { 341e3460df7SJason Zhu ret = info->read(info, (ramdisk_sector >> 9) + image_sector, 342e3460df7SJason Zhu ALIGN(hdr->ramdisk_size, hdr->page_size) >> 9, 343e3460df7SJason Zhu (void *)CONFIG_SPL_RAMDISK_ADDR); 344e3460df7SJason Zhu if (ret != (ALIGN(hdr->ramdisk_size, hdr->page_size) >> 9)) { 345e3460df7SJason Zhu ret = -EIO; 346e3460df7SJason Zhu goto out; 347e3460df7SJason Zhu } 348e3460df7SJason Zhu } 349e3460df7SJason Zhu 3502241fc0fSJason Zhu /* Load resource, and checkout the dtb */ 3512241fc0fSJason Zhu if (hdr->second_size) { 3522241fc0fSJason Zhu struct resource_img_hdr *head = 3532241fc0fSJason Zhu (struct resource_img_hdr *)(CONFIG_SPL_FDT_ADDR + 0x100000); 3542241fc0fSJason Zhu 3552241fc0fSJason Zhu ret = info->read(info, (resource_sector >> 9) + image_sector, 3562241fc0fSJason Zhu ALIGN(hdr->second_size, hdr->page_size) >> 9, 3572241fc0fSJason Zhu (void *)head); 3582241fc0fSJason Zhu if (ret != (ALIGN(hdr->second_size, hdr->page_size) >> 9)) { 3592241fc0fSJason Zhu ret = -EIO; 3602241fc0fSJason Zhu goto out; 3612241fc0fSJason Zhu } 3621cb393f1SJason Zhu #ifdef CONFIG_SPL_KERNEL_BOOT 3632241fc0fSJason Zhu if (spl_resource_image_check_header(head)) { 3642241fc0fSJason Zhu printf("Can't find kernel dtb in spl."); 3652241fc0fSJason Zhu } else { 3662241fc0fSJason Zhu struct resource_entry *entry; 3672241fc0fSJason Zhu char *dtb_temp; 3682241fc0fSJason Zhu 3692241fc0fSJason Zhu entry = spl_resource_image_get_dtb_entry(head); 3702241fc0fSJason Zhu if (!entry) { 3712241fc0fSJason Zhu ret = -EIO; 3722241fc0fSJason Zhu goto out; 3732241fc0fSJason Zhu } 3742241fc0fSJason Zhu 3752241fc0fSJason Zhu dtb_temp = (char *)((char *)head + entry->f_offset * 512); 3762241fc0fSJason Zhu memcpy((char *)CONFIG_SPL_FDT_ADDR, dtb_temp, 3772241fc0fSJason Zhu entry->f_size); 3782241fc0fSJason Zhu } 3791cb393f1SJason Zhu #endif 3802241fc0fSJason Zhu } else { 381e3460df7SJason Zhu /* Load dtb image */ 382e3460df7SJason Zhu ret = info->read(info, (dtb_sector >> 9) + image_sector, 383e3460df7SJason Zhu ALIGN(hdr->dtb_size, hdr->page_size) >> 9, 384e3460df7SJason Zhu (void *)CONFIG_SPL_FDT_ADDR); 385e3460df7SJason Zhu if (ret != (ALIGN(hdr->dtb_size, hdr->page_size) >> 9)) { 386e3460df7SJason Zhu ret = -EIO; 387e3460df7SJason Zhu goto out; 388e3460df7SJason Zhu } 3892241fc0fSJason Zhu } 390e3460df7SJason Zhu 3911cb393f1SJason Zhu spl_image->fdt_addr = (void *)CONFIG_SPL_FDT_ADDR; 3921cb393f1SJason Zhu #ifdef CONFIG_SPL_OPTEE 3931cb393f1SJason Zhu spl_image->entry_point_os = (uintptr_t)CONFIG_SPL_KERNEL_ADDR; 3941cb393f1SJason Zhu #endif 3951cb393f1SJason Zhu #ifdef CONFIG_SPL_ATF 3961cb393f1SJason Zhu spl_image->entry_point_bl33 = CONFIG_SPL_KERNEL_ADDR; 3971cb393f1SJason Zhu #endif 398e3460df7SJason Zhu ret = 0; 399e3460df7SJason Zhu out: 400e3460df7SJason Zhu free(hdr); 401e3460df7SJason Zhu 402e3460df7SJason Zhu return ret; 403e3460df7SJason Zhu } 404e3460df7SJason Zhu 40513c5d8ecSJoseph Chen int spl_load_rkfw_image(struct spl_image_info *spl_image, 40613c5d8ecSJoseph Chen struct spl_load_info *info, 407*aa415ed9SJoseph Chen u32 trust_sector, u32 uboot_sector, 408*aa415ed9SJoseph Chen u32 boot_sector) 40913c5d8ecSJoseph Chen { 41013c5d8ecSJoseph Chen int ret, try_count = RKFW_RETRY_SECTOR_TIMES; 41113c5d8ecSJoseph Chen int found_rkfw = 0; 41213c5d8ecSJoseph Chen 4131cb393f1SJason Zhu ret = rkfw_load_trust(info, trust_sector, spl_image, 41413c5d8ecSJoseph Chen &found_rkfw, try_count); 41513c5d8ecSJoseph Chen if (ret) { 41613c5d8ecSJoseph Chen printf("Load trust image failed! ret=%d\n", ret); 41713c5d8ecSJoseph Chen goto out; 41813c5d8ecSJoseph Chen } 419*aa415ed9SJoseph Chen #ifdef CONFIG_SPL_KERNEL_BOOT 420*aa415ed9SJoseph Chen if (spl_image->next_stage == SPL_NEXT_STAGE_UBOOT) { 421*aa415ed9SJoseph Chen #endif 422*aa415ed9SJoseph Chen ret = rkfw_load_uboot(info, uboot_sector, spl_image, try_count); 423e3460df7SJason Zhu if (ret) 42413c5d8ecSJoseph Chen printf("Load uboot image failed! ret=%d\n", ret); 425*aa415ed9SJoseph Chen #ifdef CONFIG_SPL_KERNEL_BOOT 426*aa415ed9SJoseph Chen } else if (spl_image->next_stage == SPL_NEXT_STAGE_KERNEL) { 427*aa415ed9SJoseph Chen #endif 428*aa415ed9SJoseph Chen ret = rkfw_load_kernel(info, boot_sector, spl_image, try_count); 429e3460df7SJason Zhu if (ret) { 430e3460df7SJason Zhu printf("Load kernel image failed! ret=%d\n", ret); 43113c5d8ecSJoseph Chen goto out; 43213c5d8ecSJoseph Chen } 433*aa415ed9SJoseph Chen #ifdef CONFIG_SPL_KERNEL_BOOT 434*aa415ed9SJoseph Chen } 435*aa415ed9SJoseph Chen #endif 43613c5d8ecSJoseph Chen 43713c5d8ecSJoseph Chen #if CONFIG_IS_ENABLED(LOAD_FIT) 43813c5d8ecSJoseph Chen spl_image->fdt_addr = 0; 43913c5d8ecSJoseph Chen #endif 4401cb393f1SJason Zhu #ifdef CONFIG_SPL_ATF 44113c5d8ecSJoseph Chen spl_image->os = IH_OS_ARM_TRUSTED_FIRMWARE; 4421cb393f1SJason Zhu #else 4431cb393f1SJason Zhu spl_image->os = IH_OS_OP_TEE; 4441cb393f1SJason Zhu #endif 44513c5d8ecSJoseph Chen 44613c5d8ecSJoseph Chen out: 44713c5d8ecSJoseph Chen /* If not found rockchip firmware, try others outside */ 44813c5d8ecSJoseph Chen return found_rkfw ? ret : -EAGAIN; 44913c5d8ecSJoseph Chen } 450