1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2016 Google, Inc 4 * Written by Simon Glass <sjg@chromium.org> 5 */ 6 7 #include <common.h> 8 #include <errno.h> 9 #include <fpga.h> 10 #include <image.h> 11 #include <linux/libfdt.h> 12 #include <spl.h> 13 14 #ifndef CONFIG_SYS_BOOTM_LEN 15 #define CONFIG_SYS_BOOTM_LEN (64 << 20) 16 #endif 17 18 __weak void board_spl_fit_post_load(ulong load_addr, size_t length) 19 { 20 } 21 22 __weak ulong board_spl_fit_size_align(ulong size) 23 { 24 return size; 25 } 26 27 /** 28 * spl_fit_get_image_name(): By using the matching configuration subnode, 29 * retrieve the name of an image, specified by a property name and an index 30 * into that. 31 * @fit: Pointer to the FDT blob. 32 * @images: Offset of the /images subnode. 33 * @type: Name of the property within the configuration subnode. 34 * @index: Index into the list of strings in this property. 35 * @outname: Name of the image 36 * 37 * Return: 0 on success, or a negative error number 38 */ 39 static int spl_fit_get_image_name(const void *fit, int images, 40 const char *type, int index, 41 char **outname) 42 { 43 const char *name, *str; 44 __maybe_unused int node; 45 int conf_node; 46 int len, i; 47 48 conf_node = fit_find_config_node(fit); 49 if (conf_node < 0) { 50 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 51 printf("No matching DT out of these options:\n"); 52 for (node = fdt_first_subnode(fit, conf_node); 53 node >= 0; 54 node = fdt_next_subnode(fit, node)) { 55 name = fdt_getprop(fit, node, "description", &len); 56 printf(" %s\n", name); 57 } 58 #endif 59 return conf_node; 60 } 61 62 name = fdt_getprop(fit, conf_node, type, &len); 63 if (!name) { 64 debug("cannot find property '%s': %d\n", type, len); 65 return -EINVAL; 66 } 67 68 str = name; 69 for (i = 0; i < index; i++) { 70 str = strchr(str, '\0') + 1; 71 if (!str || (str - name >= len)) { 72 debug("no string for index %d\n", index); 73 return -E2BIG; 74 } 75 } 76 77 *outname = (char *)str; 78 return 0; 79 } 80 81 /** 82 * spl_fit_get_image_node(): By using the matching configuration subnode, 83 * retrieve the name of an image, specified by a property name and an index 84 * into that. 85 * @fit: Pointer to the FDT blob. 86 * @images: Offset of the /images subnode. 87 * @type: Name of the property within the configuration subnode. 88 * @index: Index into the list of strings in this property. 89 * 90 * Return: the node offset of the respective image node or a negative 91 * error number. 92 */ 93 static int spl_fit_get_image_node(const void *fit, int images, 94 const char *type, int index) 95 { 96 char *str; 97 int err; 98 int node; 99 100 err = spl_fit_get_image_name(fit, images, type, index, &str); 101 if (err) 102 return err; 103 104 debug("%s: '%s'\n", type, str); 105 106 node = fdt_subnode_offset(fit, images, str); 107 if (node < 0) { 108 debug("cannot find image node '%s': %d\n", str, node); 109 return -EINVAL; 110 } 111 112 return node; 113 } 114 115 static int get_aligned_image_offset(struct spl_load_info *info, int offset) 116 { 117 /* 118 * If it is a FS read, get the first address before offset which is 119 * aligned to ARCH_DMA_MINALIGN. If it is raw read return the 120 * block number to which offset belongs. 121 */ 122 if (info->filename) 123 return offset & ~(ARCH_DMA_MINALIGN - 1); 124 125 return offset / info->bl_len; 126 } 127 128 static int get_aligned_image_overhead(struct spl_load_info *info, int offset) 129 { 130 /* 131 * If it is a FS read, get the difference between the offset and 132 * the first address before offset which is aligned to 133 * ARCH_DMA_MINALIGN. If it is raw read return the offset within the 134 * block. 135 */ 136 if (info->filename) 137 return offset & (ARCH_DMA_MINALIGN - 1); 138 139 return offset % info->bl_len; 140 } 141 142 static int get_aligned_image_size(struct spl_load_info *info, int data_size, 143 int offset) 144 { 145 data_size = data_size + get_aligned_image_overhead(info, offset); 146 147 if (info->filename) 148 return data_size; 149 150 return (data_size + info->bl_len - 1) / info->bl_len; 151 } 152 153 /** 154 * spl_load_fit_image(): load the image described in a certain FIT node 155 * @info: points to information about the device to load data from 156 * @sector: the start sector of the FIT image on the device 157 * @fit: points to the flattened device tree blob describing the FIT 158 * image 159 * @base_offset: the beginning of the data area containing the actual 160 * image data, relative to the beginning of the FIT 161 * @node: offset of the DT node describing the image to load (relative 162 * to @fit) 163 * @image_info: will be filled with information about the loaded image 164 * If the FIT node does not contain a "load" (address) property, 165 * the image gets loaded to the address pointed to by the 166 * load_addr member in this struct. 167 * 168 * Return: 0 on success or a negative error number. 169 */ 170 static int spl_load_fit_image(struct spl_load_info *info, ulong sector, 171 void *fit, ulong base_offset, int node, 172 struct spl_image_info *image_info) 173 { 174 int offset; 175 size_t length; 176 int len; 177 ulong size; 178 ulong load_addr, load_ptr; 179 void *src; 180 ulong overhead; 181 int nr_sectors; 182 int align_len = ARCH_DMA_MINALIGN - 1; 183 uint8_t image_comp = -1, type = -1; 184 const void *data; 185 bool external_data = false; 186 187 if (IS_ENABLED(CONFIG_SPL_FPGA_SUPPORT) || 188 (IS_ENABLED(CONFIG_SPL_OS_BOOT) && IS_ENABLED(CONFIG_SPL_GZIP))) { 189 if (fit_image_get_type(fit, node, &type)) 190 puts("Cannot get image type.\n"); 191 else 192 debug("%s ", genimg_get_type_name(type)); 193 } 194 195 if (IS_ENABLED(CONFIG_SPL_OS_BOOT) && IS_ENABLED(CONFIG_SPL_GZIP)) { 196 if (fit_image_get_comp(fit, node, &image_comp)) 197 puts("Cannot get image compression format.\n"); 198 else 199 debug("%s ", genimg_get_comp_name(image_comp)); 200 } 201 202 if (fit_image_get_load(fit, node, &load_addr)) 203 load_addr = image_info->load_addr; 204 205 if (!fit_image_get_data_position(fit, node, &offset)) { 206 external_data = true; 207 } else if (!fit_image_get_data_offset(fit, node, &offset)) { 208 offset += base_offset; 209 external_data = true; 210 } 211 212 if (external_data) { 213 /* External data */ 214 if (fit_image_get_data_size(fit, node, &len)) 215 return -ENOENT; 216 217 load_ptr = (load_addr + align_len) & ~align_len; 218 length = len; 219 220 overhead = get_aligned_image_overhead(info, offset); 221 nr_sectors = get_aligned_image_size(info, length, offset); 222 223 if (info->read(info, 224 sector + get_aligned_image_offset(info, offset), 225 nr_sectors, (void *)load_ptr) != nr_sectors) 226 return -EIO; 227 228 debug("External data: dst=%lx, offset=%x, size=%lx\n", 229 load_ptr, offset, (unsigned long)length); 230 src = (void *)load_ptr + overhead; 231 } else { 232 /* Embedded data */ 233 if (fit_image_get_data(fit, node, &data, &length)) { 234 puts("Cannot get image data/size\n"); 235 return -ENOENT; 236 } 237 debug("Embedded data: dst=%lx, size=%lx\n", load_addr, 238 (unsigned long)length); 239 src = (void *)data; 240 } 241 242 #ifdef CONFIG_SPL_FIT_SIGNATURE 243 printf("## Checking hash(es) for Image %s ... ", 244 fit_get_name(fit, node, NULL)); 245 if (!fit_image_verify_with_data(fit, node, 246 src, length)) 247 return -EPERM; 248 puts("OK\n"); 249 #endif 250 251 #ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS 252 board_fit_image_post_process(&src, &length); 253 #endif 254 255 if (IS_ENABLED(CONFIG_SPL_GZIP) && image_comp == IH_COMP_GZIP) { 256 size = length; 257 if (gunzip((void *)load_addr, CONFIG_SYS_BOOTM_LEN, 258 src, &size)) { 259 puts("Uncompressing error\n"); 260 return -EIO; 261 } 262 length = size; 263 } else { 264 memcpy((void *)load_addr, src, length); 265 } 266 267 if (image_info) { 268 image_info->load_addr = load_addr; 269 image_info->size = length; 270 image_info->entry_point = fdt_getprop_u32(fit, node, "entry"); 271 } 272 273 return 0; 274 } 275 276 static int spl_fit_append_fdt(struct spl_image_info *spl_image, 277 struct spl_load_info *info, ulong sector, 278 void *fit, int images, ulong base_offset) 279 { 280 struct spl_image_info image_info; 281 int node, ret; 282 283 /* Figure out which device tree the board wants to use */ 284 node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, 0); 285 if (node < 0) { 286 debug("%s: cannot find FDT node\n", __func__); 287 return node; 288 } 289 290 /* 291 * Read the device tree and place it after the image. 292 * Align the destination address to ARCH_DMA_MINALIGN. 293 */ 294 image_info.load_addr = spl_image->load_addr + spl_image->size; 295 ret = spl_load_fit_image(info, sector, fit, base_offset, node, 296 &image_info); 297 298 if (ret < 0) 299 return ret; 300 301 /* Make the load-address of the FDT available for the SPL framework */ 302 spl_image->fdt_addr = (void *)image_info.load_addr; 303 #if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY) 304 /* Try to make space, so we can inject details on the loadables */ 305 ret = fdt_shrink_to_minimum(spl_image->fdt_addr, 8192); 306 #endif 307 308 return ret; 309 } 310 311 static int spl_fit_record_loadable(const void *fit, int images, int index, 312 void *blob, struct spl_image_info *image) 313 { 314 int ret = 0; 315 #if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY) 316 char *name; 317 int node; 318 319 ret = spl_fit_get_image_name(fit, images, "loadables", 320 index, &name); 321 if (ret < 0) 322 return ret; 323 324 node = spl_fit_get_image_node(fit, images, "loadables", index); 325 326 ret = fdt_record_loadable(blob, index, name, image->load_addr, 327 image->size, image->entry_point, 328 fdt_getprop(fit, node, "type", NULL), 329 fdt_getprop(fit, node, "os", NULL)); 330 #endif 331 return ret; 332 } 333 334 static int spl_fit_image_get_os(const void *fit, int noffset, uint8_t *os) 335 { 336 #if CONFIG_IS_ENABLED(FIT_IMAGE_TINY) 337 return -ENOTSUPP; 338 #else 339 return fit_image_get_os(fit, noffset, os); 340 #endif 341 } 342 343 /* 344 * Weak default function to allow customizing SPL fit loading for load-only 345 * use cases by allowing to skip the parsing/processing of the FIT contents 346 * (so that this can be done separately in a more customized fashion) 347 */ 348 __weak bool spl_load_simple_fit_skip_processing(void) 349 { 350 return false; 351 } 352 353 int spl_load_simple_fit(struct spl_image_info *spl_image, 354 struct spl_load_info *info, ulong sector, void *fit) 355 { 356 int sectors; 357 ulong size; 358 unsigned long count; 359 struct spl_image_info image_info; 360 int node = -1; 361 int images, ret; 362 int base_offset, hsize, align_len = ARCH_DMA_MINALIGN - 1; 363 int index = 0; 364 365 /* 366 * For FIT with external data, figure out where the external images 367 * start. This is the base for the data-offset properties in each 368 * image. 369 */ 370 size = fdt_totalsize(fit); 371 size = (size + 3) & ~3; 372 size = board_spl_fit_size_align(size); 373 base_offset = (size + 3) & ~3; 374 375 /* 376 * So far we only have one block of data from the FIT. Read the entire 377 * thing, including that first block, placing it so it finishes before 378 * where we will load the image. 379 * 380 * Note that we will load the image such that its first byte will be 381 * at the load address. Since that byte may be part-way through a 382 * block, we may load the image up to one block before the load 383 * address. So take account of that here by subtracting an addition 384 * block length from the FIT start position. 385 * 386 * In fact the FIT has its own load address, but we assume it cannot 387 * be before CONFIG_SYS_TEXT_BASE. 388 * 389 * For FIT with data embedded, data is loaded as part of FIT image. 390 * For FIT with external data, data is not loaded in this step. 391 */ 392 hsize = (size + info->bl_len + align_len) & ~align_len; 393 fit = spl_get_load_buffer(-hsize, hsize); 394 sectors = get_aligned_image_size(info, size, 0); 395 count = info->read(info, sector, sectors, fit); 396 debug("fit read sector %lx, sectors=%d, dst=%p, count=%lu, size=0x%lx\n", 397 sector, sectors, fit, count, size); 398 399 if (count == 0) 400 return -EIO; 401 402 /* skip further processing if requested to enable load-only use cases */ 403 if (spl_load_simple_fit_skip_processing()) 404 return 0; 405 406 /* find the node holding the images information */ 407 images = fdt_path_offset(fit, FIT_IMAGES_PATH); 408 if (images < 0) { 409 debug("%s: Cannot find /images node: %d\n", __func__, images); 410 return -1; 411 } 412 413 #ifdef CONFIG_SPL_FPGA_SUPPORT 414 node = spl_fit_get_image_node(fit, images, "fpga", 0); 415 if (node >= 0) { 416 /* Load the image and set up the spl_image structure */ 417 ret = spl_load_fit_image(info, sector, fit, base_offset, node, 418 spl_image); 419 if (ret) { 420 printf("%s: Cannot load the FPGA: %i\n", __func__, ret); 421 return ret; 422 } 423 424 debug("FPGA bitstream at: %x, size: %x\n", 425 (u32)spl_image->load_addr, spl_image->size); 426 427 ret = fpga_load(0, (const void *)spl_image->load_addr, 428 spl_image->size, BIT_FULL); 429 if (ret) { 430 printf("%s: Cannot load the image to the FPGA\n", 431 __func__); 432 return ret; 433 } 434 435 puts("FPGA image loaded from FIT\n"); 436 node = -1; 437 } 438 #endif 439 440 /* 441 * Find the U-Boot image using the following search order: 442 * - start at 'firmware' (e.g. an ARM Trusted Firmware) 443 * - fall back 'kernel' (e.g. a Falcon-mode OS boot 444 * - fall back to using the first 'loadables' entry 445 */ 446 if (node < 0) 447 node = spl_fit_get_image_node(fit, images, FIT_FIRMWARE_PROP, 448 0); 449 #ifdef CONFIG_SPL_OS_BOOT 450 if (node < 0) 451 node = spl_fit_get_image_node(fit, images, FIT_KERNEL_PROP, 0); 452 #endif 453 if (node < 0) { 454 debug("could not find firmware image, trying loadables...\n"); 455 node = spl_fit_get_image_node(fit, images, "loadables", 0); 456 /* 457 * If we pick the U-Boot image from "loadables", start at 458 * the second image when later loading additional images. 459 */ 460 index = 1; 461 } 462 if (node < 0) { 463 debug("%s: Cannot find u-boot image node: %d\n", 464 __func__, node); 465 return -1; 466 } 467 468 /* Load the image and set up the spl_image structure */ 469 ret = spl_load_fit_image(info, sector, fit, base_offset, node, 470 spl_image); 471 if (ret) 472 return ret; 473 474 /* 475 * For backward compatibility, we treat the first node that is 476 * as a U-Boot image, if no OS-type has been declared. 477 */ 478 if (!spl_fit_image_get_os(fit, node, &spl_image->os)) 479 debug("Image OS is %s\n", genimg_get_os_name(spl_image->os)); 480 #if !defined(CONFIG_SPL_OS_BOOT) 481 else 482 spl_image->os = IH_OS_U_BOOT; 483 #endif 484 485 /* 486 * Booting a next-stage U-Boot may require us to append the FDT. 487 * We allow this to fail, as the U-Boot image might embed its FDT. 488 */ 489 if (spl_image->os == IH_OS_U_BOOT) 490 spl_fit_append_fdt(spl_image, info, sector, fit, 491 images, base_offset); 492 493 /* Now check if there are more images for us to load */ 494 for (; ; index++) { 495 uint8_t os_type = IH_OS_INVALID; 496 497 node = spl_fit_get_image_node(fit, images, "loadables", index); 498 if (node < 0) 499 break; 500 501 ret = spl_load_fit_image(info, sector, fit, base_offset, node, 502 &image_info); 503 if (ret < 0) 504 continue; 505 506 if (!spl_fit_image_get_os(fit, node, &os_type)) 507 debug("Loadable is %s\n", genimg_get_os_name(os_type)); 508 #if CONFIG_IS_ENABLED(FIT_IMAGE_TINY) 509 else 510 os_type = IH_OS_U_BOOT; 511 #endif 512 513 if (os_type == IH_OS_U_BOOT) { 514 spl_fit_append_fdt(&image_info, info, sector, 515 fit, images, base_offset); 516 spl_image->fdt_addr = image_info.fdt_addr; 517 } 518 519 /* 520 * If the "firmware" image did not provide an entry point, 521 * use the first valid entry point from the loadables. 522 */ 523 if (spl_image->entry_point == FDT_ERROR && 524 image_info.entry_point != FDT_ERROR) 525 spl_image->entry_point = image_info.entry_point; 526 527 /* Record our loadables into the FDT */ 528 if (spl_image->fdt_addr) 529 spl_fit_record_loadable(fit, images, index, 530 spl_image->fdt_addr, 531 &image_info); 532 } 533 534 /* 535 * If a platform does not provide CONFIG_SYS_UBOOT_START, U-Boot's 536 * Makefile will set it to 0 and it will end up as the entry point 537 * here. What it actually means is: use the load address. 538 */ 539 if (spl_image->entry_point == FDT_ERROR || spl_image->entry_point == 0) 540 spl_image->entry_point = spl_image->load_addr; 541 542 spl_image->flags |= SPL_FIT_FOUND; 543 544 #ifdef CONFIG_SECURE_BOOT 545 board_spl_fit_post_load((ulong)fit, size); 546 #endif 547 548 return 0; 549 } 550