1
2
3
4
5
6
7#include <common.h>
8#include <errno.h>
9#include <fpga.h>
10#include <gzip.h>
11#include <image.h>
12#include <log.h>
13#include <malloc.h>
14#include <spl.h>
15#include <sysinfo.h>
16#include <asm/cache.h>
17#include <linux/libfdt.h>
18
19DECLARE_GLOBAL_DATA_PTR;
20
21#ifndef CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ
22#define CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ (64 * 1024)
23#endif
24
25#ifndef CONFIG_SYS_BOOTM_LEN
26#define CONFIG_SYS_BOOTM_LEN (64 << 20)
27#endif
28
29__weak void board_spl_fit_post_load(ulong load_addr, size_t length)
30{
31}
32
33__weak ulong board_spl_fit_size_align(ulong size)
34{
35 return size;
36}
37
38static int find_node_from_desc(const void *fit, int node, const char *str)
39{
40 int child;
41
42 if (node < 0)
43 return -EINVAL;
44
45
46 for (child = fdt_first_subnode(fit, node); child >= 0;
47 child = fdt_next_subnode(fit, child)) {
48 int len;
49 const char *desc = fdt_getprop(fit, child, "description", &len);
50
51 if (!desc)
52 continue;
53
54 if (!strcmp(desc, str))
55 return child;
56 }
57
58 return -ENOENT;
59}
60
61
62
63
64
65
66
67
68
69
70
71
72
73static int spl_fit_get_image_name(const void *fit, int images,
74 const char *type, int index,
75 const char **outname)
76{
77 struct udevice *sysinfo;
78 const char *name, *str;
79 __maybe_unused int node;
80 int conf_node;
81 int len, i;
82 bool found = true;
83
84 conf_node = fit_find_config_node(fit);
85 if (conf_node < 0) {
86#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
87 printf("No matching DT out of these options:\n");
88 for (node = fdt_first_subnode(fit, conf_node);
89 node >= 0;
90 node = fdt_next_subnode(fit, node)) {
91 name = fdt_getprop(fit, node, "description", &len);
92 printf(" %s\n", name);
93 }
94#endif
95 return conf_node;
96 }
97
98 name = fdt_getprop(fit, conf_node, type, &len);
99 if (!name) {
100 debug("cannot find property '%s': %d\n", type, len);
101 return -EINVAL;
102 }
103
104 str = name;
105 for (i = 0; i < index; i++) {
106 str = strchr(str, '\0') + 1;
107 if (!str || (str - name >= len)) {
108 found = false;
109 break;
110 }
111 }
112
113 if (!found && CONFIG_IS_ENABLED(SYSINFO) && !sysinfo_get(&sysinfo)) {
114 int rc;
115
116
117
118
119 rc = sysinfo_get_fit_loadable(sysinfo, index - i - 1, type,
120 &str);
121 if (rc && rc != -ENOENT)
122 return rc;
123
124 if (!rc) {
125
126
127
128
129
130
131 int node;
132 int images = fdt_path_offset(fit, FIT_IMAGES_PATH);
133
134 node = find_node_from_desc(fit, images, str);
135 if (node > 0)
136 str = fdt_get_name(fit, node, NULL);
137
138 found = true;
139 }
140 }
141
142 if (!found) {
143 debug("no string for index %d\n", index);
144 return -E2BIG;
145 }
146
147 *outname = str;
148 return 0;
149}
150
151
152
153
154
155
156
157
158
159
160
161
162
163static int spl_fit_get_image_node(const void *fit, int images,
164 const char *type, int index)
165{
166 const char *str;
167 int err;
168 int node;
169
170 err = spl_fit_get_image_name(fit, images, type, index, &str);
171 if (err)
172 return err;
173
174 debug("%s: '%s'\n", type, str);
175
176 node = fdt_subnode_offset(fit, images, str);
177 if (node < 0) {
178 pr_err("cannot find image node '%s': %d\n", str, node);
179 return -EINVAL;
180 }
181
182 return node;
183}
184
185static int get_aligned_image_offset(struct spl_load_info *info, int offset)
186{
187
188
189
190
191
192 if (info->filename)
193 return offset & ~(ARCH_DMA_MINALIGN - 1);
194
195 return offset / info->bl_len;
196}
197
198static int get_aligned_image_overhead(struct spl_load_info *info, int offset)
199{
200
201
202
203
204
205
206 if (info->filename)
207 return offset & (ARCH_DMA_MINALIGN - 1);
208
209 return offset % info->bl_len;
210}
211
212static int get_aligned_image_size(struct spl_load_info *info, int data_size,
213 int offset)
214{
215 data_size = data_size + get_aligned_image_overhead(info, offset);
216
217 if (info->filename)
218 return data_size;
219
220 return (data_size + info->bl_len - 1) / info->bl_len;
221}
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240static int spl_load_fit_image(struct spl_load_info *info, ulong sector,
241 void *fit, ulong base_offset, int node,
242 struct spl_image_info *image_info)
243{
244 int offset;
245 size_t length;
246 int len;
247 ulong size;
248 ulong load_addr, load_ptr;
249 void *src;
250 ulong overhead;
251 int nr_sectors;
252 int align_len = ARCH_DMA_MINALIGN - 1;
253 uint8_t image_comp = -1, type = -1;
254 const void *data;
255 bool external_data = false;
256
257 if (IS_ENABLED(CONFIG_SPL_FPGA) ||
258 (IS_ENABLED(CONFIG_SPL_OS_BOOT) && IS_ENABLED(CONFIG_SPL_GZIP))) {
259 if (fit_image_get_type(fit, node, &type))
260 puts("Cannot get image type.\n");
261 else
262 debug("%s ", genimg_get_type_name(type));
263 }
264
265 if (IS_ENABLED(CONFIG_SPL_GZIP)) {
266 fit_image_get_comp(fit, node, &image_comp);
267 debug("%s ", genimg_get_comp_name(image_comp));
268 }
269
270 if (fit_image_get_load(fit, node, &load_addr))
271 load_addr = image_info->load_addr;
272
273 if (!fit_image_get_data_position(fit, node, &offset)) {
274 external_data = true;
275 } else if (!fit_image_get_data_offset(fit, node, &offset)) {
276 offset += base_offset;
277 external_data = true;
278 }
279
280 if (external_data) {
281
282 if (fit_image_get_data_size(fit, node, &len))
283 return -ENOENT;
284
285 load_ptr = (load_addr + align_len) & ~align_len;
286 length = len;
287
288 overhead = get_aligned_image_overhead(info, offset);
289 nr_sectors = get_aligned_image_size(info, length, offset);
290
291 if (info->read(info,
292 sector + get_aligned_image_offset(info, offset),
293 nr_sectors, (void *)load_ptr) != nr_sectors)
294 return -EIO;
295
296 debug("External data: dst=%lx, offset=%x, size=%lx\n",
297 load_ptr, offset, (unsigned long)length);
298 src = (void *)load_ptr + overhead;
299 } else {
300
301 if (fit_image_get_data(fit, node, &data, &length)) {
302 puts("Cannot get image data/size\n");
303 return -ENOENT;
304 }
305 debug("Embedded data: dst=%lx, size=%lx\n", load_addr,
306 (unsigned long)length);
307 src = (void *)data;
308 }
309
310#ifdef CONFIG_SPL_FIT_SIGNATURE
311 printf("## Checking hash(es) for Image %s ... ",
312 fit_get_name(fit, node, NULL));
313 if (!fit_image_verify_with_data(fit, node,
314 src, length))
315 return -EPERM;
316 puts("OK\n");
317#endif
318
319#ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS
320 board_fit_image_post_process(&src, &length);
321#endif
322
323 if (IS_ENABLED(CONFIG_SPL_GZIP) && image_comp == IH_COMP_GZIP) {
324 size = length;
325 if (gunzip((void *)load_addr, CONFIG_SYS_BOOTM_LEN,
326 src, &size)) {
327 puts("Uncompressing error\n");
328 return -EIO;
329 }
330 length = size;
331 } else {
332 memcpy((void *)load_addr, src, length);
333 }
334
335 if (image_info) {
336 ulong entry_point;
337
338 image_info->load_addr = load_addr;
339 image_info->size = length;
340
341 if (!fit_image_get_entry(fit, node, &entry_point))
342 image_info->entry_point = entry_point;
343 else
344 image_info->entry_point = FDT_ERROR;
345 }
346
347 return 0;
348}
349
350static int spl_fit_append_fdt(struct spl_image_info *spl_image,
351 struct spl_load_info *info, ulong sector,
352 void *fit, int images, ulong base_offset)
353{
354 struct spl_image_info image_info;
355 int node, ret = 0, index = 0;
356
357
358
359
360
361 image_info.load_addr = spl_image->load_addr + spl_image->size;
362
363
364 node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, index++);
365 if (node < 0) {
366 debug("%s: cannot find FDT node\n", __func__);
367
368
369
370
371
372 if (gd->fdt_blob)
373 memcpy((void *)image_info.load_addr, gd->fdt_blob,
374 fdt_totalsize(gd->fdt_blob));
375 else
376 return node;
377 } else {
378 ret = spl_load_fit_image(info, sector, fit, base_offset, node,
379 &image_info);
380 if (ret < 0)
381 return ret;
382 }
383
384
385 spl_image->fdt_addr = (void *)image_info.load_addr;
386#if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
387 if (CONFIG_IS_ENABLED(LOAD_FIT_APPLY_OVERLAY)) {
388 void *tmpbuffer = NULL;
389
390 for (; ; index++) {
391 node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP,
392 index);
393 if (node == -E2BIG) {
394 debug("%s: No additional FDT node\n", __func__);
395 break;
396 } else if (node < 0) {
397 debug("%s: unable to find FDT node %d\n",
398 __func__, index);
399 continue;
400 }
401
402 if (!tmpbuffer) {
403
404
405
406
407
408
409 tmpbuffer = malloc(CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ);
410 if (!tmpbuffer)
411 debug("%s: unable to allocate space for overlays\n",
412 __func__);
413 }
414 image_info.load_addr = (ulong)tmpbuffer;
415 ret = spl_load_fit_image(info, sector, fit, base_offset,
416 node, &image_info);
417 if (ret < 0)
418 break;
419
420
421 ret = fdt_increase_size(spl_image->fdt_addr,
422 image_info.size);
423 if (ret < 0)
424 break;
425
426 ret = fdt_overlay_apply_verbose(spl_image->fdt_addr,
427 (void *)image_info.load_addr);
428 if (ret) {
429 pr_err("failed to apply DT overlay %s\n",
430 fit_get_name(fit, node, NULL));
431 break;
432 }
433
434 debug("%s: DT overlay %s applied\n", __func__,
435 fit_get_name(fit, node, NULL));
436 }
437 free(tmpbuffer);
438 if (ret)
439 return ret;
440 }
441
442 ret = fdt_shrink_to_minimum(spl_image->fdt_addr, 8192);
443 if (ret < 0)
444 return ret;
445#endif
446
447 return ret;
448}
449
450static int spl_fit_record_loadable(const void *fit, int images, int index,
451 void *blob, struct spl_image_info *image)
452{
453 int ret = 0;
454#if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
455 const char *name;
456 int node;
457
458 ret = spl_fit_get_image_name(fit, images, "loadables",
459 index, &name);
460 if (ret < 0)
461 return ret;
462
463 node = spl_fit_get_image_node(fit, images, "loadables", index);
464
465 ret = fdt_record_loadable(blob, index, name, image->load_addr,
466 image->size, image->entry_point,
467 fdt_getprop(fit, node, "type", NULL),
468 fdt_getprop(fit, node, "os", NULL));
469#endif
470 return ret;
471}
472
473static int spl_fit_image_get_os(const void *fit, int noffset, uint8_t *os)
474{
475#if CONFIG_IS_ENABLED(FIT_IMAGE_TINY) && !defined(CONFIG_SPL_OS_BOOT)
476 const char *name = fdt_getprop(fit, noffset, FIT_OS_PROP, NULL);
477
478 if (!name)
479 return -ENOENT;
480
481
482
483
484
485
486 if (!strcmp(name, "u-boot"))
487 *os = IH_OS_U_BOOT;
488 else
489 *os = IH_OS_INVALID;
490
491 return 0;
492#else
493 return fit_image_get_os(fit, noffset, os);
494#endif
495}
496
497
498
499
500
501
502__weak bool spl_load_simple_fit_skip_processing(void)
503{
504 return false;
505}
506
507int spl_load_simple_fit(struct spl_image_info *spl_image,
508 struct spl_load_info *info, ulong sector, void *fit)
509{
510 int sectors;
511 ulong size;
512 unsigned long count;
513 struct spl_image_info image_info;
514 int node = -1;
515 int images, ret;
516 int base_offset, hsize, align_len = ARCH_DMA_MINALIGN - 1;
517 int index = 0;
518 int firmware_node;
519
520
521
522
523
524
525 size = fdt_totalsize(fit);
526 size = (size + 3) & ~3;
527 size = board_spl_fit_size_align(size);
528 base_offset = (size + 3) & ~3;
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547 hsize = (size + info->bl_len + align_len) & ~align_len;
548 fit = spl_get_load_buffer(-hsize, hsize);
549 sectors = get_aligned_image_size(info, size, 0);
550 count = info->read(info, sector, sectors, fit);
551 debug("fit read sector %lx, sectors=%d, dst=%p, count=%lu, size=0x%lx\n",
552 sector, sectors, fit, count, size);
553
554 if (count == 0)
555 return -EIO;
556
557
558 if (spl_load_simple_fit_skip_processing())
559 return 0;
560
561
562 images = fdt_path_offset(fit, FIT_IMAGES_PATH);
563 if (images < 0) {
564 debug("%s: Cannot find /images node: %d\n", __func__, images);
565 return -1;
566 }
567
568#ifdef CONFIG_SPL_FPGA
569 node = spl_fit_get_image_node(fit, images, "fpga", 0);
570 if (node >= 0) {
571
572 ret = spl_load_fit_image(info, sector, fit, base_offset, node,
573 spl_image);
574 if (ret) {
575 printf("%s: Cannot load the FPGA: %i\n", __func__, ret);
576 return ret;
577 }
578
579 debug("FPGA bitstream at: %x, size: %x\n",
580 (u32)spl_image->load_addr, spl_image->size);
581
582 ret = fpga_load(0, (const void *)spl_image->load_addr,
583 spl_image->size, BIT_FULL);
584 if (ret) {
585 printf("%s: Cannot load the image to the FPGA\n",
586 __func__);
587 return ret;
588 }
589
590 puts("FPGA image loaded from FIT\n");
591 node = -1;
592 }
593#endif
594
595
596
597
598
599
600
601 if (node < 0)
602 node = spl_fit_get_image_node(fit, images, FIT_FIRMWARE_PROP,
603 0);
604#ifdef CONFIG_SPL_OS_BOOT
605 if (node < 0)
606 node = spl_fit_get_image_node(fit, images, FIT_KERNEL_PROP, 0);
607#endif
608 if (node < 0) {
609 debug("could not find firmware image, trying loadables...\n");
610 node = spl_fit_get_image_node(fit, images, "loadables", 0);
611
612
613
614
615 index = 1;
616 }
617 if (node < 0) {
618 debug("%s: Cannot find u-boot image node: %d\n",
619 __func__, node);
620 return -1;
621 }
622
623
624 ret = spl_load_fit_image(info, sector, fit, base_offset, node,
625 spl_image);
626 if (ret)
627 return ret;
628
629
630
631
632
633 if (!spl_fit_image_get_os(fit, node, &spl_image->os))
634 debug("Image OS is %s\n", genimg_get_os_name(spl_image->os));
635#if !defined(CONFIG_SPL_OS_BOOT)
636 else
637 spl_image->os = IH_OS_U_BOOT;
638#endif
639
640
641
642
643
644 if (spl_image->os == IH_OS_U_BOOT) {
645 ret = spl_fit_append_fdt(spl_image, info, sector, fit,
646 images, base_offset);
647 if (!IS_ENABLED(CONFIG_OF_EMBED) && ret < 0)
648 return ret;
649 }
650
651 firmware_node = node;
652
653 for (; ; index++) {
654 uint8_t os_type = IH_OS_INVALID;
655
656 node = spl_fit_get_image_node(fit, images, "loadables", index);
657 if (node < 0)
658 break;
659
660
661
662
663
664
665 if (firmware_node == node)
666 continue;
667
668 ret = spl_load_fit_image(info, sector, fit, base_offset, node,
669 &image_info);
670 if (ret < 0)
671 continue;
672
673 if (!spl_fit_image_get_os(fit, node, &os_type))
674 debug("Loadable is %s\n", genimg_get_os_name(os_type));
675
676 if (os_type == IH_OS_U_BOOT) {
677 spl_fit_append_fdt(&image_info, info, sector,
678 fit, images, base_offset);
679 spl_image->fdt_addr = image_info.fdt_addr;
680 }
681
682
683
684
685
686 if (spl_image->entry_point == FDT_ERROR &&
687 image_info.entry_point != FDT_ERROR)
688 spl_image->entry_point = image_info.entry_point;
689
690
691 if (spl_image->fdt_addr)
692 spl_fit_record_loadable(fit, images, index,
693 spl_image->fdt_addr,
694 &image_info);
695 }
696
697
698
699
700
701
702 if (spl_image->entry_point == FDT_ERROR || spl_image->entry_point == 0)
703 spl_image->entry_point = spl_image->load_addr;
704
705 spl_image->flags |= SPL_FIT_FOUND;
706
707#ifdef CONFIG_IMX_HAB
708 board_spl_fit_post_load((ulong)fit, size);
709#endif
710
711 return 0;
712}
713