1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd 4 */ 5 6 #include <common.h> 7 #include <malloc.h> 8 #include <spl_rkfw.h> 9 10 static const __aligned(16) struct s_fip_name_id fip_name_id[] = { 11 { BL30_IMAGE_NAME, UUID_SCP_FIRMWARE_BL30 }, /* optional */ 12 { BL31_IMAGE_NAME, UUID_EL3_RUNTIME_FIRMWARE_BL31 }, /* mandatory */ 13 { BL32_IMAGE_NAME, UUID_SECURE_PAYLOAD_BL32 }, /* optional */ 14 }; 15 16 static int file2comp_id(const char *file_name, u32 *comp_id) 17 { 18 int i; 19 20 for (i = 0; i < ARRAY_SIZE(fip_name_id); i++) { 21 if (!strcmp(file_name, fip_name_id[i].name)) { 22 *comp_id = fip_name_id[i].id; 23 return 0; 24 } 25 } 26 27 return -ENOENT; 28 } 29 30 static int open_image(const char *image_name, tboot_entry *entry, 31 struct tag_tboot_header_2k *hdr) 32 { 33 u32 i, component_num, sign_offset; 34 component_data *pcompdata; 35 boot_component *pcomp; 36 int n_found = 0; 37 u32 comp_id; 38 int ret; 39 40 ret = file2comp_id(image_name, &comp_id); 41 if (ret) { 42 printf("Can't find unknown image: %s\n", image_name); 43 return ret; 44 } 45 46 component_num = (hdr->size >> 16) & 0xffff; 47 sign_offset = (hdr->size & 0xffff) << 2; 48 pcompdata = (component_data *)((char *)hdr + sizeof(tboot_header)); 49 pcomp = (boot_component *)((char *)hdr + sign_offset + SIGNATURE_SIZE); 50 51 for (i = 0; i < component_num; i++) { 52 if (comp_id == pcomp->component_id) { 53 if (n_found < MAX_BL_CODE_NUM) { 54 memcpy(&entry[n_found].component, pcomp, 55 sizeof(boot_component)); 56 memcpy(&entry[n_found].compdata, pcompdata, 57 sizeof(component_data)); 58 n_found++; 59 } else { 60 printf("Image num excess max: %d!\n", 61 MAX_BL_CODE_NUM); 62 return -EINVAL; 63 } 64 } else { 65 if (n_found > 0) 66 break; 67 } 68 69 pcomp++; 70 pcompdata++; 71 } 72 73 if (!n_found) { 74 printf("No find %s\n", image_name); 75 return -ENONET; 76 } 77 78 return n_found; 79 } 80 81 static int check_image(struct tag_tboot_header_2k *hdr) 82 { 83 u32 hash_format[] = { 0, 160, 256, 256 }; 84 85 /* HASH format identifier */ 86 return (hash_format[hdr->flags & 0x3] == 0) ? -EINVAL : 0; 87 } 88 89 static int load_image(struct spl_load_info *info, 90 struct tag_tboot_header_2k *hdr, 91 u32 image_sector, 92 const char *image_name, 93 uintptr_t *entry_point) 94 { 95 tboot_entry entry[MAX_BL_CODE_NUM]; 96 void *image_buf = NULL; 97 ulong load_addr; 98 u32 sect_off; 99 u32 sect_cnt; 100 int image_num; 101 int i, ret; 102 103 /* Parse components from image header */ 104 image_num = open_image(image_name, entry, hdr); 105 if (image_num < 0) 106 return image_num; 107 108 /* Get all component */ 109 for (i = 0; i < image_num; i++) { 110 load_addr = entry[i].compdata.load_addr; 111 sect_cnt = entry[i].component.image_size; 112 sect_off = entry[i].component.storage_addr; 113 114 printf("%s[%d]: addr=0x%lx, size=0x%lx\n", 115 image_name, i, load_addr, (ulong)sect_cnt * 512); 116 117 /* 118 * MMC/NAND controller DMA can't access sram region, so: 119 * data -> ddr buffer -> memcpy to sram region. 120 */ 121 if (load_addr < CONFIG_SYS_SDRAM_BASE || 122 load_addr >= CONFIG_SYS_SDRAM_BASE + SDRAM_MAX_SIZE) { 123 image_buf = memalign(ARCH_DMA_MINALIGN, sect_cnt * 512); 124 if (!image_buf) { 125 printf("%s: malloc failed\n", __func__); 126 return -ENOMEM; 127 } 128 } else { 129 image_buf = (void *)load_addr; 130 } 131 132 ret = info->read(info, image_sector + sect_off, 133 sect_cnt, image_buf); 134 if (ret != sect_cnt) { 135 printf("Read '%s' failed at sector: %ld, ret=%d\n", 136 image_name, (ulong)image_sector + sect_off, ret); 137 return -EIO; 138 } 139 140 /* Verify component */ 141 ret = check_image(hdr); 142 if (ret) { 143 printf("%s[%d]: verify image fail!\n", image_name, i); 144 return ret; 145 } 146 147 /* Handle sram region */ 148 if ((ulong)image_buf != load_addr) { 149 memcpy((void *)load_addr, image_buf, sect_cnt << 9); 150 free(image_buf); 151 } 152 153 /* Fill entry_point by first component */ 154 if (i == 0) 155 *entry_point = (uintptr_t)load_addr; 156 } 157 158 return ret; 159 } 160 161 static int rkfw_load_trust(struct spl_load_info *info, u32 image_sector, 162 uintptr_t *bl31_entry, uintptr_t *bl32_entry, 163 int *found_rkfw, u32 try_count) 164 { 165 struct tag_tboot_header_2k hdr; 166 u32 sect_addr = image_sector; 167 int blkcnt = 4; /* header sectors, 2KB */ 168 int i, ret = 0; 169 170 /* Find valid image header */ 171 for (i = 0; i < try_count; i++) { 172 sect_addr = image_sector + (i * RKFW_RETRY_SECTOR_SIZE); 173 if (blkcnt != info->read(info, sect_addr, blkcnt, &hdr)) 174 continue; 175 176 if (hdr.tag == TBOOT_HEAD_TAG) { 177 /* Mark it */ 178 *found_rkfw = 1; 179 180 /* bl31 is mandatory */ 181 ret = load_image(info, &hdr, sect_addr, 182 BL31_IMAGE_NAME, bl31_entry); 183 if (ret) 184 continue; 185 186 /* bl32 is optional */ 187 ret = load_image(info, &hdr, sect_addr, 188 BL32_IMAGE_NAME, bl32_entry); 189 if (ret) { 190 if (ret == -ENONET) { 191 *bl32_entry = -1; /* Not exist */ 192 ret = 0; 193 } else { 194 continue; 195 } 196 } 197 break; 198 } 199 } 200 201 return ret; 202 } 203 204 static int rkfw_load_uboot(struct spl_load_info *info, u32 image_sector, 205 uintptr_t *bl33_entry, u32 try_count) 206 { 207 struct tag_second_loader_hdr hdr; 208 int i, ret, blkcnt = 4; /* header sectors, 2KB */ 209 char *load_addr; 210 u32 sect_addr; 211 212 /* Detect valid image header */ 213 for (i = 0; i < try_count; i++) { 214 sect_addr = image_sector + (i * RKFW_RETRY_SECTOR_SIZE); 215 ret = info->read(info, sect_addr, blkcnt, &hdr); 216 if (ret != blkcnt) 217 continue; 218 219 if (!memcmp(hdr.magic, LOADER_HARD_STR, 6)) { 220 /* Load full binary image(right behind header) */ 221 sect_addr += blkcnt; 222 load_addr = (char *)((size_t)hdr.loader_load_addr); 223 blkcnt = DIV_ROUND_UP(hdr.loader_load_size, 512); 224 225 printf("u-boot.bin: addr=0x%lx, size=0x%lx\n", 226 (ulong)load_addr, (ulong)blkcnt * 512); 227 ret = info->read(info, sect_addr, blkcnt, load_addr); 228 if (ret != blkcnt) 229 continue; 230 231 break; 232 } 233 } 234 235 if (i == try_count) { 236 printf("Can not find usable uboot\n"); 237 return -ENONET; 238 } 239 240 /* Fill entry point */ 241 *bl33_entry = (uintptr_t)hdr.loader_load_addr; 242 243 return 0; 244 } 245 246 int spl_load_rkfw_image(struct spl_image_info *spl_image, 247 struct spl_load_info *info, 248 u32 trust_sector, u32 uboot_sector) 249 { 250 int ret, try_count = RKFW_RETRY_SECTOR_TIMES; 251 int found_rkfw = 0; 252 253 ret = rkfw_load_trust(info, trust_sector, 254 &spl_image->entry_point, 255 &spl_image->entry_point_bl32, 256 &found_rkfw, try_count); 257 if (ret) { 258 printf("Load trust image failed! ret=%d\n", ret); 259 goto out; 260 } 261 262 ret = rkfw_load_uboot(info, uboot_sector, 263 &spl_image->entry_point_bl33, try_count); 264 if (ret) { 265 printf("Load uboot image failed! ret=%d\n", ret); 266 goto out; 267 } 268 269 #if CONFIG_IS_ENABLED(LOAD_FIT) 270 spl_image->fdt_addr = 0; 271 #endif 272 spl_image->os = IH_OS_ARM_TRUSTED_FIRMWARE; 273 274 out: 275 /* If not found rockchip firmware, try others outside */ 276 return found_rkfw ? ret : -EAGAIN; 277 } 278