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 int spl_load_simple_fit(struct spl_image_info *spl_image, 344 struct spl_load_info *info, ulong sector, void *fit) 345 { 346 int sectors; 347 ulong size; 348 unsigned long count; 349 struct spl_image_info image_info; 350 int node = -1; 351 int images, ret; 352 int base_offset, hsize, align_len = ARCH_DMA_MINALIGN - 1; 353 int index = 0; 354 355 /* 356 * For FIT with external data, figure out where the external images 357 * start. This is the base for the data-offset properties in each 358 * image. 359 */ 360 size = fdt_totalsize(fit); 361 size = (size + 3) & ~3; 362 size = board_spl_fit_size_align(size); 363 base_offset = (size + 3) & ~3; 364 365 /* 366 * So far we only have one block of data from the FIT. Read the entire 367 * thing, including that first block, placing it so it finishes before 368 * where we will load the image. 369 * 370 * Note that we will load the image such that its first byte will be 371 * at the load address. Since that byte may be part-way through a 372 * block, we may load the image up to one block before the load 373 * address. So take account of that here by subtracting an addition 374 * block length from the FIT start position. 375 * 376 * In fact the FIT has its own load address, but we assume it cannot 377 * be before CONFIG_SYS_TEXT_BASE. 378 * 379 * For FIT with data embedded, data is loaded as part of FIT image. 380 * For FIT with external data, data is not loaded in this step. 381 */ 382 hsize = (size + info->bl_len + align_len) & ~align_len; 383 fit = spl_get_load_buffer(-hsize, hsize); 384 sectors = get_aligned_image_size(info, size, 0); 385 count = info->read(info, sector, sectors, fit); 386 debug("fit read sector %lx, sectors=%d, dst=%p, count=%lu, size=0x%lx\n", 387 sector, sectors, fit, count, size); 388 389 if (count == 0) 390 return -EIO; 391 392 /* find the node holding the images information */ 393 images = fdt_path_offset(fit, FIT_IMAGES_PATH); 394 if (images < 0) { 395 debug("%s: Cannot find /images node: %d\n", __func__, images); 396 return -1; 397 } 398 399 #ifdef CONFIG_SPL_FPGA_SUPPORT 400 node = spl_fit_get_image_node(fit, images, "fpga", 0); 401 if (node >= 0) { 402 /* Load the image and set up the spl_image structure */ 403 ret = spl_load_fit_image(info, sector, fit, base_offset, node, 404 spl_image); 405 if (ret) { 406 printf("%s: Cannot load the FPGA: %i\n", __func__, ret); 407 return ret; 408 } 409 410 debug("FPGA bitstream at: %x, size: %x\n", 411 (u32)spl_image->load_addr, spl_image->size); 412 413 ret = fpga_load(0, (const void *)spl_image->load_addr, 414 spl_image->size, BIT_FULL); 415 if (ret) { 416 printf("%s: Cannot load the image to the FPGA\n", 417 __func__); 418 return ret; 419 } 420 421 puts("FPGA image loaded from FIT\n"); 422 node = -1; 423 } 424 #endif 425 426 /* 427 * Find the U-Boot image using the following search order: 428 * - start at 'firmware' (e.g. an ARM Trusted Firmware) 429 * - fall back 'kernel' (e.g. a Falcon-mode OS boot 430 * - fall back to using the first 'loadables' entry 431 */ 432 if (node < 0) 433 node = spl_fit_get_image_node(fit, images, FIT_FIRMWARE_PROP, 434 0); 435 #ifdef CONFIG_SPL_OS_BOOT 436 if (node < 0) 437 node = spl_fit_get_image_node(fit, images, FIT_KERNEL_PROP, 0); 438 #endif 439 if (node < 0) { 440 debug("could not find firmware image, trying loadables...\n"); 441 node = spl_fit_get_image_node(fit, images, "loadables", 0); 442 /* 443 * If we pick the U-Boot image from "loadables", start at 444 * the second image when later loading additional images. 445 */ 446 index = 1; 447 } 448 if (node < 0) { 449 debug("%s: Cannot find u-boot image node: %d\n", 450 __func__, node); 451 return -1; 452 } 453 454 /* Load the image and set up the spl_image structure */ 455 ret = spl_load_fit_image(info, sector, fit, base_offset, node, 456 spl_image); 457 if (ret) 458 return ret; 459 460 /* 461 * For backward compatibility, we treat the first node that is 462 * as a U-Boot image, if no OS-type has been declared. 463 */ 464 if (!spl_fit_image_get_os(fit, node, &spl_image->os)) 465 debug("Image OS is %s\n", genimg_get_os_name(spl_image->os)); 466 #if !defined(CONFIG_SPL_OS_BOOT) 467 else 468 spl_image->os = IH_OS_U_BOOT; 469 #endif 470 471 /* 472 * Booting a next-stage U-Boot may require us to append the FDT. 473 * We allow this to fail, as the U-Boot image might embed its FDT. 474 */ 475 if (spl_image->os == IH_OS_U_BOOT) 476 spl_fit_append_fdt(spl_image, info, sector, fit, 477 images, base_offset); 478 479 /* Now check if there are more images for us to load */ 480 for (; ; index++) { 481 uint8_t os_type = IH_OS_INVALID; 482 483 node = spl_fit_get_image_node(fit, images, "loadables", index); 484 if (node < 0) 485 break; 486 487 ret = spl_load_fit_image(info, sector, fit, base_offset, node, 488 &image_info); 489 if (ret < 0) 490 continue; 491 492 if (!spl_fit_image_get_os(fit, node, &os_type)) 493 debug("Loadable is %s\n", genimg_get_os_name(os_type)); 494 #if CONFIG_IS_ENABLED(FIT_IMAGE_TINY) 495 else 496 os_type = IH_OS_U_BOOT; 497 #endif 498 499 if (os_type == IH_OS_U_BOOT) { 500 spl_fit_append_fdt(&image_info, info, sector, 501 fit, images, base_offset); 502 spl_image->fdt_addr = image_info.fdt_addr; 503 } 504 505 /* 506 * If the "firmware" image did not provide an entry point, 507 * use the first valid entry point from the loadables. 508 */ 509 if (spl_image->entry_point == FDT_ERROR && 510 image_info.entry_point != FDT_ERROR) 511 spl_image->entry_point = image_info.entry_point; 512 513 /* Record our loadables into the FDT */ 514 if (spl_image->fdt_addr) 515 spl_fit_record_loadable(fit, images, index, 516 spl_image->fdt_addr, 517 &image_info); 518 } 519 520 /* 521 * If a platform does not provide CONFIG_SYS_UBOOT_START, U-Boot's 522 * Makefile will set it to 0 and it will end up as the entry point 523 * here. What it actually means is: use the load address. 524 */ 525 if (spl_image->entry_point == FDT_ERROR || spl_image->entry_point == 0) 526 spl_image->entry_point = spl_image->load_addr; 527 528 spl_image->flags |= SPL_FIT_FOUND; 529 530 #ifdef CONFIG_SECURE_BOOT 531 board_spl_fit_post_load((ulong)fit, size); 532 #endif 533 534 return 0; 535 } 536