Annotation of elwix/tools/uboot_mkimage/common/image.c, revision 1.1.1.1
1.1 misho 1: /*
2: * (C) Copyright 2008 Semihalf
3: *
4: * (C) Copyright 2000-2006
5: * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
6: *
7: * See file CREDITS for list of people who contributed to this
8: * project.
9: *
10: * This program is free software; you can redistribute it and/or
11: * modify it under the terms of the GNU General Public License as
12: * published by the Free Software Foundation; either version 2 of
13: * the License, or (at your option) any later version.
14: *
15: * This program is distributed in the hope that it will be useful,
16: * but WITHOUT ANY WARRANTY; without even the implied warranty of
17: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: * GNU General Public License for more details.
19: *
20: * You should have received a copy of the GNU General Public License
21: * along with this program; if not, write to the Free Software
22: * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23: * MA 02111-1307 USA
24: */
25:
26: #ifndef USE_HOSTCC
27: #include <common.h>
28: #include <watchdog.h>
29:
30: #ifdef CONFIG_SHOW_BOOT_PROGRESS
31: #include <status_led.h>
32: #endif
33:
34: #ifdef CONFIG_HAS_DATAFLASH
35: #include <dataflash.h>
36: #endif
37:
38: #ifdef CONFIG_LOGBUFFER
39: #include <logbuff.h>
40: #endif
41:
42: #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)
43: #include <rtc.h>
44: #endif
45:
46: #include <image.h>
47:
48: #if defined(CONFIG_FIT) || defined (CONFIG_OF_LIBFDT)
49: #include <fdt.h>
50: #include <libfdt.h>
51: #include <fdt_support.h>
52: #endif
53:
54: #if defined(CONFIG_FIT)
55: #include <u-boot/md5.h>
56: #include <sha1.h>
57:
58: static int fit_check_ramdisk (const void *fit, int os_noffset,
59: uint8_t arch, int verify);
60: #endif
61:
62: #ifdef CONFIG_CMD_BDI
63: extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
64: #endif
65:
66: DECLARE_GLOBAL_DATA_PTR;
67:
68: static const image_header_t* image_get_ramdisk (ulong rd_addr, uint8_t arch,
69: int verify);
70: #else
71: #include "mkimage.h"
72: #include <u-boot/md5.h>
73: #include <time.h>
74: #include <image.h>
75: #endif /* !USE_HOSTCC*/
76:
77: static table_entry_t uimage_arch[] = {
78: { IH_ARCH_INVALID, NULL, "Invalid ARCH", },
79: { IH_ARCH_ALPHA, "alpha", "Alpha", },
80: { IH_ARCH_ARM, "arm", "ARM", },
81: { IH_ARCH_I386, "x86", "Intel x86", },
82: { IH_ARCH_IA64, "ia64", "IA64", },
83: { IH_ARCH_M68K, "m68k", "M68K", },
84: { IH_ARCH_MICROBLAZE, "microblaze", "MicroBlaze", },
85: { IH_ARCH_MIPS, "mips", "MIPS", },
86: { IH_ARCH_MIPS64, "mips64", "MIPS 64 Bit", },
87: { IH_ARCH_NIOS2, "nios2", "NIOS II", },
88: { IH_ARCH_PPC, "powerpc", "PowerPC", },
89: { IH_ARCH_PPC, "ppc", "PowerPC", },
90: { IH_ARCH_S390, "s390", "IBM S390", },
91: { IH_ARCH_SH, "sh", "SuperH", },
92: { IH_ARCH_SPARC, "sparc", "SPARC", },
93: { IH_ARCH_SPARC64, "sparc64", "SPARC 64 Bit", },
94: { IH_ARCH_BLACKFIN, "blackfin", "Blackfin", },
95: { IH_ARCH_AVR32, "avr32", "AVR32", },
96: { -1, "", "", },
97: };
98:
99: static table_entry_t uimage_os[] = {
100: { IH_OS_INVALID, NULL, "Invalid OS", },
101: { IH_OS_LINUX, "linux", "Linux", },
102: #if defined(CONFIG_LYNXKDI) || defined(USE_HOSTCC)
103: { IH_OS_LYNXOS, "lynxos", "LynxOS", },
104: #endif
105: { IH_OS_NETBSD, "netbsd", "NetBSD", },
106: { IH_OS_OSE, "ose", "Enea OSE", },
107: { IH_OS_RTEMS, "rtems", "RTEMS", },
108: { IH_OS_U_BOOT, "u-boot", "U-Boot", },
109: #if defined(CONFIG_CMD_ELF) || defined(USE_HOSTCC)
110: { IH_OS_QNX, "qnx", "QNX", },
111: { IH_OS_VXWORKS, "vxworks", "VxWorks", },
112: #endif
113: #if defined(CONFIG_INTEGRITY) || defined(USE_HOSTCC)
114: { IH_OS_INTEGRITY,"integrity", "INTEGRITY", },
115: #endif
116: #ifdef USE_HOSTCC
117: { IH_OS_4_4BSD, "4_4bsd", "4_4BSD", },
118: { IH_OS_DELL, "dell", "Dell", },
119: { IH_OS_ESIX, "esix", "Esix", },
120: { IH_OS_FREEBSD, "freebsd", "FreeBSD", },
121: { IH_OS_IRIX, "irix", "Irix", },
122: { IH_OS_NCR, "ncr", "NCR", },
123: { IH_OS_OPENBSD, "openbsd", "OpenBSD", },
124: { IH_OS_PSOS, "psos", "pSOS", },
125: { IH_OS_SCO, "sco", "SCO", },
126: { IH_OS_SOLARIS, "solaris", "Solaris", },
127: { IH_OS_SVR4, "svr4", "SVR4", },
128: #endif
129: { -1, "", "", },
130: };
131:
132: static table_entry_t uimage_type[] = {
133: { IH_TYPE_INVALID, NULL, "Invalid Image", },
134: { IH_TYPE_FILESYSTEM, "filesystem", "Filesystem Image", },
135: { IH_TYPE_FIRMWARE, "firmware", "Firmware", },
136: { IH_TYPE_KERNEL, "kernel", "Kernel Image", },
137: { IH_TYPE_MULTI, "multi", "Multi-File Image", },
138: { IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", },
139: { IH_TYPE_SCRIPT, "script", "Script", },
140: { IH_TYPE_STANDALONE, "standalone", "Standalone Program", },
141: { IH_TYPE_FLATDT, "flat_dt", "Flat Device Tree", },
142: { IH_TYPE_KWBIMAGE, "kwbimage", "Kirkwood Boot Image",},
143: { IH_TYPE_IMXIMAGE, "imximage", "Freescale i.MX Boot Image",},
144: { -1, "", "", },
145: };
146:
147: static table_entry_t uimage_comp[] = {
148: { IH_COMP_NONE, "none", "uncompressed", },
149: { IH_COMP_BZIP2, "bzip2", "bzip2 compressed", },
150: { IH_COMP_GZIP, "gzip", "gzip compressed", },
151: { IH_COMP_LZMA, "lzma", "lzma compressed", },
152: { IH_COMP_LZO, "lzo", "lzo compressed", },
153: { -1, "", "", },
154: };
155:
156: uint32_t crc32 (uint32_t, const unsigned char *, uint);
157: uint32_t crc32_wd (uint32_t, const unsigned char *, uint, uint);
158: #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
159: static void genimg_print_time (time_t timestamp);
160: #endif
161:
162: /*****************************************************************************/
163: /* Legacy format routines */
164: /*****************************************************************************/
165: int image_check_hcrc (const image_header_t *hdr)
166: {
167: ulong hcrc;
168: ulong len = image_get_header_size ();
169: image_header_t header;
170:
171: /* Copy header so we can blank CRC field for re-calculation */
172: memmove (&header, (char *)hdr, image_get_header_size ());
173: image_set_hcrc (&header, 0);
174:
175: hcrc = crc32 (0, (unsigned char *)&header, len);
176:
177: return (hcrc == image_get_hcrc (hdr));
178: }
179:
180: int image_check_dcrc (const image_header_t *hdr)
181: {
182: ulong data = image_get_data (hdr);
183: ulong len = image_get_data_size (hdr);
184: ulong dcrc = crc32_wd (0, (unsigned char *)data, len, CHUNKSZ_CRC32);
185:
186: return (dcrc == image_get_dcrc (hdr));
187: }
188:
189: /**
190: * image_multi_count - get component (sub-image) count
191: * @hdr: pointer to the header of the multi component image
192: *
193: * image_multi_count() returns number of components in a multi
194: * component image.
195: *
196: * Note: no checking of the image type is done, caller must pass
197: * a valid multi component image.
198: *
199: * returns:
200: * number of components
201: */
202: ulong image_multi_count (const image_header_t *hdr)
203: {
204: ulong i, count = 0;
205: uint32_t *size;
206:
207: /* get start of the image payload, which in case of multi
208: * component images that points to a table of component sizes */
209: size = (uint32_t *)image_get_data (hdr);
210:
211: /* count non empty slots */
212: for (i = 0; size[i]; ++i)
213: count++;
214:
215: return count;
216: }
217:
218: /**
219: * image_multi_getimg - get component data address and size
220: * @hdr: pointer to the header of the multi component image
221: * @idx: index of the requested component
222: * @data: pointer to a ulong variable, will hold component data address
223: * @len: pointer to a ulong variable, will hold component size
224: *
225: * image_multi_getimg() returns size and data address for the requested
226: * component in a multi component image.
227: *
228: * Note: no checking of the image type is done, caller must pass
229: * a valid multi component image.
230: *
231: * returns:
232: * data address and size of the component, if idx is valid
233: * 0 in data and len, if idx is out of range
234: */
235: void image_multi_getimg (const image_header_t *hdr, ulong idx,
236: ulong *data, ulong *len)
237: {
238: int i;
239: uint32_t *size;
240: ulong offset, count, img_data;
241:
242: /* get number of component */
243: count = image_multi_count (hdr);
244:
245: /* get start of the image payload, which in case of multi
246: * component images that points to a table of component sizes */
247: size = (uint32_t *)image_get_data (hdr);
248:
249: /* get address of the proper component data start, which means
250: * skipping sizes table (add 1 for last, null entry) */
251: img_data = image_get_data (hdr) + (count + 1) * sizeof (uint32_t);
252:
253: if (idx < count) {
254: *len = uimage_to_cpu (size[idx]);
255: offset = 0;
256:
257: /* go over all indices preceding requested component idx */
258: for (i = 0; i < idx; i++) {
259: /* add up i-th component size, rounding up to 4 bytes */
260: offset += (uimage_to_cpu (size[i]) + 3) & ~3 ;
261: }
262:
263: /* calculate idx-th component data address */
264: *data = img_data + offset;
265: } else {
266: *len = 0;
267: *data = 0;
268: }
269: }
270:
271: static void image_print_type (const image_header_t *hdr)
272: {
273: const char *os, *arch, *type, *comp;
274:
275: os = genimg_get_os_name (image_get_os (hdr));
276: arch = genimg_get_arch_name (image_get_arch (hdr));
277: type = genimg_get_type_name (image_get_type (hdr));
278: comp = genimg_get_comp_name (image_get_comp (hdr));
279:
280: printf ("%s %s %s (%s)\n", arch, os, type, comp);
281: }
282:
283: /**
284: * image_print_contents - prints out the contents of the legacy format image
285: * @ptr: pointer to the legacy format image header
286: * @p: pointer to prefix string
287: *
288: * image_print_contents() formats a multi line legacy image contents description.
289: * The routine prints out all header fields followed by the size/offset data
290: * for MULTI/SCRIPT images.
291: *
292: * returns:
293: * no returned results
294: */
295: void image_print_contents (const void *ptr)
296: {
297: const image_header_t *hdr = (const image_header_t *)ptr;
298: const char *p;
299:
300: #ifdef USE_HOSTCC
301: p = "";
302: #else
303: p = " ";
304: #endif
305:
306: printf ("%sImage Name: %.*s\n", p, IH_NMLEN, image_get_name (hdr));
307: #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
308: printf ("%sCreated: ", p);
309: genimg_print_time ((time_t)image_get_time (hdr));
310: #endif
311: printf ("%sImage Type: ", p);
312: image_print_type (hdr);
313: printf ("%sData Size: ", p);
314: genimg_print_size (image_get_data_size (hdr));
315: printf ("%sLoad Address: %08x\n", p, image_get_load (hdr));
316: printf ("%sEntry Point: %08x\n", p, image_get_ep (hdr));
317:
318: if (image_check_type (hdr, IH_TYPE_MULTI) ||
319: image_check_type (hdr, IH_TYPE_SCRIPT)) {
320: int i;
321: ulong data, len;
322: ulong count = image_multi_count (hdr);
323:
324: printf ("%sContents:\n", p);
325: for (i = 0; i < count; i++) {
326: image_multi_getimg (hdr, i, &data, &len);
327:
328: printf ("%s Image %d: ", p, i);
329: genimg_print_size (len);
330:
331: if (image_check_type (hdr, IH_TYPE_SCRIPT) && i > 0) {
332: /*
333: * the user may need to know offsets
334: * if planning to do something with
335: * multiple files
336: */
337: printf ("%s Offset = 0x%08lx\n", p, data);
338: }
339: }
340: }
341: }
342:
343:
344: #ifndef USE_HOSTCC
345: /**
346: * image_get_ramdisk - get and verify ramdisk image
347: * @rd_addr: ramdisk image start address
348: * @arch: expected ramdisk architecture
349: * @verify: checksum verification flag
350: *
351: * image_get_ramdisk() returns a pointer to the verified ramdisk image
352: * header. Routine receives image start address and expected architecture
353: * flag. Verification done covers data and header integrity and os/type/arch
354: * fields checking.
355: *
356: * If dataflash support is enabled routine checks for dataflash addresses
357: * and handles required dataflash reads.
358: *
359: * returns:
360: * pointer to a ramdisk image header, if image was found and valid
361: * otherwise, return NULL
362: */
363: static const image_header_t *image_get_ramdisk (ulong rd_addr, uint8_t arch,
364: int verify)
365: {
366: const image_header_t *rd_hdr = (const image_header_t *)rd_addr;
367:
368: if (!image_check_magic (rd_hdr)) {
369: puts ("Bad Magic Number\n");
370: show_boot_progress (-10);
371: return NULL;
372: }
373:
374: if (!image_check_hcrc (rd_hdr)) {
375: puts ("Bad Header Checksum\n");
376: show_boot_progress (-11);
377: return NULL;
378: }
379:
380: show_boot_progress (10);
381: image_print_contents (rd_hdr);
382:
383: if (verify) {
384: puts(" Verifying Checksum ... ");
385: if (!image_check_dcrc (rd_hdr)) {
386: puts ("Bad Data CRC\n");
387: show_boot_progress (-12);
388: return NULL;
389: }
390: puts("OK\n");
391: }
392:
393: show_boot_progress (11);
394:
395: if (!image_check_os (rd_hdr, IH_OS_LINUX) ||
396: !image_check_arch (rd_hdr, arch) ||
397: !image_check_type (rd_hdr, IH_TYPE_RAMDISK)) {
398: printf ("No Linux %s Ramdisk Image\n",
399: genimg_get_arch_name(arch));
400: show_boot_progress (-13);
401: return NULL;
402: }
403:
404: return rd_hdr;
405: }
406: #endif /* !USE_HOSTCC */
407:
408: /*****************************************************************************/
409: /* Shared dual-format routines */
410: /*****************************************************************************/
411: #ifndef USE_HOSTCC
412: int getenv_yesno (char *var)
413: {
414: char *s = getenv (var);
415: return (s && (*s == 'n')) ? 0 : 1;
416: }
417:
418: ulong getenv_bootm_low(void)
419: {
420: char *s = getenv ("bootm_low");
421: if (s) {
422: ulong tmp = simple_strtoul (s, NULL, 16);
423: return tmp;
424: }
425:
426: #if defined(CONFIG_SYS_SDRAM_BASE)
427: return CONFIG_SYS_SDRAM_BASE;
428: #elif defined(CONFIG_ARM)
429: return gd->bd->bi_dram[0].start;
430: #else
431: return 0;
432: #endif
433: }
434:
435: phys_size_t getenv_bootm_size(void)
436: {
437: phys_size_t tmp;
438: char *s = getenv ("bootm_size");
439: if (s) {
440: tmp = (phys_size_t)simple_strtoull (s, NULL, 16);
441: return tmp;
442: }
443: s = getenv("bootm_low");
444: if (s)
445: tmp = (phys_size_t)simple_strtoull (s, NULL, 16);
446: else
447: tmp = 0;
448:
449:
450: #if defined(CONFIG_ARM)
451: return gd->bd->bi_dram[0].size - tmp;
452: #else
453: return gd->bd->bi_memsize - tmp;
454: #endif
455: }
456:
457: void memmove_wd (void *to, void *from, size_t len, ulong chunksz)
458: {
459: if (to == from)
460: return;
461:
462: #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
463: while (len > 0) {
464: size_t tail = (len > chunksz) ? chunksz : len;
465: WATCHDOG_RESET ();
466: memmove (to, from, tail);
467: to += tail;
468: from += tail;
469: len -= tail;
470: }
471: #else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
472: memmove (to, from, len);
473: #endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
474: }
475: #endif /* !USE_HOSTCC */
476:
477: void genimg_print_size (uint32_t size)
478: {
479: #ifndef USE_HOSTCC
480: printf ("%d Bytes = ", size);
481: print_size (size, "\n");
482: #else
483: printf ("%d Bytes = %.2f kB = %.2f MB\n",
484: size, (double)size / 1.024e3,
485: (double)size / 1.048576e6);
486: #endif
487: }
488:
489: #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
490: static void genimg_print_time (time_t timestamp)
491: {
492: #ifndef USE_HOSTCC
493: struct rtc_time tm;
494:
495: to_tm (timestamp, &tm);
496: printf ("%4d-%02d-%02d %2d:%02d:%02d UTC\n",
497: tm.tm_year, tm.tm_mon, tm.tm_mday,
498: tm.tm_hour, tm.tm_min, tm.tm_sec);
499: #else
500: printf ("%s", ctime(×tamp));
501: #endif
502: }
503: #endif /* CONFIG_TIMESTAMP || CONFIG_CMD_DATE || USE_HOSTCC */
504:
505: /**
506: * get_table_entry_name - translate entry id to long name
507: * @table: pointer to a translation table for entries of a specific type
508: * @msg: message to be returned when translation fails
509: * @id: entry id to be translated
510: *
511: * get_table_entry_name() will go over translation table trying to find
512: * entry that matches given id. If matching entry is found, its long
513: * name is returned to the caller.
514: *
515: * returns:
516: * long entry name if translation succeeds
517: * msg otherwise
518: */
519: char *get_table_entry_name (table_entry_t *table, char *msg, int id)
520: {
521: for (; table->id >= 0; ++table) {
522: if (table->id == id)
523: #if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC)
524: return table->lname;
525: #else
526: return table->lname + gd->reloc_off;
527: #endif
528: }
529: return (msg);
530: }
531:
532: const char *genimg_get_os_name (uint8_t os)
533: {
534: return (get_table_entry_name (uimage_os, "Unknown OS", os));
535: }
536:
537: const char *genimg_get_arch_name (uint8_t arch)
538: {
539: return (get_table_entry_name (uimage_arch, "Unknown Architecture", arch));
540: }
541:
542: const char *genimg_get_type_name (uint8_t type)
543: {
544: return (get_table_entry_name (uimage_type, "Unknown Image", type));
545: }
546:
547: const char *genimg_get_comp_name (uint8_t comp)
548: {
549: return (get_table_entry_name (uimage_comp, "Unknown Compression", comp));
550: }
551:
552: /**
553: * get_table_entry_id - translate short entry name to id
554: * @table: pointer to a translation table for entries of a specific type
555: * @table_name: to be used in case of error
556: * @name: entry short name to be translated
557: *
558: * get_table_entry_id() will go over translation table trying to find
559: * entry that matches given short name. If matching entry is found,
560: * its id returned to the caller.
561: *
562: * returns:
563: * entry id if translation succeeds
564: * -1 otherwise
565: */
566: int get_table_entry_id (table_entry_t *table,
567: const char *table_name, const char *name)
568: {
569: table_entry_t *t;
570: #ifdef USE_HOSTCC
571: int first = 1;
572:
573: for (t = table; t->id >= 0; ++t) {
574: if (t->sname && strcasecmp(t->sname, name) == 0)
575: return (t->id);
576: }
577:
578: fprintf (stderr, "\nInvalid %s Type - valid names are", table_name);
579: for (t = table; t->id >= 0; ++t) {
580: if (t->sname == NULL)
581: continue;
582: fprintf (stderr, "%c %s", (first) ? ':' : ',', t->sname);
583: first = 0;
584: }
585: fprintf (stderr, "\n");
586: #else
587: for (t = table; t->id >= 0; ++t) {
588: #ifdef CONFIG_NEEDS_MANUAL_RELOC
589: if (t->sname && strcmp(t->sname + gd->reloc_off, name) == 0)
590: #else
591: if (t->sname && strcmp(t->sname, name) == 0)
592: #endif
593: return (t->id);
594: }
595: debug ("Invalid %s Type: %s\n", table_name, name);
596: #endif /* USE_HOSTCC */
597: return (-1);
598: }
599:
600: int genimg_get_os_id (const char *name)
601: {
602: return (get_table_entry_id (uimage_os, "OS", name));
603: }
604:
605: int genimg_get_arch_id (const char *name)
606: {
607: return (get_table_entry_id (uimage_arch, "CPU", name));
608: }
609:
610: int genimg_get_type_id (const char *name)
611: {
612: return (get_table_entry_id (uimage_type, "Image", name));
613: }
614:
615: int genimg_get_comp_id (const char *name)
616: {
617: return (get_table_entry_id (uimage_comp, "Compression", name));
618: }
619:
620: #ifndef USE_HOSTCC
621: /**
622: * genimg_get_format - get image format type
623: * @img_addr: image start address
624: *
625: * genimg_get_format() checks whether provided address points to a valid
626: * legacy or FIT image.
627: *
628: * New uImage format and FDT blob are based on a libfdt. FDT blob
629: * may be passed directly or embedded in a FIT image. In both situations
630: * genimg_get_format() must be able to dectect libfdt header.
631: *
632: * returns:
633: * image format type or IMAGE_FORMAT_INVALID if no image is present
634: */
635: int genimg_get_format (void *img_addr)
636: {
637: ulong format = IMAGE_FORMAT_INVALID;
638: const image_header_t *hdr;
639: #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
640: char *fit_hdr;
641: #endif
642:
643: hdr = (const image_header_t *)img_addr;
644: if (image_check_magic(hdr))
645: format = IMAGE_FORMAT_LEGACY;
646: #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
647: else {
648: fit_hdr = (char *)img_addr;
649: if (fdt_check_header (fit_hdr) == 0)
650: format = IMAGE_FORMAT_FIT;
651: }
652: #endif
653:
654: return format;
655: }
656:
657: /**
658: * genimg_get_image - get image from special storage (if necessary)
659: * @img_addr: image start address
660: *
661: * genimg_get_image() checks if provided image start adddress is located
662: * in a dataflash storage. If so, image is moved to a system RAM memory.
663: *
664: * returns:
665: * image start address after possible relocation from special storage
666: */
667: ulong genimg_get_image (ulong img_addr)
668: {
669: ulong ram_addr = img_addr;
670:
671: #ifdef CONFIG_HAS_DATAFLASH
672: ulong h_size, d_size;
673:
674: if (addr_dataflash (img_addr)){
675: /* ger RAM address */
676: ram_addr = CONFIG_SYS_LOAD_ADDR;
677:
678: /* get header size */
679: h_size = image_get_header_size ();
680: #if defined(CONFIG_FIT)
681: if (sizeof(struct fdt_header) > h_size)
682: h_size = sizeof(struct fdt_header);
683: #endif
684:
685: /* read in header */
686: debug (" Reading image header from dataflash address "
687: "%08lx to RAM address %08lx\n", img_addr, ram_addr);
688:
689: read_dataflash (img_addr, h_size, (char *)ram_addr);
690:
691: /* get data size */
692: switch (genimg_get_format ((void *)ram_addr)) {
693: case IMAGE_FORMAT_LEGACY:
694: d_size = image_get_data_size ((const image_header_t *)ram_addr);
695: debug (" Legacy format image found at 0x%08lx, size 0x%08lx\n",
696: ram_addr, d_size);
697: break;
698: #if defined(CONFIG_FIT)
699: case IMAGE_FORMAT_FIT:
700: d_size = fit_get_size ((const void *)ram_addr) - h_size;
701: debug (" FIT/FDT format image found at 0x%08lx, size 0x%08lx\n",
702: ram_addr, d_size);
703: break;
704: #endif
705: default:
706: printf (" No valid image found at 0x%08lx\n", img_addr);
707: return ram_addr;
708: }
709:
710: /* read in image data */
711: debug (" Reading image remaining data from dataflash address "
712: "%08lx to RAM address %08lx\n", img_addr + h_size,
713: ram_addr + h_size);
714:
715: read_dataflash (img_addr + h_size, d_size,
716: (char *)(ram_addr + h_size));
717:
718: }
719: #endif /* CONFIG_HAS_DATAFLASH */
720:
721: return ram_addr;
722: }
723:
724: /**
725: * fit_has_config - check if there is a valid FIT configuration
726: * @images: pointer to the bootm command headers structure
727: *
728: * fit_has_config() checks if there is a FIT configuration in use
729: * (if FTI support is present).
730: *
731: * returns:
732: * 0, no FIT support or no configuration found
733: * 1, configuration found
734: */
735: int genimg_has_config (bootm_headers_t *images)
736: {
737: #if defined(CONFIG_FIT)
738: if (images->fit_uname_cfg)
739: return 1;
740: #endif
741: return 0;
742: }
743:
744: /**
745: * boot_get_ramdisk - main ramdisk handling routine
746: * @argc: command argument count
747: * @argv: command argument list
748: * @images: pointer to the bootm images structure
749: * @arch: expected ramdisk architecture
750: * @rd_start: pointer to a ulong variable, will hold ramdisk start address
751: * @rd_end: pointer to a ulong variable, will hold ramdisk end
752: *
753: * boot_get_ramdisk() is responsible for finding a valid ramdisk image.
754: * Curently supported are the following ramdisk sources:
755: * - multicomponent kernel/ramdisk image,
756: * - commandline provided address of decicated ramdisk image.
757: *
758: * returns:
759: * 0, if ramdisk image was found and valid, or skiped
760: * rd_start and rd_end are set to ramdisk start/end addresses if
761: * ramdisk image is found and valid
762: *
763: * 1, if ramdisk image is found but corrupted, or invalid
764: * rd_start and rd_end are set to 0 if no ramdisk exists
765: */
766: int boot_get_ramdisk (int argc, char * const argv[], bootm_headers_t *images,
767: uint8_t arch, ulong *rd_start, ulong *rd_end)
768: {
769: ulong rd_addr, rd_load;
770: ulong rd_data, rd_len;
771: const image_header_t *rd_hdr;
772: #if defined(CONFIG_FIT)
773: void *fit_hdr;
774: const char *fit_uname_config = NULL;
775: const char *fit_uname_ramdisk = NULL;
776: ulong default_addr;
777: int rd_noffset;
778: int cfg_noffset;
779: const void *data;
780: size_t size;
781: #endif
782:
783: *rd_start = 0;
784: *rd_end = 0;
785:
786: /*
787: * Look for a '-' which indicates to ignore the
788: * ramdisk argument
789: */
790: if ((argc >= 3) && (strcmp(argv[2], "-") == 0)) {
791: debug ("## Skipping init Ramdisk\n");
792: rd_len = rd_data = 0;
793: } else if (argc >= 3 || genimg_has_config (images)) {
794: #if defined(CONFIG_FIT)
795: if (argc >= 3) {
796: /*
797: * If the init ramdisk comes from the FIT image and
798: * the FIT image address is omitted in the command
799: * line argument, try to use os FIT image address or
800: * default load address.
801: */
802: if (images->fit_uname_os)
803: default_addr = (ulong)images->fit_hdr_os;
804: else
805: default_addr = load_addr;
806:
807: if (fit_parse_conf (argv[2], default_addr,
808: &rd_addr, &fit_uname_config)) {
809: debug ("* ramdisk: config '%s' from image at 0x%08lx\n",
810: fit_uname_config, rd_addr);
811: } else if (fit_parse_subimage (argv[2], default_addr,
812: &rd_addr, &fit_uname_ramdisk)) {
813: debug ("* ramdisk: subimage '%s' from image at 0x%08lx\n",
814: fit_uname_ramdisk, rd_addr);
815: } else
816: #endif
817: {
818: rd_addr = simple_strtoul(argv[2], NULL, 16);
819: debug ("* ramdisk: cmdline image address = 0x%08lx\n",
820: rd_addr);
821: }
822: #if defined(CONFIG_FIT)
823: } else {
824: /* use FIT configuration provided in first bootm
825: * command argument
826: */
827: rd_addr = (ulong)images->fit_hdr_os;
828: fit_uname_config = images->fit_uname_cfg;
829: debug ("* ramdisk: using config '%s' from image at 0x%08lx\n",
830: fit_uname_config, rd_addr);
831:
832: /*
833: * Check whether configuration has ramdisk defined,
834: * if not, don't try to use it, quit silently.
835: */
836: fit_hdr = (void *)rd_addr;
837: cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config);
838: if (cfg_noffset < 0) {
839: debug ("* ramdisk: no such config\n");
840: return 1;
841: }
842:
843: rd_noffset = fit_conf_get_ramdisk_node (fit_hdr, cfg_noffset);
844: if (rd_noffset < 0) {
845: debug ("* ramdisk: no ramdisk in config\n");
846: return 0;
847: }
848: }
849: #endif
850:
851: /* copy from dataflash if needed */
852: rd_addr = genimg_get_image (rd_addr);
853:
854: /*
855: * Check if there is an initrd image at the
856: * address provided in the second bootm argument
857: * check image type, for FIT images get FIT node.
858: */
859: switch (genimg_get_format ((void *)rd_addr)) {
860: case IMAGE_FORMAT_LEGACY:
861: printf ("## Loading init Ramdisk from Legacy "
862: "Image at %08lx ...\n", rd_addr);
863:
864: show_boot_progress (9);
865: rd_hdr = image_get_ramdisk (rd_addr, arch,
866: images->verify);
867:
868: if (rd_hdr == NULL)
869: return 1;
870:
871: rd_data = image_get_data (rd_hdr);
872: rd_len = image_get_data_size (rd_hdr);
873: rd_load = image_get_load (rd_hdr);
874: break;
875: #if defined(CONFIG_FIT)
876: case IMAGE_FORMAT_FIT:
877: fit_hdr = (void *)rd_addr;
878: printf ("## Loading init Ramdisk from FIT "
879: "Image at %08lx ...\n", rd_addr);
880:
881: show_boot_progress (120);
882: if (!fit_check_format (fit_hdr)) {
883: puts ("Bad FIT ramdisk image format!\n");
884: show_boot_progress (-120);
885: return 1;
886: }
887: show_boot_progress (121);
888:
889: if (!fit_uname_ramdisk) {
890: /*
891: * no ramdisk image node unit name, try to get config
892: * node first. If config unit node name is NULL
893: * fit_conf_get_node() will try to find default config node
894: */
895: show_boot_progress (122);
896: cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config);
897: if (cfg_noffset < 0) {
898: puts ("Could not find configuration node\n");
899: show_boot_progress (-122);
900: return 1;
901: }
902: fit_uname_config = fdt_get_name (fit_hdr, cfg_noffset, NULL);
903: printf (" Using '%s' configuration\n", fit_uname_config);
904:
905: rd_noffset = fit_conf_get_ramdisk_node (fit_hdr, cfg_noffset);
906: fit_uname_ramdisk = fit_get_name (fit_hdr, rd_noffset, NULL);
907: } else {
908: /* get ramdisk component image node offset */
909: show_boot_progress (123);
910: rd_noffset = fit_image_get_node (fit_hdr, fit_uname_ramdisk);
911: }
912: if (rd_noffset < 0) {
913: puts ("Could not find subimage node\n");
914: show_boot_progress (-124);
915: return 1;
916: }
917:
918: printf (" Trying '%s' ramdisk subimage\n", fit_uname_ramdisk);
919:
920: show_boot_progress (125);
921: if (!fit_check_ramdisk (fit_hdr, rd_noffset, arch, images->verify))
922: return 1;
923:
924: /* get ramdisk image data address and length */
925: if (fit_image_get_data (fit_hdr, rd_noffset, &data, &size)) {
926: puts ("Could not find ramdisk subimage data!\n");
927: show_boot_progress (-127);
928: return 1;
929: }
930: show_boot_progress (128);
931:
932: rd_data = (ulong)data;
933: rd_len = size;
934:
935: if (fit_image_get_load (fit_hdr, rd_noffset, &rd_load)) {
936: puts ("Can't get ramdisk subimage load address!\n");
937: show_boot_progress (-129);
938: return 1;
939: }
940: show_boot_progress (129);
941:
942: images->fit_hdr_rd = fit_hdr;
943: images->fit_uname_rd = fit_uname_ramdisk;
944: images->fit_noffset_rd = rd_noffset;
945: break;
946: #endif
947: default:
948: puts ("Wrong Ramdisk Image Format\n");
949: rd_data = rd_len = rd_load = 0;
950: return 1;
951: }
952:
953: #if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO)
954: /*
955: * We need to copy the ramdisk to SRAM to let Linux boot
956: */
957: if (rd_data) {
958: memmove ((void *)rd_load, (uchar *)rd_data, rd_len);
959: rd_data = rd_load;
960: }
961: #endif /* CONFIG_B2 || CONFIG_EVB4510 || CONFIG_ARMADILLO */
962:
963: } else if (images->legacy_hdr_valid &&
964: image_check_type (&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) {
965: /*
966: * Now check if we have a legacy mult-component image,
967: * get second entry data start address and len.
968: */
969: show_boot_progress (13);
970: printf ("## Loading init Ramdisk from multi component "
971: "Legacy Image at %08lx ...\n",
972: (ulong)images->legacy_hdr_os);
973:
974: image_multi_getimg (images->legacy_hdr_os, 1, &rd_data, &rd_len);
975: } else {
976: /*
977: * no initrd image
978: */
979: show_boot_progress (14);
980: rd_len = rd_data = 0;
981: }
982:
983: if (!rd_data) {
984: debug ("## No init Ramdisk\n");
985: } else {
986: *rd_start = rd_data;
987: *rd_end = rd_data + rd_len;
988: }
989: debug (" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n",
990: *rd_start, *rd_end);
991:
992: return 0;
993: }
994:
995: #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
996: /**
997: * boot_ramdisk_high - relocate init ramdisk
998: * @lmb: pointer to lmb handle, will be used for memory mgmt
999: * @rd_data: ramdisk data start address
1000: * @rd_len: ramdisk data length
1001: * @initrd_start: pointer to a ulong variable, will hold final init ramdisk
1002: * start address (after possible relocation)
1003: * @initrd_end: pointer to a ulong variable, will hold final init ramdisk
1004: * end address (after possible relocation)
1005: *
1006: * boot_ramdisk_high() takes a relocation hint from "initrd_high" environement
1007: * variable and if requested ramdisk data is moved to a specified location.
1008: *
1009: * Initrd_start and initrd_end are set to final (after relocation) ramdisk
1010: * start/end addresses if ramdisk image start and len were provided,
1011: * otherwise set initrd_start and initrd_end set to zeros.
1012: *
1013: * returns:
1014: * 0 - success
1015: * -1 - failure
1016: */
1017: int boot_ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len,
1018: ulong *initrd_start, ulong *initrd_end)
1019: {
1020: char *s;
1021: ulong initrd_high;
1022: int initrd_copy_to_ram = 1;
1023:
1024: if ((s = getenv ("initrd_high")) != NULL) {
1025: /* a value of "no" or a similar string will act like 0,
1026: * turning the "load high" feature off. This is intentional.
1027: */
1028: initrd_high = simple_strtoul (s, NULL, 16);
1029: if (initrd_high == ~0)
1030: initrd_copy_to_ram = 0;
1031: } else {
1032: /* not set, no restrictions to load high */
1033: initrd_high = ~0;
1034: }
1035:
1036:
1037: #ifdef CONFIG_LOGBUFFER
1038: /* Prevent initrd from overwriting logbuffer */
1039: lmb_reserve(lmb, logbuffer_base() - LOGBUFF_OVERHEAD, LOGBUFF_RESERVE);
1040: #endif
1041:
1042: debug ("## initrd_high = 0x%08lx, copy_to_ram = %d\n",
1043: initrd_high, initrd_copy_to_ram);
1044:
1045: if (rd_data) {
1046: if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */
1047: debug (" in-place initrd\n");
1048: *initrd_start = rd_data;
1049: *initrd_end = rd_data + rd_len;
1050: lmb_reserve(lmb, rd_data, rd_len);
1051: } else {
1052: if (initrd_high)
1053: *initrd_start = (ulong)lmb_alloc_base (lmb, rd_len, 0x1000, initrd_high);
1054: else
1055: *initrd_start = (ulong)lmb_alloc (lmb, rd_len, 0x1000);
1056:
1057: if (*initrd_start == 0) {
1058: puts ("ramdisk - allocation error\n");
1059: goto error;
1060: }
1061: show_boot_progress (12);
1062:
1063: *initrd_end = *initrd_start + rd_len;
1064: printf (" Loading Ramdisk to %08lx, end %08lx ... ",
1065: *initrd_start, *initrd_end);
1066:
1067: memmove_wd ((void *)*initrd_start,
1068: (void *)rd_data, rd_len, CHUNKSZ);
1069:
1070: puts ("OK\n");
1071: }
1072: } else {
1073: *initrd_start = 0;
1074: *initrd_end = 0;
1075: }
1076: debug (" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n",
1077: *initrd_start, *initrd_end);
1078:
1079: return 0;
1080:
1081: error:
1082: return -1;
1083: }
1084: #endif /* CONFIG_SYS_BOOT_RAMDISK_HIGH */
1085:
1086: #ifdef CONFIG_OF_LIBFDT
1087: static void fdt_error (const char *msg)
1088: {
1089: puts ("ERROR: ");
1090: puts (msg);
1091: puts (" - must RESET the board to recover.\n");
1092: }
1093:
1094: static const image_header_t *image_get_fdt (ulong fdt_addr)
1095: {
1096: const image_header_t *fdt_hdr = (const image_header_t *)fdt_addr;
1097:
1098: image_print_contents (fdt_hdr);
1099:
1100: puts (" Verifying Checksum ... ");
1101: if (!image_check_hcrc (fdt_hdr)) {
1102: fdt_error ("fdt header checksum invalid");
1103: return NULL;
1104: }
1105:
1106: if (!image_check_dcrc (fdt_hdr)) {
1107: fdt_error ("fdt checksum invalid");
1108: return NULL;
1109: }
1110: puts ("OK\n");
1111:
1112: if (!image_check_type (fdt_hdr, IH_TYPE_FLATDT)) {
1113: fdt_error ("uImage is not a fdt");
1114: return NULL;
1115: }
1116: if (image_get_comp (fdt_hdr) != IH_COMP_NONE) {
1117: fdt_error ("uImage is compressed");
1118: return NULL;
1119: }
1120: if (fdt_check_header ((char *)image_get_data (fdt_hdr)) != 0) {
1121: fdt_error ("uImage data is not a fdt");
1122: return NULL;
1123: }
1124: return fdt_hdr;
1125: }
1126:
1127: /**
1128: * fit_check_fdt - verify FIT format FDT subimage
1129: * @fit_hdr: pointer to the FIT header
1130: * fdt_noffset: FDT subimage node offset within FIT image
1131: * @verify: data CRC verification flag
1132: *
1133: * fit_check_fdt() verifies integrity of the FDT subimage and from
1134: * specified FIT image.
1135: *
1136: * returns:
1137: * 1, on success
1138: * 0, on failure
1139: */
1140: #if defined(CONFIG_FIT)
1141: static int fit_check_fdt (const void *fit, int fdt_noffset, int verify)
1142: {
1143: fit_image_print (fit, fdt_noffset, " ");
1144:
1145: if (verify) {
1146: puts (" Verifying Hash Integrity ... ");
1147: if (!fit_image_check_hashes (fit, fdt_noffset)) {
1148: fdt_error ("Bad Data Hash");
1149: return 0;
1150: }
1151: puts ("OK\n");
1152: }
1153:
1154: if (!fit_image_check_type (fit, fdt_noffset, IH_TYPE_FLATDT)) {
1155: fdt_error ("Not a FDT image");
1156: return 0;
1157: }
1158:
1159: if (!fit_image_check_comp (fit, fdt_noffset, IH_COMP_NONE)) {
1160: fdt_error ("FDT image is compressed");
1161: return 0;
1162: }
1163:
1164: return 1;
1165: }
1166: #endif /* CONFIG_FIT */
1167:
1168: #ifndef CONFIG_SYS_FDT_PAD
1169: #define CONFIG_SYS_FDT_PAD 0x3000
1170: #endif
1171:
1172: /**
1173: * boot_relocate_fdt - relocate flat device tree
1174: * @lmb: pointer to lmb handle, will be used for memory mgmt
1175: * @bootmap_base: base address of the bootmap region
1176: * @of_flat_tree: pointer to a char* variable, will hold fdt start address
1177: * @of_size: pointer to a ulong variable, will hold fdt length
1178: *
1179: * boot_relocate_fdt() allocates a region of memory within the bootmap and
1180: * relocates the of_flat_tree into that region, even if the fdt is already in
1181: * the bootmap. It also expands the size of the fdt by CONFIG_SYS_FDT_PAD
1182: * bytes.
1183: *
1184: * of_flat_tree and of_size are set to final (after relocation) values
1185: *
1186: * returns:
1187: * 0 - success
1188: * 1 - failure
1189: */
1190: #if defined(CONFIG_SYS_BOOTMAPSZ)
1191: int boot_relocate_fdt (struct lmb *lmb, ulong bootmap_base,
1192: char **of_flat_tree, ulong *of_size)
1193: {
1194: void *fdt_blob = *of_flat_tree;
1195: void *of_start = 0;
1196: ulong of_len = 0;
1197: int err;
1198:
1199: /* nothing to do */
1200: if (*of_size == 0)
1201: return 0;
1202:
1203: if (fdt_check_header (fdt_blob) != 0) {
1204: fdt_error ("image is not a fdt");
1205: goto error;
1206: }
1207:
1208: /* position on a 4K boundary before the alloc_current */
1209: /* Pad the FDT by a specified amount */
1210: of_len = *of_size + CONFIG_SYS_FDT_PAD;
1211: of_start = (void *)(unsigned long)lmb_alloc_base(lmb, of_len, 0x1000,
1212: (CONFIG_SYS_BOOTMAPSZ + bootmap_base));
1213:
1214: if (of_start == 0) {
1215: puts("device tree - allocation error\n");
1216: goto error;
1217: }
1218:
1219: debug ("## device tree at %p ... %p (len=%ld [0x%lX])\n",
1220: fdt_blob, fdt_blob + *of_size - 1, of_len, of_len);
1221:
1222: printf (" Loading Device Tree to %p, end %p ... ",
1223: of_start, of_start + of_len - 1);
1224:
1225: err = fdt_open_into (fdt_blob, of_start, of_len);
1226: if (err != 0) {
1227: fdt_error ("fdt move failed");
1228: goto error;
1229: }
1230: puts ("OK\n");
1231:
1232: *of_flat_tree = of_start;
1233: *of_size = of_len;
1234:
1235: set_working_fdt_addr(*of_flat_tree);
1236: return 0;
1237:
1238: error:
1239: return 1;
1240: }
1241: #endif /* CONFIG_SYS_BOOTMAPSZ */
1242:
1243: /**
1244: * boot_get_fdt - main fdt handling routine
1245: * @argc: command argument count
1246: * @argv: command argument list
1247: * @images: pointer to the bootm images structure
1248: * @of_flat_tree: pointer to a char* variable, will hold fdt start address
1249: * @of_size: pointer to a ulong variable, will hold fdt length
1250: *
1251: * boot_get_fdt() is responsible for finding a valid flat device tree image.
1252: * Curently supported are the following ramdisk sources:
1253: * - multicomponent kernel/ramdisk image,
1254: * - commandline provided address of decicated ramdisk image.
1255: *
1256: * returns:
1257: * 0, if fdt image was found and valid, or skipped
1258: * of_flat_tree and of_size are set to fdt start address and length if
1259: * fdt image is found and valid
1260: *
1261: * 1, if fdt image is found but corrupted
1262: * of_flat_tree and of_size are set to 0 if no fdt exists
1263: */
1264: int boot_get_fdt (int flag, int argc, char * const argv[], bootm_headers_t *images,
1265: char **of_flat_tree, ulong *of_size)
1266: {
1267: const image_header_t *fdt_hdr;
1268: ulong fdt_addr;
1269: char *fdt_blob = NULL;
1270: ulong image_start, image_end;
1271: ulong load_start, load_end;
1272: #if defined(CONFIG_FIT)
1273: void *fit_hdr;
1274: const char *fit_uname_config = NULL;
1275: const char *fit_uname_fdt = NULL;
1276: ulong default_addr;
1277: int cfg_noffset;
1278: int fdt_noffset;
1279: const void *data;
1280: size_t size;
1281: #endif
1282:
1283: *of_flat_tree = NULL;
1284: *of_size = 0;
1285:
1286: if (argc > 3 || genimg_has_config (images)) {
1287: #if defined(CONFIG_FIT)
1288: if (argc > 3) {
1289: /*
1290: * If the FDT blob comes from the FIT image and the
1291: * FIT image address is omitted in the command line
1292: * argument, try to use ramdisk or os FIT image
1293: * address or default load address.
1294: */
1295: if (images->fit_uname_rd)
1296: default_addr = (ulong)images->fit_hdr_rd;
1297: else if (images->fit_uname_os)
1298: default_addr = (ulong)images->fit_hdr_os;
1299: else
1300: default_addr = load_addr;
1301:
1302: if (fit_parse_conf (argv[3], default_addr,
1303: &fdt_addr, &fit_uname_config)) {
1304: debug ("* fdt: config '%s' from image at 0x%08lx\n",
1305: fit_uname_config, fdt_addr);
1306: } else if (fit_parse_subimage (argv[3], default_addr,
1307: &fdt_addr, &fit_uname_fdt)) {
1308: debug ("* fdt: subimage '%s' from image at 0x%08lx\n",
1309: fit_uname_fdt, fdt_addr);
1310: } else
1311: #endif
1312: {
1313: fdt_addr = simple_strtoul(argv[3], NULL, 16);
1314: debug ("* fdt: cmdline image address = 0x%08lx\n",
1315: fdt_addr);
1316: }
1317: #if defined(CONFIG_FIT)
1318: } else {
1319: /* use FIT configuration provided in first bootm
1320: * command argument
1321: */
1322: fdt_addr = (ulong)images->fit_hdr_os;
1323: fit_uname_config = images->fit_uname_cfg;
1324: debug ("* fdt: using config '%s' from image at 0x%08lx\n",
1325: fit_uname_config, fdt_addr);
1326:
1327: /*
1328: * Check whether configuration has FDT blob defined,
1329: * if not quit silently.
1330: */
1331: fit_hdr = (void *)fdt_addr;
1332: cfg_noffset = fit_conf_get_node (fit_hdr,
1333: fit_uname_config);
1334: if (cfg_noffset < 0) {
1335: debug ("* fdt: no such config\n");
1336: return 0;
1337: }
1338:
1339: fdt_noffset = fit_conf_get_fdt_node (fit_hdr,
1340: cfg_noffset);
1341: if (fdt_noffset < 0) {
1342: debug ("* fdt: no fdt in config\n");
1343: return 0;
1344: }
1345: }
1346: #endif
1347:
1348: debug ("## Checking for 'FDT'/'FDT Image' at %08lx\n",
1349: fdt_addr);
1350:
1351: /* copy from dataflash if needed */
1352: fdt_addr = genimg_get_image (fdt_addr);
1353:
1354: /*
1355: * Check if there is an FDT image at the
1356: * address provided in the second bootm argument
1357: * check image type, for FIT images get a FIT node.
1358: */
1359: switch (genimg_get_format ((void *)fdt_addr)) {
1360: case IMAGE_FORMAT_LEGACY:
1361: /* verify fdt_addr points to a valid image header */
1362: printf ("## Flattened Device Tree from Legacy Image at %08lx\n",
1363: fdt_addr);
1364: fdt_hdr = image_get_fdt (fdt_addr);
1365: if (!fdt_hdr)
1366: goto error;
1367:
1368: /*
1369: * move image data to the load address,
1370: * make sure we don't overwrite initial image
1371: */
1372: image_start = (ulong)fdt_hdr;
1373: image_end = image_get_image_end (fdt_hdr);
1374:
1375: load_start = image_get_load (fdt_hdr);
1376: load_end = load_start + image_get_data_size (fdt_hdr);
1377:
1378: if ((load_start < image_end) && (load_end > image_start)) {
1379: fdt_error ("fdt overwritten");
1380: goto error;
1381: }
1382:
1383: debug (" Loading FDT from 0x%08lx to 0x%08lx\n",
1384: image_get_data (fdt_hdr), load_start);
1385:
1386: memmove ((void *)load_start,
1387: (void *)image_get_data (fdt_hdr),
1388: image_get_data_size (fdt_hdr));
1389:
1390: fdt_blob = (char *)load_start;
1391: break;
1392: case IMAGE_FORMAT_FIT:
1393: /*
1394: * This case will catch both: new uImage format
1395: * (libfdt based) and raw FDT blob (also libfdt
1396: * based).
1397: */
1398: #if defined(CONFIG_FIT)
1399: /* check FDT blob vs FIT blob */
1400: if (fit_check_format ((const void *)fdt_addr)) {
1401: /*
1402: * FIT image
1403: */
1404: fit_hdr = (void *)fdt_addr;
1405: printf ("## Flattened Device Tree from FIT Image at %08lx\n",
1406: fdt_addr);
1407:
1408: if (!fit_uname_fdt) {
1409: /*
1410: * no FDT blob image node unit name,
1411: * try to get config node first. If
1412: * config unit node name is NULL
1413: * fit_conf_get_node() will try to
1414: * find default config node
1415: */
1416: cfg_noffset = fit_conf_get_node (fit_hdr,
1417: fit_uname_config);
1418:
1419: if (cfg_noffset < 0) {
1420: fdt_error ("Could not find configuration node\n");
1421: goto error;
1422: }
1423:
1424: fit_uname_config = fdt_get_name (fit_hdr,
1425: cfg_noffset, NULL);
1426: printf (" Using '%s' configuration\n",
1427: fit_uname_config);
1428:
1429: fdt_noffset = fit_conf_get_fdt_node (fit_hdr,
1430: cfg_noffset);
1431: fit_uname_fdt = fit_get_name (fit_hdr,
1432: fdt_noffset, NULL);
1433: } else {
1434: /* get FDT component image node offset */
1435: fdt_noffset = fit_image_get_node (fit_hdr,
1436: fit_uname_fdt);
1437: }
1438: if (fdt_noffset < 0) {
1439: fdt_error ("Could not find subimage node\n");
1440: goto error;
1441: }
1442:
1443: printf (" Trying '%s' FDT blob subimage\n",
1444: fit_uname_fdt);
1445:
1446: if (!fit_check_fdt (fit_hdr, fdt_noffset,
1447: images->verify))
1448: goto error;
1449:
1450: /* get ramdisk image data address and length */
1451: if (fit_image_get_data (fit_hdr, fdt_noffset,
1452: &data, &size)) {
1453: fdt_error ("Could not find FDT subimage data");
1454: goto error;
1455: }
1456:
1457: /* verift that image data is a proper FDT blob */
1458: if (fdt_check_header ((char *)data) != 0) {
1459: fdt_error ("Subimage data is not a FTD");
1460: goto error;
1461: }
1462:
1463: /*
1464: * move image data to the load address,
1465: * make sure we don't overwrite initial image
1466: */
1467: image_start = (ulong)fit_hdr;
1468: image_end = fit_get_end (fit_hdr);
1469:
1470: if (fit_image_get_load (fit_hdr, fdt_noffset,
1471: &load_start) == 0) {
1472: load_end = load_start + size;
1473:
1474: if ((load_start < image_end) &&
1475: (load_end > image_start)) {
1476: fdt_error ("FDT overwritten");
1477: goto error;
1478: }
1479:
1480: printf (" Loading FDT from 0x%08lx to 0x%08lx\n",
1481: (ulong)data, load_start);
1482:
1483: memmove ((void *)load_start,
1484: (void *)data, size);
1485:
1486: fdt_blob = (char *)load_start;
1487: } else {
1488: fdt_blob = (char *)data;
1489: }
1490:
1491: images->fit_hdr_fdt = fit_hdr;
1492: images->fit_uname_fdt = fit_uname_fdt;
1493: images->fit_noffset_fdt = fdt_noffset;
1494: break;
1495: } else
1496: #endif
1497: {
1498: /*
1499: * FDT blob
1500: */
1501: fdt_blob = (char *)fdt_addr;
1502: debug ("* fdt: raw FDT blob\n");
1503: printf ("## Flattened Device Tree blob at %08lx\n", (long)fdt_blob);
1504: }
1505: break;
1506: default:
1507: puts ("ERROR: Did not find a cmdline Flattened Device Tree\n");
1508: goto error;
1509: }
1510:
1511: printf (" Booting using the fdt blob at 0x%x\n", (int)fdt_blob);
1512:
1513: } else if (images->legacy_hdr_valid &&
1514: image_check_type (&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) {
1515:
1516: ulong fdt_data, fdt_len;
1517:
1518: /*
1519: * Now check if we have a legacy multi-component image,
1520: * get second entry data start address and len.
1521: */
1522: printf ("## Flattened Device Tree from multi "
1523: "component Image at %08lX\n",
1524: (ulong)images->legacy_hdr_os);
1525:
1526: image_multi_getimg (images->legacy_hdr_os, 2, &fdt_data, &fdt_len);
1527: if (fdt_len) {
1528:
1529: fdt_blob = (char *)fdt_data;
1530: printf (" Booting using the fdt at 0x%x\n", (int)fdt_blob);
1531:
1532: if (fdt_check_header (fdt_blob) != 0) {
1533: fdt_error ("image is not a fdt");
1534: goto error;
1535: }
1536:
1537: if (fdt_totalsize(fdt_blob) != fdt_len) {
1538: fdt_error ("fdt size != image size");
1539: goto error;
1540: }
1541: } else {
1542: debug ("## No Flattened Device Tree\n");
1543: return 0;
1544: }
1545: } else {
1546: debug ("## No Flattened Device Tree\n");
1547: return 0;
1548: }
1549:
1550: *of_flat_tree = fdt_blob;
1551: *of_size = fdt_totalsize(fdt_blob);
1552: debug (" of_flat_tree at 0x%08lx size 0x%08lx\n",
1553: (ulong)*of_flat_tree, *of_size);
1554:
1555: return 0;
1556:
1557: error:
1558: *of_flat_tree = 0;
1559: *of_size = 0;
1560: return 1;
1561: }
1562: #endif /* CONFIG_OF_LIBFDT */
1563:
1564: #ifdef CONFIG_SYS_BOOT_GET_CMDLINE
1565: /**
1566: * boot_get_cmdline - allocate and initialize kernel cmdline
1567: * @lmb: pointer to lmb handle, will be used for memory mgmt
1568: * @cmd_start: pointer to a ulong variable, will hold cmdline start
1569: * @cmd_end: pointer to a ulong variable, will hold cmdline end
1570: * @bootmap_base: ulong variable, holds offset in physical memory to
1571: * base of bootmap
1572: *
1573: * boot_get_cmdline() allocates space for kernel command line below
1574: * BOOTMAPSZ + bootmap_base address. If "bootargs" U-boot environemnt
1575: * variable is present its contents is copied to allocated kernel
1576: * command line.
1577: *
1578: * returns:
1579: * 0 - success
1580: * -1 - failure
1581: */
1582: int boot_get_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end,
1583: ulong bootmap_base)
1584: {
1585: char *cmdline;
1586: char *s;
1587:
1588: cmdline = (char *)(ulong)lmb_alloc_base(lmb, CONFIG_SYS_BARGSIZE, 0xf,
1589: CONFIG_SYS_BOOTMAPSZ + bootmap_base);
1590:
1591: if (cmdline == NULL)
1592: return -1;
1593:
1594: if ((s = getenv("bootargs")) == NULL)
1595: s = "";
1596:
1597: strcpy(cmdline, s);
1598:
1599: *cmd_start = (ulong) & cmdline[0];
1600: *cmd_end = *cmd_start + strlen(cmdline);
1601:
1602: debug ("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end);
1603:
1604: return 0;
1605: }
1606: #endif /* CONFIG_SYS_BOOT_GET_CMDLINE */
1607:
1608: #ifdef CONFIG_SYS_BOOT_GET_KBD
1609: /**
1610: * boot_get_kbd - allocate and initialize kernel copy of board info
1611: * @lmb: pointer to lmb handle, will be used for memory mgmt
1612: * @kbd: double pointer to board info data
1613: * @bootmap_base: ulong variable, holds offset in physical memory to
1614: * base of bootmap
1615: *
1616: * boot_get_kbd() allocates space for kernel copy of board info data below
1617: * BOOTMAPSZ + bootmap_base address and kernel board info is initialized with
1618: * the current u-boot board info data.
1619: *
1620: * returns:
1621: * 0 - success
1622: * -1 - failure
1623: */
1624: int boot_get_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base)
1625: {
1626: *kbd = (bd_t *)(ulong)lmb_alloc_base(lmb, sizeof(bd_t), 0xf,
1627: CONFIG_SYS_BOOTMAPSZ + bootmap_base);
1628: if (*kbd == NULL)
1629: return -1;
1630:
1631: **kbd = *(gd->bd);
1632:
1633: debug ("## kernel board info at 0x%08lx\n", (ulong)*kbd);
1634:
1635: #if defined(DEBUG) && defined(CONFIG_CMD_BDI)
1636: do_bdinfo(NULL, 0, 0, NULL);
1637: #endif
1638:
1639: return 0;
1640: }
1641: #endif /* CONFIG_SYS_BOOT_GET_KBD */
1642: #endif /* !USE_HOSTCC */
1643:
1644: #if defined(CONFIG_FIT)
1645: /*****************************************************************************/
1646: /* New uImage format routines */
1647: /*****************************************************************************/
1648: #ifndef USE_HOSTCC
1649: static int fit_parse_spec (const char *spec, char sepc, ulong addr_curr,
1650: ulong *addr, const char **name)
1651: {
1652: const char *sep;
1653:
1654: *addr = addr_curr;
1655: *name = NULL;
1656:
1657: sep = strchr (spec, sepc);
1658: if (sep) {
1659: if (sep - spec > 0)
1660: *addr = simple_strtoul (spec, NULL, 16);
1661:
1662: *name = sep + 1;
1663: return 1;
1664: }
1665:
1666: return 0;
1667: }
1668:
1669: /**
1670: * fit_parse_conf - parse FIT configuration spec
1671: * @spec: input string, containing configuration spec
1672: * @add_curr: current image address (to be used as a possible default)
1673: * @addr: pointer to a ulong variable, will hold FIT image address of a given
1674: * configuration
1675: * @conf_name double pointer to a char, will hold pointer to a configuration
1676: * unit name
1677: *
1678: * fit_parse_conf() expects configuration spec in the for of [<addr>]#<conf>,
1679: * where <addr> is a FIT image address that contains configuration
1680: * with a <conf> unit name.
1681: *
1682: * Address part is optional, and if omitted default add_curr will
1683: * be used instead.
1684: *
1685: * returns:
1686: * 1 if spec is a valid configuration string,
1687: * addr and conf_name are set accordingly
1688: * 0 otherwise
1689: */
1690: inline int fit_parse_conf (const char *spec, ulong addr_curr,
1691: ulong *addr, const char **conf_name)
1692: {
1693: return fit_parse_spec (spec, '#', addr_curr, addr, conf_name);
1694: }
1695:
1696: /**
1697: * fit_parse_subimage - parse FIT subimage spec
1698: * @spec: input string, containing subimage spec
1699: * @add_curr: current image address (to be used as a possible default)
1700: * @addr: pointer to a ulong variable, will hold FIT image address of a given
1701: * subimage
1702: * @image_name: double pointer to a char, will hold pointer to a subimage name
1703: *
1704: * fit_parse_subimage() expects subimage spec in the for of
1705: * [<addr>]:<subimage>, where <addr> is a FIT image address that contains
1706: * subimage with a <subimg> unit name.
1707: *
1708: * Address part is optional, and if omitted default add_curr will
1709: * be used instead.
1710: *
1711: * returns:
1712: * 1 if spec is a valid subimage string,
1713: * addr and image_name are set accordingly
1714: * 0 otherwise
1715: */
1716: inline int fit_parse_subimage (const char *spec, ulong addr_curr,
1717: ulong *addr, const char **image_name)
1718: {
1719: return fit_parse_spec (spec, ':', addr_curr, addr, image_name);
1720: }
1721: #endif /* !USE_HOSTCC */
1722:
1723: static void fit_get_debug (const void *fit, int noffset,
1724: char *prop_name, int err)
1725: {
1726: debug ("Can't get '%s' property from FIT 0x%08lx, "
1727: "node: offset %d, name %s (%s)\n",
1728: prop_name, (ulong)fit, noffset,
1729: fit_get_name (fit, noffset, NULL),
1730: fdt_strerror (err));
1731: }
1732:
1733: /**
1734: * fit_print_contents - prints out the contents of the FIT format image
1735: * @fit: pointer to the FIT format image header
1736: * @p: pointer to prefix string
1737: *
1738: * fit_print_contents() formats a multi line FIT image contents description.
1739: * The routine prints out FIT image properties (root node level) follwed by
1740: * the details of each component image.
1741: *
1742: * returns:
1743: * no returned results
1744: */
1745: void fit_print_contents (const void *fit)
1746: {
1747: char *desc;
1748: char *uname;
1749: int images_noffset;
1750: int confs_noffset;
1751: int noffset;
1752: int ndepth;
1753: int count = 0;
1754: int ret;
1755: const char *p;
1756: #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
1757: time_t timestamp;
1758: #endif
1759:
1760: #ifdef USE_HOSTCC
1761: p = "";
1762: #else
1763: p = " ";
1764: #endif
1765:
1766: /* Root node properties */
1767: ret = fit_get_desc (fit, 0, &desc);
1768: printf ("%sFIT description: ", p);
1769: if (ret)
1770: printf ("unavailable\n");
1771: else
1772: printf ("%s\n", desc);
1773:
1774: #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
1775: ret = fit_get_timestamp (fit, 0, ×tamp);
1776: printf ("%sCreated: ", p);
1777: if (ret)
1778: printf ("unavailable\n");
1779: else
1780: genimg_print_time (timestamp);
1781: #endif
1782:
1783: /* Find images parent node offset */
1784: images_noffset = fdt_path_offset (fit, FIT_IMAGES_PATH);
1785: if (images_noffset < 0) {
1786: printf ("Can't find images parent node '%s' (%s)\n",
1787: FIT_IMAGES_PATH, fdt_strerror (images_noffset));
1788: return;
1789: }
1790:
1791: /* Process its subnodes, print out component images details */
1792: for (ndepth = 0, count = 0, noffset = fdt_next_node (fit, images_noffset, &ndepth);
1793: (noffset >= 0) && (ndepth > 0);
1794: noffset = fdt_next_node (fit, noffset, &ndepth)) {
1795: if (ndepth == 1) {
1796: /*
1797: * Direct child node of the images parent node,
1798: * i.e. component image node.
1799: */
1800: printf ("%s Image %u (%s)\n", p, count++,
1801: fit_get_name(fit, noffset, NULL));
1802:
1803: fit_image_print (fit, noffset, p);
1804: }
1805: }
1806:
1807: /* Find configurations parent node offset */
1808: confs_noffset = fdt_path_offset (fit, FIT_CONFS_PATH);
1809: if (confs_noffset < 0) {
1810: debug ("Can't get configurations parent node '%s' (%s)\n",
1811: FIT_CONFS_PATH, fdt_strerror (confs_noffset));
1812: return;
1813: }
1814:
1815: /* get default configuration unit name from default property */
1816: uname = (char *)fdt_getprop (fit, noffset, FIT_DEFAULT_PROP, NULL);
1817: if (uname)
1818: printf ("%s Default Configuration: '%s'\n", p, uname);
1819:
1820: /* Process its subnodes, print out configurations details */
1821: for (ndepth = 0, count = 0, noffset = fdt_next_node (fit, confs_noffset, &ndepth);
1822: (noffset >= 0) && (ndepth > 0);
1823: noffset = fdt_next_node (fit, noffset, &ndepth)) {
1824: if (ndepth == 1) {
1825: /*
1826: * Direct child node of the configurations parent node,
1827: * i.e. configuration node.
1828: */
1829: printf ("%s Configuration %u (%s)\n", p, count++,
1830: fit_get_name(fit, noffset, NULL));
1831:
1832: fit_conf_print (fit, noffset, p);
1833: }
1834: }
1835: }
1836:
1837: /**
1838: * fit_image_print - prints out the FIT component image details
1839: * @fit: pointer to the FIT format image header
1840: * @image_noffset: offset of the component image node
1841: * @p: pointer to prefix string
1842: *
1843: * fit_image_print() lists all mandatory properies for the processed component
1844: * image. If present, hash nodes are printed out as well. Load
1845: * address for images of type firmware is also printed out. Since the load
1846: * address is not mandatory for firmware images, it will be output as
1847: * "unavailable" when not present.
1848: *
1849: * returns:
1850: * no returned results
1851: */
1852: void fit_image_print (const void *fit, int image_noffset, const char *p)
1853: {
1854: char *desc;
1855: uint8_t type, arch, os, comp;
1856: size_t size;
1857: ulong load, entry;
1858: const void *data;
1859: int noffset;
1860: int ndepth;
1861: int ret;
1862:
1863: /* Mandatory properties */
1864: ret = fit_get_desc (fit, image_noffset, &desc);
1865: printf ("%s Description: ", p);
1866: if (ret)
1867: printf ("unavailable\n");
1868: else
1869: printf ("%s\n", desc);
1870:
1871: fit_image_get_type (fit, image_noffset, &type);
1872: printf ("%s Type: %s\n", p, genimg_get_type_name (type));
1873:
1874: fit_image_get_comp (fit, image_noffset, &comp);
1875: printf ("%s Compression: %s\n", p, genimg_get_comp_name (comp));
1876:
1877: ret = fit_image_get_data (fit, image_noffset, &data, &size);
1878:
1879: #ifndef USE_HOSTCC
1880: printf ("%s Data Start: ", p);
1881: if (ret)
1882: printf ("unavailable\n");
1883: else
1884: printf ("0x%08lx\n", (ulong)data);
1885: #endif
1886:
1887: printf ("%s Data Size: ", p);
1888: if (ret)
1889: printf ("unavailable\n");
1890: else
1891: genimg_print_size (size);
1892:
1893: /* Remaining, type dependent properties */
1894: if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
1895: (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) ||
1896: (type == IH_TYPE_FLATDT)) {
1897: fit_image_get_arch (fit, image_noffset, &arch);
1898: printf ("%s Architecture: %s\n", p, genimg_get_arch_name (arch));
1899: }
1900:
1901: if (type == IH_TYPE_KERNEL) {
1902: fit_image_get_os (fit, image_noffset, &os);
1903: printf ("%s OS: %s\n", p, genimg_get_os_name (os));
1904: }
1905:
1906: if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
1907: (type == IH_TYPE_FIRMWARE)) {
1908: ret = fit_image_get_load (fit, image_noffset, &load);
1909: printf ("%s Load Address: ", p);
1910: if (ret)
1911: printf ("unavailable\n");
1912: else
1913: printf ("0x%08lx\n", load);
1914: }
1915:
1916: if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE)) {
1917: fit_image_get_entry (fit, image_noffset, &entry);
1918: printf ("%s Entry Point: ", p);
1919: if (ret)
1920: printf ("unavailable\n");
1921: else
1922: printf ("0x%08lx\n", entry);
1923: }
1924:
1925: /* Process all hash subnodes of the component image node */
1926: for (ndepth = 0, noffset = fdt_next_node (fit, image_noffset, &ndepth);
1927: (noffset >= 0) && (ndepth > 0);
1928: noffset = fdt_next_node (fit, noffset, &ndepth)) {
1929: if (ndepth == 1) {
1930: /* Direct child node of the component image node */
1931: fit_image_print_hash (fit, noffset, p);
1932: }
1933: }
1934: }
1935:
1936: /**
1937: * fit_image_print_hash - prints out the hash node details
1938: * @fit: pointer to the FIT format image header
1939: * @noffset: offset of the hash node
1940: * @p: pointer to prefix string
1941: *
1942: * fit_image_print_hash() lists properies for the processed hash node
1943: *
1944: * returns:
1945: * no returned results
1946: */
1947: void fit_image_print_hash (const void *fit, int noffset, const char *p)
1948: {
1949: char *algo;
1950: uint8_t *value;
1951: int value_len;
1952: int i, ret;
1953:
1954: /*
1955: * Check subnode name, must be equal to "hash".
1956: * Multiple hash nodes require unique unit node
1957: * names, e.g. hash@1, hash@2, etc.
1958: */
1959: if (strncmp (fit_get_name(fit, noffset, NULL),
1960: FIT_HASH_NODENAME,
1961: strlen(FIT_HASH_NODENAME)) != 0)
1962: return;
1963:
1964: debug ("%s Hash node: '%s'\n", p,
1965: fit_get_name (fit, noffset, NULL));
1966:
1967: printf ("%s Hash algo: ", p);
1968: if (fit_image_hash_get_algo (fit, noffset, &algo)) {
1969: printf ("invalid/unsupported\n");
1970: return;
1971: }
1972: printf ("%s\n", algo);
1973:
1974: ret = fit_image_hash_get_value (fit, noffset, &value,
1975: &value_len);
1976: printf ("%s Hash value: ", p);
1977: if (ret) {
1978: printf ("unavailable\n");
1979: } else {
1980: for (i = 0; i < value_len; i++)
1981: printf ("%02x", value[i]);
1982: printf ("\n");
1983: }
1984:
1985: debug ("%s Hash len: %d\n", p, value_len);
1986: }
1987:
1988: /**
1989: * fit_get_desc - get node description property
1990: * @fit: pointer to the FIT format image header
1991: * @noffset: node offset
1992: * @desc: double pointer to the char, will hold pointer to the descrption
1993: *
1994: * fit_get_desc() reads description property from a given node, if
1995: * description is found pointer to it is returened in third call argument.
1996: *
1997: * returns:
1998: * 0, on success
1999: * -1, on failure
2000: */
2001: int fit_get_desc (const void *fit, int noffset, char **desc)
2002: {
2003: int len;
2004:
2005: *desc = (char *)fdt_getprop (fit, noffset, FIT_DESC_PROP, &len);
2006: if (*desc == NULL) {
2007: fit_get_debug (fit, noffset, FIT_DESC_PROP, len);
2008: return -1;
2009: }
2010:
2011: return 0;
2012: }
2013:
2014: /**
2015: * fit_get_timestamp - get node timestamp property
2016: * @fit: pointer to the FIT format image header
2017: * @noffset: node offset
2018: * @timestamp: pointer to the time_t, will hold read timestamp
2019: *
2020: * fit_get_timestamp() reads timestamp poperty from given node, if timestamp
2021: * is found and has a correct size its value is retured in third call
2022: * argument.
2023: *
2024: * returns:
2025: * 0, on success
2026: * -1, on property read failure
2027: * -2, on wrong timestamp size
2028: */
2029: int fit_get_timestamp (const void *fit, int noffset, time_t *timestamp)
2030: {
2031: int len;
2032: const void *data;
2033:
2034: data = fdt_getprop (fit, noffset, FIT_TIMESTAMP_PROP, &len);
2035: if (data == NULL) {
2036: fit_get_debug (fit, noffset, FIT_TIMESTAMP_PROP, len);
2037: return -1;
2038: }
2039: if (len != sizeof (uint32_t)) {
2040: debug ("FIT timestamp with incorrect size of (%u)\n", len);
2041: return -2;
2042: }
2043:
2044: *timestamp = uimage_to_cpu (*((uint32_t *)data));
2045: return 0;
2046: }
2047:
2048: /**
2049: * fit_image_get_node - get node offset for component image of a given unit name
2050: * @fit: pointer to the FIT format image header
2051: * @image_uname: component image node unit name
2052: *
2053: * fit_image_get_node() finds a component image (withing the '/images'
2054: * node) of a provided unit name. If image is found its node offset is
2055: * returned to the caller.
2056: *
2057: * returns:
2058: * image node offset when found (>=0)
2059: * negative number on failure (FDT_ERR_* code)
2060: */
2061: int fit_image_get_node (const void *fit, const char *image_uname)
2062: {
2063: int noffset, images_noffset;
2064:
2065: images_noffset = fdt_path_offset (fit, FIT_IMAGES_PATH);
2066: if (images_noffset < 0) {
2067: debug ("Can't find images parent node '%s' (%s)\n",
2068: FIT_IMAGES_PATH, fdt_strerror (images_noffset));
2069: return images_noffset;
2070: }
2071:
2072: noffset = fdt_subnode_offset (fit, images_noffset, image_uname);
2073: if (noffset < 0) {
2074: debug ("Can't get node offset for image unit name: '%s' (%s)\n",
2075: image_uname, fdt_strerror (noffset));
2076: }
2077:
2078: return noffset;
2079: }
2080:
2081: /**
2082: * fit_image_get_os - get os id for a given component image node
2083: * @fit: pointer to the FIT format image header
2084: * @noffset: component image node offset
2085: * @os: pointer to the uint8_t, will hold os numeric id
2086: *
2087: * fit_image_get_os() finds os property in a given component image node.
2088: * If the property is found, its (string) value is translated to the numeric
2089: * id which is returned to the caller.
2090: *
2091: * returns:
2092: * 0, on success
2093: * -1, on failure
2094: */
2095: int fit_image_get_os (const void *fit, int noffset, uint8_t *os)
2096: {
2097: int len;
2098: const void *data;
2099:
2100: /* Get OS name from property data */
2101: data = fdt_getprop (fit, noffset, FIT_OS_PROP, &len);
2102: if (data == NULL) {
2103: fit_get_debug (fit, noffset, FIT_OS_PROP, len);
2104: *os = -1;
2105: return -1;
2106: }
2107:
2108: /* Translate OS name to id */
2109: *os = genimg_get_os_id (data);
2110: return 0;
2111: }
2112:
2113: /**
2114: * fit_image_get_arch - get arch id for a given component image node
2115: * @fit: pointer to the FIT format image header
2116: * @noffset: component image node offset
2117: * @arch: pointer to the uint8_t, will hold arch numeric id
2118: *
2119: * fit_image_get_arch() finds arch property in a given component image node.
2120: * If the property is found, its (string) value is translated to the numeric
2121: * id which is returned to the caller.
2122: *
2123: * returns:
2124: * 0, on success
2125: * -1, on failure
2126: */
2127: int fit_image_get_arch (const void *fit, int noffset, uint8_t *arch)
2128: {
2129: int len;
2130: const void *data;
2131:
2132: /* Get architecture name from property data */
2133: data = fdt_getprop (fit, noffset, FIT_ARCH_PROP, &len);
2134: if (data == NULL) {
2135: fit_get_debug (fit, noffset, FIT_ARCH_PROP, len);
2136: *arch = -1;
2137: return -1;
2138: }
2139:
2140: /* Translate architecture name to id */
2141: *arch = genimg_get_arch_id (data);
2142: return 0;
2143: }
2144:
2145: /**
2146: * fit_image_get_type - get type id for a given component image node
2147: * @fit: pointer to the FIT format image header
2148: * @noffset: component image node offset
2149: * @type: pointer to the uint8_t, will hold type numeric id
2150: *
2151: * fit_image_get_type() finds type property in a given component image node.
2152: * If the property is found, its (string) value is translated to the numeric
2153: * id which is returned to the caller.
2154: *
2155: * returns:
2156: * 0, on success
2157: * -1, on failure
2158: */
2159: int fit_image_get_type (const void *fit, int noffset, uint8_t *type)
2160: {
2161: int len;
2162: const void *data;
2163:
2164: /* Get image type name from property data */
2165: data = fdt_getprop (fit, noffset, FIT_TYPE_PROP, &len);
2166: if (data == NULL) {
2167: fit_get_debug (fit, noffset, FIT_TYPE_PROP, len);
2168: *type = -1;
2169: return -1;
2170: }
2171:
2172: /* Translate image type name to id */
2173: *type = genimg_get_type_id (data);
2174: return 0;
2175: }
2176:
2177: /**
2178: * fit_image_get_comp - get comp id for a given component image node
2179: * @fit: pointer to the FIT format image header
2180: * @noffset: component image node offset
2181: * @comp: pointer to the uint8_t, will hold comp numeric id
2182: *
2183: * fit_image_get_comp() finds comp property in a given component image node.
2184: * If the property is found, its (string) value is translated to the numeric
2185: * id which is returned to the caller.
2186: *
2187: * returns:
2188: * 0, on success
2189: * -1, on failure
2190: */
2191: int fit_image_get_comp (const void *fit, int noffset, uint8_t *comp)
2192: {
2193: int len;
2194: const void *data;
2195:
2196: /* Get compression name from property data */
2197: data = fdt_getprop (fit, noffset, FIT_COMP_PROP, &len);
2198: if (data == NULL) {
2199: fit_get_debug (fit, noffset, FIT_COMP_PROP, len);
2200: *comp = -1;
2201: return -1;
2202: }
2203:
2204: /* Translate compression name to id */
2205: *comp = genimg_get_comp_id (data);
2206: return 0;
2207: }
2208:
2209: /**
2210: * fit_image_get_load - get load address property for a given component image node
2211: * @fit: pointer to the FIT format image header
2212: * @noffset: component image node offset
2213: * @load: pointer to the uint32_t, will hold load address
2214: *
2215: * fit_image_get_load() finds load address property in a given component image node.
2216: * If the property is found, its value is returned to the caller.
2217: *
2218: * returns:
2219: * 0, on success
2220: * -1, on failure
2221: */
2222: int fit_image_get_load (const void *fit, int noffset, ulong *load)
2223: {
2224: int len;
2225: const uint32_t *data;
2226:
2227: data = fdt_getprop (fit, noffset, FIT_LOAD_PROP, &len);
2228: if (data == NULL) {
2229: fit_get_debug (fit, noffset, FIT_LOAD_PROP, len);
2230: return -1;
2231: }
2232:
2233: *load = uimage_to_cpu (*data);
2234: return 0;
2235: }
2236:
2237: /**
2238: * fit_image_get_entry - get entry point address property for a given component image node
2239: * @fit: pointer to the FIT format image header
2240: * @noffset: component image node offset
2241: * @entry: pointer to the uint32_t, will hold entry point address
2242: *
2243: * fit_image_get_entry() finds entry point address property in a given component image node.
2244: * If the property is found, its value is returned to the caller.
2245: *
2246: * returns:
2247: * 0, on success
2248: * -1, on failure
2249: */
2250: int fit_image_get_entry (const void *fit, int noffset, ulong *entry)
2251: {
2252: int len;
2253: const uint32_t *data;
2254:
2255: data = fdt_getprop (fit, noffset, FIT_ENTRY_PROP, &len);
2256: if (data == NULL) {
2257: fit_get_debug (fit, noffset, FIT_ENTRY_PROP, len);
2258: return -1;
2259: }
2260:
2261: *entry = uimage_to_cpu (*data);
2262: return 0;
2263: }
2264:
2265: /**
2266: * fit_image_get_data - get data property and its size for a given component image node
2267: * @fit: pointer to the FIT format image header
2268: * @noffset: component image node offset
2269: * @data: double pointer to void, will hold data property's data address
2270: * @size: pointer to size_t, will hold data property's data size
2271: *
2272: * fit_image_get_data() finds data property in a given component image node.
2273: * If the property is found its data start address and size are returned to
2274: * the caller.
2275: *
2276: * returns:
2277: * 0, on success
2278: * -1, on failure
2279: */
2280: int fit_image_get_data (const void *fit, int noffset,
2281: const void **data, size_t *size)
2282: {
2283: int len;
2284:
2285: *data = fdt_getprop (fit, noffset, FIT_DATA_PROP, &len);
2286: if (*data == NULL) {
2287: fit_get_debug (fit, noffset, FIT_DATA_PROP, len);
2288: *size = 0;
2289: return -1;
2290: }
2291:
2292: *size = len;
2293: return 0;
2294: }
2295:
2296: /**
2297: * fit_image_hash_get_algo - get hash algorithm name
2298: * @fit: pointer to the FIT format image header
2299: * @noffset: hash node offset
2300: * @algo: double pointer to char, will hold pointer to the algorithm name
2301: *
2302: * fit_image_hash_get_algo() finds hash algorithm property in a given hash node.
2303: * If the property is found its data start address is returned to the caller.
2304: *
2305: * returns:
2306: * 0, on success
2307: * -1, on failure
2308: */
2309: int fit_image_hash_get_algo (const void *fit, int noffset, char **algo)
2310: {
2311: int len;
2312:
2313: *algo = (char *)fdt_getprop (fit, noffset, FIT_ALGO_PROP, &len);
2314: if (*algo == NULL) {
2315: fit_get_debug (fit, noffset, FIT_ALGO_PROP, len);
2316: return -1;
2317: }
2318:
2319: return 0;
2320: }
2321:
2322: /**
2323: * fit_image_hash_get_value - get hash value and length
2324: * @fit: pointer to the FIT format image header
2325: * @noffset: hash node offset
2326: * @value: double pointer to uint8_t, will hold address of a hash value data
2327: * @value_len: pointer to an int, will hold hash data length
2328: *
2329: * fit_image_hash_get_value() finds hash value property in a given hash node.
2330: * If the property is found its data start address and size are returned to
2331: * the caller.
2332: *
2333: * returns:
2334: * 0, on success
2335: * -1, on failure
2336: */
2337: int fit_image_hash_get_value (const void *fit, int noffset, uint8_t **value,
2338: int *value_len)
2339: {
2340: int len;
2341:
2342: *value = (uint8_t *)fdt_getprop (fit, noffset, FIT_VALUE_PROP, &len);
2343: if (*value == NULL) {
2344: fit_get_debug (fit, noffset, FIT_VALUE_PROP, len);
2345: *value_len = 0;
2346: return -1;
2347: }
2348:
2349: *value_len = len;
2350: return 0;
2351: }
2352:
2353: /**
2354: * fit_set_timestamp - set node timestamp property
2355: * @fit: pointer to the FIT format image header
2356: * @noffset: node offset
2357: * @timestamp: timestamp value to be set
2358: *
2359: * fit_set_timestamp() attempts to set timestamp property in the requested
2360: * node and returns operation status to the caller.
2361: *
2362: * returns:
2363: * 0, on success
2364: * -1, on property read failure
2365: */
2366: int fit_set_timestamp (void *fit, int noffset, time_t timestamp)
2367: {
2368: uint32_t t;
2369: int ret;
2370:
2371: t = cpu_to_uimage (timestamp);
2372: ret = fdt_setprop (fit, noffset, FIT_TIMESTAMP_PROP, &t,
2373: sizeof (uint32_t));
2374: if (ret) {
2375: printf ("Can't set '%s' property for '%s' node (%s)\n",
2376: FIT_TIMESTAMP_PROP, fit_get_name (fit, noffset, NULL),
2377: fdt_strerror (ret));
2378: return -1;
2379: }
2380:
2381: return 0;
2382: }
2383:
2384: /**
2385: * calculate_hash - calculate and return hash for provided input data
2386: * @data: pointer to the input data
2387: * @data_len: data length
2388: * @algo: requested hash algorithm
2389: * @value: pointer to the char, will hold hash value data (caller must
2390: * allocate enough free space)
2391: * value_len: length of the calculated hash
2392: *
2393: * calculate_hash() computes input data hash according to the requested algorithm.
2394: * Resulting hash value is placed in caller provided 'value' buffer, length
2395: * of the calculated hash is returned via value_len pointer argument.
2396: *
2397: * returns:
2398: * 0, on success
2399: * -1, when algo is unsupported
2400: */
2401: static int calculate_hash (const void *data, int data_len, const char *algo,
2402: uint8_t *value, int *value_len)
2403: {
2404: if (strcmp (algo, "crc32") == 0 ) {
2405: *((uint32_t *)value) = crc32_wd (0, data, data_len,
2406: CHUNKSZ_CRC32);
2407: *((uint32_t *)value) = cpu_to_uimage (*((uint32_t *)value));
2408: *value_len = 4;
2409: } else if (strcmp (algo, "sha1") == 0 ) {
2410: sha1_csum_wd ((unsigned char *) data, data_len,
2411: (unsigned char *) value, CHUNKSZ_SHA1);
2412: *value_len = 20;
2413: } else if (strcmp (algo, "md5") == 0 ) {
2414: md5_wd ((unsigned char *)data, data_len, value, CHUNKSZ_MD5);
2415: *value_len = 16;
2416: } else {
2417: debug ("Unsupported hash alogrithm\n");
2418: return -1;
2419: }
2420: return 0;
2421: }
2422:
2423: #ifdef USE_HOSTCC
2424: /**
2425: * fit_set_hashes - process FIT component image nodes and calculate hashes
2426: * @fit: pointer to the FIT format image header
2427: *
2428: * fit_set_hashes() adds hash values for all component images in the FIT blob.
2429: * Hashes are calculated for all component images which have hash subnodes
2430: * with algorithm property set to one of the supported hash algorithms.
2431: *
2432: * returns
2433: * 0, on success
2434: * libfdt error code, on failure
2435: */
2436: int fit_set_hashes (void *fit)
2437: {
2438: int images_noffset;
2439: int noffset;
2440: int ndepth;
2441: int ret;
2442:
2443: /* Find images parent node offset */
2444: images_noffset = fdt_path_offset (fit, FIT_IMAGES_PATH);
2445: if (images_noffset < 0) {
2446: printf ("Can't find images parent node '%s' (%s)\n",
2447: FIT_IMAGES_PATH, fdt_strerror (images_noffset));
2448: return images_noffset;
2449: }
2450:
2451: /* Process its subnodes, print out component images details */
2452: for (ndepth = 0, noffset = fdt_next_node (fit, images_noffset, &ndepth);
2453: (noffset >= 0) && (ndepth > 0);
2454: noffset = fdt_next_node (fit, noffset, &ndepth)) {
2455: if (ndepth == 1) {
2456: /*
2457: * Direct child node of the images parent node,
2458: * i.e. component image node.
2459: */
2460: ret = fit_image_set_hashes (fit, noffset);
2461: if (ret)
2462: return ret;
2463: }
2464: }
2465:
2466: return 0;
2467: }
2468:
2469: /**
2470: * fit_image_set_hashes - calculate/set hashes for given component image node
2471: * @fit: pointer to the FIT format image header
2472: * @image_noffset: requested component image node
2473: *
2474: * fit_image_set_hashes() adds hash values for an component image node. All
2475: * existing hash subnodes are checked, if algorithm property is set to one of
2476: * the supported hash algorithms, hash value is computed and corresponding
2477: * hash node property is set, for example:
2478: *
2479: * Input component image node structure:
2480: *
2481: * o image@1 (at image_noffset)
2482: * | - data = [binary data]
2483: * o hash@1
2484: * |- algo = "sha1"
2485: *
2486: * Output component image node structure:
2487: *
2488: * o image@1 (at image_noffset)
2489: * | - data = [binary data]
2490: * o hash@1
2491: * |- algo = "sha1"
2492: * |- value = sha1(data)
2493: *
2494: * returns:
2495: * 0 on sucess
2496: * <0 on failure
2497: */
2498: int fit_image_set_hashes (void *fit, int image_noffset)
2499: {
2500: const void *data;
2501: size_t size;
2502: char *algo;
2503: uint8_t value[FIT_MAX_HASH_LEN];
2504: int value_len;
2505: int noffset;
2506: int ndepth;
2507:
2508: /* Get image data and data length */
2509: if (fit_image_get_data (fit, image_noffset, &data, &size)) {
2510: printf ("Can't get image data/size\n");
2511: return -1;
2512: }
2513:
2514: /* Process all hash subnodes of the component image node */
2515: for (ndepth = 0, noffset = fdt_next_node (fit, image_noffset, &ndepth);
2516: (noffset >= 0) && (ndepth > 0);
2517: noffset = fdt_next_node (fit, noffset, &ndepth)) {
2518: if (ndepth == 1) {
2519: /* Direct child node of the component image node */
2520:
2521: /*
2522: * Check subnode name, must be equal to "hash".
2523: * Multiple hash nodes require unique unit node
2524: * names, e.g. hash@1, hash@2, etc.
2525: */
2526: if (strncmp (fit_get_name(fit, noffset, NULL),
2527: FIT_HASH_NODENAME,
2528: strlen(FIT_HASH_NODENAME)) != 0) {
2529: /* Not a hash subnode, skip it */
2530: continue;
2531: }
2532:
2533: if (fit_image_hash_get_algo (fit, noffset, &algo)) {
2534: printf ("Can't get hash algo property for "
2535: "'%s' hash node in '%s' image node\n",
2536: fit_get_name (fit, noffset, NULL),
2537: fit_get_name (fit, image_noffset, NULL));
2538: return -1;
2539: }
2540:
2541: if (calculate_hash (data, size, algo, value, &value_len)) {
2542: printf ("Unsupported hash algorithm (%s) for "
2543: "'%s' hash node in '%s' image node\n",
2544: algo, fit_get_name (fit, noffset, NULL),
2545: fit_get_name (fit, image_noffset, NULL));
2546: return -1;
2547: }
2548:
2549: if (fit_image_hash_set_value (fit, noffset, value,
2550: value_len)) {
2551: printf ("Can't set hash value for "
2552: "'%s' hash node in '%s' image node\n",
2553: fit_get_name (fit, noffset, NULL),
2554: fit_get_name (fit, image_noffset, NULL));
2555: return -1;
2556: }
2557: }
2558: }
2559:
2560: return 0;
2561: }
2562:
2563: /**
2564: * fit_image_hash_set_value - set hash value in requested has node
2565: * @fit: pointer to the FIT format image header
2566: * @noffset: hash node offset
2567: * @value: hash value to be set
2568: * @value_len: hash value length
2569: *
2570: * fit_image_hash_set_value() attempts to set hash value in a node at offset
2571: * given and returns operation status to the caller.
2572: *
2573: * returns
2574: * 0, on success
2575: * -1, on failure
2576: */
2577: int fit_image_hash_set_value (void *fit, int noffset, uint8_t *value,
2578: int value_len)
2579: {
2580: int ret;
2581:
2582: ret = fdt_setprop (fit, noffset, FIT_VALUE_PROP, value, value_len);
2583: if (ret) {
2584: printf ("Can't set hash '%s' property for '%s' node (%s)\n",
2585: FIT_VALUE_PROP, fit_get_name (fit, noffset, NULL),
2586: fdt_strerror (ret));
2587: return -1;
2588: }
2589:
2590: return 0;
2591: }
2592: #endif /* USE_HOSTCC */
2593:
2594: /**
2595: * fit_image_check_hashes - verify data intergity
2596: * @fit: pointer to the FIT format image header
2597: * @image_noffset: component image node offset
2598: *
2599: * fit_image_check_hashes() goes over component image hash nodes,
2600: * re-calculates each data hash and compares with the value stored in hash
2601: * node.
2602: *
2603: * returns:
2604: * 1, if all hashes are valid
2605: * 0, otherwise (or on error)
2606: */
2607: int fit_image_check_hashes (const void *fit, int image_noffset)
2608: {
2609: const void *data;
2610: size_t size;
2611: char *algo;
2612: uint8_t *fit_value;
2613: int fit_value_len;
2614: uint8_t value[FIT_MAX_HASH_LEN];
2615: int value_len;
2616: int noffset;
2617: int ndepth;
2618: char *err_msg = "";
2619:
2620: /* Get image data and data length */
2621: if (fit_image_get_data (fit, image_noffset, &data, &size)) {
2622: printf ("Can't get image data/size\n");
2623: return 0;
2624: }
2625:
2626: /* Process all hash subnodes of the component image node */
2627: for (ndepth = 0, noffset = fdt_next_node (fit, image_noffset, &ndepth);
2628: (noffset >= 0) && (ndepth > 0);
2629: noffset = fdt_next_node (fit, noffset, &ndepth)) {
2630: if (ndepth == 1) {
2631: /* Direct child node of the component image node */
2632:
2633: /*
2634: * Check subnode name, must be equal to "hash".
2635: * Multiple hash nodes require unique unit node
2636: * names, e.g. hash@1, hash@2, etc.
2637: */
2638: if (strncmp (fit_get_name(fit, noffset, NULL),
2639: FIT_HASH_NODENAME,
2640: strlen(FIT_HASH_NODENAME)) != 0)
2641: continue;
2642:
2643: if (fit_image_hash_get_algo (fit, noffset, &algo)) {
2644: err_msg = " error!\nCan't get hash algo "
2645: "property";
2646: goto error;
2647: }
2648: printf ("%s", algo);
2649:
2650: if (fit_image_hash_get_value (fit, noffset, &fit_value,
2651: &fit_value_len)) {
2652: err_msg = " error!\nCan't get hash value "
2653: "property";
2654: goto error;
2655: }
2656:
2657: if (calculate_hash (data, size, algo, value, &value_len)) {
2658: err_msg = " error!\nUnsupported hash algorithm";
2659: goto error;
2660: }
2661:
2662: if (value_len != fit_value_len) {
2663: err_msg = " error !\nBad hash value len";
2664: goto error;
2665: } else if (memcmp (value, fit_value, value_len) != 0) {
2666: err_msg = " error!\nBad hash value";
2667: goto error;
2668: }
2669: printf ("+ ");
2670: }
2671: }
2672:
2673: return 1;
2674:
2675: error:
2676: printf ("%s for '%s' hash node in '%s' image node\n",
2677: err_msg, fit_get_name (fit, noffset, NULL),
2678: fit_get_name (fit, image_noffset, NULL));
2679: return 0;
2680: }
2681:
2682: /**
2683: * fit_all_image_check_hashes - verify data intergity for all images
2684: * @fit: pointer to the FIT format image header
2685: *
2686: * fit_all_image_check_hashes() goes over all images in the FIT and
2687: * for every images checks if all it's hashes are valid.
2688: *
2689: * returns:
2690: * 1, if all hashes of all images are valid
2691: * 0, otherwise (or on error)
2692: */
2693: int fit_all_image_check_hashes (const void *fit)
2694: {
2695: int images_noffset;
2696: int noffset;
2697: int ndepth;
2698: int count;
2699:
2700: /* Find images parent node offset */
2701: images_noffset = fdt_path_offset (fit, FIT_IMAGES_PATH);
2702: if (images_noffset < 0) {
2703: printf ("Can't find images parent node '%s' (%s)\n",
2704: FIT_IMAGES_PATH, fdt_strerror (images_noffset));
2705: return 0;
2706: }
2707:
2708: /* Process all image subnodes, check hashes for each */
2709: printf ("## Checking hash(es) for FIT Image at %08lx ...\n",
2710: (ulong)fit);
2711: for (ndepth = 0, count = 0,
2712: noffset = fdt_next_node (fit, images_noffset, &ndepth);
2713: (noffset >= 0) && (ndepth > 0);
2714: noffset = fdt_next_node (fit, noffset, &ndepth)) {
2715: if (ndepth == 1) {
2716: /*
2717: * Direct child node of the images parent node,
2718: * i.e. component image node.
2719: */
2720: printf (" Hash(es) for Image %u (%s): ", count++,
2721: fit_get_name (fit, noffset, NULL));
2722:
2723: if (!fit_image_check_hashes (fit, noffset))
2724: return 0;
2725: printf ("\n");
2726: }
2727: }
2728: return 1;
2729: }
2730:
2731: /**
2732: * fit_image_check_os - check whether image node is of a given os type
2733: * @fit: pointer to the FIT format image header
2734: * @noffset: component image node offset
2735: * @os: requested image os
2736: *
2737: * fit_image_check_os() reads image os property and compares its numeric
2738: * id with the requested os. Comparison result is returned to the caller.
2739: *
2740: * returns:
2741: * 1 if image is of given os type
2742: * 0 otherwise (or on error)
2743: */
2744: int fit_image_check_os (const void *fit, int noffset, uint8_t os)
2745: {
2746: uint8_t image_os;
2747:
2748: if (fit_image_get_os (fit, noffset, &image_os))
2749: return 0;
2750: return (os == image_os);
2751: }
2752:
2753: /**
2754: * fit_image_check_arch - check whether image node is of a given arch
2755: * @fit: pointer to the FIT format image header
2756: * @noffset: component image node offset
2757: * @arch: requested imagearch
2758: *
2759: * fit_image_check_arch() reads image arch property and compares its numeric
2760: * id with the requested arch. Comparison result is returned to the caller.
2761: *
2762: * returns:
2763: * 1 if image is of given arch
2764: * 0 otherwise (or on error)
2765: */
2766: int fit_image_check_arch (const void *fit, int noffset, uint8_t arch)
2767: {
2768: uint8_t image_arch;
2769:
2770: if (fit_image_get_arch (fit, noffset, &image_arch))
2771: return 0;
2772: return (arch == image_arch);
2773: }
2774:
2775: /**
2776: * fit_image_check_type - check whether image node is of a given type
2777: * @fit: pointer to the FIT format image header
2778: * @noffset: component image node offset
2779: * @type: requested image type
2780: *
2781: * fit_image_check_type() reads image type property and compares its numeric
2782: * id with the requested type. Comparison result is returned to the caller.
2783: *
2784: * returns:
2785: * 1 if image is of given type
2786: * 0 otherwise (or on error)
2787: */
2788: int fit_image_check_type (const void *fit, int noffset, uint8_t type)
2789: {
2790: uint8_t image_type;
2791:
2792: if (fit_image_get_type (fit, noffset, &image_type))
2793: return 0;
2794: return (type == image_type);
2795: }
2796:
2797: /**
2798: * fit_image_check_comp - check whether image node uses given compression
2799: * @fit: pointer to the FIT format image header
2800: * @noffset: component image node offset
2801: * @comp: requested image compression type
2802: *
2803: * fit_image_check_comp() reads image compression property and compares its
2804: * numeric id with the requested compression type. Comparison result is
2805: * returned to the caller.
2806: *
2807: * returns:
2808: * 1 if image uses requested compression
2809: * 0 otherwise (or on error)
2810: */
2811: int fit_image_check_comp (const void *fit, int noffset, uint8_t comp)
2812: {
2813: uint8_t image_comp;
2814:
2815: if (fit_image_get_comp (fit, noffset, &image_comp))
2816: return 0;
2817: return (comp == image_comp);
2818: }
2819:
2820: /**
2821: * fit_check_format - sanity check FIT image format
2822: * @fit: pointer to the FIT format image header
2823: *
2824: * fit_check_format() runs a basic sanity FIT image verification.
2825: * Routine checks for mandatory properties, nodes, etc.
2826: *
2827: * returns:
2828: * 1, on success
2829: * 0, on failure
2830: */
2831: int fit_check_format (const void *fit)
2832: {
2833: /* mandatory / node 'description' property */
2834: if (fdt_getprop (fit, 0, FIT_DESC_PROP, NULL) == NULL) {
2835: debug ("Wrong FIT format: no description\n");
2836: return 0;
2837: }
2838:
2839: #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
2840: /* mandatory / node 'timestamp' property */
2841: if (fdt_getprop (fit, 0, FIT_TIMESTAMP_PROP, NULL) == NULL) {
2842: debug ("Wrong FIT format: no timestamp\n");
2843: return 0;
2844: }
2845: #endif
2846:
2847: /* mandatory subimages parent '/images' node */
2848: if (fdt_path_offset (fit, FIT_IMAGES_PATH) < 0) {
2849: debug ("Wrong FIT format: no images parent node\n");
2850: return 0;
2851: }
2852:
2853: return 1;
2854: }
2855:
2856: /**
2857: * fit_conf_get_node - get node offset for configuration of a given unit name
2858: * @fit: pointer to the FIT format image header
2859: * @conf_uname: configuration node unit name
2860: *
2861: * fit_conf_get_node() finds a configuration (withing the '/configurations'
2862: * parant node) of a provided unit name. If configuration is found its node offset
2863: * is returned to the caller.
2864: *
2865: * When NULL is provided in second argument fit_conf_get_node() will search
2866: * for a default configuration node instead. Default configuration node unit name
2867: * is retrived from FIT_DEFAULT_PROP property of the '/configurations' node.
2868: *
2869: * returns:
2870: * configuration node offset when found (>=0)
2871: * negative number on failure (FDT_ERR_* code)
2872: */
2873: int fit_conf_get_node (const void *fit, const char *conf_uname)
2874: {
2875: int noffset, confs_noffset;
2876: int len;
2877:
2878: confs_noffset = fdt_path_offset (fit, FIT_CONFS_PATH);
2879: if (confs_noffset < 0) {
2880: debug ("Can't find configurations parent node '%s' (%s)\n",
2881: FIT_CONFS_PATH, fdt_strerror (confs_noffset));
2882: return confs_noffset;
2883: }
2884:
2885: if (conf_uname == NULL) {
2886: /* get configuration unit name from the default property */
2887: debug ("No configuration specified, trying default...\n");
2888: conf_uname = (char *)fdt_getprop (fit, confs_noffset, FIT_DEFAULT_PROP, &len);
2889: if (conf_uname == NULL) {
2890: fit_get_debug (fit, confs_noffset, FIT_DEFAULT_PROP, len);
2891: return len;
2892: }
2893: debug ("Found default configuration: '%s'\n", conf_uname);
2894: }
2895:
2896: noffset = fdt_subnode_offset (fit, confs_noffset, conf_uname);
2897: if (noffset < 0) {
2898: debug ("Can't get node offset for configuration unit name: '%s' (%s)\n",
2899: conf_uname, fdt_strerror (noffset));
2900: }
2901:
2902: return noffset;
2903: }
2904:
2905: static int __fit_conf_get_prop_node (const void *fit, int noffset,
2906: const char *prop_name)
2907: {
2908: char *uname;
2909: int len;
2910:
2911: /* get kernel image unit name from configuration kernel property */
2912: uname = (char *)fdt_getprop (fit, noffset, prop_name, &len);
2913: if (uname == NULL)
2914: return len;
2915:
2916: return fit_image_get_node (fit, uname);
2917: }
2918:
2919: /**
2920: * fit_conf_get_kernel_node - get kernel image node offset that corresponds to
2921: * a given configuration
2922: * @fit: pointer to the FIT format image header
2923: * @noffset: configuration node offset
2924: *
2925: * fit_conf_get_kernel_node() retrives kernel image node unit name from
2926: * configuration FIT_KERNEL_PROP property and translates it to the node
2927: * offset.
2928: *
2929: * returns:
2930: * image node offset when found (>=0)
2931: * negative number on failure (FDT_ERR_* code)
2932: */
2933: int fit_conf_get_kernel_node (const void *fit, int noffset)
2934: {
2935: return __fit_conf_get_prop_node (fit, noffset, FIT_KERNEL_PROP);
2936: }
2937:
2938: /**
2939: * fit_conf_get_ramdisk_node - get ramdisk image node offset that corresponds to
2940: * a given configuration
2941: * @fit: pointer to the FIT format image header
2942: * @noffset: configuration node offset
2943: *
2944: * fit_conf_get_ramdisk_node() retrives ramdisk image node unit name from
2945: * configuration FIT_KERNEL_PROP property and translates it to the node
2946: * offset.
2947: *
2948: * returns:
2949: * image node offset when found (>=0)
2950: * negative number on failure (FDT_ERR_* code)
2951: */
2952: int fit_conf_get_ramdisk_node (const void *fit, int noffset)
2953: {
2954: return __fit_conf_get_prop_node (fit, noffset, FIT_RAMDISK_PROP);
2955: }
2956:
2957: /**
2958: * fit_conf_get_fdt_node - get fdt image node offset that corresponds to
2959: * a given configuration
2960: * @fit: pointer to the FIT format image header
2961: * @noffset: configuration node offset
2962: *
2963: * fit_conf_get_fdt_node() retrives fdt image node unit name from
2964: * configuration FIT_KERNEL_PROP property and translates it to the node
2965: * offset.
2966: *
2967: * returns:
2968: * image node offset when found (>=0)
2969: * negative number on failure (FDT_ERR_* code)
2970: */
2971: int fit_conf_get_fdt_node (const void *fit, int noffset)
2972: {
2973: return __fit_conf_get_prop_node (fit, noffset, FIT_FDT_PROP);
2974: }
2975:
2976: /**
2977: * fit_conf_print - prints out the FIT configuration details
2978: * @fit: pointer to the FIT format image header
2979: * @noffset: offset of the configuration node
2980: * @p: pointer to prefix string
2981: *
2982: * fit_conf_print() lists all mandatory properies for the processed
2983: * configuration node.
2984: *
2985: * returns:
2986: * no returned results
2987: */
2988: void fit_conf_print (const void *fit, int noffset, const char *p)
2989: {
2990: char *desc;
2991: char *uname;
2992: int ret;
2993:
2994: /* Mandatory properties */
2995: ret = fit_get_desc (fit, noffset, &desc);
2996: printf ("%s Description: ", p);
2997: if (ret)
2998: printf ("unavailable\n");
2999: else
3000: printf ("%s\n", desc);
3001:
3002: uname = (char *)fdt_getprop (fit, noffset, FIT_KERNEL_PROP, NULL);
3003: printf ("%s Kernel: ", p);
3004: if (uname == NULL)
3005: printf ("unavailable\n");
3006: else
3007: printf ("%s\n", uname);
3008:
3009: /* Optional properties */
3010: uname = (char *)fdt_getprop (fit, noffset, FIT_RAMDISK_PROP, NULL);
3011: if (uname)
3012: printf ("%s Init Ramdisk: %s\n", p, uname);
3013:
3014: uname = (char *)fdt_getprop (fit, noffset, FIT_FDT_PROP, NULL);
3015: if (uname)
3016: printf ("%s FDT: %s\n", p, uname);
3017: }
3018:
3019: /**
3020: * fit_check_ramdisk - verify FIT format ramdisk subimage
3021: * @fit_hdr: pointer to the FIT ramdisk header
3022: * @rd_noffset: ramdisk subimage node offset within FIT image
3023: * @arch: requested ramdisk image architecture type
3024: * @verify: data CRC verification flag
3025: *
3026: * fit_check_ramdisk() verifies integrity of the ramdisk subimage and from
3027: * specified FIT image.
3028: *
3029: * returns:
3030: * 1, on success
3031: * 0, on failure
3032: */
3033: #ifndef USE_HOSTCC
3034: static int fit_check_ramdisk (const void *fit, int rd_noffset, uint8_t arch, int verify)
3035: {
3036: fit_image_print (fit, rd_noffset, " ");
3037:
3038: if (verify) {
3039: puts (" Verifying Hash Integrity ... ");
3040: if (!fit_image_check_hashes (fit, rd_noffset)) {
3041: puts ("Bad Data Hash\n");
3042: show_boot_progress (-125);
3043: return 0;
3044: }
3045: puts ("OK\n");
3046: }
3047:
3048: show_boot_progress (126);
3049: if (!fit_image_check_os (fit, rd_noffset, IH_OS_LINUX) ||
3050: !fit_image_check_arch (fit, rd_noffset, arch) ||
3051: !fit_image_check_type (fit, rd_noffset, IH_TYPE_RAMDISK)) {
3052: printf ("No Linux %s Ramdisk Image\n",
3053: genimg_get_arch_name(arch));
3054: show_boot_progress (-126);
3055: return 0;
3056: }
3057:
3058: show_boot_progress (127);
3059: return 1;
3060: }
3061: #endif /* USE_HOSTCC */
3062: #endif /* CONFIG_FIT */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>