diff options
82 files changed, 8248 insertions, 3225 deletions
@@ -2890,7 +2890,9 @@ clobber: clean @rm -f $(OBJS) $(obj)*.bak $(obj)ctags $(obj)etags $(obj)TAGS \ $(obj)cscope.* $(obj)*.*~ @rm -f $(obj)u-boot $(obj)u-boot.map $(obj)u-boot.hex $(ALL) - @rm -f $(obj)tools/{crc32.c,environment.c,env/crc32.c,sha1.c,inca-swap-bytes} + @rm -f $(obj)tools/{crc32.c,environment.c,env/crc32.c,md5.c,sha1.c,inca-swap-bytes} + @rm -f $(obj)tools/{image.c,fdt.c,fdt_ro.c,fdt_rw.c,fdt_strerror.c} + @rm -f $(obj)tools/{fdt_wip.c,libfdt_internal.h} @rm -f $(obj)cpu/mpc824x/bedbug_603e.c @rm -f $(obj)include/asm/proc $(obj)include/asm/arch $(obj)include/asm @[ ! -d $(obj)nand_spl ] || find $(obj)nand_spl -lname "*" -print | xargs rm -f @@ -1678,6 +1678,8 @@ The following options need to be configured: example, some LED's) on your board. At the moment, the following checkpoints are implemented: +Legacy uImage format: + Arg Where When 1 common/cmd_bootm.c before attempting to boot an image -1 common/cmd_bootm.c Image header has bad magic number @@ -1688,25 +1690,26 @@ The following options need to be configured: 4 common/cmd_bootm.c Image data has correct checksum -4 common/cmd_bootm.c Image is for unsupported architecture 5 common/cmd_bootm.c Architecture check OK - -5 common/cmd_bootm.c Wrong Image Type (not kernel, multi, standalone) + -5 common/cmd_bootm.c Wrong Image Type (not kernel, multi) 6 common/cmd_bootm.c Image Type check OK -6 common/cmd_bootm.c gunzip uncompression error -7 common/cmd_bootm.c Unimplemented compression type 7 common/cmd_bootm.c Uncompression OK - -8 common/cmd_bootm.c Wrong Image Type (not kernel, multi, standalone) - 8 common/cmd_bootm.c Image Type check OK + 8 common/cmd_bootm.c No uncompress/copy overwrite error -9 common/cmd_bootm.c Unsupported OS (not Linux, BSD, VxWorks, QNX) - 9 common/cmd_bootm.c Start initial ramdisk verification - -10 common/cmd_bootm.c Ramdisk header has bad magic number - -11 common/cmd_bootm.c Ramdisk header has bad checksum - 10 common/cmd_bootm.c Ramdisk header is OK - -12 common/cmd_bootm.c Ramdisk data has bad checksum - 11 common/cmd_bootm.c Ramdisk data has correct checksum - 12 common/cmd_bootm.c Ramdisk verification complete, start loading - -13 common/cmd_bootm.c Wrong Image Type (not PPC Linux Ramdisk) - 13 common/cmd_bootm.c Start multifile image verification - 14 common/cmd_bootm.c No initial ramdisk, no multifile, continue. - 15 common/cmd_bootm.c All preparation done, transferring control to OS + + 9 common/image.c Start initial ramdisk verification + -10 common/image.c Ramdisk header has bad magic number + -11 common/image.c Ramdisk header has bad checksum + 10 common/image.c Ramdisk header is OK + -12 common/image.c Ramdisk data has bad checksum + 11 common/image.c Ramdisk data has correct checksum + 12 common/image.c Ramdisk verification complete, start loading + -13 common/image.c Wrong Image Type (not PPC Linux Ramdisk) + 13 common/image.c Start multifile image verification + 14 common/image.c No initial ramdisk, no multifile, continue. + + 15 lib_<arch>/bootm.c All preparation done, transferring control to OS -30 lib_ppc/board.c Fatal error, hang the system -31 post/post.c POST test failed, detected by post_output_backlog() @@ -1776,6 +1779,59 @@ The following options need to be configured: -83 common/cmd_net.c some error in automatic boot or autoscript 84 common/cmd_net.c end without errors +FIT uImage format: + + Arg Where When + 100 common/cmd_bootm.c Kernel FIT Image has correct format + -100 common/cmd_bootm.c Kernel FIT Image has incorrect format + 101 common/cmd_bootm.c No Kernel subimage unit name, using configuration + -101 common/cmd_bootm.c Can't get configuration for kernel subimage + 102 common/cmd_bootm.c Kernel unit name specified + -103 common/cmd_bootm.c Can't get kernel subimage node offset + 103 common/cmd_bootm.c Found configuration node + 104 common/cmd_bootm.c Got kernel subimage node offset + -104 common/cmd_bootm.c Kernel subimage hash verification failed + 105 common/cmd_bootm.c Kernel subimage hash verification OK + -105 common/cmd_bootm.c Kernel subimage is for unsupported architecture + 106 common/cmd_bootm.c Architecture check OK + -106 common/cmd_bootm.c Kernel subimage has wrong typea + 107 common/cmd_bootm.c Kernel subimge type OK + -107 common/cmd_bootm.c Can't get kernel subimage data/size + 108 common/cmd_bootm.c Got kernel subimage data/size + -108 common/cmd_bootm.c Wrong image type (not legacy, FIT) + -109 common/cmd_bootm.c Can't get kernel subimage type + -110 common/cmd_bootm.c Can't get kernel subimage comp + -111 common/cmd_bootm.c Can't get kernel subimage os + -112 common/cmd_bootm.c Can't get kernel subimage load address + -113 common/cmd_bootm.c Image uncompress/copy overwrite error + + 120 common/image.c Start initial ramdisk verification + -120 common/image.c Ramdisk FIT image has incorrect format + 121 common/image.c Ramdisk FIT image has correct format + 122 common/image.c No Ramdisk subimage unit name, using configuration + -122 common/image.c Can't get configuration for ramdisk subimage + 123 common/image.c Ramdisk unit name specified + -124 common/image.c Can't get ramdisk subimage node offset + 125 common/image.c Got ramdisk subimage node offset + -125 common/image.c Ramdisk subimage hash verification failed + 126 common/image.c Ramdisk subimage hash verification OK + -126 common/image.c Ramdisk subimage for unsupported architecture + 127 common/image.c Architecture check OK + -127 common/image.c Can't get ramdisk subimage data/size + 128 common/image.c Got ramdisk subimage data/size + 129 common/image.c Can't get ramdisk load address + -129 common/image.c Got ramdisk load address + + -130 common/cmd_doc.c Icorrect FIT image format + 131 common/cmd_doc.c FIT image format OK + + -140 common/cmd_ide.c Icorrect FIT image format + 141 common/cmd_ide.c FIT image format OK + + -150 common/cmd_nand.c Icorrect FIT image format + 151 common/cmd_nand.c FIT image format OK + + Modem Support: -------------- @@ -2656,6 +2712,14 @@ Some configuration options can be set using Environment Variables: configuration from the BOOTP server, but not try to load any image using TFTP + autoscript - if set to "yes" commands like "loadb", "loady", + "bootp", "tftpb", "rarpboot" and "nfs" will attempt + to automatically run script images (by internally + calling "autoscript"). + + autoscript_uname - if script image is in a format (FIT) this + variable is used to get script subimage unit name. + autostart - if set to "yes", an image loaded using the "bootp", "rarpboot", "tftpboot" or "diskboot" commands will be automatically started (by internally calling @@ -2870,10 +2934,24 @@ o If neither SROM nor the environment contain a MAC address, an error Image Formats: ============== -The "boot" commands of this monitor operate on "image" files which -can be basicly anything, preceeded by a special header; see the -definitions in include/image.h for details; basicly, the header -defines the following image properties: +U-Boot is capable of booting (and performing other auxiliary operations on) +images in two formats: + +New uImage format (FIT) +----------------------- + +Flexible and powerful format based on Flattened Image Tree -- FIT (similar +to Flattened Device Tree). It allows the use of images with multiple +components (several kernels, ramdisks, etc.), with contents protected by +SHA1, MD5 or CRC32. More details are found in the doc/uImage.FIT directory. + + +Old uImage format +----------------- + +Old image format is based on binary files which can be basically anything, +preceded by a special header; see the definitions in include/image.h for +details; basically, the header defines the following image properties: * Target Operating System (Provisions for OpenBSD, NetBSD, FreeBSD, 4.4BSD, Linux, SVR4, Esix, Solaris, Irix, SCO, Dell, NCR, VxWorks, diff --git a/board/cray/L1/L1.c b/board/cray/L1/L1.c index 5264bafd4b..a72ba4620b 100644 --- a/board/cray/L1/L1.c +++ b/board/cray/L1/L1.c @@ -139,8 +139,15 @@ int misc_init_r (void) struct rtc_time tm; char bootcmd[32]; - hdr = (image_header_t *) (CFG_MONITOR_BASE - sizeof (image_header_t)); - timestamp = (time_t) hdr->ih_time; + hdr = (image_header_t *) (CFG_MONITOR_BASE - image_get_header_size ()); +#if defined(CONFIG_FIT) + if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { + puts ("Non legacy image format not supported\n"); + return -1; + } +#endif + + timestamp = (time_t)image_get_time (hdr); to_tm (timestamp, &tm); printf ("Welcome to U-Boot on Cray L1. Compiled %4d-%02d-%02d %2d:%02d:%02d (UTC)\n", tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); diff --git a/board/esd/common/auto_update.c b/board/esd/common/auto_update.c index a76b00fe49..1bf81c699c 100644 --- a/board/esd/common/auto_update.c +++ b/board/esd/common/auto_update.c @@ -89,24 +89,28 @@ extern block_dev_desc_t ide_dev_desc[CFG_IDE_MAXDEVICE]; int au_check_cksum_valid(int i, long nbytes) { image_header_t *hdr; - unsigned long checksum; hdr = (image_header_t *)LOAD_ADDR; +#if defined(CONFIG_FIT) + if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { + puts ("Non legacy image format not supported\n"); + return -1; + } +#endif - if ((au_image[i].type == AU_FIRMWARE) && (au_image[i].size != ntohl(hdr->ih_size))) { + if ((au_image[i].type == AU_FIRMWARE) && + (au_image[i].size != image_get_data_size (hdr))) { printf ("Image %s has wrong size\n", au_image[i].name); return -1; } - if (nbytes != (sizeof(*hdr) + ntohl(hdr->ih_size))) { + if (nbytes != (image_get_image_size (hdr))) { printf ("Image %s bad total SIZE\n", au_image[i].name); return -1; } - /* check the data CRC */ - checksum = ntohl(hdr->ih_dcrc); - if (crc32 (0, (uchar *)(LOAD_ADDR + sizeof(*hdr)), ntohl(hdr->ih_size)) - != checksum) { + /* check the data CRC */ + if (!image_check_dcrc (hdr)) { printf ("Image %s bad data checksum\n", au_image[i].name); return -1; } @@ -120,51 +124,53 @@ int au_check_header_valid(int i, long nbytes) unsigned long checksum; hdr = (image_header_t *)LOAD_ADDR; +#if defined(CONFIG_FIT) + if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { + puts ("Non legacy image format not supported\n"); + return -1; + } +#endif + /* check the easy ones first */ #undef CHECK_VALID_DEBUG #ifdef CHECK_VALID_DEBUG - printf("magic %#x %#x ", ntohl(hdr->ih_magic), IH_MAGIC); - printf("arch %#x %#x ", hdr->ih_arch, IH_CPU_PPC); - printf("size %#x %#lx ", ntohl(hdr->ih_size), nbytes); - printf("type %#x %#x ", hdr->ih_type, IH_TYPE_KERNEL); + printf("magic %#x %#x ", image_get_magic (hdr), IH_MAGIC); + printf("arch %#x %#x ", image_get_arch (hdr), IH_ARCH_PPC); + printf("size %#x %#lx ", image_get_data_size (hdr), nbytes); + printf("type %#x %#x ", image_get_type (hdr), IH_TYPE_KERNEL); #endif - if (nbytes < sizeof(*hdr)) + if (nbytes < image_get_header_size ()) { printf ("Image %s bad header SIZE\n", au_image[i].name); return -1; } - if (ntohl(hdr->ih_magic) != IH_MAGIC || hdr->ih_arch != IH_CPU_PPC) + if (!image_check_magic (hdr) || !image_check_arch (hdr, IH_ARCH_PPC)) { printf ("Image %s bad MAGIC or ARCH\n", au_image[i].name); return -1; } - /* check the hdr CRC */ - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (uchar *)hdr, sizeof(*hdr)) != checksum) { + if (!image_check_hcrc (hdr)) { printf ("Image %s bad header checksum\n", au_image[i].name); return -1; } - hdr->ih_hcrc = htonl(checksum); /* check the type - could do this all in one gigantic if() */ - if ((au_image[i].type == AU_FIRMWARE) && (hdr->ih_type != IH_TYPE_FIRMWARE)) { + if ((au_image[i].type == AU_FIRMWARE) && !image_check_type (hdr, IH_TYPE_FIRMWARE)) { printf ("Image %s wrong type\n", au_image[i].name); return -1; } - if ((au_image[i].type == AU_SCRIPT) && (hdr->ih_type != IH_TYPE_SCRIPT)) { + if ((au_image[i].type == AU_SCRIPT) && !image_check_type (hdr, IH_TYPE_SCRIPT)) { printf ("Image %s wrong type\n", au_image[i].name); return -1; } /* recycle checksum */ - checksum = ntohl(hdr->ih_size); + checksum = image_get_data_size (hdr); #if 0 /* test-only */ /* for kernel and app the image header must also fit into flash */ if (idx != IDX_DISK) - checksum += sizeof(*hdr); + checksum += image_get_header_size (); /* check the size does not exceed space in flash. HUSH scripts */ /* all have ausize[] set to 0 */ if ((ausize[idx] != 0) && (ausize[idx] < checksum)) { @@ -190,17 +196,23 @@ int au_do_update(int i, long sz) #endif hdr = (image_header_t *)LOAD_ADDR; +#if defined(CONFIG_FIT) + if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { + puts ("Non legacy image format not supported\n"); + return -1; + } +#endif switch (au_image[i].type) { case AU_SCRIPT: printf("Executing script %s\n", au_image[i].name); /* execute a script */ - if (hdr->ih_type == IH_TYPE_SCRIPT) { - addr = (char *)((char *)hdr + sizeof(*hdr)); + if (image_check_type (hdr, IH_TYPE_SCRIPT)) { + addr = (char *)((char *)hdr + image_get_header_size ()); /* stick a NULL at the end of the script, otherwise */ /* parse_string_outer() runs off the end. */ - addr[ntohl(hdr->ih_size)] = 0; + addr[image_get_data_size (hdr)] = 0; addr += 8; /* @@ -231,8 +243,8 @@ int au_do_update(int i, long sz) */ if (au_image[i].type == AU_FIRMWARE) { char *orig = (char*)start; - char *new = (char *)((char *)hdr + sizeof(*hdr)); - nbytes = ntohl(hdr->ih_size); + char *new = (char *)((char *)hdr + image_get_header_size ()); + nbytes = image_get_data_size (hdr); while(--nbytes) { if (*orig++ != *new++) { @@ -272,12 +284,12 @@ int au_do_update(int i, long sz) /* strip the header - except for the kernel and ramdisk */ if (au_image[i].type != AU_FIRMWARE) { addr = (char *)hdr; - off = sizeof(*hdr); - nbytes = sizeof(*hdr) + ntohl(hdr->ih_size); + off = image_get_header_size (); + nbytes = image_get_image_size (hdr); } else { - addr = (char *)((char *)hdr + sizeof(*hdr)); + addr = (char *)((char *)hdr + image_get_header_size ()); off = 0; - nbytes = ntohl(hdr->ih_size); + nbytes = image_get_data_size (hdr); } /* @@ -305,15 +317,15 @@ int au_do_update(int i, long sz) * check the dcrc of the copy */ if (au_image[i].type != AU_NAND) { - rc = crc32 (0, (uchar *)(start + off), ntohl(hdr->ih_size)); + rc = crc32 (0, (uchar *)(start + off), image_get_data_size (hdr)); } else { #if defined(CONFIG_CMD_NAND) && defined(CFG_NAND_LEGACY) rc = nand_legacy_rw(nand_dev_desc, NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP, start, nbytes, (size_t *)&total, (uchar *)addr); - rc = crc32 (0, (uchar *)(addr + off), ntohl(hdr->ih_size)); + rc = crc32 (0, (uchar *)(addr + off), image_get_data_size (hdr)); #endif } - if (rc != ntohl(hdr->ih_dcrc)) { + if (rc != image_get_dcrc (hdr)) { printf ("Image %s Bad Data Checksum After COPY\n", au_image[i].name); return -1; } @@ -497,10 +509,10 @@ int do_auto_update(void) printf("Reading %s ...", au_image[i].name); /* just read the header */ - sz = do_fat_read(au_image[i].name, LOAD_ADDR, sizeof(image_header_t), LS_NO); + sz = do_fat_read(au_image[i].name, LOAD_ADDR, image_get_header_size (), LS_NO); debug ("read %s sz %ld hdr %d\n", - au_image[i].name, sz, sizeof(image_header_t)); - if (sz <= 0 || sz < sizeof(image_header_t)) { + au_image[i].name, sz, image_get_header_size ()); + if (sz <= 0 || sz < image_get_header_size ()) { puts(" not found\n"); continue; } @@ -510,8 +522,8 @@ int do_auto_update(void) } sz = do_fat_read(au_image[i].name, LOAD_ADDR, MAX_LOADSZ, LS_NO); debug ("read %s sz %ld hdr %d\n", - au_image[i].name, sz, sizeof(image_header_t)); - if (sz <= 0 || sz <= sizeof(image_header_t)) { + au_image[i].name, sz, image_get_header_size ()); + if (sz <= 0 || sz <= image_get_header_size ()) { puts(" not found\n"); continue; } diff --git a/board/mcc200/auto_update.c b/board/mcc200/auto_update.c index 28e4c877b5..5580c11887 100644 --- a/board/mcc200/auto_update.c +++ b/board/mcc200/auto_update.c @@ -141,18 +141,21 @@ extern void lcd_enable(void); int au_check_cksum_valid(int idx, long nbytes) { image_header_t *hdr; - unsigned long checksum; hdr = (image_header_t *)LOAD_ADDR; +#if defined(CONFIG_FIT) + if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { + puts ("Non legacy image format not supported\n"); + return -1; + } +#endif - if (nbytes != (sizeof(*hdr) + ntohl(hdr->ih_size))) { + if (nbytes != image_get_image_size (hdr)) { printf ("Image %s bad total SIZE\n", aufile[idx]); return -1; } /* check the data CRC */ - checksum = ntohl(hdr->ih_dcrc); - - if (crc32 (0, (uchar *)(LOAD_ADDR + sizeof(*hdr)), ntohl(hdr->ih_size)) != checksum) { + if (!image_check_dcrc (hdr)) { printf ("Image %s bad data checksum\n", aufile[idx]); return -1; } @@ -165,59 +168,62 @@ int au_check_header_valid(int idx, long nbytes) unsigned long checksum, fsize; hdr = (image_header_t *)LOAD_ADDR; +#if defined(CONFIG_FIT) + if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { + puts ("Non legacy image format not supported\n"); + return -1; + } +#endif + /* check the easy ones first */ #undef CHECK_VALID_DEBUG #ifdef CHECK_VALID_DEBUG - printf("magic %#x %#x ", ntohl(hdr->ih_magic), IH_MAGIC); - printf("arch %#x %#x ", hdr->ih_arch, IH_CPU_ARM); - printf("size %#x %#lx ", ntohl(hdr->ih_size), nbytes); - printf("type %#x %#x ", hdr->ih_type, IH_TYPE_KERNEL); + printf("magic %#x %#x ", image_get_magic (hdr), IH_MAGIC); + printf("arch %#x %#x ", image_get_arch (hdr), IH_ARCH_ARM); + printf("size %#x %#lx ", image_get_data_size (hdr), nbytes); + printf("type %#x %#x ", image_get_type (hdr), IH_TYPE_KERNEL); #endif - if (nbytes < sizeof(*hdr)) { + if (nbytes < image_get_header_size ()) { printf ("Image %s bad header SIZE\n", aufile[idx]); ausize[idx] = 0; return -1; } - if (ntohl(hdr->ih_magic) != IH_MAGIC || hdr->ih_arch != IH_CPU_PPC) { + if (!image_check_magic (hdr) || !image_check_arch (hdr, IH_ARCH_PPC)) { printf ("Image %s bad MAGIC or ARCH\n", aufile[idx]); ausize[idx] = 0; return -1; } /* check the hdr CRC */ - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (uchar *)hdr, sizeof(*hdr)) != checksum) { + if (!image_check_hcrc (hdr)) { printf ("Image %s bad header checksum\n", aufile[idx]); ausize[idx] = 0; return -1; } - hdr->ih_hcrc = htonl(checksum); /* check the type - could do this all in one gigantic if() */ - if ((idx == IDX_FIRMWARE) && (hdr->ih_type != IH_TYPE_FIRMWARE)) { + if ((idx == IDX_FIRMWARE) && !image_check_type (hdr, IH_TYPE_FIRMWARE)) { printf ("Image %s wrong type\n", aufile[idx]); ausize[idx] = 0; return -1; } - if ((idx == IDX_KERNEL) && (hdr->ih_type != IH_TYPE_KERNEL)) { + if ((idx == IDX_KERNEL) && !image_check_type (hdr, IH_TYPE_KERNEL)) { printf ("Image %s wrong type\n", aufile[idx]); ausize[idx] = 0; return -1; } if ((idx == IDX_ROOTFS) && - ( (hdr->ih_type != IH_TYPE_RAMDISK) && (hdr->ih_type != IH_TYPE_FILESYSTEM) ) - ) { + (!image_check_type (hdr, IH_TYPE_RAMDISK) && + !image_check_type (hdr, IH_TYPE_FILESYSTEM))) { printf ("Image %s wrong type\n", aufile[idx]); ausize[idx] = 0; return -1; } /* recycle checksum */ - checksum = ntohl(hdr->ih_size); + checksum = image_get_data_size (hdr); - fsize = checksum + sizeof(*hdr); + fsize = checksum + image_get_header_size (); /* for kernel and ramdisk the image header must also fit into flash */ - if (idx == IDX_KERNEL || hdr->ih_type == IH_TYPE_RAMDISK) - checksum += sizeof(*hdr); + if (idx == IDX_KERNEL || image_check_type (hdr, IH_TYPE_RAMDISK)) + checksum += image_get_header_size (); /* check the size does not exceed space in flash. HUSH scripts */ if ((ausize[idx] != 0) && (ausize[idx] < checksum)) { @@ -240,13 +246,19 @@ int au_do_update(int idx, long sz) uint nbytes; hdr = (image_header_t *)LOAD_ADDR; +#if defined(CONFIG_FIT) + if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { + puts ("Non legacy image format not supported\n"); + return -1; + } +#endif /* execute a script */ - if (hdr->ih_type == IH_TYPE_SCRIPT) { - addr = (char *)((char *)hdr + sizeof(*hdr)); + if (image_check_type (hdr, IH_TYPE_SCRIPT)) { + addr = (char *)((char *)hdr + image_get_header_size ()); /* stick a NULL at the end of the script, otherwise */ /* parse_string_outer() runs off the end. */ - addr[ntohl(hdr->ih_size)] = 0; + addr[image_get_data_size (hdr)] = 0; addr += 8; parse_string_outer(addr, FLAG_PARSE_SEMICOLON); return 0; @@ -278,19 +290,20 @@ int au_do_update(int idx, long sz) #endif /* strip the header - except for the kernel and ramdisk */ - if (hdr->ih_type == IH_TYPE_KERNEL || hdr->ih_type == IH_TYPE_RAMDISK) { + if (image_check_type (hdr, IH_TYPE_KERNEL) || + image_check_type (hdr, IH_TYPE_RAMDISK)) { addr = (char *)hdr; - off = sizeof(*hdr); - nbytes = sizeof(*hdr) + ntohl(hdr->ih_size); + off = image_get_header_size (); + nbytes = image_get_image_size (hdr); } else { - addr = (char *)((char *)hdr + sizeof(*hdr)); + addr = (char *)((char *)hdr + image_get_header_size ()); #ifdef AU_UPDATE_TEST /* copy it to where Linux goes */ if (idx == IDX_FIRMWARE) start = aufl_layout[1].start; #endif off = 0; - nbytes = ntohl(hdr->ih_size); + nbytes = image_get_data_size (hdr); } /* copy the data from RAM to FLASH */ @@ -306,7 +319,8 @@ int au_do_update(int idx, long sz) #endif /* check the data CRC of the copy */ - if (crc32 (0, (uchar *)(start + off), ntohl(hdr->ih_size)) != ntohl(hdr->ih_dcrc)) { + if (crc32 (0, (uchar *)(start + off), image_get_data_size (hdr)) != + image_get_dcrc (hdr)) { printf ("Image %s Bad Data Checksum after COPY\n", aufile[idx]); return -1; } @@ -442,10 +456,10 @@ int do_auto_update(void) for (i = 0; i < AU_MAXFILES; i++) { ulong imsize; /* just read the header */ - sz = file_fat_read(aufile[i], LOAD_ADDR, sizeof(image_header_t)); + sz = file_fat_read(aufile[i], LOAD_ADDR, image_get_header_size ()); debug ("read %s sz %ld hdr %d\n", - aufile[i], sz, sizeof(image_header_t)); - if (sz <= 0 || sz < sizeof(image_header_t)) { + aufile[i], sz, image_get_header_size ()); + if (sz <= 0 || sz < image_get_header_size ()) { debug ("%s not found\n", aufile[i]); ausize[i] = 0; continue; @@ -474,14 +488,14 @@ int do_auto_update(void) sz = file_fat_read(aufile[i], LOAD_ADDR, ausize[i]); debug ("read %s sz %ld hdr %d\n", - aufile[i], sz, sizeof(image_header_t)); + aufile[i], sz, image_get_header_size ()); if (sz != ausize[i]) { printf ("%s: size %d read %d?\n", aufile[i], ausize[i], sz); continue; } - if (sz <= 0 || sz <= sizeof(image_header_t)) { + if (sz <= 0 || sz <= image_get_header_size ()) { debug ("%s not found\n", aufile[i]); continue; } diff --git a/board/mpl/common/common_util.c b/board/mpl/common/common_util.c index 8d4cbe852e..785d204696 100644 --- a/board/mpl/common/common_util.c +++ b/board/mpl/common/common_util.c @@ -57,9 +57,6 @@ extern int mem_test(ulong start, ulong ramsize, int quiet); extern flash_info_t flash_info[]; /* info for FLASH chips */ -static image_header_t header; - - static int mpl_prg(uchar *src, ulong size) { @@ -77,7 +74,7 @@ mpl_prg(uchar *src, ulong size) info = &flash_info[0]; #if defined(CONFIG_PIP405) || defined(CONFIG_MIP405) || defined(CONFIG_PATI) - if (ntohl(magic[0]) != IH_MAGIC) { + if (uimage_to_cpu (magic[0]) != IH_MAGIC) { puts("Bad Magic number\n"); return -1; } @@ -179,44 +176,46 @@ mpl_prg(uchar *src, ulong size) static int mpl_prg_image(uchar *ld_addr) { - unsigned long len, checksum; + unsigned long len; uchar *data; - image_header_t *hdr = &header; + image_header_t *hdr = (image_header_t *)ld_addr; int rc; - /* Copy header so we can blank CRC field for re-calculation */ - memcpy (&header, (char *)ld_addr, sizeof(image_header_t)); - if (ntohl(hdr->ih_magic) != IH_MAGIC) { +#if defined(CONFIG_FIT) + if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { + puts ("Non legacy image format not supported\n"); + return -1; + } +#endif + + if (!image_check_magic (hdr)) { puts("Bad Magic Number\n"); return 1; } - print_image_hdr(hdr); - if (hdr->ih_os != IH_OS_U_BOOT) { + image_print_contents (hdr); + if (!image_check_os (hdr, IH_OS_U_BOOT)) { puts("No U-Boot Image\n"); return 1; } - if (hdr->ih_type != IH_TYPE_FIRMWARE) { + if (!image_check_type (hdr, IH_TYPE_FIRMWARE)) { puts("No Firmware Image\n"); return 1; } - data = (uchar *)&header; - len = sizeof(image_header_t); - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - if (crc32 (0, (uchar *)data, len) != checksum) { + if (!image_check_hcrc (hdr)) { puts("Bad Header Checksum\n"); return 1; } - data = ld_addr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); puts("Verifying Checksum ... "); - if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { + if (!image_check_dcrc (hdr)) { puts("Bad Data CRC\n"); return 1; } puts("OK\n"); - if (hdr->ih_comp != IH_COMP_NONE) { + data = (uchar *)image_get_data (hdr); + len = image_get_data_size (hdr); + + if (image_get_comp (hdr) != IH_COMP_NONE) { uchar *buf; /* reserve space for uncompressed image */ if ((buf = malloc(IMAGE_SIZE)) == NULL) { @@ -224,7 +223,7 @@ mpl_prg_image(uchar *ld_addr) return 1; } - switch (hdr->ih_comp) { + switch (image_get_comp (hdr)) { case IH_COMP_GZIP: puts("Uncompressing (GZIP) ... "); rc = gunzip ((void *)(buf), IMAGE_SIZE, data, &len); @@ -253,7 +252,8 @@ mpl_prg_image(uchar *ld_addr) break; #endif default: - printf ("Unimplemented compression type %d\n", hdr->ih_comp); + printf ("Unimplemented compression type %d\n", + image_get_comp (hdr)); free(buf); return 1; } diff --git a/board/pn62/cmd_pn62.c b/board/pn62/cmd_pn62.c index ffa20cde3b..3f53e4b7ca 100644 --- a/board/pn62/cmd_pn62.c +++ b/board/pn62/cmd_pn62.c @@ -157,8 +157,15 @@ int do_loadpci (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) char *s; if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) { - printf("Running autoscript at addr 0x%08lX ...\n", load_addr); - rcode = autoscript (bd, load_addr); + printf ("Running autoscript at addr 0x%08lX", load_addr); + + s = getenv ("autoscript_uname"); + if (s) + printf (":%s ...\n", s); + else + puts (" ...\n"); + + rcode = autoscript (load_addr, s); } } #endif diff --git a/board/siemens/common/fpga.c b/board/siemens/common/fpga.c index f022ed6d51..48c185082f 100644 --- a/board/siemens/common/fpga.c +++ b/board/siemens/common/fpga.c @@ -131,45 +131,44 @@ static int fpga_reset (fpga_t* fpga) static int fpga_load (fpga_t* fpga, ulong addr, int checkall) { volatile uchar *fpga_addr = (volatile uchar *)fpga->conf_base; - image_header_t hdr; - ulong len, checksum; - uchar *data = (uchar *)&hdr; - char *s, msg[32]; + image_header_t *hdr = (image_header_t *)addr; + ulong len; + uchar *data; + char msg[32]; int verify, i; +#if defined(CONFIG_FIT) + if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { + puts ("Non legacy image format not supported\n"); + return -1; + } +#endif + /* * Check the image header and data of the net-list */ - memcpy (&hdr, (char *)addr, sizeof(image_header_t)); - - if (hdr.ih_magic != IH_MAGIC) { + if (!image_check_magic (hdr)) { strcpy (msg, "Bad Image Magic Number"); goto failure; } - len = sizeof(image_header_t); - - checksum = hdr.ih_hcrc; - hdr.ih_hcrc = 0; - - if (crc32 (0, data, len) != checksum) { + if (!image_check_hcrc (hdr)) { strcpy (msg, "Bad Image Header CRC"); goto failure; } - data = (uchar*)(addr + sizeof(image_header_t)); - len = hdr.ih_size; + data = (uchar*)image_get_data (hdr); + len = image_get_data_size (hdr); - s = getenv ("verify"); - verify = (s && (*s == 'n')) ? 0 : 1; + verify = getenv_verify (); if (verify) { - if (crc32 (0, data, len) != hdr.ih_dcrc) { + if (!image_check_dcrc (hdr)) { strcpy (msg, "Bad Image Data CRC"); goto failure; } } - if (checkall && fpga_get_version(fpga, (char *)(hdr.ih_name)) < 0) + if (checkall && fpga_get_version(fpga, image_get_name (hdr)) < 0) return 1; /* align length */ @@ -184,7 +183,7 @@ static int fpga_load (fpga_t* fpga, ulong addr, int checkall) goto failure; } - printf ("(%s)... ", hdr.ih_name); + printf ("(%s)... ", image_get_name (hdr)); /* * Copy data to FPGA */ @@ -341,7 +340,14 @@ int fpga_init (void) } hdr = (image_header_t *)addr; - if ((new_id = fpga_get_version(fpga, (char *)(hdr->ih_name))) == -1) +#if defined(CONFIG_FIT) + if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { + puts ("Non legacy image format not supported\n"); + return -1; + } +#endif + + if ((new_id = fpga_get_version(fpga, image_get_name (hdr))) == -1) return 1; do_load = 1; diff --git a/board/trab/auto_update.c b/board/trab/auto_update.c index 54d3645ffa..46110cc763 100644 --- a/board/trab/auto_update.c +++ b/board/trab/auto_update.c @@ -209,21 +209,21 @@ int au_check_cksum_valid(int idx, long nbytes) { image_header_t *hdr; - unsigned long checksum; hdr = (image_header_t *)LOAD_ADDR; +#if defined(CONFIG_FIT) + if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { + puts ("Non legacy image format not supported\n"); + return -1; + } +#endif - if (nbytes != (sizeof(*hdr) + ntohl(hdr->ih_size))) - { + if (nbytes != image_get_image_size (hdr)) { printf ("Image %s bad total SIZE\n", aufile[idx]); return -1; } /* check the data CRC */ - checksum = ntohl(hdr->ih_dcrc); - - if (crc32 (0, (uchar *)(LOAD_ADDR + sizeof(*hdr)), ntohl(hdr->ih_size)) - != checksum) - { + if (!image_check_dcrc (hdr)) { printf ("Image %s bad data checksum\n", aufile[idx]); return -1; } @@ -238,54 +238,55 @@ au_check_header_valid(int idx, long nbytes) unsigned char buf[4]; hdr = (image_header_t *)LOAD_ADDR; +#if defined(CONFIG_FIT) + if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { + puts ("Non legacy image format not supported\n"); + return -1; + } +#endif + /* check the easy ones first */ #undef CHECK_VALID_DEBUG #ifdef CHECK_VALID_DEBUG - printf("magic %#x %#x ", ntohl(hdr->ih_magic), IH_MAGIC); - printf("arch %#x %#x ", hdr->ih_arch, IH_CPU_ARM); - printf("size %#x %#lx ", ntohl(hdr->ih_size), nbytes); - printf("type %#x %#x ", hdr->ih_type, IH_TYPE_KERNEL); + printf("magic %#x %#x ", image_get_magic (hdr), IH_MAGIC); + printf("arch %#x %#x ", image_get_arch (hdr), IH_ARCH_ARM); + printf("size %#x %#lx ", image_get_data_size (hdr), nbytes); + printf("type %#x %#x ", image_get_type (hdr), IH_TYPE_KERNEL); #endif - if (nbytes < sizeof(*hdr)) - { + if (nbytes < image_get_header_size ()) { printf ("Image %s bad header SIZE\n", aufile[idx]); return -1; } - if (ntohl(hdr->ih_magic) != IH_MAGIC || hdr->ih_arch != IH_CPU_ARM) - { + if (!image_check_magic (hdr) || !image_check_arch (hdr, IH_ARCH_ARM)) { printf ("Image %s bad MAGIC or ARCH\n", aufile[idx]); return -1; } /* check the hdr CRC */ - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (uchar *)hdr, sizeof(*hdr)) != checksum) { + if (!image_check_hcrc (hdr)) { printf ("Image %s bad header checksum\n", aufile[idx]); return -1; } - hdr->ih_hcrc = htonl(checksum); /* check the type - could do this all in one gigantic if() */ - if ((idx == IDX_FIRMWARE) && (hdr->ih_type != IH_TYPE_FIRMWARE)) { + if ((idx == IDX_FIRMWARE) && + !image_check_type (hdr, IH_TYPE_FIRMWARE)) { printf ("Image %s wrong type\n", aufile[idx]); return -1; } - if ((idx == IDX_KERNEL) && (hdr->ih_type != IH_TYPE_KERNEL)) { + if ((idx == IDX_KERNEL) && !image_check_type (hdr, IH_TYPE_KERNEL)) { printf ("Image %s wrong type\n", aufile[idx]); return -1; } - if ((idx == IDX_DISK) && (hdr->ih_type != IH_TYPE_FILESYSTEM)) { + if ((idx == IDX_DISK) && !image_check_type (hdr, IH_TYPE_FILESYSTEM)) { printf ("Image %s wrong type\n", aufile[idx]); return -1; } - if ((idx == IDX_APP) && (hdr->ih_type != IH_TYPE_RAMDISK) - && (hdr->ih_type != IH_TYPE_FILESYSTEM)) { + if ((idx == IDX_APP) && !image_check_type (hdr, IH_TYPE_RAMDISK) + && !image_check_type (hdr, IH_TYPE_FILESYSTEM)) { printf ("Image %s wrong type\n", aufile[idx]); return -1; } if ((idx == IDX_PREPARE || idx == IDX_PREINST || idx == IDX_POSTINST) - && (hdr->ih_type != IH_TYPE_SCRIPT)) - { + && !image_check_type (hdr, IH_TYPE_SCRIPT)) { printf ("Image %s wrong type\n", aufile[idx]); return -1; } @@ -293,10 +294,10 @@ au_check_header_valid(int idx, long nbytes) if (idx == IDX_PREPARE) return 0; /* recycle checksum */ - checksum = ntohl(hdr->ih_size); + checksum = image_get_data_size (hdr); /* for kernel and app the image header must also fit into flash */ if ((idx != IDX_DISK) && (idx != IDX_FIRMWARE)) - checksum += sizeof(*hdr); + checksum += image_get_header_size (); /* check the size does not exceed space in flash. HUSH scripts */ /* all have ausize[] set to 0 */ if ((ausize[idx] != 0) && (ausize[idx] < checksum)) { @@ -310,10 +311,10 @@ au_check_header_valid(int idx, long nbytes) printf ("buf[0] %#x buf[1] %#x buf[2] %#x buf[3] %#x " "as int %#x time %#x\n", buf[0], buf[1], buf[2], buf[3], - *((unsigned int *)buf), ntohl(hdr->ih_time)); + *((unsigned int *)buf), image_get_time (hdr)); #endif /* check it */ - if (*((unsigned int *)buf) >= ntohl(hdr->ih_time)) { + if (*((unsigned int *)buf) >= image_get_time (hdr)) { printf ("Image %s is too old\n", aufile[idx]); return -1; } @@ -335,16 +336,22 @@ au_do_update(int idx, long sz) uint nbytes; hdr = (image_header_t *)LOAD_ADDR; +#if defined(CONFIG_FIT) + if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { + puts ("Non legacy image format not supported\n"); + return -1; + } +#endif /* disable the power switch */ *CPLD_VFD_BK |= POWER_OFF; /* execute a script */ - if (hdr->ih_type == IH_TYPE_SCRIPT) { - addr = (char *)((char *)hdr + sizeof(*hdr)); + if (image_check_type (hdr, IH_TYPE_SCRIPT)) { + addr = (char *)((char *)hdr + image_get_header_size ()); /* stick a NULL at the end of the script, otherwise */ /* parse_string_outer() runs off the end. */ - addr[ntohl(hdr->ih_size)] = 0; + addr[image_get_data_size (hdr)] = 0; addr += 8; parse_string_outer(addr, FLAG_PARSE_SEMICOLON); return 0; @@ -372,19 +379,20 @@ au_do_update(int idx, long sz) flash_sect_erase(start, end); wait_ms(100); /* strip the header - except for the kernel and ramdisk */ - if (hdr->ih_type == IH_TYPE_KERNEL || hdr->ih_type == IH_TYPE_RAMDISK) { + if (image_check_type (hdr, IH_TYPE_KERNEL) || + image_check_type (hdr, IH_TYPE_RAMDISK)) { addr = (char *)hdr; - off = sizeof(*hdr); - nbytes = sizeof(*hdr) + ntohl(hdr->ih_size); + off = image_get_header_size (); + nbytes = image_get_image_size (hdr); } else { - addr = (char *)((char *)hdr + sizeof(*hdr)); + addr = (char *)((char *)hdr + image_get_header_size ()); #ifdef AU_UPDATE_TEST /* copy it to where Linux goes */ if (idx == IDX_FIRMWARE) start = aufl_layout[1].start; #endif off = 0; - nbytes = ntohl(hdr->ih_size); + nbytes = image_get_data_size (hdr); } /* copy the data from RAM to FLASH */ @@ -396,7 +404,8 @@ au_do_update(int idx, long sz) } /* check the dcrc of the copy */ - if (crc32 (0, (uchar *)(start + off), ntohl(hdr->ih_size)) != ntohl(hdr->ih_dcrc)) { + if (crc32 (0, (uchar *)(start + off), image_get_data_size (hdr)) != + image_get_dcrc (hdr)) { printf ("Image %s Bad Data Checksum After COPY\n", aufile[idx]); return -1; } @@ -423,17 +432,24 @@ au_update_eeprom(int idx) } hdr = (image_header_t *)LOAD_ADDR; +#if defined(CONFIG_FIT) + if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { + puts ("Non legacy image format not supported\n"); + return -1; + } +#endif + /* write the time field into EEPROM */ off = auee_off[idx].time; - val = ntohl(hdr->ih_time); + val = image_get_time (hdr); i2c_write_multiple(0x54, off, 1, &val, sizeof(val)); /* write the size field into EEPROM */ off = auee_off[idx].size; - val = ntohl(hdr->ih_size); + val = image_get_data_size (hdr); i2c_write_multiple(0x54, off, 1, &val, sizeof(val)); /* write the dcrc field into EEPROM */ off = auee_off[idx].dcrc; - val = ntohl(hdr->ih_dcrc); + val = image_get_dcrc (hdr); i2c_write_multiple(0x54, off, 1, &val, sizeof(val)); /* enable the power switch */ *CPLD_VFD_BK &= ~POWER_OFF; @@ -577,10 +593,10 @@ do_auto_update(void) /* just loop thru all the possible files */ for (i = 0; i < AU_MAXFILES; i++) { /* just read the header */ - sz = file_fat_read(aufile[i], LOAD_ADDR, sizeof(image_header_t)); + sz = file_fat_read(aufile[i], LOAD_ADDR, image_get_header_size ()); debug ("read %s sz %ld hdr %d\n", - aufile[i], sz, sizeof(image_header_t)); - if (sz <= 0 || sz < sizeof(image_header_t)) { + aufile[i], sz, image_get_header_size ()); + if (sz <= 0 || sz < image_get_header_size ()) { debug ("%s not found\n", aufile[i]); continue; } @@ -590,8 +606,8 @@ do_auto_update(void) } sz = file_fat_read(aufile[i], LOAD_ADDR, MAX_LOADSZ); debug ("read %s sz %ld hdr %d\n", - aufile[i], sz, sizeof(image_header_t)); - if (sz <= 0 || sz <= sizeof(image_header_t)) { + aufile[i], sz, image_get_header_size ()); + if (sz <= 0 || sz <= image_get_header_size ()) { debug ("%s not found\n", aufile[i]); continue; } diff --git a/common/Makefile b/common/Makefile index 56176ca2af..1c81fcfe4f 100644 --- a/common/Makefile +++ b/common/Makefile @@ -36,6 +36,8 @@ COBJS-y += cmd_autoscript.o COBJS-$(CONFIG_CMD_BDI) += cmd_bdinfo.o COBJS-$(CONFIG_CMD_BEDBUG) += cmd_bedbug.o COBJS-$(CONFIG_CMD_BMP) += cmd_bmp.o +COBJS-y += image.o +COBJS-y += gunzip.o COBJS-y += cmd_boot.o COBJS-$(CONFIG_CMD_BOOTLDR) += cmd_bootldr.o COBJS-y += cmd_bootm.o @@ -94,6 +96,7 @@ COBJS-$(CONFIG_CMD_STRINGS) += cmd_strings.o COBJS-$(CONFIG_CMD_TERMINAL) += cmd_terminal.o COBJS-$(CONFIG_CMD_UNIVERSE) += cmd_universe.o COBJS-$(CONFIG_CMD_USB) += cmd_usb.o +COBJS-$(CONFIG_CMD_XIMG) += cmd_ximg.o COBJS-y += cmd_vfd.o COBJS-y += command.o COBJS-y += console.o diff --git a/common/cmd_autoscript.c b/common/cmd_autoscript.c index a6038a6eff..1a37b90d79 100644 --- a/common/cmd_autoscript.c +++ b/common/cmd_autoscript.c @@ -49,57 +49,110 @@ #if defined(CONFIG_AUTOSCRIPT) || defined(CONFIG_CMD_AUTOSCRIPT) -extern image_header_t header; /* from cmd_bootm.c */ int -autoscript (ulong addr) +autoscript (ulong addr, const char *fit_uname) { - ulong crc, data, len; - image_header_t *hdr = &header; - ulong *len_ptr; - char *cmd; - int rcode = 0; - int verify; + ulong len; + image_header_t *hdr; + ulong *data; + char *cmd; + int rcode = 0; + int verify; +#if defined(CONFIG_FIT) + const void* fit_hdr; + int noffset; + const void *fit_data; + size_t fit_len; +#endif - cmd = getenv ("verify"); - verify = (cmd && (*cmd == 'n')) ? 0 : 1; + verify = getenv_verify (); + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *)addr; - memmove (hdr, (char *)addr, sizeof(image_header_t)); + if (!image_check_magic (hdr)) { + puts ("Bad magic number\n"); + return 1; + } - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - puts ("Bad magic number\n"); - return 1; - } + if (!image_check_hcrc (hdr)) { + puts ("Bad header crc\n"); + return 1; + } - crc = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - len = sizeof (image_header_t); - data = (ulong)hdr; - if (crc32(0, (uchar *)data, len) != crc) { - puts ("Bad header crc\n"); - return 1; - } + if (verify) { + if (!image_check_dcrc (hdr)) { + puts ("Bad data crc\n"); + return 1; + } + } - data = addr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); + if (!image_check_type (hdr, IH_TYPE_SCRIPT)) { + puts ("Bad image type\n"); + return 1; + } + + /* get length of script */ + data = (ulong *)image_get_data (hdr); - if (verify) { - if (crc32(0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { - puts ("Bad data crc\n"); + if ((len = uimage_to_cpu (*data)) == 0) { + puts ("Empty Script\n"); return 1; } - } - if (hdr->ih_type != IH_TYPE_SCRIPT) { - puts ("Bad image type\n"); - return 1; - } + /* + * scripts are just multi-image files with one component, seek + * past the zero-terminated sequence of image lengths to get + * to the actual image data + */ + while (*data++); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + if (fit_uname == NULL) { + puts ("No FIT subimage unit name\n"); + return 1; + } - /* get length of script */ - len_ptr = (ulong *)data; + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + puts ("Bad FIT image format\n"); + return 1; + } + + /* get script component image node offset */ + noffset = fit_image_get_node (fit_hdr, fit_uname); + if (noffset < 0) { + printf ("Can't find '%s' FIT subimage\n", fit_uname); + return 1; + } + + if (!fit_image_check_type (fit_hdr, noffset, IH_TYPE_SCRIPT)) { + puts ("Not a image image\n"); + return 1; + } + + /* verify integrity */ + if (verify) { + if (!fit_image_check_hashes (fit_hdr, noffset)) { + puts ("Bad Data Hash\n"); + return 1; + } + } - if ((len = ntohl(*len_ptr)) == 0) { - puts ("Empty Script\n"); + /* get script subimage data address and length */ + if (fit_image_get_data (fit_hdr, noffset, &fit_data, &fit_len)) { + puts ("Could not find script subimage data\n"); + return 1; + } + + data = (ulong *)fit_data; + len = (ulong)fit_len; + break; +#endif + default: + puts ("Wrong image format for autoscript\n"); return 1; } @@ -109,10 +162,8 @@ autoscript (ulong addr) return 1; } - while (*len_ptr++); - /* make sure cmd is null terminated */ - memmove (cmd, (char *)len_ptr, len); + memmove (cmd, (char *)data, len); *(cmd + len) = 0; #ifdef CFG_HUSH_PARSER /*?? */ @@ -158,25 +209,35 @@ do_autoscript (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { ulong addr; int rcode; + const char *fit_uname = NULL; + /* Find script image */ if (argc < 2) { addr = CFG_LOAD_ADDR; + debug ("* autoscr: default load address = 0x%08lx\n", addr); +#if defined(CONFIG_FIT) + } else if (fit_parse_subimage (argv[1], load_addr, &addr, &fit_uname)) { + debug ("* autoscr: subimage '%s' from FIT image at 0x%08lx\n", + fit_uname, addr); +#endif } else { - addr = simple_strtoul (argv[1],0,16); + addr = simple_strtoul(argv[1], NULL, 16); + debug ("* autoscr: cmdline image address = 0x%08lx\n", addr); } - printf ("## Executing script at %08lx\n",addr); - rcode = autoscript (addr); + printf ("## Executing script at %08lx\n", addr); + rcode = autoscript (addr, fit_uname); return rcode; } -#if defined(CONFIG_CMD_AUTOSCRIPT) U_BOOT_CMD( autoscr, 2, 0, do_autoscript, "autoscr - run script from memory\n", "[addr] - run script starting at addr" " - A valid autoscr header must be present\n" -); +#if defined(CONFIG_FIT) + "For FIT format uImage addr must include subimage\n" + "unit name in the form of addr:<subimg_uname>\n" #endif - +); #endif diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 5a8572602c..9e5ce4b38f 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -21,6 +21,7 @@ * MA 02111-1307 USA */ + /* * Boot support */ @@ -32,56 +33,24 @@ #include <zlib.h> #include <bzlib.h> #include <environment.h> +#include <lmb.h> #include <asm/byteorder.h> -#if defined(CONFIG_OF_LIBFDT) -#include <fdt.h> -#include <libfdt.h> -#include <fdt_support.h> -#endif -#if defined(CONFIG_OF_FLAT_TREE) -#include <ft_build.h> -#endif - -DECLARE_GLOBAL_DATA_PTR; - -/*cmd_boot.c*/ -extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); - -#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) -#include <rtc.h> -#endif - #ifdef CFG_HUSH_PARSER #include <hush.h> #endif -#ifdef CFG_INIT_RAM_LOCK -#include <asm/cache.h> -#endif - -#ifdef CONFIG_LOGBUFFER -#include <logbuff.h> -#endif +DECLARE_GLOBAL_DATA_PTR; -#ifdef CONFIG_HAS_DATAFLASH -#include <dataflash.h> +extern int gunzip (void *dst, int dstlen, unsigned char *src, unsigned long *lenp); +#ifndef CFG_BOOTM_LEN +#define CFG_BOOTM_LEN 0x800000 /* use 8MByte as default max gunzip size */ #endif -/* - * Some systems (for example LWMON) have very short watchdog periods; - * we must make sure to split long operations like memmove() or - * crc32() into reasonable chunks. - */ -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) -# define CHUNKSZ (64 * 1024) +#ifdef CONFIG_BZIP2 +extern void bz_internal_error(int); #endif -int gunzip (void *, int, unsigned char *, unsigned long *); - -static void *zalloc(void *, unsigned, unsigned); -static void zfree(void *, void *, unsigned); - #if defined(CONFIG_CMD_IMI) static int image_info (unsigned long addr); #endif @@ -92,12 +61,19 @@ extern flash_info_t flash_info[]; /* info for FLASH chips */ static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); #endif -static void print_type (image_header_t *hdr); +#ifdef CONFIG_SILENT_CONSOLE +static void fixup_silent_linux (void); +#endif -#ifdef __I386__ -image_header_t *fake_header(image_header_t *hdr, void *ptr, int size); +static image_header_t *image_get_kernel (ulong img_addr, int verify); +#if defined(CONFIG_FIT) +static int fit_check_kernel (const void *fit, int os_noffset, int verify); #endif +static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag,int argc, char *argv[], + bootm_headers_t *images, ulong *os_data, ulong *os_len); +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + /* * Continue booting an OS image; caller already has: * - copied image header to global variable `header' @@ -106,203 +82,135 @@ image_header_t *fake_header(image_header_t *hdr, void *ptr, int size); * - loaded (first part of) image to header load address, * - disabled interrupts. */ -typedef void boot_os_Fcn (cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - ulong addr, /* of image to boot */ - ulong *len_ptr, /* multi-file image length table */ - int verify); /* getenv("verify")[0] != 'n' */ - -#ifdef DEBUG -extern int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); -#endif - -#ifdef CONFIG_PPC -static boot_os_Fcn do_bootm_linux; -#else -extern boot_os_Fcn do_bootm_linux; +typedef void boot_os_fn (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + bootm_headers_t *images); /* pointers to os/initrd/fdt */ + +extern boot_os_fn do_bootm_linux; +static boot_os_fn do_bootm_netbsd; +#if defined(CONFIG_LYNXKDI) +static boot_os_fn do_bootm_lynxkdi; +extern void lynxkdi_boot (image_header_t *); #endif -#ifdef CONFIG_SILENT_CONSOLE -static void fixup_silent_linux (void); -#endif -static boot_os_Fcn do_bootm_netbsd; -static boot_os_Fcn do_bootm_rtems; +static boot_os_fn do_bootm_rtems; #if defined(CONFIG_CMD_ELF) -static boot_os_Fcn do_bootm_vxworks; -static boot_os_Fcn do_bootm_qnxelf; -int do_bootvx ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ); -int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ); +static boot_os_fn do_bootm_vxworks; +static boot_os_fn do_bootm_qnxelf; +int do_bootvx (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); #endif #if defined(CONFIG_ARTOS) && defined(CONFIG_PPC) -static boot_os_Fcn do_bootm_artos; -#endif -#ifdef CONFIG_LYNXKDI -static boot_os_Fcn do_bootm_lynxkdi; -extern void lynxkdi_boot( image_header_t * ); +extern uchar (*env_get_char)(int); /* Returns a character from the environment */ +static boot_os_fn do_bootm_artos; #endif -#ifndef CFG_BOOTM_LEN -#define CFG_BOOTM_LEN 0x800000 /* use 8MByte as default max gunzip size */ -#endif +ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */ +static bootm_headers_t images; /* pointers to os/initrd/fdt images */ -image_header_t header; +void __board_lmb_reserve(struct lmb *lmb) +{ + /* please define platform specific board_lmb_reserve() */ +} +void board_lmb_reserve(struct lmb *lmb) __attribute__((weak, alias("__board_lmb_reserve"))); -ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */ +/*******************************************************************/ +/* bootm - boot application image from image in memory */ +/*******************************************************************/ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { - ulong iflag; - ulong addr; - ulong data, len, checksum; - ulong *len_ptr; - uint unc_len = CFG_BOOTM_LEN; - int i, verify; - char *name, *s; - int (*appl)(int, char *[]); - image_header_t *hdr = &header; + ulong iflag; + const char *type_name; + uint unc_len = CFG_BOOTM_LEN; + uint8_t comp, type, os; - s = getenv ("verify"); - verify = (s && (*s == 'n')) ? 0 : 1; + void *os_hdr; + ulong os_data, os_len; + ulong image_start, image_end; + ulong load_start, load_end; + ulong mem_start, mem_size; - if (argc < 2) { - addr = load_addr; - } else { - addr = simple_strtoul(argv[1], NULL, 16); - } + struct lmb lmb; - show_boot_progress (1); - printf ("## Booting image at %08lx ...\n", addr); + memset ((void *)&images, 0, sizeof (images)); + images.verify = getenv_verify(); + images.autostart = getenv_autostart(); + images.lmb = &lmb; - /* Copy header so we can blank CRC field for re-calculation */ -#ifdef CONFIG_HAS_DATAFLASH - if (addr_dataflash(addr)){ - read_dataflash(addr, sizeof(image_header_t), (char *)&header); - } else -#endif - memmove (&header, (char *)addr, sizeof(image_header_t)); - - if (ntohl(hdr->ih_magic) != IH_MAGIC) { -#ifdef __I386__ /* correct image format not implemented yet - fake it */ - if (fake_header(hdr, (void*)addr, -1) != NULL) { - /* to compensate for the addition below */ - addr -= sizeof(image_header_t); - /* turnof verify, - * fake_header() does not fake the data crc - */ - verify = 0; - } else -#endif /* __I386__ */ - { - puts ("Bad Magic Number\n"); - show_boot_progress (-1); - return 1; - } - } - show_boot_progress (2); + lmb_init(&lmb); - data = (ulong)&header; - len = sizeof(image_header_t); + mem_start = getenv_bootm_low(); + mem_size = getenv_bootm_size(); - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; + lmb_add(&lmb, mem_start, mem_size); - if (crc32 (0, (uchar *)data, len) != checksum) { - puts ("Bad Header Checksum\n"); - show_boot_progress (-2); - return 1; - } - show_boot_progress (3); + board_lmb_reserve(&lmb); -#ifdef CONFIG_HAS_DATAFLASH - if (addr_dataflash(addr)){ - len = ntohl(hdr->ih_size) + sizeof(image_header_t); - read_dataflash(addr, len, (char *)CFG_LOAD_ADDR); - addr = CFG_LOAD_ADDR; + /* get kernel image header, start address and length */ + os_hdr = boot_get_kernel (cmdtp, flag, argc, argv, + &images, &os_data, &os_len); + if (os_len == 0) { + puts ("ERROR: can't get kernel image!\n"); + return 1; } -#endif + /* get image parameters */ + switch (genimg_get_format (os_hdr)) { + case IMAGE_FORMAT_LEGACY: + type = image_get_type (os_hdr); + comp = image_get_comp (os_hdr); + os = image_get_os (os_hdr); - /* for multi-file images we need the data part, too */ - print_image_hdr ((image_header_t *)addr); + image_end = image_get_image_end (os_hdr); + load_start = image_get_load (os_hdr); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + if (fit_image_get_type (images.fit_hdr_os, + images.fit_noffset_os, &type)) { + puts ("Can't get image type!\n"); + show_boot_progress (-109); + return 1; + } - data = addr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); + if (fit_image_get_comp (images.fit_hdr_os, + images.fit_noffset_os, &comp)) { + puts ("Can't get image compression!\n"); + show_boot_progress (-110); + return 1; + } - if (verify) { - puts (" Verifying Checksum ... "); - if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { - printf ("Bad Data CRC\n"); - show_boot_progress (-3); + if (fit_image_get_os (images.fit_hdr_os, + images.fit_noffset_os, &os)) { + puts ("Can't get image OS!\n"); + show_boot_progress (-111); return 1; } - puts ("OK\n"); - } - show_boot_progress (4); - len_ptr = (ulong *)data; - -#if defined(__ARM__) - if (hdr->ih_arch != IH_CPU_ARM) -#elif defined(__avr32__) - if (hdr->ih_arch != IH_CPU_AVR32) -#elif defined(__bfin__) - if (hdr->ih_arch != IH_CPU_BLACKFIN) -#elif defined(__I386__) - if (hdr->ih_arch != IH_CPU_I386) -#elif defined(__M68K__) - if (hdr->ih_arch != IH_CPU_M68K) -#elif defined(__microblaze__) - if (hdr->ih_arch != IH_CPU_MICROBLAZE) -#elif defined(__mips__) - if (hdr->ih_arch != IH_CPU_MIPS) -#elif defined(__nios__) - if (hdr->ih_arch != IH_CPU_NIOS) -#elif defined(__nios2__) - if (hdr->ih_arch != IH_CPU_NIOS2) -#elif defined(__PPC__) - if (hdr->ih_arch != IH_CPU_PPC) -#elif defined(__sh__) - if (hdr->ih_arch != IH_CPU_SH) -#else -# error Unknown CPU type -#endif - { - printf ("Unsupported Architecture 0x%x\n", hdr->ih_arch); - show_boot_progress (-4); - return 1; - } - show_boot_progress (5); - - switch (hdr->ih_type) { - case IH_TYPE_STANDALONE: - name = "Standalone Application"; - /* A second argument overwrites the load address */ - if (argc > 2) { - hdr->ih_load = htonl(simple_strtoul(argv[2], NULL, 16)); + image_end = fit_get_end (images.fit_hdr_os); + + if (fit_image_get_load (images.fit_hdr_os, images.fit_noffset_os, + &load_start)) { + puts ("Can't get image load address!\n"); + show_boot_progress (-112); + return 1; } break; - case IH_TYPE_KERNEL: - name = "Kernel Image"; - break; - case IH_TYPE_MULTI: - name = "Multi-File Image"; - len = ntohl(len_ptr[0]); - /* OS kernel is always the first image */ - data += 8; /* kernel_len + terminator */ - for (i=1; len_ptr[i]; ++i) - data += 4; - break; - default: printf ("Wrong Image Type for %s command\n", cmdtp->name); - show_boot_progress (-5); +#endif + default: + puts ("ERROR: unknown image format type!\n"); return 1; } - show_boot_progress (6); + + image_start = (ulong)os_hdr; + load_end = 0; + type_name = genimg_get_type_name (type); /* * We have reached the point of no return: we are going to * overwrite all exception vector code, so we cannot easily * recover from any failures any more... */ - iflag = disable_interrupts(); #ifdef CONFIG_AMIGAONEG3SE @@ -316,138 +224,113 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) dcache_disable(); #endif - switch (hdr->ih_comp) { + switch (comp) { case IH_COMP_NONE: - if(ntohl(hdr->ih_load) == addr) { - printf (" XIP %s ... ", name); + if (load_start == (ulong)os_hdr) { + printf (" XIP %s ... ", type_name); } else { -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - size_t l = len; - void *to = (void *)ntohl(hdr->ih_load); - void *from = (void *)data; - - printf (" Loading %s ... ", name); - - while (l > 0) { - size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l; - WATCHDOG_RESET(); - memmove (to, from, tail); - to += tail; - from += tail; - l -= tail; - } -#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ - memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len); -#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ + printf (" Loading %s ... ", type_name); + + memmove_wd ((void *)load_start, + (void *)os_data, os_len, CHUNKSZ); + + load_end = load_start + os_len; + puts("OK\n"); } break; case IH_COMP_GZIP: - printf (" Uncompressing %s ... ", name); - if (gunzip ((void *)ntohl(hdr->ih_load), unc_len, - (uchar *)data, &len) != 0) { - puts ("GUNZIP ERROR - must RESET board to recover\n"); + printf (" Uncompressing %s ... ", type_name); + if (gunzip ((void *)load_start, unc_len, + (uchar *)os_data, &os_len) != 0) { + puts ("GUNZIP: uncompress or overwrite error " + "- must RESET board to recover\n"); show_boot_progress (-6); do_reset (cmdtp, flag, argc, argv); } + + load_end = load_start + os_len; break; #ifdef CONFIG_BZIP2 case IH_COMP_BZIP2: - printf (" Uncompressing %s ... ", name); + printf (" Uncompressing %s ... ", type_name); /* * If we've got less than 4 MB of malloc() space, * use slower decompression algorithm which requires * at most 2300 KB of memory. */ - i = BZ2_bzBuffToBuffDecompress ((char*)ntohl(hdr->ih_load), - &unc_len, (char *)data, len, - CFG_MALLOC_LEN < (4096 * 1024), 0); + int i = BZ2_bzBuffToBuffDecompress ((char*)load_start, + &unc_len, (char *)os_data, os_len, + CFG_MALLOC_LEN < (4096 * 1024), 0); if (i != BZ_OK) { - printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i); + printf ("BUNZIP2: uncompress or overwrite error %d " + "- must RESET board to recover\n", i); show_boot_progress (-6); do_reset (cmdtp, flag, argc, argv); } + + load_end = load_start + unc_len; break; #endif /* CONFIG_BZIP2 */ default: if (iflag) enable_interrupts(); - printf ("Unimplemented compression type %d\n", hdr->ih_comp); + printf ("Unimplemented compression type %d\n", comp); show_boot_progress (-7); return 1; } puts ("OK\n"); + debug (" kernel loaded at 0x%08lx, end = 0x%08lx\n", load_start, load_end); show_boot_progress (7); - switch (hdr->ih_type) { - case IH_TYPE_STANDALONE: - if (iflag) - enable_interrupts(); + if ((load_start < image_end) && (load_end > image_start)) { + debug ("image_start = 0x%lX, image_end = 0x%lx\n", image_start, image_end); + debug ("load_start = 0x%lx, load_end = 0x%lx\n", load_start, load_end); - /* load (and uncompress), but don't start if "autostart" - * is set to "no" - */ - if (((s = getenv("autostart")) != NULL) && (strcmp(s,"no") == 0)) { - char buf[32]; - sprintf(buf, "%lX", len); - setenv("filesize", buf); - return 0; - } - appl = (int (*)(int, char *[]))ntohl(hdr->ih_ep); - (*appl)(argc-1, &argv[1]); - return 0; - case IH_TYPE_KERNEL: - case IH_TYPE_MULTI: - /* handled below */ - break; - default: - if (iflag) - enable_interrupts(); - printf ("Can't boot image type %d\n", hdr->ih_type); - show_boot_progress (-8); - return 1; + puts ("ERROR: image overwritten - must RESET the board to recover.\n"); + show_boot_progress (-113); + do_reset (cmdtp, flag, argc, argv); } + show_boot_progress (8); - switch (hdr->ih_os) { + lmb_reserve(&lmb, load_start, (load_end - load_start)); + + switch (os) { default: /* handled by (original) Linux case */ case IH_OS_LINUX: #ifdef CONFIG_SILENT_CONSOLE fixup_silent_linux(); #endif - do_bootm_linux (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_linux (cmdtp, flag, argc, argv, &images); break; + case IH_OS_NETBSD: - do_bootm_netbsd (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_netbsd (cmdtp, flag, argc, argv, &images); break; #ifdef CONFIG_LYNXKDI case IH_OS_LYNXOS: - do_bootm_lynxkdi (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_lynxkdi (cmdtp, flag, argc, argv, &images); break; #endif case IH_OS_RTEMS: - do_bootm_rtems (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_rtems (cmdtp, flag, argc, argv, &images); break; #if defined(CONFIG_CMD_ELF) case IH_OS_VXWORKS: - do_bootm_vxworks (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_vxworks (cmdtp, flag, argc, argv, &images); break; + case IH_OS_QNX: - do_bootm_qnxelf (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_qnxelf (cmdtp, flag, argc, argv, &images); break; #endif + #ifdef CONFIG_ARTOS case IH_OS_ARTOS: - do_bootm_artos (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_artos (cmdtp, flag, argc, argv, &images); break; #endif } @@ -455,94 +338,94 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) show_boot_progress (-9); #ifdef DEBUG puts ("\n## Control returned to monitor - resetting...\n"); - do_reset (cmdtp, flag, argc, argv); + if (images.autostart) + do_reset (cmdtp, flag, argc, argv); #endif + if (!images.autostart && iflag) + enable_interrupts(); + return 1; } -U_BOOT_CMD( - bootm, CFG_MAXARGS, 1, do_bootm, - "bootm - boot application image from memory\n", - "[addr [arg ...]]\n - boot application image stored in memory\n" - "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n" - "\t'arg' can be the address of an initrd image\n" -#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) - "\tWhen booting a Linux kernel which requires a flat device-tree\n" - "\ta third argument is required which is the address of the\n" - "\tdevice-tree blob. To boot that kernel without an initrd image,\n" - "\tuse a '-' for the second argument. If you do not pass a third\n" - "\ta bd_info struct will be passed instead\n" -#endif -); - -#ifdef CONFIG_SILENT_CONSOLE -static void -fixup_silent_linux () +/** + * image_get_kernel - verify legacy format kernel image + * @img_addr: in RAM address of the legacy format image to be verified + * @verify: data CRC verification flag + * + * image_get_kernel() verifies legacy image integrity and returns pointer to + * legacy image header if image verification was completed successfully. + * + * returns: + * pointer to a legacy image header if valid image was found + * otherwise return NULL + */ +static image_header_t *image_get_kernel (ulong img_addr, int verify) { - char buf[256], *start, *end; - char *cmdline = getenv ("bootargs"); + image_header_t *hdr = (image_header_t *)img_addr; - /* Only fix cmdline when requested */ - if (!(gd->flags & GD_FLG_SILENT)) - return; + if (!image_check_magic(hdr)) { + puts ("Bad Magic Number\n"); + show_boot_progress (-1); + return NULL; + } + show_boot_progress (2); - debug ("before silent fix-up: %s\n", cmdline); - if (cmdline) { - if ((start = strstr (cmdline, "console=")) != NULL) { - end = strchr (start, ' '); - strncpy (buf, cmdline, (start - cmdline + 8)); - if (end) - strcpy (buf + (start - cmdline + 8), end); - else - buf[start - cmdline + 8] = '\0'; - } else { - strcpy (buf, cmdline); - strcat (buf, " console="); + if (!image_check_hcrc (hdr)) { + puts ("Bad Header Checksum\n"); + show_boot_progress (-2); + return NULL; + } + + show_boot_progress (3); + image_print_contents (hdr); + + if (verify) { + puts (" Verifying Checksum ... "); + if (!image_check_dcrc (hdr)) { + printf ("Bad Data CRC\n"); + show_boot_progress (-3); + return NULL; } - } else { - strcpy (buf, "console="); + puts ("OK\n"); } + show_boot_progress (4); - setenv ("bootargs", buf); - debug ("after silent fix-up: %s\n", buf); + if (!image_check_target_arch (hdr)) { + printf ("Unsupported Architecture 0x%x\n", image_get_arch (hdr)); + show_boot_progress (-4); + return NULL; + } + return hdr; } -#endif /* CONFIG_SILENT_CONSOLE */ -#ifdef CONFIG_PPC -static void __attribute__((noinline)) -do_bootm_linux (cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - ulong addr, - ulong *len_ptr, - int verify) +/** + * fit_check_kernel - verify FIT format kernel subimage + * @fit_hdr: pointer to the FIT image header + * os_noffset: kernel subimage node offset within FIT image + * @verify: data CRC verification flag + * + * fit_check_kernel() verifies integrity of the kernel subimage and from + * specified FIT image. + * + * returns: + * 1, on success + * 0, on failure + */ +#if defined (CONFIG_FIT) +static int fit_check_kernel (const void *fit, int os_noffset, int verify) { - ulong sp; - ulong len, checksum; - ulong initrd_start, initrd_end; - ulong cmd_start, cmd_end; - ulong initrd_high; - ulong data; - int initrd_copy_to_ram = 1; - char *cmdline; - char *s; - bd_t *kbd; - void (*kernel)(bd_t *, ulong, ulong, ulong, ulong); - image_header_t *hdr = &header; -#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) - char *of_flat_tree = NULL; - ulong of_data = 0; -#endif + fit_image_print (fit, os_noffset, " "); - if ((s = getenv ("initrd_high")) != NULL) { - /* a value of "no" or a similar string will act like 0, - * turning the "load high" feature off. This is intentional. - */ - initrd_high = simple_strtoul(s, NULL, 16); - if (initrd_high == ~0) - initrd_copy_to_ram = 0; - } else { /* not set, no restrictions to load high */ - initrd_high = ~0; + if (verify) { + puts (" Verifying Hash Integrity ... "); + if (!fit_image_check_hashes (fit, os_noffset)) { + puts ("Bad Data Hash\n"); + show_boot_progress (-104); + return 0; + } + puts ("OK\n"); } + show_boot_progress (105); #ifdef CONFIG_LOGBUFFER #ifndef CONFIG_ALT_LB_ADDR @@ -555,525 +438,445 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, debug ("## Logbuffer at 0x%08lX ", CONFIG_ALT_LB_ADDR); #endif #endif + if (!fit_image_check_target_arch (fit, os_noffset)) { + puts ("Unsupported Architecture\n"); + show_boot_progress (-105); + return 0; + } - /* - * Booting a (Linux) kernel image - * - * Allocate space for command line and board info - the - * address should be as high as possible within the reach of - * the kernel (see CFG_BOOTMAPSZ settings), but in unused - * memory, which means far enough below the current stack - * pointer. - */ - - asm( "mr %0,1": "=r"(sp) : ); - - debug ("## Current stack ends at 0x%08lX ", sp); - - sp -= 2048; /* just to be sure */ - if (sp > CFG_BOOTMAPSZ) - sp = CFG_BOOTMAPSZ; - sp &= ~0xF; - - debug ("=> set upper limit to 0x%08lX\n", sp); - - cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF); - kbd = (bd_t *)(((ulong)cmdline - sizeof(bd_t)) & ~0xF); - - if ((s = getenv("bootargs")) == NULL) - s = ""; - - strcpy (cmdline, s); - - cmd_start = (ulong)&cmdline[0]; - cmd_end = cmd_start + strlen(cmdline); - - *kbd = *(gd->bd); + show_boot_progress (106); + if (!fit_image_check_type (fit, os_noffset, IH_TYPE_KERNEL)) { + puts ("Not a kernel image\n"); + show_boot_progress (-106); + return 0; + } -#ifdef DEBUG - printf ("## cmdline at 0x%08lX ... 0x%08lX\n", cmd_start, cmd_end); + show_boot_progress (107); + return 1; +} +#endif /* CONFIG_FIT */ - do_bdinfo (NULL, 0, 0, NULL); +/** + * boot_get_kernel - find kernel image + * @os_data: pointer to a ulong variable, will hold os data start address + * @os_len: pointer to a ulong variable, will hold os data length + * + * boot_get_kernel() tries to find a kernel image, verifies its integrity + * and locates kernel data. + * + * returns: + * pointer to image header if valid image was found, plus kernel start + * address and length, otherwise NULL + */ +static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + bootm_headers_t *images, ulong *os_data, ulong *os_len) +{ + image_header_t *hdr; + ulong img_addr; +#if defined(CONFIG_FIT) + void *fit_hdr; + const char *fit_uname_config = NULL; + const char *fit_uname_kernel = NULL; + const void *data; + size_t len; + int cfg_noffset; + int os_noffset; #endif - if ((s = getenv ("clocks_in_mhz")) != NULL) { - /* convert all clock information to MHz */ - kbd->bi_intfreq /= 1000000L; - kbd->bi_busfreq /= 1000000L; -#if defined(CONFIG_MPC8220) - kbd->bi_inpfreq /= 1000000L; - kbd->bi_pcifreq /= 1000000L; - kbd->bi_pevfreq /= 1000000L; - kbd->bi_flbfreq /= 1000000L; - kbd->bi_vcofreq /= 1000000L; -#endif -#if defined(CONFIG_CPM2) - kbd->bi_cpmfreq /= 1000000L; - kbd->bi_brgfreq /= 1000000L; - kbd->bi_sccfreq /= 1000000L; - kbd->bi_vco /= 1000000L; + /* find out kernel image address */ + if (argc < 2) { + img_addr = load_addr; + debug ("* kernel: default image load address = 0x%08lx\n", + load_addr); +#if defined(CONFIG_FIT) + } else if (fit_parse_conf (argv[1], load_addr, &img_addr, + &fit_uname_config)) { + debug ("* kernel: config '%s' from image at 0x%08lx\n", + fit_uname_config, img_addr); + } else if (fit_parse_subimage (argv[1], load_addr, &img_addr, + &fit_uname_kernel)) { + debug ("* kernel: subimage '%s' from image at 0x%08lx\n", + fit_uname_kernel, img_addr); #endif -#if defined(CONFIG_MPC5xxx) - kbd->bi_ipbfreq /= 1000000L; - kbd->bi_pcifreq /= 1000000L; -#endif /* CONFIG_MPC5xxx */ + } else { + img_addr = simple_strtoul(argv[1], NULL, 16); + debug ("* kernel: cmdline image address = 0x%08lx\n", img_addr); } - kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong)) ntohl(hdr->ih_ep); - - /* - * Check if there is an initrd image - */ + show_boot_progress (1); -#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) - /* Look for a '-' which indicates to ignore the ramdisk argument */ - if (argc >= 3 && strcmp(argv[2], "-") == 0) { - debug ("Skipping initrd\n"); - len = data = 0; + /* copy from dataflash if needed */ + img_addr = genimg_get_image (img_addr); + + /* check image type, for FIT images get FIT kernel node */ + *os_data = *os_len = 0; + switch (genimg_get_format ((void *)img_addr)) { + case IMAGE_FORMAT_LEGACY: + printf ("## Booting kernel from Legacy Image at %08lx ...\n", + img_addr); + hdr = image_get_kernel (img_addr, images->verify); + if (!hdr) + return NULL; + show_boot_progress (5); + + /* get os_data and os_len */ + switch (image_get_type (hdr)) { + case IH_TYPE_KERNEL: + *os_data = image_get_data (hdr); + *os_len = image_get_data_size (hdr); + break; + case IH_TYPE_MULTI: + image_multi_getimg (hdr, 0, os_data, os_len); + break; + default: + printf ("Wrong Image Type for %s command\n", cmdtp->name); + show_boot_progress (-5); + return NULL; } - else -#endif - if (argc >= 3) { - debug ("Not skipping initrd\n"); - show_boot_progress (9); + images->legacy_hdr_os = hdr; + images->legacy_hdr_valid = 1; - addr = simple_strtoul(argv[2], NULL, 16); - - printf ("## Loading RAMDisk Image at %08lx ...\n", addr); - - /* Copy header so we can blank CRC field for re-calculation */ - memmove (&header, (char *)addr, sizeof(image_header_t)); - - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - puts ("Bad Magic Number\n"); - show_boot_progress (-10); - do_reset (cmdtp, flag, argc, argv); + show_boot_progress (6); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (void *)img_addr; + printf ("## Booting kernel from FIT Image at %08lx ...\n", + img_addr); + + if (!fit_check_format (fit_hdr)) { + puts ("Bad FIT kernel image format!\n"); + show_boot_progress (-100); + return NULL; } + show_boot_progress (100); - data = (ulong)&header; - len = sizeof(image_header_t); - - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; + if (!fit_uname_kernel) { + /* + * no kernel image node unit name, try to get config + * node first. If config unit node name is NULL + * fit_conf_get_node() will try to find default config node + */ + show_boot_progress (101); + cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config); + if (cfg_noffset < 0) { + show_boot_progress (-101); + return NULL; + } + /* save configuration uname provided in the first + * bootm argument + */ + images->fit_uname_cfg = fdt_get_name (fit_hdr, cfg_noffset, NULL); + printf (" Using '%s' configuration\n", images->fit_uname_cfg); + show_boot_progress (103); - if (crc32 (0, (uchar *)data, len) != checksum) { - puts ("Bad Header Checksum\n"); - show_boot_progress (-11); - do_reset (cmdtp, flag, argc, argv); + os_noffset = fit_conf_get_kernel_node (fit_hdr, cfg_noffset); + fit_uname_kernel = fit_get_name (fit_hdr, os_noffset, NULL); + } else { + /* get kernel component image node offset */ + show_boot_progress (102); + os_noffset = fit_image_get_node (fit_hdr, fit_uname_kernel); + } + if (os_noffset < 0) { + show_boot_progress (-103); + return NULL; } - show_boot_progress (10); + printf (" Trying '%s' kernel subimage\n", fit_uname_kernel); - print_image_hdr (hdr); + show_boot_progress (104); + if (!fit_check_kernel (fit_hdr, os_noffset, images->verify)) + return NULL; - data = addr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); + /* get kernel image data address and length */ + if (fit_image_get_data (fit_hdr, os_noffset, &data, &len)) { + puts ("Could not find kernel subimage data!\n"); + show_boot_progress (-107); + return NULL; + } + show_boot_progress (108); - if (verify) { - ulong csum = 0; -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - ulong cdata = data, edata = cdata + len; -#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ + *os_len = len; + *os_data = (ulong)data; + images->fit_hdr_os = fit_hdr; + images->fit_uname_os = fit_uname_kernel; + images->fit_noffset_os = os_noffset; + break; +#endif + default: + printf ("Wrong Image Format for %s command\n", cmdtp->name); + show_boot_progress (-108); + return NULL; + } - puts (" Verifying Checksum ... "); + debug (" kernel data at 0x%08lx, len = 0x%08lx (%d)\n", + *os_data, *os_len, *os_len); -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + return (void *)img_addr; +} - while (cdata < edata) { - ulong chunk = edata - cdata; +U_BOOT_CMD( + bootm, CFG_MAXARGS, 1, do_bootm, + "bootm - boot application image from memory\n", + "[addr [arg ...]]\n - boot application image stored in memory\n" + "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n" + "\t'arg' can be the address of an initrd image\n" +#if defined(CONFIG_OF_LIBFDT) + "\tWhen booting a Linux kernel which requires a flat device-tree\n" + "\ta third argument is required which is the address of the\n" + "\tdevice-tree blob. To boot that kernel without an initrd image,\n" + "\tuse a '-' for the second argument. If you do not pass a third\n" + "\ta bd_info struct will be passed instead\n" +#endif +#if defined(CONFIG_FIT) + "\t\nFor the new multi component uImage format (FIT) addresses\n" + "\tmust be extened to include component or configuration unit name:\n" + "\taddr:<subimg_uname> - direct component image specification\n" + "\taddr#<conf_uname> - configuration specification\n" + "\tUse iminfo command to get the list of existing component\n" + "\timages and configurations.\n" +#endif +); - if (chunk > CHUNKSZ) - chunk = CHUNKSZ; - csum = crc32 (csum, (uchar *)cdata, chunk); - cdata += chunk; +/*******************************************************************/ +/* bootd - boot default image */ +/*******************************************************************/ +#if defined(CONFIG_CMD_BOOTD) +int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int rcode = 0; - WATCHDOG_RESET(); - } -#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ - csum = crc32 (0, (uchar *)data, len); -#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ - - if (csum != ntohl(hdr->ih_dcrc)) { - puts ("Bad Data CRC\n"); - show_boot_progress (-12); - do_reset (cmdtp, flag, argc, argv); - } - puts ("OK\n"); - } +#ifndef CFG_HUSH_PARSER + if (run_command (getenv ("bootcmd"), flag) < 0) + rcode = 1; +#else + if (parse_string_outer (getenv ("bootcmd"), + FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0) + rcode = 1; +#endif + return rcode; +} - show_boot_progress (11); +U_BOOT_CMD( + boot, 1, 1, do_bootd, + "boot - boot default, i.e., run 'bootcmd'\n", + NULL +); - if ((hdr->ih_os != IH_OS_LINUX) || - (hdr->ih_arch != IH_CPU_PPC) || - (hdr->ih_type != IH_TYPE_RAMDISK) ) { - puts ("No Linux PPC Ramdisk Image\n"); - show_boot_progress (-13); - do_reset (cmdtp, flag, argc, argv); - } +/* keep old command name "bootd" for backward compatibility */ +U_BOOT_CMD( + bootd, 1, 1, do_bootd, + "bootd - boot default, i.e., run 'bootcmd'\n", + NULL +); - /* - * Now check if we have a multifile image - */ - } else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) { - u_long tail = ntohl(len_ptr[0]) % 4; - int i; - - show_boot_progress (13); - - /* skip kernel length and terminator */ - data = (ulong)(&len_ptr[2]); - /* skip any additional image length fields */ - for (i=1; len_ptr[i]; ++i) - data += 4; - /* add kernel length, and align */ - data += ntohl(len_ptr[0]); - if (tail) { - data += 4 - tail; - } +#endif - len = ntohl(len_ptr[1]); - } else { - /* - * no initrd image - */ - show_boot_progress (14); +/*******************************************************************/ +/* iminfo - print header info for a requested image */ +/*******************************************************************/ +#if defined(CONFIG_CMD_IMI) +int do_iminfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int arg; + ulong addr; + int rcode = 0; - len = data = 0; + if (argc < 2) { + return image_info (load_addr); } -#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) - if(argc > 3) { - of_flat_tree = (char *) simple_strtoul(argv[3], NULL, 16); - hdr = (image_header_t *)of_flat_tree; -#if defined(CONFIG_OF_FLAT_TREE) - if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) { -#else - if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) != 0) { -#endif -#ifndef CFG_NO_FLASH - if (addr2info((ulong)of_flat_tree) != NULL) - of_data = (ulong)of_flat_tree; -#endif - } else if (ntohl(hdr->ih_magic) == IH_MAGIC) { - printf("## Flat Device Tree at %08lX\n", hdr); - print_image_hdr(hdr); - - if ((ntohl(hdr->ih_load) < ((unsigned long)hdr + ntohl(hdr->ih_size) + sizeof(hdr))) && - ((ntohl(hdr->ih_load) + ntohl(hdr->ih_size)) > (unsigned long)hdr)) { - puts ("ERROR: fdt overwritten - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } + for (arg = 1; arg < argc; ++arg) { + addr = simple_strtoul (argv[arg], NULL, 16); + if (image_info (addr) != 0) + rcode = 1; + } + return rcode; +} - puts (" Verifying Checksum ... "); - memmove (&header, (char *)hdr, sizeof(image_header_t)); - checksum = ntohl(header.ih_hcrc); - header.ih_hcrc = 0; +static int image_info (ulong addr) +{ + void *hdr = (void *)addr; - if(checksum != crc32(0, (uchar *)&header, sizeof(image_header_t))) { - puts ("ERROR: fdt header checksum invalid - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } + printf ("\n## Checking Image at %08lx ...\n", addr); - checksum = ntohl(hdr->ih_dcrc); - addr = (ulong)((uchar *)(hdr) + sizeof(image_header_t)); + switch (genimg_get_format (hdr)) { + case IMAGE_FORMAT_LEGACY: + puts (" Legacy image found\n"); + if (!image_check_magic (hdr)) { + puts (" Bad Magic Number\n"); + return 1; + } - if(checksum != crc32(0, (uchar *)addr, ntohl(hdr->ih_size))) { - puts ("ERROR: fdt checksum invalid - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } - puts ("OK\n"); + if (!image_check_hcrc (hdr)) { + puts (" Bad Header Checksum\n"); + return 1; + } - if (ntohl(hdr->ih_type) != IH_TYPE_FLATDT) { - puts ("ERROR: uImage is not a fdt - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } - if (ntohl(hdr->ih_comp) != IH_COMP_NONE) { - puts ("ERROR: uImage is compressed - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } -#if defined(CONFIG_OF_FLAT_TREE) - if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) { -#else - if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) != 0) { -#endif - puts ("ERROR: uImage data is not a fdt - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } + image_print_contents (hdr); - memmove((void *)ntohl(hdr->ih_load), - (void *)(of_flat_tree + sizeof(image_header_t)), - ntohl(hdr->ih_size)); - of_flat_tree = (char *)ntohl(hdr->ih_load); - } else { - puts ("Did not find a flat Flat Device Tree.\n" - "Must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } - printf (" Booting using the fdt at 0x%x\n", - of_flat_tree); - } else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1]) && (len_ptr[2])) { - u_long tail = ntohl(len_ptr[0]) % 4; - int i; - - /* skip kernel length, initrd length, and terminator */ - of_flat_tree = (char *)(&len_ptr[3]); - /* skip any additional image length fields */ - for (i=2; len_ptr[i]; ++i) - of_flat_tree += 4; - /* add kernel length, and align */ - of_flat_tree += ntohl(len_ptr[0]); - if (tail) { - of_flat_tree += 4 - tail; + puts (" Verifying Checksum ... "); + if (!image_check_dcrc (hdr)) { + puts (" Bad Data CRC\n"); + return 1; } + puts ("OK\n"); + return 0; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + puts (" FIT image found\n"); - /* add initrd length, and align */ - tail = ntohl(len_ptr[1]) % 4; - of_flat_tree += ntohl(len_ptr[1]); - if (tail) { - of_flat_tree += 4 - tail; + if (!fit_check_format (hdr)) { + puts ("Bad FIT image format!\n"); + return 1; } -#ifndef CFG_NO_FLASH - /* move the blob if it is in flash (set of_data to !null) */ - if (addr2info ((ulong)of_flat_tree) != NULL) - of_data = (ulong)of_flat_tree; + fit_print_contents (hdr); + return 0; #endif + default: + puts ("Unknown image format!\n"); + break; + } + return 1; +} -#if defined(CONFIG_OF_FLAT_TREE) - if (*((ulong *)(of_flat_tree)) != OF_DT_HEADER) { -#else - if (fdt_check_header (of_flat_tree) != 0) { +U_BOOT_CMD( + iminfo, CFG_MAXARGS, 1, do_iminfo, + "iminfo - print header information for application image\n", + "addr [addr ...]\n" + " - print header information for application image starting at\n" + " address 'addr' in memory; this includes verification of the\n" + " image contents (magic number, header and payload checksums)\n" +); #endif - puts ("ERROR: image is not a fdt - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } -#if defined(CONFIG_OF_FLAT_TREE) - if (((struct boot_param_header *)of_flat_tree)->totalsize != - ntohl (len_ptr[2])) { -#else - if (be32_to_cpu (fdt_totalsize (of_flat_tree)) != - ntohl(len_ptr[2])) { -#endif - puts ("ERROR: fdt size != image size - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } - } -#endif - if (!data) { - debug ("No initrd\n"); - } - if (data) { - if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ - initrd_start = data; - initrd_end = initrd_start + len; - } else { - initrd_start = (ulong)kbd - len; - initrd_start &= ~(4096 - 1); /* align on page */ +/*******************************************************************/ +/* imls - list all images found in flash */ +/*******************************************************************/ +#if defined(CONFIG_CMD_IMLS) +int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + flash_info_t *info; + int i, j; + void *hdr; + + for (i = 0, info = &flash_info[0]; + i < CFG_MAX_FLASH_BANKS; ++i, ++info) { - if (initrd_high) { - ulong nsp; + if (info->flash_id == FLASH_UNKNOWN) + goto next_bank; + for (j = 0; j < info->sector_count; ++j) { - /* - * the inital ramdisk does not need to be within - * CFG_BOOTMAPSZ as it is not accessed until after - * the mm system is initialised. - * - * do the stack bottom calculation again and see if - * the initrd will fit just below the monitor stack - * bottom without overwriting the area allocated - * above for command line args and board info. - */ - asm( "mr %0,1": "=r"(nsp) : ); - nsp -= 2048; /* just to be sure */ - nsp &= ~0xF; - if (nsp > initrd_high) /* limit as specified */ - nsp = initrd_high; - nsp -= len; - nsp &= ~(4096 - 1); /* align on page */ - if (nsp >= sp) - initrd_start = nsp; - } + hdr = (void *)info->start[j]; + if (!hdr) + goto next_sector; - show_boot_progress (12); - - debug ("## initrd at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", - data, data + len - 1, len, len); - - initrd_end = initrd_start + len; - printf (" Loading Ramdisk to %08lx, end %08lx ... ", - initrd_start, initrd_end); -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - { - size_t l = len; - void *to = (void *)initrd_start; - void *from = (void *)data; - - while (l > 0) { - size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l; - WATCHDOG_RESET(); - memmove (to, from, tail); - to += tail; - from += tail; - l -= tail; + switch (genimg_get_format (hdr)) { + case IMAGE_FORMAT_LEGACY: + if (!image_check_hcrc (hdr)) + goto next_sector; + + printf ("Legacy Image at %08lX:\n", (ulong)hdr); + image_print_contents (hdr); + + puts (" Verifying Checksum ... "); + if (!image_check_dcrc (hdr)) { + puts ("Bad Data CRC\n"); + } else { + puts ("OK\n"); + } + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + if (!fit_check_format (hdr)) + goto next_sector; + + printf ("FIT Image at %08lX:\n", (ulong)hdr); + fit_print_contents (hdr); + break; +#endif + default: + goto next_sector; } + +next_sector: ; } -#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ - memmove ((void *)initrd_start, (void *)data, len); -#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ - puts ("OK\n"); - } - } else { - initrd_start = 0; - initrd_end = 0; +next_bank: ; } -#if defined(CONFIG_OF_LIBFDT) + return (0); +} -#ifdef CFG_BOOTMAPSZ - /* - * The blob must be within CFG_BOOTMAPSZ, - * so we flag it to be copied if it is not. - */ - if (of_flat_tree >= (char *)CFG_BOOTMAPSZ) - of_data = (ulong)of_flat_tree; +U_BOOT_CMD( + imls, 1, 1, do_imls, + "imls - list all images found in flash\n", + "\n" + " - Prints information about all images found at sector\n" + " boundaries in flash.\n" +); #endif - /* move of_flat_tree if needed */ - if (of_data) { - int err; - ulong of_start, of_len; - - of_len = be32_to_cpu(fdt_totalsize(of_data)); - - /* position on a 4K boundary before the kbd */ - of_start = (ulong)kbd - of_len; - of_start &= ~(4096 - 1); /* align on page */ - debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", - of_data, of_data + of_len - 1, of_len, of_len); - - of_flat_tree = (char *)of_start; - printf (" Loading Device Tree to %08lx, end %08lx ... ", - of_start, of_start + of_len - 1); - err = fdt_open_into((void *)of_data, (void *)of_start, of_len); - if (err != 0) { - puts ("ERROR: fdt move failed - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } - puts ("OK\n"); - } - /* - * Add the chosen node if it doesn't exist, add the env and bd_t - * if the user wants it (the logic is in the subroutines). - */ - if (of_flat_tree) { - if (fdt_chosen(of_flat_tree, initrd_start, initrd_end, 0) < 0) { - puts ("ERROR: /chosen node create failed - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); +/*******************************************************************/ +/* helper routines */ +/*******************************************************************/ +#ifdef CONFIG_SILENT_CONSOLE +static void fixup_silent_linux () +{ + char buf[256], *start, *end; + char *cmdline = getenv ("bootargs"); + + /* Only fix cmdline when requested */ + if (!(gd->flags & GD_FLG_SILENT)) + return; + + debug ("before silent fix-up: %s\n", cmdline); + if (cmdline) { + if ((start = strstr (cmdline, "console=")) != NULL) { + end = strchr (start, ' '); + strncpy (buf, cmdline, (start - cmdline + 8)); + if (end) + strcpy (buf + (start - cmdline + 8), end); + else + buf[start - cmdline + 8] = '\0'; + } else { + strcpy (buf, cmdline); + strcat (buf, " console="); } -#ifdef CONFIG_OF_BOARD_SETUP - /* Call the board-specific fixup routine */ - ft_board_setup(of_flat_tree, gd->bd); -#endif + } else { + strcpy (buf, "console="); } -#endif /* CONFIG_OF_LIBFDT */ -#if defined(CONFIG_OF_FLAT_TREE) -#ifdef CFG_BOOTMAPSZ - /* - * The blob must be within CFG_BOOTMAPSZ, - * so we flag it to be copied if it is not. - */ - if (of_flat_tree >= (char *)CFG_BOOTMAPSZ) - of_data = (ulong)of_flat_tree; -#endif - /* move of_flat_tree if needed */ - if (of_data) { - ulong of_start, of_len; - of_len = ((struct boot_param_header *)of_data)->totalsize; - - /* provide extra 8k pad */ - of_start = (ulong)kbd - of_len - 8192; - of_start &= ~(4096 - 1); /* align on page */ - debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", - of_data, of_data + of_len - 1, of_len, of_len); - - of_flat_tree = (char *)of_start; - printf (" Loading Device Tree to %08lx, end %08lx ... ", - of_start, of_start + of_len - 1); - memmove ((void *)of_start, (void *)of_data, of_len); - puts ("OK\n"); - } - /* - * Create the /chosen node and modify the blob with board specific - * values as needed. - */ - ft_setup(of_flat_tree, kbd, initrd_start, initrd_end); - /* ft_dump_blob(of_flat_tree); */ -#endif - debug ("## Transferring control to Linux (at address %08lx) ...\n", - (ulong)kernel); + setenv ("bootargs", buf); + debug ("after silent fix-up: %s\n", buf); +} +#endif /* CONFIG_SILENT_CONSOLE */ - show_boot_progress (15); -#if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500) - unlock_ram_in_cache(); -#endif +/*******************************************************************/ +/* OS booting routines */ +/*******************************************************************/ -#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) - if (of_flat_tree) { /* device tree; boot new style */ - /* - * Linux Kernel Parameters (passing device tree): - * r3: pointer to the fdt, followed by the board info data - * r4: physical pointer to the kernel itself - * r5: NULL - * r6: NULL - * r7: NULL - */ - (*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0); - /* does not return */ +static void do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + bootm_headers_t *images) +{ + void (*loader)(bd_t *, image_header_t *, char *, char *); + image_header_t *os_hdr, *hdr; + ulong kernel_data, kernel_len; + char *consdev; + char *cmdline; + +#if defined(CONFIG_FIT) + if (!images->legacy_hdr_valid) { + fit_unsupported_reset ("NetBSD"); + do_reset (cmdtp, flag, argc, argv); } #endif - /* - * Linux Kernel Parameters (passing board info data): - * r3: ptr to board info data - * r4: initrd_start or 0 if no initrd - * r5: initrd_end - unused if r4 is 0 - * r6: Start of command line string - * r7: End of command line string - */ - (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); - /* does not return */ -} -#endif /* CONFIG_PPC */ - -static void -do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - ulong addr, - ulong *len_ptr, - int verify) -{ - image_header_t *hdr = &header; - - void (*loader)(bd_t *, image_header_t *, char *, char *); - image_header_t *img_addr; - char *consdev; - char *cmdline; - + hdr = images->legacy_hdr_os; /* * Booting a (NetBSD) kernel image @@ -1086,11 +889,12 @@ do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, * line, the name of the console device, and (optionally) the * address of the original image header. */ - - img_addr = 0; - if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) - img_addr = (image_header_t *) addr; - + os_hdr = NULL; + if (image_check_type (hdr, IH_TYPE_MULTI)) { + image_multi_getimg (hdr, 1, &kernel_data, &kernel_len); + if (kernel_len) + os_hdr = hdr; + } consdev = ""; #if defined (CONFIG_8xx_CONS_SMC1) @@ -1107,21 +911,21 @@ do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, ulong len; int i; - for (i=2, len=0 ; i<argc ; i+=1) + for (i = 2, len = 0; i < argc; i += 1) len += strlen (argv[i]) + 1; cmdline = malloc (len); - for (i=2, len=0 ; i<argc ; i+=1) { + for (i = 2, len = 0; i < argc; i += 1) { if (i > 2) cmdline[len++] = ' '; strcpy (&cmdline[len], argv[i]); len += strlen (argv[i]); } - } else if ((cmdline = getenv("bootargs")) == NULL) { + } else if ((cmdline = getenv ("bootargs")) == NULL) { cmdline = ""; } - loader = (void (*)(bd_t *, image_header_t *, char *, char *)) ntohl(hdr->ih_ep); + loader = (void (*)(bd_t *, image_header_t *, char *, char *))image_get_ep (hdr); printf ("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n", (ulong)loader); @@ -1135,20 +939,101 @@ do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, * r5: console device * r6: boot args string */ - (*loader) (gd->bd, img_addr, consdev, cmdline); + (*loader) (gd->bd, os_hdr, consdev, cmdline); } -#if defined(CONFIG_ARTOS) && defined(CONFIG_PPC) +#ifdef CONFIG_LYNXKDI +static void do_bootm_lynxkdi (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + bootm_headers_t *images) +{ + image_header_t *hdr = images->legacy_hdr_os; -/* Function that returns a character from the environment */ -extern uchar (*env_get_char)(int); +#if defined(CONFIG_FIT) + if (!images->legacy_hdr_valid) { + fit_unsupported_reset ("Lynx"); + do_reset (cmdtp, flag, argc, argv); + } +#endif -static void -do_bootm_artos (cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - ulong addr, - ulong *len_ptr, - int verify) + lynxkdi_boot ((image_header_t *)hdr); +} +#endif /* CONFIG_LYNXKDI */ + +static void do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + bootm_headers_t *images) +{ + image_header_t *hdr = images->legacy_hdr_os; + void (*entry_point)(bd_t *); + +#if defined(CONFIG_FIT) + if (!images->legacy_hdr_valid) { + fit_unsupported_reset ("RTEMS"); + do_reset (cmdtp, flag, argc, argv); + } +#endif + + entry_point = (void (*)(bd_t *))image_get_ep (hdr); + + printf ("## Transferring control to RTEMS (at address %08lx) ...\n", + (ulong)entry_point); + + show_boot_progress (15); + + /* + * RTEMS Parameters: + * r3: ptr to board info data + */ + (*entry_point)(gd->bd); +} + +#if defined(CONFIG_CMD_ELF) +static void do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + bootm_headers_t *images) +{ + char str[80]; + image_header_t *hdr = images->legacy_hdr_os; + +#if defined(CONFIG_FIT) + if (hdr == NULL) { + fit_unsupported_reset ("VxWorks"); + do_reset (cmdtp, flag, argc, argv); + } +#endif + + sprintf(str, "%x", image_get_ep (hdr)); /* write entry-point into string */ + setenv("loadaddr", str); + do_bootvx(cmdtp, 0, 0, NULL); +} + +static void do_bootm_qnxelf(cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + bootm_headers_t *images) +{ + char *local_args[2]; + char str[16]; + image_header_t *hdr = images->legacy_hdr_os; + +#if defined(CONFIG_FIT) + if (!images->legacy_hdr_valid) { + fit_unsupported_reset ("QNX"); + do_reset (cmdtp, flag, argc, argv); + } +#endif + + sprintf(str, "%x", image_get_ep (hdr)); /* write entry-point into string */ + local_args[0] = argv[0]; + local_args[1] = str; /* and provide it via the arguments */ + do_bootelf(cmdtp, 0, 2, local_args); +} +#endif + +#if defined(CONFIG_ARTOS) && defined(CONFIG_PPC) +static void do_bootm_artos (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + bootm_headers_t *images) { ulong top; char *s, *cmdline; @@ -1156,7 +1041,14 @@ do_bootm_artos (cmd_tbl_t *cmdtp, int flag, int i, j, nxt, len, envno, envsz; bd_t *kbd; void (*entry)(bd_t *bd, char *cmdline, char **fwenv, ulong top); - image_header_t *hdr = &header; + image_header_t *hdr = images->legacy_hdr_os; + +#if defined(CONFIG_FIT) + if (!images->legacy_hdr_valid) { + fit_unsupported_reset ("ARTOS"); + do_reset (cmdtp, flag, argc, argv); + } +#endif /* * Booting an ARTOS kernel image + application @@ -1177,27 +1069,27 @@ do_bootm_artos (cmd_tbl_t *cmdtp, int flag, debug ("=> set upper limit to 0x%08lX\n", top); /* first check the artos specific boot args, then the linux args*/ - if ((s = getenv("abootargs")) == NULL && (s = getenv("bootargs")) == NULL) + if ((s = getenv( "abootargs")) == NULL && (s = getenv ("bootargs")) == NULL) s = ""; /* get length of cmdline, and place it */ - len = strlen(s); + len = strlen (s); top = (top - (len + 1)) & ~0xF; cmdline = (char *)top; debug ("## cmdline at 0x%08lX ", top); - strcpy(cmdline, s); + strcpy (cmdline, s); /* copy bdinfo */ - top = (top - sizeof(bd_t)) & ~0xF; + top = (top - sizeof (bd_t)) & ~0xF; debug ("## bd at 0x%08lX ", top); kbd = (bd_t *)top; - memcpy(kbd, gd->bd, sizeof(bd_t)); + memcpy (kbd, gd->bd, sizeof (bd_t)); /* first find number of env entries, and their size */ envno = 0; envsz = 0; - for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { - for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) + for (i = 0; env_get_char (i) != '\0'; i = nxt + 1) { + for (nxt = i; env_get_char (nxt) != '\0'; ++nxt) ; envno++; envsz += (nxt - i) + 1; /* plus trailing zero */ @@ -1205,7 +1097,7 @@ do_bootm_artos (cmd_tbl_t *cmdtp, int flag, envno++; /* plus the terminating zero */ debug ("## %u envvars total size %u ", envno, envsz); - top = (top - sizeof(char **)*envno) & ~0xF; + top = (top - sizeof (char **) * envno) & ~0xF; fwenv = (char **)top; debug ("## fwenv at 0x%08lX ", top); @@ -1214,428 +1106,17 @@ do_bootm_artos (cmd_tbl_t *cmdtp, int flag, ss = fwenv; /* now copy them */ - for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { - for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) + for (i = 0; env_get_char (i) != '\0'; i = nxt + 1) { + for (nxt = i; env_get_char (nxt) != '\0'; ++nxt) ; *ss++ = s; for (j = i; j < nxt; ++j) - *s++ = env_get_char(j); + *s++ = env_get_char (j); *s++ = '\0'; } *ss++ = NULL; /* terminate */ - entry = (void (*)(bd_t *, char *, char **, ulong))ntohl(hdr->ih_ep); - (*entry)(kbd, cmdline, fwenv, top); -} -#endif - - -#if defined(CONFIG_CMD_BOOTD) -int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ - int rcode = 0; -#ifndef CFG_HUSH_PARSER - if (run_command (getenv ("bootcmd"), flag) < 0) rcode = 1; -#else - if (parse_string_outer(getenv("bootcmd"), - FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0 ) rcode = 1; -#endif - return rcode; -} - -U_BOOT_CMD( - boot, 1, 1, do_bootd, - "boot - boot default, i.e., run 'bootcmd'\n", - NULL -); - -/* keep old command name "bootd" for backward compatibility */ -U_BOOT_CMD( - bootd, 1, 1, do_bootd, - "bootd - boot default, i.e., run 'bootcmd'\n", - NULL -); - -#endif - -#if defined(CONFIG_CMD_IMI) -int do_iminfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ - int arg; - ulong addr; - int rcode=0; - - if (argc < 2) { - return image_info (load_addr); - } - - for (arg=1; arg <argc; ++arg) { - addr = simple_strtoul(argv[arg], NULL, 16); - if (image_info (addr) != 0) rcode = 1; - } - return rcode; -} - -static int image_info (ulong addr) -{ - ulong data, len, checksum; - image_header_t *hdr = &header; - - printf ("\n## Checking Image at %08lx ...\n", addr); - - /* Copy header so we can blank CRC field for re-calculation */ - memmove (&header, (char *)addr, sizeof(image_header_t)); - - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - puts (" Bad Magic Number\n"); - return 1; - } - - data = (ulong)&header; - len = sizeof(image_header_t); - - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (uchar *)data, len) != checksum) { - puts (" Bad Header Checksum\n"); - return 1; - } - - /* for multi-file images we need the data part, too */ - print_image_hdr ((image_header_t *)addr); - - data = addr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); - - puts (" Verifying Checksum ... "); - if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { - puts (" Bad Data CRC\n"); - return 1; - } - puts ("OK\n"); - return 0; + entry = (void (*)(bd_t *, char *, char **, ulong))image_get_ep (hdr); + (*entry) (kbd, cmdline, fwenv, top); } - -U_BOOT_CMD( - iminfo, CFG_MAXARGS, 1, do_iminfo, - "iminfo - print header information for application image\n", - "addr [addr ...]\n" - " - print header information for application image starting at\n" - " address 'addr' in memory; this includes verification of the\n" - " image contents (magic number, header and payload checksums)\n" -); - #endif - -#if defined(CONFIG_CMD_IMLS) -/*----------------------------------------------------------------------- - * List all images found in flash. - */ -int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ - flash_info_t *info; - int i, j; - image_header_t *hdr; - ulong data, len, checksum; - - for (i=0, info=&flash_info[0]; i<CFG_MAX_FLASH_BANKS; ++i, ++info) { - if (info->flash_id == FLASH_UNKNOWN) - goto next_bank; - for (j=0; j<info->sector_count; ++j) { - - if (!(hdr=(image_header_t *)info->start[j]) || - (ntohl(hdr->ih_magic) != IH_MAGIC)) - goto next_sector; - - /* Copy header so we can blank CRC field for re-calculation */ - memmove (&header, (char *)hdr, sizeof(image_header_t)); - - checksum = ntohl(header.ih_hcrc); - header.ih_hcrc = 0; - - if (crc32 (0, (uchar *)&header, sizeof(image_header_t)) - != checksum) - goto next_sector; - - printf ("Image at %08lX:\n", (ulong)hdr); - print_image_hdr( hdr ); - - data = (ulong)hdr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); - - puts (" Verifying Checksum ... "); - if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { - puts (" Bad Data CRC\n"); - } - puts ("OK\n"); -next_sector: ; - } -next_bank: ; - } - - return (0); -} - -U_BOOT_CMD( - imls, 1, 1, do_imls, - "imls - list all images found in flash\n", - "\n" - " - Prints information about all images found at sector\n" - " boundaries in flash.\n" -); -#endif - -void -print_image_hdr (image_header_t *hdr) -{ -#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) - time_t timestamp = (time_t)ntohl(hdr->ih_time); - struct rtc_time tm; -#endif - - printf (" Image Name: %.*s\n", IH_NMLEN, hdr->ih_name); -#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) - to_tm (timestamp, &tm); - printf (" Created: %4d-%02d-%02d %2d:%02d:%02d UTC\n", - tm.tm_year, tm.tm_mon, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); -#endif - puts (" Image Type: "); print_type(hdr); - printf ("\n Data Size: %d Bytes = ", ntohl(hdr->ih_size)); - print_size (ntohl(hdr->ih_size), "\n"); - printf (" Load Address: %08x\n" - " Entry Point: %08x\n", - ntohl(hdr->ih_load), ntohl(hdr->ih_ep)); - - if (hdr->ih_type == IH_TYPE_MULTI) { - int i; - ulong len; - ulong *len_ptr = (ulong *)((ulong)hdr + sizeof(image_header_t)); - - puts (" Contents:\n"); - for (i=0; (len = ntohl(*len_ptr)); ++i, ++len_ptr) { - printf (" Image %d: %8ld Bytes = ", i, len); - print_size (len, "\n"); - } - } -} - - -static void -print_type (image_header_t *hdr) -{ - char *os, *arch, *type, *comp; - - switch (hdr->ih_os) { - case IH_OS_INVALID: os = "Invalid OS"; break; - case IH_OS_NETBSD: os = "NetBSD"; break; - case IH_OS_LINUX: os = "Linux"; break; - case IH_OS_VXWORKS: os = "VxWorks"; break; - case IH_OS_QNX: os = "QNX"; break; - case IH_OS_U_BOOT: os = "U-Boot"; break; - case IH_OS_RTEMS: os = "RTEMS"; break; -#ifdef CONFIG_ARTOS - case IH_OS_ARTOS: os = "ARTOS"; break; -#endif -#ifdef CONFIG_LYNXKDI - case IH_OS_LYNXOS: os = "LynxOS"; break; -#endif - default: os = "Unknown OS"; break; - } - - switch (hdr->ih_arch) { - case IH_CPU_INVALID: arch = "Invalid CPU"; break; - case IH_CPU_ALPHA: arch = "Alpha"; break; - case IH_CPU_ARM: arch = "ARM"; break; - case IH_CPU_AVR32: arch = "AVR32"; break; - case IH_CPU_BLACKFIN: arch = "Blackfin"; break; - case IH_CPU_I386: arch = "Intel x86"; break; - case IH_CPU_IA64: arch = "IA64"; break; - case IH_CPU_M68K: arch = "M68K"; break; - case IH_CPU_MICROBLAZE: arch = "Microblaze"; break; - case IH_CPU_MIPS64: arch = "MIPS 64 Bit"; break; - case IH_CPU_MIPS: arch = "MIPS"; break; - case IH_CPU_NIOS2: arch = "Nios-II"; break; - case IH_CPU_NIOS: arch = "Nios"; break; - case IH_CPU_PPC: arch = "PowerPC"; break; - case IH_CPU_S390: arch = "IBM S390"; break; - case IH_CPU_SH: arch = "SuperH"; break; - case IH_CPU_SPARC64: arch = "SPARC 64 Bit"; break; - case IH_CPU_SPARC: arch = "SPARC"; break; - default: arch = "Unknown Architecture"; break; - } - - switch (hdr->ih_type) { - case IH_TYPE_INVALID: type = "Invalid Image"; break; - case IH_TYPE_STANDALONE:type = "Standalone Program"; break; - case IH_TYPE_KERNEL: type = "Kernel Image"; break; - case IH_TYPE_RAMDISK: type = "RAMDisk Image"; break; - case IH_TYPE_MULTI: type = "Multi-File Image"; break; - case IH_TYPE_FIRMWARE: type = "Firmware"; break; - case IH_TYPE_SCRIPT: type = "Script"; break; - case IH_TYPE_FLATDT: type = "Flat Device Tree"; break; - default: type = "Unknown Image"; break; - } - - switch (hdr->ih_comp) { - case IH_COMP_NONE: comp = "uncompressed"; break; - case IH_COMP_GZIP: comp = "gzip compressed"; break; - case IH_COMP_BZIP2: comp = "bzip2 compressed"; break; - default: comp = "unknown compression"; break; - } - - printf ("%s %s %s (%s)", arch, os, type, comp); -} - -#define ZALLOC_ALIGNMENT 16 - -static void *zalloc(void *x, unsigned items, unsigned size) -{ - void *p; - - size *= items; - size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1); - - p = malloc (size); - - return (p); -} - -static void zfree(void *x, void *addr, unsigned nb) -{ - free (addr); -} - -#define HEAD_CRC 2 -#define EXTRA_FIELD 4 -#define ORIG_NAME 8 -#define COMMENT 0x10 -#define RESERVED 0xe0 - -#define DEFLATED 8 - -int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp) -{ - z_stream s; - int r, i, flags; - - /* skip header */ - i = 10; - flags = src[3]; - if (src[2] != DEFLATED || (flags & RESERVED) != 0) { - puts ("Error: Bad gzipped data\n"); - return (-1); - } - if ((flags & EXTRA_FIELD) != 0) - i = 12 + src[10] + (src[11] << 8); - if ((flags & ORIG_NAME) != 0) - while (src[i++] != 0) - ; - if ((flags & COMMENT) != 0) - while (src[i++] != 0) - ; - if ((flags & HEAD_CRC) != 0) - i += 2; - if (i >= *lenp) { - puts ("Error: gunzip out of data in header\n"); - return (-1); - } - - s.zalloc = zalloc; - s.zfree = zfree; -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - s.outcb = (cb_func)WATCHDOG_RESET; -#else - s.outcb = Z_NULL; -#endif /* CONFIG_HW_WATCHDOG */ - - r = inflateInit2(&s, -MAX_WBITS); - if (r != Z_OK) { - printf ("Error: inflateInit2() returned %d\n", r); - return (-1); - } - s.next_in = src + i; - s.avail_in = *lenp - i; - s.next_out = dst; - s.avail_out = dstlen; - r = inflate(&s, Z_FINISH); - if (r != Z_OK && r != Z_STREAM_END) { - printf ("Error: inflate() returned %d\n", r); - return (-1); - } - *lenp = s.next_out - (unsigned char *) dst; - inflateEnd(&s); - - return (0); -} - -#ifdef CONFIG_BZIP2 -void bz_internal_error(int errcode) -{ - printf ("BZIP2 internal error %d\n", errcode); -} -#endif /* CONFIG_BZIP2 */ - -static void -do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) -{ - image_header_t *hdr = &header; - void (*entry_point)(bd_t *); - - entry_point = (void (*)(bd_t *)) ntohl(hdr->ih_ep); - - printf ("## Transferring control to RTEMS (at address %08lx) ...\n", - (ulong)entry_point); - - show_boot_progress (15); - - /* - * RTEMS Parameters: - * r3: ptr to board info data - */ - - (*entry_point ) ( gd->bd ); -} - -#if defined(CONFIG_CMD_ELF) -static void -do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) -{ - image_header_t *hdr = &header; - char str[80]; - - sprintf(str, "%x", ntohl(hdr->ih_ep)); /* write entry-point into string */ - setenv("loadaddr", str); - do_bootvx(cmdtp, 0, 0, NULL); -} - -static void -do_bootm_qnxelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) -{ - image_header_t *hdr = &header; - char *local_args[2]; - char str[16]; - - sprintf(str, "%x", ntohl(hdr->ih_ep)); /* write entry-point into string */ - local_args[0] = argv[0]; - local_args[1] = str; /* and provide it via the arguments */ - do_bootelf(cmdtp, 0, 2, local_args); -} -#endif - -#ifdef CONFIG_LYNXKDI -static void -do_bootm_lynxkdi (cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - ulong addr, - ulong *len_ptr, - int verify) -{ - lynxkdi_boot( &header ); -} - -#endif /* CONFIG_LYNXKDI */ diff --git a/common/cmd_doc.c b/common/cmd_doc.c index 3d717c039d..83aba3744e 100644 --- a/common/cmd_doc.c +++ b/common/cmd_doc.c @@ -205,6 +205,9 @@ int do_docboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ulong offset = 0; image_header_t *hdr; int rcode = 0; +#if defined(CONFIG_FIT) + const void *fit_hdr; +#endif show_boot_progress (34); switch (argc) { @@ -261,21 +264,36 @@ int do_docboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } show_boot_progress (38); - hdr = (image_header_t *)addr; + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *)addr; - if (hdr->ih_magic == IH_MAGIC) { + image_print_contents (hdr); - print_image_hdr (hdr); + cnt = image_get_image_size (hdr); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + show_boot_progress (-130); + puts ("** Bad FIT image format\n"); + return 1; + } + show_boot_progress (131); + puts ("Fit image detected...\n"); - cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); - cnt -= SECTORSIZE; - } else { - puts ("\n** Bad Magic Number **\n"); + cnt = fit_get_size (fit_hdr); + break; +#endif + default: show_boot_progress (-39); + puts ("** Unknown image type\n"); return 1; } show_boot_progress (39); + cnt -= SECTORSIZE; if (doc_rw (doc_dev_desc + dev, 1, offset + SECTORSIZE, cnt, NULL, (u_char *)(addr+SECTORSIZE))) { printf ("** Read error on %d\n", dev); @@ -284,6 +302,12 @@ int do_docboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } show_boot_progress (40); +#if defined(CONFIG_FIT) + /* This cannot be done earlier, we need complete FIT image in RAM first */ + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) + fit_print_contents ((const void *)addr); +#endif + /* Loading ok, update default load address */ load_addr = addr; diff --git a/common/cmd_fdc.c b/common/cmd_fdc.c index 7349412c77..bf283702d3 100644 --- a/common/cmd_fdc.c +++ b/common/cmd_fdc.c @@ -788,6 +788,9 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) int i,nrofblk; char *ep; int rcode = 0; +#if defined(CONFIG_FIT) + const void *fit_hdr; +#endif switch (argc) { case 1: @@ -835,14 +838,31 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) printf("result%d: 0x%02X\n",i,pCMD->result[i]); return 1; } - hdr = (image_header_t *)addr; - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - printf ("Bad Magic Number\n"); + + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *)addr; + image_print_contents (hdr); + + imsize = image_get_image_size (hdr); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + puts ("** Bad FIT image format\n"); + return 1; + } + puts ("Fit image detected...\n"); + + imsize = fit_get_size (fit_hdr); + break; +#endif + default: + puts ("** Unknown image type\n"); return 1; } - print_image_hdr(hdr); - imsize= ntohl(hdr->ih_size)+sizeof(image_header_t); nrofblk=imsize/512; if((imsize%512)>0) nrofblk++; @@ -858,23 +878,28 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) printf("OK %ld Bytes loaded.\n",imsize); flush_cache (addr, imsize); - /* Loading ok, update default load address */ +#if defined(CONFIG_FIT) + /* This cannot be done earlier, we need complete FIT image in RAM first */ + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) + fit_print_contents ((const void *)addr); +#endif + + /* Loading ok, update default load address */ load_addr = addr; - if(hdr->ih_type == IH_TYPE_KERNEL) { - /* Check if we should attempt an auto-start */ - if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) { - char *local_args[2]; - extern int do_bootm (cmd_tbl_t *, int, int, char *[]); - local_args[0] = argv[0]; - local_args[1] = NULL; + /* Check if we should attempt an auto-start */ + if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) { + char *local_args[2]; + extern int do_bootm (cmd_tbl_t *, int, int, char *[]); - printf ("Automatic boot of image at addr 0x%08lX ...\n", addr); + local_args[0] = argv[0]; + local_args[1] = NULL; - do_bootm (cmdtp, 0, 1, local_args); - rcode ++; - } + printf ("Automatic boot of image at addr 0x%08lX ...\n", addr); + + do_bootm (cmdtp, 0, 1, local_args); + rcode ++; } return rcode; } diff --git a/common/cmd_fpga.c b/common/cmd_fpga.c index f55447ab1f..9141dcce92 100644 --- a/common/cmd_fpga.c +++ b/common/cmd_fpga.c @@ -164,6 +164,10 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) char *devstr = getenv ("fpga"); char *datastr = getenv ("fpgadata"); int rc = FPGA_FAIL; +#if defined (CONFIG_FIT) + const char *fit_uname = NULL; + ulong fit_addr; +#endif if (devstr) dev = (int) simple_strtoul (devstr, NULL, 16); @@ -173,9 +177,22 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) switch (argc) { case 5: /* fpga <op> <dev> <data> <datasize> */ data_size = simple_strtoul (argv[4], NULL, 16); + case 4: /* fpga <op> <dev> <data> */ - fpga_data = (void *) simple_strtoul (argv[3], NULL, 16); +#if defined(CONFIG_FIT) + if (fit_parse_subimage (argv[3], (ulong)fpga_data, + &fit_addr, &fit_uname)) { + fpga_data = (void *)fit_addr; + debug ("* fpga: subimage '%s' from FIT image at 0x%08lx\n", + fit_uname, fit_addr); + } else +#endif + { + fpga_data = (void *) simple_strtoul (argv[3], NULL, 16); + debug ("* fpga: cmdline image address = 0x%08lx\n", (ulong)fpga_data); + } PRINTF ("%s: fpga_data = 0x%x\n", __FUNCTION__, (uint) fpga_data); + case 3: /* fpga <op> <dev | data addr> */ dev = (int) simple_strtoul (argv[2], NULL, 16); PRINTF ("%s: device = %d\n", __FUNCTION__, dev); @@ -183,14 +200,29 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) if ((argc == 3) && (dev > fpga_count ())) { /* must be buffer ptr */ PRINTF ("%s: Assuming buffer pointer in arg 3\n", __FUNCTION__); - fpga_data = (void *) dev; + +#if defined(CONFIG_FIT) + if (fit_parse_subimage (argv[2], (ulong)fpga_data, + &fit_addr, &fit_uname)) { + fpga_data = (void *)fit_addr; + debug ("* fpga: subimage '%s' from FIT image at 0x%08lx\n", + fit_uname, fit_addr); + } else +#endif + { + fpga_data = (void *) dev; + debug ("* fpga: cmdline image address = 0x%08lx\n", (ulong)fpga_data); + } + PRINTF ("%s: fpga_data = 0x%x\n", __FUNCTION__, (uint) fpga_data); dev = FPGA_INVALID_DEVICE; /* reset device num */ } + case 2: /* fpga <op> */ op = (int) fpga_get_op (argv[1]); break; + default: PRINTF ("%s: Too many or too few args (%d)\n", __FUNCTION__, argc); @@ -216,19 +248,61 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) break; case FPGA_LOADMK: - { - image_header_t header; - image_header_t *hdr = &header; - ulong data; - - memmove (&header, (char *)fpga_data, sizeof(image_header_t)); - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - puts ("Bad Magic Number\n"); - return 1; + switch (genimg_get_format (fpga_data)) { + case IMAGE_FORMAT_LEGACY: + { + image_header_t *hdr = (image_header_t *)fpga_data; + ulong data; + + data = (ulong)image_get_data (hdr); + data_size = image_get_data_size (hdr); + rc = fpga_load (dev, (void *)data, data_size); + } + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + { + const void *fit_hdr = (const void *)fpga_data; + int noffset; + void *fit_data; + + if (fit_uname == NULL) { + puts ("No FIT subimage unit name\n"); + return 1; + } + + if (!fit_check_format (fit_hdr)) { + puts ("Bad FIT image format\n"); + return 1; + } + + /* get fpga component image node offset */ + noffset = fit_image_get_node (fit_hdr, fit_uname); + if (noffset < 0) { + printf ("Can't find '%s' FIT subimage\n", fit_uname); + return 1; + } + + /* verify integrity */ + if (!fit_image_check_hashes (fit_hdr, noffset)) { + puts ("Bad Data Hash\n"); + return 1; + } + + /* get fpga subimage data address and length */ + if (fit_image_get_data (fit_hdr, noffset, &fit_data, &data_size)) { + puts ("Could not find fpga subimage data\n"); + return 1; + } + + rc = fpga_load (dev, fit_data, data_size); } - data = ((ulong)fpga_data + sizeof(image_header_t)); - data_size = ntohl(hdr->ih_size); - rc = fpga_load (dev, (void *)data, data_size); + break; +#endif + default: + puts ("** Unknown image type\n"); + rc = FPGA_FAIL; + break; } break; @@ -283,4 +357,9 @@ U_BOOT_CMD (fpga, 6, 1, do_fpga, "\tload\tLoad device from memory buffer\n" "\tloadb\tLoad device from bitstream buffer (Xilinx devices only)\n" "\tloadmk\tLoad device generated with mkimage\n" - "\tdump\tLoad device to memory buffer\n"); + "\tdump\tLoad device to memory buffer\n" +#if defined(CONFIG_FIT) + "\tFor loadmk operating on FIT format uImage address must include\n" + "\tsubimage unit name in the form of addr:<subimg_uname>\n" +#endif +); diff --git a/common/cmd_ide.c b/common/cmd_ide.c index c38be4f1a7..8ace970c73 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -366,10 +366,13 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) char *boot_device = NULL; char *ep; int dev, part = 0; - ulong addr, cnt, checksum; + ulong addr, cnt; disk_partition_t info; image_header_t *hdr; int rcode = 0; +#if defined(CONFIG_FIT) + const void *fit_hdr; +#endif show_boot_progress (41); switch (argc) { @@ -446,29 +449,43 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } show_boot_progress (48); - hdr = (image_header_t *)addr; + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *)addr; - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - printf("\n** Bad Magic Number **\n"); - show_boot_progress (-49); - return 1; - } - show_boot_progress (49); + show_boot_progress (49); - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; + if (!image_check_hcrc (hdr)) { + puts ("\n** Bad Header Checksum **\n"); + show_boot_progress (-50); + return 1; + } + show_boot_progress (50); + + image_print_contents (hdr); - if (crc32 (0, (uchar *)hdr, sizeof(image_header_t)) != checksum) { - puts ("\n** Bad Header Checksum **\n"); - show_boot_progress (-50); + cnt = image_get_image_size (hdr); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + show_boot_progress (-140); + puts ("** Bad FIT image format\n"); + return 1; + } + show_boot_progress (141); + puts ("Fit image detected...\n"); + + cnt = fit_get_size (fit_hdr); + break; +#endif + default: + show_boot_progress (-49); + puts ("** Unknown image type\n"); return 1; } - show_boot_progress (50); - hdr->ih_hcrc = htonl(checksum); /* restore checksum for later use */ - print_image_hdr (hdr); - - cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); cnt += info.blksz - 1; cnt /= info.blksz; cnt -= 1; @@ -481,6 +498,11 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } show_boot_progress (51); +#if defined(CONFIG_FIT) + /* This cannot be done earlier, we need complete FIT image in RAM first */ + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) + fit_print_contents ((const void *)addr); +#endif /* Loading ok, update default load address */ diff --git a/common/cmd_load.c b/common/cmd_load.c index 204c3ebf19..1b75a7b5ec 100644 --- a/common/cmd_load.c +++ b/common/cmd_load.c @@ -521,8 +521,15 @@ int do_load_serial_bin (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) char *s; if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) { - printf("Running autoscript at addr 0x%08lX ...\n", load_addr); - rcode = autoscript (load_addr); + printf ("Running autoscript at addr 0x%08lX", load_addr); + + s = getenv ("autoscript_uname"); + if (s) + printf (":%s ...\n", s); + else + puts (" ...\n"); + + rcode = autoscript (load_addr, s); } } #endif diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 8d6c959584..7b1f830465 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -484,6 +484,9 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, ulong cnt; image_header_t *hdr; int jffs2 = 0; +#if defined(CONFIG_FIT) + const void *fit_hdr; +#endif s = strchr(cmd, '.'); if (s != NULL && @@ -512,18 +515,35 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, } show_boot_progress (56); - hdr = (image_header_t *) addr; + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *)addr; + + show_boot_progress (57); + image_print_contents (hdr); - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic); + cnt = image_get_image_size (hdr); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + show_boot_progress (-150); + puts ("** Bad FIT image format\n"); + return 1; + } + show_boot_progress (151); + puts ("Fit image detected...\n"); + + cnt = fit_get_size (fit_hdr); + break; +#endif + default: show_boot_progress (-57); + puts ("** Unknown image type\n"); return 1; } - show_boot_progress (57); - - print_image_hdr(hdr); - cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t)); if (jffs2) { nand_read_options_t opts; memset(&opts, 0, sizeof(opts)); @@ -543,6 +563,12 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, } show_boot_progress (58); +#if defined(CONFIG_FIT) + /* This cannot be done earlier, we need complete FIT image in RAM first */ + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) + fit_print_contents ((const void *)addr); +#endif + /* Loading ok, update default load address */ load_addr = addr; @@ -925,6 +951,10 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ulong offset = 0; image_header_t *hdr; int rcode = 0; +#if defined(CONFIG_FIT) + const void *fit_hdr; +#endif + show_boot_progress (52); switch (argc) { case 1: @@ -980,17 +1010,31 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } show_boot_progress (56); - hdr = (image_header_t *)addr; - - if (ntohl(hdr->ih_magic) == IH_MAGIC) { + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *)addr; + image_print_contents (hdr); - print_image_hdr (hdr); - - cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); + cnt = image_get_image_size (hdr); cnt -= SECTORSIZE; - } else { - printf ("\n** Bad Magic Number 0x%x **\n", ntohl(hdr->ih_magic)); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + show_boot_progress (-150); + puts ("** Bad FIT image format\n"); + return 1; + } + show_boot_progress (151); + puts ("Fit image detected...\n"); + + cnt = fit_get_size (fit_hdr); + break; +#endif + default: show_boot_progress (-57); + puts ("** Unknown image type\n"); return 1; } show_boot_progress (57); @@ -1004,6 +1048,12 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } show_boot_progress (58); +#if defined(CONFIG_FIT) + /* This cannot be done earlier, we need complete FIT image in RAM first */ + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) + fit_print_contents ((const void *)addr); +#endif + /* Loading ok, update default load address */ load_addr = addr; diff --git a/common/cmd_net.c b/common/cmd_net.c index dbf6b861b1..79e910c764 100644 --- a/common/cmd_net.c +++ b/common/cmd_net.c @@ -220,9 +220,16 @@ netboot_common (proto_t proto, cmd_tbl_t *cmdtp, int argc, char *argv[]) #ifdef CONFIG_AUTOSCRIPT if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) { - printf("Running autoscript at addr 0x%08lX ...\n", load_addr); + printf ("Running autoscript at addr 0x%08lX", load_addr); + + s = getenv ("autoscript_uname"); + if (s) + printf (":%s ...\n", s); + else + puts (" ...\n"); + show_boot_progress (83); - rcode = autoscript (load_addr); + rcode = autoscript (load_addr, s); } #endif if (rcode < 0) diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c index 1cdec159f5..f49531e96b 100644 --- a/common/cmd_scsi.c +++ b/common/cmd_scsi.c @@ -207,10 +207,13 @@ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) char *boot_device = NULL; char *ep; int dev, part = 0; - ulong addr, cnt, checksum; + ulong addr, cnt; disk_partition_t info; image_header_t *hdr; int rcode = 0; +#if defined(CONFIG_FIT) + const void *fit_hdr; +#endif switch (argc) { case 1: @@ -273,24 +276,35 @@ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return 1; } - hdr = (image_header_t *)addr; + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *)addr; - if (ntohl(hdr->ih_magic) == IH_MAGIC) { - printf("\n** Bad Magic Number **\n"); - return 1; - } + if (!image_check_hcrc (hdr)) { + puts ("\n** Bad Header Checksum **\n"); + return 1; + } - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; + image_print_contents (hdr); + cnt = image_get_image_size (hdr); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + puts ("** Bad FIT image format\n"); + return 1; + } + puts ("Fit image detected...\n"); - if (crc32 (0, (uchar *)hdr, sizeof(image_header_t)) != checksum) { - puts ("\n** Bad Header Checksum **\n"); + cnt = fit_get_size (fit_hdr); + break; +#endif + default: + puts ("** Unknown image type\n"); return 1; } - hdr->ih_hcrc = htonl(checksum); /* restore checksum for later use */ - print_image_hdr (hdr); - cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); cnt += info.blksz - 1; cnt /= info.blksz; cnt -= 1; @@ -300,6 +314,13 @@ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) printf ("** Read error on %d:%d\n", dev, part); return 1; } + +#if defined(CONFIG_FIT) + /* This cannot be done earlier, we need complete FIT image in RAM first */ + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) + fit_print_contents ((const void *)addr); +#endif + /* Loading ok, update default load address */ load_addr = addr; diff --git a/common/cmd_usb.c b/common/cmd_usb.c index ad3240708b..23413b5103 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -311,11 +311,13 @@ int do_usbboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) char *boot_device = NULL; char *ep; int dev, part=1, rcode; - ulong addr, cnt, checksum; + ulong addr, cnt; disk_partition_t info; image_header_t *hdr; block_dev_desc_t *stor_dev; - +#if defined(CONFIG_FIT) + const void *fit_hdr; +#endif switch (argc) { case 1: @@ -386,25 +388,36 @@ int do_usbboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return 1; } - hdr = (image_header_t *)addr; + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *)addr; - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - printf("\n** Bad Magic Number **\n"); - return 1; - } + if (!image_check_hcrc (hdr)) { + puts ("\n** Bad Header Checksum **\n"); + return 1; + } - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; + image_print_contents (hdr); - if (crc32 (0, (uchar *)hdr, sizeof(image_header_t)) != checksum) { - puts ("\n** Bad Header Checksum **\n"); + cnt = image_get_image_size (hdr); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + puts ("** Bad FIT image format\n"); + return 1; + } + puts ("Fit image detected...\n"); + + cnt = fit_get_size (fit_hdr); + break; +#endif + default: + puts ("** Unknown image type\n"); return 1; } - hdr->ih_hcrc = htonl(checksum); /* restore checksum for later use */ - print_image_hdr (hdr); - - cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); cnt += info.blksz - 1; cnt /= info.blksz; cnt -= 1; @@ -414,6 +427,13 @@ int do_usbboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) printf ("\n** Read error on %d:%d\n", dev, part); return 1; } + +#if defined(CONFIG_FIT) + /* This cannot be done earlier, we need complete FIT image in RAM first */ + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) + fit_print_contents ((const void *)addr); +#endif + /* Loading ok, update default load address */ load_addr = addr; diff --git a/common/cmd_ximg.c b/common/cmd_ximg.c index 52e0614496..7916fc1972 100644 --- a/common/cmd_ximg.c +++ b/common/cmd_ximg.c @@ -24,7 +24,6 @@ * MA 02111-1307 USA */ -#if defined(CONFIG_CMD_XIMG) /* * Multi Image extract @@ -37,92 +36,136 @@ int do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { - ulong addr = load_addr, dest = 0; - ulong data, len, checksum; - ulong *len_ptr; - int i, verify, part = 0; - char pbuf[10], *s; - image_header_t header; + ulong addr = load_addr; + ulong dest = 0; + ulong data, len, count; + int verify; + int part = 0; + char pbuf[10]; + image_header_t *hdr; +#if defined(CONFIG_FIT) + const char *uname = NULL; + const void* fit_hdr; + int noffset; + const void *fit_data; + size_t fit_len; +#endif - s = getenv("verify"); - verify = (s && (*s == 'n')) ? 0 : 1; + verify = getenv_verify (); if (argc > 1) { addr = simple_strtoul(argv[1], NULL, 16); } if (argc > 2) { part = simple_strtoul(argv[2], NULL, 16); +#if defined(CONFIG_FIT) + uname = argv[2]; +#endif } if (argc > 3) { dest = simple_strtoul(argv[3], NULL, 16); } - printf("## Copying from image at %08lx ...\n", addr); - - /* Copy header so we can blank CRC field for re-calculation */ - memmove(&header, (char *) addr, sizeof (image_header_t)); - - if (ntohl(header.ih_magic) != IH_MAGIC) { - printf("Bad Magic Number\n"); - return 1; - } + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: - data = (ulong) & header; - len = sizeof (image_header_t); + printf("## Copying part %d from legacy image " + "at %08lx ...\n", part, addr); - checksum = ntohl(header.ih_hcrc); - header.ih_hcrc = 0; + hdr = (image_header_t *)addr; + if (!image_check_magic (hdr)) { + printf("Bad Magic Number\n"); + return 1; + } - if (crc32(0, (char *) data, len) != checksum) { - printf("Bad Header Checksum\n"); - return 1; - } + if (!image_check_hcrc (hdr)) { + printf("Bad Header Checksum\n"); + return 1; + } #ifdef DEBUG - print_image_hdr((image_header_t *) addr); + image_print_contents (hdr); #endif - data = addr + sizeof (image_header_t); - len = ntohl(header.ih_size); + if (!image_check_type (hdr, IH_TYPE_MULTI)) { + printf("Wrong Image Type for %s command\n", + cmdtp->name); + return 1; + } - if (header.ih_type != IH_TYPE_MULTI) { - printf("Wrong Image Type for %s command\n", cmdtp->name); - return 1; - } + if (image_get_comp (hdr) != IH_COMP_NONE) { + printf("Wrong Compression Type for %s command\n", + cmdtp->name); + return 1; + } - if (header.ih_comp != IH_COMP_NONE) { - printf("Wrong Compression Type for %s command\n", cmdtp->name); - return 1; - } + if (verify) { + printf(" Verifying Checksum ... "); + if (!image_check_dcrc (hdr)) { + printf("Bad Data CRC\n"); + return 1; + } + printf("OK\n"); + } - if (verify) { - printf(" Verifying Checksum ... "); - if (crc32(0, (char *) data, len) != ntohl(header.ih_dcrc)) { - printf("Bad Data CRC\n"); + count = image_multi_count (hdr); + if (part >= count) { + printf("Bad Image Part\n"); + return 1; + } + + image_multi_getimg (hdr, part, &data, &len); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + if (uname == NULL) { + puts ("No FIT subimage unit name\n"); + return 1; + } + + printf("## Copying '%s' subimage from FIT image " + "at %08lx ...\n", uname, addr); + + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + puts ("Bad FIT image format\n"); + return 1; + } + + /* get subimage node offset */ + noffset = fit_image_get_node (fit_hdr, uname); + if (noffset < 0) { + printf ("Can't find '%s' FIT subimage\n", uname); return 1; } - printf("OK\n"); - } - len_ptr = (ulong *) data; - - data += 4; /* terminator */ - for (i = 0; len_ptr[i]; ++i) { - data += 4; - if (argc > 2 && part > i) { - u_long tail; - len = ntohl(len_ptr[i]); - tail = len % 4; - data += len; - if (tail) { - data += 4 - tail; + if (fit_image_check_comp (fit_hdr, noffset, IH_COMP_NONE)) { + printf("Wrong Compression Type for %s command\n", + cmdtp->name); + return 1; + } + + /* verify integrity */ + if (verify) { + if (!fit_image_check_hashes (fit_hdr, noffset)) { + puts ("Bad Data Hash\n"); + return 1; } } - } - if (argc > 2 && part >= i) { - printf("Bad Image Part\n"); + + /* get subimage data address and length */ + if (fit_image_get_data (fit_hdr, noffset, &fit_data, &fit_len)) { + puts ("Could not find script subimage data\n"); + return 1; + } + + data = (ulong)fit_data; + len = (ulong)fit_len; + break; +#endif + default: + puts ("Invalid image type for imxtract\n"); return 1; } - len = ntohl(len_ptr[part]); if (argc > 3) { memcpy((char *) dest, (char *) data, len); @@ -139,6 +182,9 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) U_BOOT_CMD(imxtract, 4, 1, do_imgextract, "imxtract- extract a part of a multi-image\n", "addr part [dest]\n" - " - extract <part> from image at <addr> and copy to <dest>\n"); - + " - extract <part> from legacy image at <addr> and copy to <dest>\n" +#if defined(CONFIG_FIT) + "addr uname [dest]\n" + " - extract <uname> subimage from FIT image at <addr> and copy to <dest>\n" #endif +); diff --git a/common/gunzip.c b/common/gunzip.c new file mode 100644 index 0000000000..74f0bf9f3e --- /dev/null +++ b/common/gunzip.c @@ -0,0 +1,113 @@ +/* + * (C) Copyright 2000-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <watchdog.h> +#include <command.h> +#include <image.h> +#include <malloc.h> +#include <zlib.h> + +#define ZALLOC_ALIGNMENT 16 +#define HEAD_CRC 2 +#define EXTRA_FIELD 4 +#define ORIG_NAME 8 +#define COMMENT 0x10 +#define RESERVED 0xe0 +#define DEFLATED 8 + +int gunzip(void *, int, unsigned char *, unsigned long *); +void *zalloc(void *, unsigned, unsigned); +void zfree(void *, void *, unsigned); + +void *zalloc(void *x, unsigned items, unsigned size) +{ + void *p; + + size *= items; + size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1); + + p = malloc (size); + + return (p); +} + +void zfree(void *x, void *addr, unsigned nb) +{ + free (addr); +} + +int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp) +{ + z_stream s; + int r, i, flags; + + /* skip header */ + i = 10; + flags = src[3]; + if (src[2] != DEFLATED || (flags & RESERVED) != 0) { + puts ("Error: Bad gzipped data\n"); + return (-1); + } + if ((flags & EXTRA_FIELD) != 0) + i = 12 + src[10] + (src[11] << 8); + if ((flags & ORIG_NAME) != 0) + while (src[i++] != 0) + ; + if ((flags & COMMENT) != 0) + while (src[i++] != 0) + ; + if ((flags & HEAD_CRC) != 0) + i += 2; + if (i >= *lenp) { + puts ("Error: gunzip out of data in header\n"); + return (-1); + } + + s.zalloc = zalloc; + s.zfree = zfree; +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + s.outcb = (cb_func)WATCHDOG_RESET; +#else + s.outcb = Z_NULL; +#endif /* CONFIG_HW_WATCHDOG */ + + r = inflateInit2(&s, -MAX_WBITS); + if (r != Z_OK) { + printf ("Error: inflateInit2() returned %d\n", r); + return (-1); + } + s.next_in = src + i; + s.avail_in = *lenp - i; + s.next_out = dst; + s.avail_out = dstlen; + r = inflate(&s, Z_FINISH); + if (r != Z_OK && r != Z_STREAM_END) { + printf ("Error: inflate() returned %d\n", r); + return (-1); + } + *lenp = s.next_out - (unsigned char *) dst; + inflateEnd(&s); + + return (0); +} diff --git a/common/image.c b/common/image.c new file mode 100644 index 0000000000..f04826a5c8 --- /dev/null +++ b/common/image.c @@ -0,0 +1,2541 @@ +/* + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#ifndef USE_HOSTCC +#include <common.h> +#include <watchdog.h> + +#ifdef CONFIG_SHOW_BOOT_PROGRESS +#include <status_led.h> +#endif + +#ifdef CONFIG_HAS_DATAFLASH +#include <dataflash.h> +#endif + +#ifdef CONFIG_LOGBUFFER +#include <logbuff.h> +#endif + +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) +#include <rtc.h> +#endif + +#include <image.h> + +#if defined(CONFIG_FIT) || defined (CONFIG_OF_LIBFDT) +#include <fdt.h> +#include <libfdt.h> +#include <fdt_support.h> +#endif + +#if defined(CONFIG_FIT) +#include <md5.h> +#include <sha1.h> + +static int fit_check_ramdisk (const void *fit, int os_noffset, + uint8_t arch, int verify); +#endif + +#ifdef CONFIG_CMD_BDI +extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +#endif + +DECLARE_GLOBAL_DATA_PTR; + +static image_header_t* image_get_ramdisk (ulong rd_addr, uint8_t arch, + int verify); +#else +#include "mkimage.h" +#include <md5.h> +#include <time.h> +#include <image.h> +#endif /* !USE_HOSTCC*/ + +typedef struct table_entry { + int id; /* as defined in image.h */ + char *sname; /* short (input) name */ + char *lname; /* long (output) name */ +} table_entry_t; + +static table_entry_t uimage_arch[] = { + { IH_ARCH_INVALID, NULL, "Invalid ARCH", }, + { IH_ARCH_ALPHA, "alpha", "Alpha", }, + { IH_ARCH_ARM, "arm", "ARM", }, + { IH_ARCH_I386, "x86", "Intel x86", }, + { IH_ARCH_IA64, "ia64", "IA64", }, + { IH_ARCH_M68K, "m68k", "M68K", }, + { IH_ARCH_MICROBLAZE, "microblaze", "MicroBlaze", }, + { IH_ARCH_MIPS, "mips", "MIPS", }, + { IH_ARCH_MIPS64, "mips64", "MIPS 64 Bit", }, + { IH_ARCH_NIOS, "nios", "NIOS", }, + { IH_ARCH_NIOS2, "nios2", "NIOS II", }, + { IH_ARCH_PPC, "ppc", "PowerPC", }, + { IH_ARCH_S390, "s390", "IBM S390", }, + { IH_ARCH_SH, "sh", "SuperH", }, + { IH_ARCH_SPARC, "sparc", "SPARC", }, + { IH_ARCH_SPARC64, "sparc64", "SPARC 64 Bit", }, + { IH_ARCH_BLACKFIN, "blackfin", "Blackfin", }, + { IH_ARCH_AVR32, "avr32", "AVR32", }, + { -1, "", "", }, +}; + +static table_entry_t uimage_os[] = { + { IH_OS_INVALID, NULL, "Invalid OS", }, +#if defined(CONFIG_ARTOS) || defined(USE_HOSTCC) + { IH_OS_ARTOS, "artos", "ARTOS", }, +#endif + { IH_OS_LINUX, "linux", "Linux", }, +#if defined(CONFIG_LYNXKDI) || defined(USE_HOSTCC) + { IH_OS_LYNXOS, "lynxos", "LynxOS", }, +#endif + { IH_OS_NETBSD, "netbsd", "NetBSD", }, + { IH_OS_RTEMS, "rtems", "RTEMS", }, + { IH_OS_U_BOOT, "u-boot", "U-Boot", }, +#if defined(CONFIG_CMD_ELF) || defined(USE_HOSTCC) + { IH_OS_QNX, "qnx", "QNX", }, + { IH_OS_VXWORKS, "vxworks", "VxWorks", }, +#endif +#ifdef USE_HOSTCC + { IH_OS_4_4BSD, "4_4bsd", "4_4BSD", }, + { IH_OS_DELL, "dell", "Dell", }, + { IH_OS_ESIX, "esix", "Esix", }, + { IH_OS_FREEBSD, "freebsd", "FreeBSD", }, + { IH_OS_IRIX, "irix", "Irix", }, + { IH_OS_NCR, "ncr", "NCR", }, + { IH_OS_OPENBSD, "openbsd", "OpenBSD", }, + { IH_OS_PSOS, "psos", "pSOS", }, + { IH_OS_SCO, "sco", "SCO", }, + { IH_OS_SOLARIS, "solaris", "Solaris", }, + { IH_OS_SVR4, "svr4", "SVR4", }, +#endif + { -1, "", "", }, +}; + +static table_entry_t uimage_type[] = { + { IH_TYPE_INVALID, NULL, "Invalid Image", }, + { IH_TYPE_FILESYSTEM, "filesystem", "Filesystem Image", }, + { IH_TYPE_FIRMWARE, "firmware", "Firmware", }, + { IH_TYPE_KERNEL, "kernel", "Kernel Image", }, + { IH_TYPE_MULTI, "multi", "Multi-File Image", }, + { IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", }, + { IH_TYPE_SCRIPT, "script", "Script", }, + { IH_TYPE_STANDALONE, "standalone", "Standalone Program", }, + { IH_TYPE_FLATDT, "flat_dt", "Flat Device Tree", }, + { -1, "", "", }, +}; + +static table_entry_t uimage_comp[] = { + { IH_COMP_NONE, "none", "uncompressed", }, + { IH_COMP_BZIP2, "bzip2", "bzip2 compressed", }, + { IH_COMP_GZIP, "gzip", "gzip compressed", }, + { -1, "", "", }, +}; + +unsigned long crc32 (unsigned long, const unsigned char *, unsigned int); +static void genimg_print_size (uint32_t size); +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) +static void genimg_print_time (time_t timestamp); +#endif + +/*****************************************************************************/ +/* Legacy format routines */ +/*****************************************************************************/ +int image_check_hcrc (image_header_t *hdr) +{ + ulong hcrc; + ulong len = image_get_header_size (); + image_header_t header; + + /* Copy header so we can blank CRC field for re-calculation */ + memmove (&header, (char *)hdr, image_get_header_size ()); + image_set_hcrc (&header, 0); + + hcrc = crc32 (0, (unsigned char *)&header, len); + + return (hcrc == image_get_hcrc (hdr)); +} + +int image_check_dcrc (image_header_t *hdr) +{ + ulong data = image_get_data (hdr); + ulong len = image_get_data_size (hdr); + ulong dcrc = crc32 (0, (unsigned char *)data, len); + + return (dcrc == image_get_dcrc (hdr)); +} + +#ifndef USE_HOSTCC +int image_check_dcrc_wd (image_header_t *hdr, ulong chunksz) +{ + ulong dcrc = 0; + ulong len = image_get_data_size (hdr); + ulong data = image_get_data (hdr); + +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + ulong cdata = data; + ulong edata = cdata + len; + + while (cdata < edata) { + ulong chunk = edata - cdata; + + if (chunk > chunksz) + chunk = chunksz; + dcrc = crc32 (dcrc, (unsigned char *)cdata, chunk); + cdata += chunk; + + WATCHDOG_RESET (); + } +#else + dcrc = crc32 (0, (unsigned char *)data, len); +#endif + + return (dcrc == image_get_dcrc (hdr)); +} +#endif /* !USE_HOSTCC */ + +/** + * image_multi_count - get component (sub-image) count + * @hdr: pointer to the header of the multi component image + * + * image_multi_count() returns number of components in a multi + * component image. + * + * Note: no checking of the image type is done, caller must pass + * a valid multi component image. + * + * returns: + * number of components + */ +ulong image_multi_count (image_header_t *hdr) +{ + ulong i, count = 0; + uint32_t *size; + + /* get start of the image payload, which in case of multi + * component images that points to a table of component sizes */ + size = (uint32_t *)image_get_data (hdr); + + /* count non empty slots */ + for (i = 0; size[i]; ++i) + count++; + + return count; +} + +/** + * image_multi_getimg - get component data address and size + * @hdr: pointer to the header of the multi component image + * @idx: index of the requested component + * @data: pointer to a ulong variable, will hold component data address + * @len: pointer to a ulong variable, will hold component size + * + * image_multi_getimg() returns size and data address for the requested + * component in a multi component image. + * + * Note: no checking of the image type is done, caller must pass + * a valid multi component image. + * + * returns: + * data address and size of the component, if idx is valid + * 0 in data and len, if idx is out of range + */ +void image_multi_getimg (image_header_t *hdr, ulong idx, + ulong *data, ulong *len) +{ + int i; + uint32_t *size; + ulong offset, tail, count, img_data; + + /* get number of component */ + count = image_multi_count (hdr); + + /* get start of the image payload, which in case of multi + * component images that points to a table of component sizes */ + size = (uint32_t *)image_get_data (hdr); + + /* get address of the proper component data start, which means + * skipping sizes table (add 1 for last, null entry) */ + img_data = image_get_data (hdr) + (count + 1) * sizeof (uint32_t); + + if (idx < count) { + *len = uimage_to_cpu (size[idx]); + offset = 0; + tail = 0; + + /* go over all indices preceding requested component idx */ + for (i = 0; i < idx; i++) { + /* add up i-th component size */ + offset += uimage_to_cpu (size[i]); + + /* add up alignment for i-th component */ + tail += (4 - uimage_to_cpu (size[i]) % 4); + } + + /* calculate idx-th component data address */ + *data = img_data + offset + tail; + } else { + *len = 0; + *data = 0; + } +} + +static void image_print_type (image_header_t *hdr) +{ + const char *os, *arch, *type, *comp; + + os = genimg_get_os_name (image_get_os (hdr)); + arch = genimg_get_arch_name (image_get_arch (hdr)); + type = genimg_get_type_name (image_get_type (hdr)); + comp = genimg_get_comp_name (image_get_comp (hdr)); + + printf ("%s %s %s (%s)\n", arch, os, type, comp); +} + +/** + * __image_print_contents - prints out the contents of the legacy format image + * @hdr: pointer to the legacy format image header + * @p: pointer to prefix string + * + * __image_print_contents() formats a multi line legacy image contents description. + * The routine prints out all header fields followed by the size/offset data + * for MULTI/SCRIPT images. + * + * returns: + * no returned results + */ +static void __image_print_contents (image_header_t *hdr, const char *p) +{ + printf ("%sImage Name: %.*s\n", p, IH_NMLEN, image_get_name (hdr)); +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) + printf ("%sCreated: ", p); + genimg_print_time ((time_t)image_get_time (hdr)); +#endif + printf ("%sImage Type: ", p); + image_print_type (hdr); + printf ("%sData Size: ", p); + genimg_print_size (image_get_data_size (hdr)); + printf ("%sLoad Address: %08x\n", p, image_get_load (hdr)); + printf ("%sEntry Point: %08x\n", p, image_get_ep (hdr)); + + if (image_check_type (hdr, IH_TYPE_MULTI) || + image_check_type (hdr, IH_TYPE_SCRIPT)) { + int i; + ulong data, len; + ulong count = image_multi_count (hdr); + + printf ("%sContents:\n", p); + for (i = 0; i < count; i++) { + image_multi_getimg (hdr, i, &data, &len); + + printf ("%s Image %d: ", p, i); + genimg_print_size (len); + + if (image_check_type (hdr, IH_TYPE_SCRIPT) && i > 0) { + /* + * the user may need to know offsets + * if planning to do something with + * multiple files + */ + printf ("%s Offset = 0x%08lx\n", p, data); + } + } + } +} + +inline void image_print_contents (image_header_t *hdr) +{ + __image_print_contents (hdr, " "); +} + +inline void image_print_contents_noindent (image_header_t *hdr) +{ + __image_print_contents (hdr, ""); +} + +#ifndef USE_HOSTCC +/** + * image_get_ramdisk - get and verify ramdisk image + * @rd_addr: ramdisk image start address + * @arch: expected ramdisk architecture + * @verify: checksum verification flag + * + * image_get_ramdisk() returns a pointer to the verified ramdisk image + * header. Routine receives image start address and expected architecture + * flag. Verification done covers data and header integrity and os/type/arch + * fields checking. + * + * If dataflash support is enabled routine checks for dataflash addresses + * and handles required dataflash reads. + * + * returns: + * pointer to a ramdisk image header, if image was found and valid + * otherwise, return NULL + */ +static image_header_t* image_get_ramdisk (ulong rd_addr, uint8_t arch, + int verify) +{ + image_header_t *rd_hdr = (image_header_t *)rd_addr; + + if (!image_check_magic (rd_hdr)) { + puts ("Bad Magic Number\n"); + show_boot_progress (-10); + return NULL; + } + + if (!image_check_hcrc (rd_hdr)) { + puts ("Bad Header Checksum\n"); + show_boot_progress (-11); + return NULL; + } + + show_boot_progress (10); + image_print_contents (rd_hdr); + + if (verify) { + puts(" Verifying Checksum ... "); + if (!image_check_dcrc_wd (rd_hdr, CHUNKSZ)) { + puts ("Bad Data CRC\n"); + show_boot_progress (-12); + return NULL; + } + puts("OK\n"); + } + + show_boot_progress (11); + + if (!image_check_os (rd_hdr, IH_OS_LINUX) || + !image_check_arch (rd_hdr, arch) || + !image_check_type (rd_hdr, IH_TYPE_RAMDISK)) { + printf ("No Linux %s Ramdisk Image\n", + genimg_get_arch_name(arch)); + show_boot_progress (-13); + return NULL; + } + + return rd_hdr; +} +#endif /* !USE_HOSTCC */ + +/*****************************************************************************/ +/* Shared dual-format routines */ +/*****************************************************************************/ +#ifndef USE_HOSTCC +int getenv_verify (void) +{ + char *s = getenv ("verify"); + return (s && (*s == 'n')) ? 0 : 1; +} + +int getenv_autostart (void) +{ + char *s = getenv ("autostart"); + return (s && (*s == 'n')) ? 0 : 1; +} + +ulong getenv_bootm_low(void) +{ + char *s = getenv ("bootm_low"); + if (s) { + ulong tmp = simple_strtoul (s, NULL, 16); + return tmp; + } + +#if defined(CFG_SDRAM_BASE) + return CFG_SDRAM_BASE; +#elif defined(CONFIG_ARM) + return gd->bd->bi_dram[0].start; +#else + return 0; +#endif +} + +ulong getenv_bootm_size(void) +{ + char *s = getenv ("bootm_size"); + if (s) { + ulong tmp = simple_strtoul (s, NULL, 16); + return tmp; + } + +#if defined(CONFIG_ARM) + return gd->bd->bi_dram[0].size; +#else + return gd->bd->bi_memsize; +#endif +} + +void memmove_wd (void *to, void *from, size_t len, ulong chunksz) +{ +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + while (len > 0) { + size_t tail = (len > chunksz) ? chunksz : len; + WATCHDOG_RESET (); + memmove (to, from, tail); + to += tail; + from += tail; + len -= tail; + } +#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ + memmove (to, from, len); +#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ +} +#endif /* !USE_HOSTCC */ + +static void genimg_print_size (uint32_t size) +{ +#ifndef USE_HOSTCC + printf ("%d Bytes = ", size); + print_size (size, "\n"); +#else + printf ("%d Bytes = %.2f kB = %.2f MB\n", + size, (double)size / 1.024e3, + (double)size / 1.048576e6); +#endif +} + +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) +static void genimg_print_time (time_t timestamp) +{ +#ifndef USE_HOSTCC + struct rtc_time tm; + + to_tm (timestamp, &tm); + printf ("%4d-%02d-%02d %2d:%02d:%02d UTC\n", + tm.tm_year, tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); +#else + printf ("%s", ctime(×tamp)); +#endif +} +#endif /* CONFIG_TIMESTAMP || CONFIG_CMD_DATE || USE_HOSTCC */ + +/** + * get_table_entry_name - translate entry id to long name + * @table: pointer to a translation table for entries of a specific type + * @msg: message to be returned when translation fails + * @id: entry id to be translated + * + * get_table_entry_name() will go over translation table trying to find + * entry that matches given id. If matching entry is found, its long + * name is returned to the caller. + * + * returns: + * long entry name if translation succeeds + * msg otherwise + */ +static char *get_table_entry_name (table_entry_t *table, char *msg, int id) +{ + for (; table->id >= 0; ++table) { + if (table->id == id) + return (table->lname); + } + return (msg); +} + +const char *genimg_get_os_name (uint8_t os) +{ + return (get_table_entry_name (uimage_os, "Unknown OS", os)); +} + +const char *genimg_get_arch_name (uint8_t arch) +{ + return (get_table_entry_name (uimage_arch, "Unknown Architecture", arch)); +} + +const char *genimg_get_type_name (uint8_t type) +{ + return (get_table_entry_name (uimage_type, "Unknown Image", type)); +} + +const char *genimg_get_comp_name (uint8_t comp) +{ + return (get_table_entry_name (uimage_comp, "Unknown Compression", comp)); +} + +/** + * get_table_entry_id - translate short entry name to id + * @table: pointer to a translation table for entries of a specific type + * @table_name: to be used in case of error + * @name: entry short name to be translated + * + * get_table_entry_id() will go over translation table trying to find + * entry that matches given short name. If matching entry is found, + * its id returned to the caller. + * + * returns: + * entry id if translation succeeds + * -1 otherwise + */ +static int get_table_entry_id (table_entry_t *table, + const char *table_name, const char *name) +{ + table_entry_t *t; +#ifdef USE_HOSTCC + int first = 1; + + for (t = table; t->id >= 0; ++t) { + if (t->sname && strcasecmp(t->sname, name) == 0) + return (t->id); + } + + fprintf (stderr, "\nInvalid %s Type - valid names are", table_name); + for (t = table; t->id >= 0; ++t) { + if (t->sname == NULL) + continue; + fprintf (stderr, "%c %s", (first) ? ':' : ',', t->sname); + first = 0; + } + fprintf (stderr, "\n"); +#else + for (t = table; t->id >= 0; ++t) { + if (t->sname && strcmp(t->sname, name) == 0) + return (t->id); + } + debug ("Invalid %s Type: %s\n", table_name, name); +#endif /* USE_HOSTCC */ + return (-1); +} + +int genimg_get_os_id (const char *name) +{ + return (get_table_entry_id (uimage_os, "OS", name)); +} + +int genimg_get_arch_id (const char *name) +{ + return (get_table_entry_id (uimage_arch, "CPU", name)); +} + +int genimg_get_type_id (const char *name) +{ + return (get_table_entry_id (uimage_type, "Image", name)); +} + +int genimg_get_comp_id (const char *name) +{ + return (get_table_entry_id (uimage_comp, "Compression", name)); +} + +#ifndef USE_HOSTCC +/** + * genimg_get_format - get image format type + * @img_addr: image start address + * + * genimg_get_format() checks whether provided address points to a valid + * legacy or FIT image. + * + * New uImage format and FDT blob are based on a libfdt. FDT blob + * may be passed directly or embedded in a FIT image. In both situations + * genimg_get_format() must be able to dectect libfdt header. + * + * returns: + * image format type or IMAGE_FORMAT_INVALID if no image is present + */ +int genimg_get_format (void *img_addr) +{ + ulong format = IMAGE_FORMAT_INVALID; + image_header_t *hdr; +#if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) + char *fit_hdr; +#endif + + hdr = (image_header_t *)img_addr; + if (image_check_magic(hdr)) + format = IMAGE_FORMAT_LEGACY; +#if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) + else { + fit_hdr = (char *)img_addr; + if (fdt_check_header (fit_hdr) == 0) + format = IMAGE_FORMAT_FIT; + } +#endif + + return format; +} + +/** + * genimg_get_image - get image from special storage (if necessary) + * @img_addr: image start address + * + * genimg_get_image() checks if provided image start adddress is located + * in a dataflash storage. If so, image is moved to a system RAM memory. + * + * returns: + * image start address after possible relocation from special storage + */ +ulong genimg_get_image (ulong img_addr) +{ + ulong ram_addr = img_addr; + +#ifdef CONFIG_HAS_DATAFLASH + ulong h_size, d_size; + + if (addr_dataflash (img_addr)){ + /* ger RAM address */ + ram_addr = CFG_LOAD_ADDR; + + /* get header size */ + h_size = image_get_header_size (); +#if defined(CONFIG_FIT) + if (sizeof(struct fdt_header) > h_size) + h_size = sizeof(struct fdt_header); +#endif + + /* read in header */ + debug (" Reading image header from dataflash address " + "%08lx to RAM address %08lx\n", img_addr, ram_addr); + + read_dataflash (img_addr, h_size, (char *)ram_addr); + + /* get data size */ + switch (genimg_get_format ((void *)ram_addr)) { + case IMAGE_FORMAT_LEGACY: + d_size = image_get_data_size ((image_header_t *)ram_addr); + debug (" Legacy format image found at 0x%08lx, size 0x%08lx\n", + ram_addr, d_size); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + d_size = fit_get_size ((const void *)ram_addr) - h_size; + debug (" FIT/FDT format image found at 0x%08lx, size 0x%08lx\n", + ram_addr, d_size); + break; +#endif + default: + printf (" No valid image found at 0x%08lx\n", img_addr); + return ram_addr; + } + + /* read in image data */ + debug (" Reading image remaining data from dataflash address " + "%08lx to RAM address %08lx\n", img_addr + h_size, + ram_addr + h_size); + + read_dataflash (img_addr + h_size, d_size, + (char *)(ram_addr + h_size)); + + } +#endif /* CONFIG_HAS_DATAFLASH */ + + return ram_addr; +} + +/** + * fit_has_config - check if there is a valid FIT configuration + * @images: pointer to the bootm command headers structure + * + * fit_has_config() checks if there is a FIT configuration in use + * (if FTI support is present). + * + * returns: + * 0, no FIT support or no configuration found + * 1, configuration found + */ +int genimg_has_config (bootm_headers_t *images) +{ +#if defined(CONFIG_FIT) + if (images->fit_uname_cfg) + return 1; +#endif + return 0; +} + +/** + * boot_get_ramdisk - main ramdisk handling routine + * @argc: command argument count + * @argv: command argument list + * @images: pointer to the bootm images structure + * @arch: expected ramdisk architecture + * @rd_start: pointer to a ulong variable, will hold ramdisk start address + * @rd_end: pointer to a ulong variable, will hold ramdisk end + * + * boot_get_ramdisk() is responsible for finding a valid ramdisk image. + * Curently supported are the following ramdisk sources: + * - multicomponent kernel/ramdisk image, + * - commandline provided address of decicated ramdisk image. + * + * returns: + * 0, if ramdisk image was found and valid, or skiped + * rd_start and rd_end are set to ramdisk start/end addresses if + * ramdisk image is found and valid + * + * 1, if ramdisk image is found but corrupted + * rd_start and rd_end are set to 0 if no ramdisk exists + */ +int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images, + uint8_t arch, ulong *rd_start, ulong *rd_end) +{ + ulong rd_addr, rd_load; + ulong rd_data, rd_len; + image_header_t *rd_hdr; +#if defined(CONFIG_FIT) + void *fit_hdr; + const char *fit_uname_config = NULL; + const char *fit_uname_ramdisk = NULL; + ulong default_addr; + int rd_noffset; + int cfg_noffset; + const void *data; + size_t size; +#endif + + *rd_start = 0; + *rd_end = 0; + + /* + * Look for a '-' which indicates to ignore the + * ramdisk argument + */ + if ((argc >= 3) && (strcmp(argv[2], "-") == 0)) { + debug ("## Skipping init Ramdisk\n"); + rd_len = rd_data = 0; + } else if (argc >= 3 || genimg_has_config (images)) { +#if defined(CONFIG_FIT) + if (argc >= 3) { + /* + * If the init ramdisk comes from the FIT image and + * the FIT image address is omitted in the command + * line argument, try to use os FIT image address or + * default load address. + */ + if (images->fit_uname_os) + default_addr = (ulong)images->fit_hdr_os; + else + default_addr = load_addr; + + if (fit_parse_conf (argv[2], default_addr, + &rd_addr, &fit_uname_config)) { + debug ("* ramdisk: config '%s' from image at 0x%08lx\n", + fit_uname_config, rd_addr); + } else if (fit_parse_subimage (argv[2], default_addr, + &rd_addr, &fit_uname_ramdisk)) { + debug ("* ramdisk: subimage '%s' from image at 0x%08lx\n", + fit_uname_ramdisk, rd_addr); + } else +#endif + { + rd_addr = simple_strtoul(argv[2], NULL, 16); + debug ("* ramdisk: cmdline image address = 0x%08lx\n", + rd_addr); + } +#if defined(CONFIG_FIT) + } else { + /* use FIT configuration provided in first bootm + * command argument + */ + rd_addr = (ulong)images->fit_hdr_os; + fit_uname_config = images->fit_uname_cfg; + debug ("* ramdisk: using config '%s' from image at 0x%08lx\n", + fit_uname_config, rd_addr); + + /* + * Check whether configuration has ramdisk defined, + * if not, don't try to use it, quit silently. + */ + fit_hdr = (void *)rd_addr; + cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config); + if (cfg_noffset < 0) { + debug ("* ramdisk: no such config\n"); + return 0; + } + + rd_noffset = fit_conf_get_ramdisk_node (fit_hdr, cfg_noffset); + if (rd_noffset < 0) { + debug ("* ramdisk: no ramdisk in config\n"); + return 0; + } + } +#endif + + /* copy from dataflash if needed */ + rd_addr = genimg_get_image (rd_addr); + + /* + * Check if there is an initrd image at the + * address provided in the second bootm argument + * check image type, for FIT images get FIT node. + */ + switch (genimg_get_format ((void *)rd_addr)) { + case IMAGE_FORMAT_LEGACY: + printf ("## Loading init Ramdisk from Legacy " + "Image at %08lx ...\n", rd_addr); + + show_boot_progress (9); + rd_hdr = image_get_ramdisk (rd_addr, arch, + images->verify); + + if (rd_hdr == NULL) + return 1; + + rd_data = image_get_data (rd_hdr); + rd_len = image_get_data_size (rd_hdr); + rd_load = image_get_load (rd_hdr); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (void *)rd_addr; + printf ("## Loading init Ramdisk from FIT " + "Image at %08lx ...\n", rd_addr); + + show_boot_progress (120); + if (!fit_check_format (fit_hdr)) { + puts ("Bad FIT ramdisk image format!\n"); + show_boot_progress (-120); + return 0; + } + show_boot_progress (121); + + if (!fit_uname_ramdisk) { + /* + * no ramdisk image node unit name, try to get config + * node first. If config unit node name is NULL + * fit_conf_get_node() will try to find default config node + */ + show_boot_progress (122); + cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config); + if (cfg_noffset < 0) { + puts ("Could not find configuration node\n"); + show_boot_progress (-122); + return 0; + } + fit_uname_config = fdt_get_name (fit_hdr, cfg_noffset, NULL); + printf (" Using '%s' configuration\n", fit_uname_config); + + rd_noffset = fit_conf_get_ramdisk_node (fit_hdr, cfg_noffset); + fit_uname_ramdisk = fit_get_name (fit_hdr, rd_noffset, NULL); + } else { + /* get ramdisk component image node offset */ + show_boot_progress (123); + rd_noffset = fit_image_get_node (fit_hdr, fit_uname_ramdisk); + } + if (rd_noffset < 0) { + puts ("Could not find subimage node\n"); + show_boot_progress (-124); + return 0; + } + + printf (" Trying '%s' ramdisk subimage\n", fit_uname_ramdisk); + + show_boot_progress (125); + if (!fit_check_ramdisk (fit_hdr, rd_noffset, arch, images->verify)) + return 0; + + /* get ramdisk image data address and length */ + if (fit_image_get_data (fit_hdr, rd_noffset, &data, &size)) { + puts ("Could not find ramdisk subimage data!\n"); + show_boot_progress (-127); + return 0; + } + show_boot_progress (128); + + rd_data = (ulong)data; + rd_len = size; + + if (fit_image_get_load (fit_hdr, rd_noffset, &rd_load)) { + puts ("Can't get ramdisk subimage load address!\n"); + show_boot_progress (-129); + return 0; + } + show_boot_progress (129); + + images->fit_hdr_rd = fit_hdr; + images->fit_uname_rd = fit_uname_ramdisk; + images->fit_noffset_rd = rd_noffset; + break; +#endif + default: + puts ("Wrong Ramdisk Image Format\n"); + rd_data = rd_len = rd_load = 0; + } + +#if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO) + /* + * We need to copy the ramdisk to SRAM to let Linux boot + */ + if (rd_data) { + memmove ((void *)rd_load, (uchar *)rd_data, rd_len); + rd_data = rd_load; + } +#endif /* CONFIG_B2 || CONFIG_EVB4510 || CONFIG_ARMADILLO */ + + } else if (images->legacy_hdr_valid && + image_check_type (images->legacy_hdr_os, IH_TYPE_MULTI)) { + /* + * Now check if we have a legacy mult-component image, + * get second entry data start address and len. + */ + show_boot_progress (13); + printf ("## Loading init Ramdisk from multi component " + "Legacy Image at %08lx ...\n", + (ulong)images->legacy_hdr_os); + + image_multi_getimg (images->legacy_hdr_os, 1, &rd_data, &rd_len); + } else { + /* + * no initrd image + */ + show_boot_progress (14); + rd_len = rd_data = 0; + } + + if (!rd_data) { + debug ("## No init Ramdisk\n"); + } else { + *rd_start = rd_data; + *rd_end = rd_data + rd_len; + } + debug (" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n", + *rd_start, *rd_end); + + return 0; +} + +#if defined(CONFIG_PPC) || defined(CONFIG_M68K) +/** + * boot_ramdisk_high - relocate init ramdisk + * @lmb: pointer to lmb handle, will be used for memory mgmt + * @rd_data: ramdisk data start address + * @rd_len: ramdisk data length + * @initrd_start: pointer to a ulong variable, will hold final init ramdisk + * start address (after possible relocation) + * @initrd_end: pointer to a ulong variable, will hold final init ramdisk + * end address (after possible relocation) + * + * boot_ramdisk_high() takes a relocation hint from "initrd_high" environement + * variable and if requested ramdisk data is moved to a specified location. + * + * Initrd_start and initrd_end are set to final (after relocation) ramdisk + * start/end addresses if ramdisk image start and len were provided, + * otherwise set initrd_start and initrd_end set to zeros. + * + * returns: + * 0 - success + * -1 - failure + */ +int boot_ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len, + ulong *initrd_start, ulong *initrd_end) +{ + char *s; + ulong initrd_high; + int initrd_copy_to_ram = 1; + + if ((s = getenv ("initrd_high")) != NULL) { + /* a value of "no" or a similar string will act like 0, + * turning the "load high" feature off. This is intentional. + */ + initrd_high = simple_strtoul (s, NULL, 16); + if (initrd_high == ~0) + initrd_copy_to_ram = 0; + } else { + /* not set, no restrictions to load high */ + initrd_high = ~0; + } + + debug ("## initrd_high = 0x%08lx, copy_to_ram = %d\n", + initrd_high, initrd_copy_to_ram); + + if (rd_data) { + if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ + debug (" in-place initrd\n"); + *initrd_start = rd_data; + *initrd_end = rd_data + rd_len; + lmb_reserve(lmb, rd_data, rd_len); + } else { + if (initrd_high) + *initrd_start = lmb_alloc_base (lmb, rd_len, 0x1000, initrd_high); + else + *initrd_start = lmb_alloc (lmb, rd_len, 0x1000); + + if (*initrd_start == 0) { + puts ("ramdisk - allocation error\n"); + goto error; + } + show_boot_progress (12); + + *initrd_end = *initrd_start + rd_len; + printf (" Loading Ramdisk to %08lx, end %08lx ... ", + *initrd_start, *initrd_end); + + memmove_wd ((void *)*initrd_start, + (void *)rd_data, rd_len, CHUNKSZ); + + puts ("OK\n"); + } + } else { + *initrd_start = 0; + *initrd_end = 0; + } + debug (" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n", + *initrd_start, *initrd_end); + + return 0; + +error: + return -1; +} + +/** + * boot_get_cmdline - allocate and initialize kernel cmdline + * @lmb: pointer to lmb handle, will be used for memory mgmt + * @cmd_start: pointer to a ulong variable, will hold cmdline start + * @cmd_end: pointer to a ulong variable, will hold cmdline end + * @bootmap_base: ulong variable, holds offset in physical memory to + * base of bootmap + * + * boot_get_cmdline() allocates space for kernel command line below + * BOOTMAPSZ + bootmap_base address. If "bootargs" U-boot environemnt + * variable is present its contents is copied to allocated kernel + * command line. + * + * returns: + * 0 - success + * -1 - failure + */ +int boot_get_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, + ulong bootmap_base) +{ + char *cmdline; + char *s; + + cmdline = (char *)lmb_alloc_base(lmb, CFG_BARGSIZE, 0xf, + CFG_BOOTMAPSZ + bootmap_base); + + if (cmdline == NULL) + return -1; + + if ((s = getenv("bootargs")) == NULL) + s = ""; + + strcpy(cmdline, s); + + *cmd_start = (ulong) & cmdline[0]; + *cmd_end = *cmd_start + strlen(cmdline); + + debug ("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end); + + return 0; +} + +/** + * boot_get_kbd - allocate and initialize kernel copy of board info + * @lmb: pointer to lmb handle, will be used for memory mgmt + * @kbd: double pointer to board info data + * @bootmap_base: ulong variable, holds offset in physical memory to + * base of bootmap + * + * boot_get_kbd() allocates space for kernel copy of board info data below + * BOOTMAPSZ + bootmap_base address and kernel board info is initialized with + * the current u-boot board info data. + * + * returns: + * 0 - success + * -1 - failure + */ +int boot_get_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base) +{ + *kbd = (bd_t *)lmb_alloc_base(lmb, sizeof(bd_t), 0xf, + CFG_BOOTMAPSZ + bootmap_base); + if (*kbd == NULL) + return -1; + + **kbd = *(gd->bd); + + debug ("## kernel board info at 0x%08lx\n", (ulong)*kbd); + +#if defined(DEBUG) && defined(CONFIG_CMD_BDI) + do_bdinfo(NULL, 0, 0, NULL); +#endif + + return 0; +} +#endif /* CONFIG_PPC || CONFIG_M68K */ +#endif /* !USE_HOSTCC */ + +#if defined(CONFIG_FIT) +/*****************************************************************************/ +/* New uImage format routines */ +/*****************************************************************************/ +#ifndef USE_HOSTCC +static int fit_parse_spec (const char *spec, char sepc, ulong addr_curr, + ulong *addr, const char **name) +{ + const char *sep; + + *addr = addr_curr; + *name = NULL; + + sep = strchr (spec, sepc); + if (sep) { + if (sep - spec > 0) + *addr = simple_strtoul (spec, NULL, 16); + + *name = sep + 1; + return 1; + } + + return 0; +} + +/** + * fit_parse_conf - parse FIT configuration spec + * @spec: input string, containing configuration spec + * @add_curr: current image address (to be used as a possible default) + * @addr: pointer to a ulong variable, will hold FIT image address of a given + * configuration + * @conf_name double pointer to a char, will hold pointer to a configuration + * unit name + * + * fit_parse_conf() expects configuration spec in the for of [<addr>]#<conf>, + * where <addr> is a FIT image address that contains configuration + * with a <conf> unit name. + * + * Address part is optional, and if omitted default add_curr will + * be used instead. + * + * returns: + * 1 if spec is a valid configuration string, + * addr and conf_name are set accordingly + * 0 otherwise + */ +inline int fit_parse_conf (const char *spec, ulong addr_curr, + ulong *addr, const char **conf_name) +{ + return fit_parse_spec (spec, '#', addr_curr, addr, conf_name); +} + +/** + * fit_parse_subimage - parse FIT subimage spec + * @spec: input string, containing subimage spec + * @add_curr: current image address (to be used as a possible default) + * @addr: pointer to a ulong variable, will hold FIT image address of a given + * subimage + * @image_name: double pointer to a char, will hold pointer to a subimage name + * + * fit_parse_subimage() expects subimage spec in the for of + * [<addr>]:<subimage>, where <addr> is a FIT image address that contains + * subimage with a <subimg> unit name. + * + * Address part is optional, and if omitted default add_curr will + * be used instead. + * + * returns: + * 1 if spec is a valid subimage string, + * addr and image_name are set accordingly + * 0 otherwise + */ +inline int fit_parse_subimage (const char *spec, ulong addr_curr, + ulong *addr, const char **image_name) +{ + return fit_parse_spec (spec, ':', addr_curr, addr, image_name); +} +#endif /* !USE_HOSTCC */ + +static void fit_get_debug (const void *fit, int noffset, + char *prop_name, int err) +{ + debug ("Can't get '%s' property from FIT 0x%08lx, " + "node: offset %d, name %s (%s)\n", + prop_name, (ulong)fit, noffset, + fit_get_name (fit, noffset, NULL), + fdt_strerror (err)); +} + +/** + * __fit_print_contents - prints out the contents of the FIT format image + * @fit: pointer to the FIT format image header + * @p: pointer to prefix string + * + * __fit_print_contents() formats a multi line FIT image contents description. + * The routine prints out FIT image properties (root node level) follwed by + * the details of each component image. + * + * returns: + * no returned results + */ +static void __fit_print_contents (const void *fit, const char *p) +{ + char *desc; + char *uname; + int images_noffset; + int confs_noffset; + int noffset; + int ndepth; + int count = 0; + int ret; +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) + time_t timestamp; +#endif + + /* Root node properties */ + ret = fit_get_desc (fit, 0, &desc); + printf ("%sFIT description: ", p); + if (ret) + printf ("unavailable\n"); + else + printf ("%s\n", desc); + +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) + ret = fit_get_timestamp (fit, 0, ×tamp); + printf ("%sCreated: ", p); + if (ret) + printf ("unavailable\n"); + else + genimg_print_time (timestamp); +#endif + + /* Find images parent node offset */ + images_noffset = fdt_path_offset (fit, FIT_IMAGES_PATH); + if (images_noffset < 0) { + printf ("Can't find images parent node '%s' (%s)\n", + FIT_IMAGES_PATH, fdt_strerror (images_noffset)); + return; + } + + /* Process its subnodes, print out component images details */ + for (ndepth = 0, count = 0, noffset = fdt_next_node (fit, images_noffset, &ndepth); + (noffset >= 0) && (ndepth > 0); + noffset = fdt_next_node (fit, noffset, &ndepth)) { + if (ndepth == 1) { + /* + * Direct child node of the images parent node, + * i.e. component image node. + */ + printf ("%s Image %u (%s)\n", p, count++, + fit_get_name(fit, noffset, NULL)); + + fit_image_print (fit, noffset, p); + } + } + + /* Find configurations parent node offset */ + confs_noffset = fdt_path_offset (fit, FIT_CONFS_PATH); + if (confs_noffset < 0) { + debug ("Can't get configurations parent node '%s' (%s)\n", + FIT_CONFS_PATH, fdt_strerror (confs_noffset)); + return; + } + + /* get default configuration unit name from default property */ + uname = (char *)fdt_getprop (fit, noffset, FIT_DEFAULT_PROP, NULL); + if (uname) + printf ("%s Default Configuration: '%s'\n", p, uname); + + /* Process its subnodes, print out configurations details */ + for (ndepth = 0, count = 0, noffset = fdt_next_node (fit, confs_noffset, &ndepth); + (noffset >= 0) && (ndepth > 0); + noffset = fdt_next_node (fit, noffset, &ndepth)) { + if (ndepth == 1) { + /* + * Direct child node of the configurations parent node, + * i.e. configuration node. + */ + printf ("%s Configuration %u (%s)\n", p, count++, + fit_get_name(fit, noffset, NULL)); + + fit_conf_print (fit, noffset, p); + } + } +} + +inline void fit_print_contents (const void *fit) +{ + __fit_print_contents (fit, " "); +} + +inline void fit_print_contents_noindent (const void *fit) +{ + __fit_print_contents (fit, ""); +} + +/** + * fit_image_print - prints out the FIT component image details + * @fit: pointer to the FIT format image header + * @image_noffset: offset of the component image node + * @p: pointer to prefix string + * + * fit_image_print() lists all mandatory properies for the processed component + * image. If present, hash nodes are printed out as well. + * + * returns: + * no returned results + */ +void fit_image_print (const void *fit, int image_noffset, const char *p) +{ + char *desc; + uint8_t type, arch, os, comp; + size_t size; + ulong load, entry; + const void *data; + int noffset; + int ndepth; + int ret; + + /* Mandatory properties */ + ret = fit_get_desc (fit, image_noffset, &desc); + printf ("%s Description: ", p); + if (ret) + printf ("unavailable\n"); + else + printf ("%s\n", desc); + + fit_image_get_type (fit, image_noffset, &type); + printf ("%s Type: %s\n", p, genimg_get_type_name (type)); + + fit_image_get_comp (fit, image_noffset, &comp); + printf ("%s Compression: %s\n", p, genimg_get_comp_name (comp)); + + ret = fit_image_get_data (fit, image_noffset, &data, &size); + +#ifndef USE_HOSTCC + printf ("%s Data Start: ", p); + if (ret) + printf ("unavailable\n"); + else + printf ("0x%08lx\n", (ulong)data); +#endif + + printf ("%s Data Size: ", p); + if (ret) + printf ("unavailable\n"); + else + genimg_print_size (size); + + /* Remaining, type dependent properties */ + if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || + (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) || + (type == IH_TYPE_FLATDT)) { + fit_image_get_arch (fit, image_noffset, &arch); + printf ("%s Architecture: %s\n", p, genimg_get_arch_name (arch)); + } + + if (type == IH_TYPE_KERNEL) { + fit_image_get_os (fit, image_noffset, &os); + printf ("%s OS: %s\n", p, genimg_get_os_name (os)); + } + + if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE)) { + ret = fit_image_get_load (fit, image_noffset, &load); + printf ("%s Load Address: ", p); + if (ret) + printf ("unavailable\n"); + else + printf ("0x%08lx\n", load); + + fit_image_get_entry (fit, image_noffset, &entry); + printf ("%s Entry Point: ", p); + if (ret) + printf ("unavailable\n"); + else + printf ("0x%08lx\n", entry); + } + + /* Process all hash subnodes of the component image node */ + for (ndepth = 0, noffset = fdt_next_node (fit, image_noffset, &ndepth); + (noffset >= 0) && (ndepth > 0); + noffset = fdt_next_node (fit, noffset, &ndepth)) { + if (ndepth == 1) { + /* Direct child node of the component image node */ + fit_image_print_hash (fit, noffset, p); + } + } +} + +/** + * fit_image_print_hash - prints out the hash node details + * @fit: pointer to the FIT format image header + * @noffset: offset of the hash node + * @p: pointer to prefix string + * + * fit_image_print_hash() lists properies for the processed hash node + * + * returns: + * no returned results + */ +void fit_image_print_hash (const void *fit, int noffset, const char *p) +{ + char *algo; + uint8_t *value; + int value_len; + int i, ret; + + /* + * Check subnode name, must be equal to "hash". + * Multiple hash nodes require unique unit node + * names, e.g. hash@1, hash@2, etc. + */ + if (strncmp (fit_get_name(fit, noffset, NULL), + FIT_HASH_NODENAME, + strlen(FIT_HASH_NODENAME)) != 0) + return; + + debug ("%s Hash node: '%s'\n", p, + fit_get_name (fit, noffset, NULL)); + + printf ("%s Hash algo: ", p); + if (fit_image_hash_get_algo (fit, noffset, &algo)) { + printf ("invalid/unsupported\n"); + return; + } + printf ("%s\n", algo); + + ret = fit_image_hash_get_value (fit, noffset, &value, + &value_len); + printf ("%s Hash value: ", p); + if (ret) { + printf ("unavailable\n"); + } else { + for (i = 0; i < value_len; i++) + printf ("%02x", value[i]); + printf ("\n"); + } + + debug ("%s Hash len: %d\n", p, value_len); +} + +/** + * fit_get_desc - get node description property + * @fit: pointer to the FIT format image header + * @noffset: node offset + * @desc: double pointer to the char, will hold pointer to the descrption + * + * fit_get_desc() reads description property from a given node, if + * description is found pointer to it is returened in third call argument. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_get_desc (const void *fit, int noffset, char **desc) +{ + int len; + + *desc = (char *)fdt_getprop (fit, noffset, FIT_DESC_PROP, &len); + if (*desc == NULL) { + fit_get_debug (fit, noffset, FIT_DESC_PROP, len); + return -1; + } + + return 0; +} + +/** + * fit_get_timestamp - get node timestamp property + * @fit: pointer to the FIT format image header + * @noffset: node offset + * @timestamp: pointer to the time_t, will hold read timestamp + * + * fit_get_timestamp() reads timestamp poperty from given node, if timestamp + * is found and has a correct size its value is retured in third call + * argument. + * + * returns: + * 0, on success + * -1, on property read failure + * -2, on wrong timestamp size + */ +int fit_get_timestamp (const void *fit, int noffset, time_t *timestamp) +{ + int len; + const void *data; + + data = fdt_getprop (fit, noffset, FIT_TIMESTAMP_PROP, &len); + if (data == NULL) { + fit_get_debug (fit, noffset, FIT_TIMESTAMP_PROP, len); + return -1; + } + if (len != sizeof (uint32_t)) { + debug ("FIT timestamp with incorrect size of (%u)\n", len); + return -2; + } + + *timestamp = uimage_to_cpu (*((uint32_t *)data)); + return 0; +} + +/** + * fit_image_get_node - get node offset for component image of a given unit name + * @fit: pointer to the FIT format image header + * @image_uname: component image node unit name + * + * fit_image_get_node() finds a component image (withing the '/images' + * node) of a provided unit name. If image is found its node offset is + * returned to the caller. + * + * returns: + * image node offset when found (>=0) + * negative number on failure (FDT_ERR_* code) + */ +int fit_image_get_node (const void *fit, const char *image_uname) +{ + int noffset, images_noffset; + + images_noffset = fdt_path_offset (fit, FIT_IMAGES_PATH); + if (images_noffset < 0) { + debug ("Can't find images parent node '%s' (%s)\n", + FIT_IMAGES_PATH, fdt_strerror (images_noffset)); + return images_noffset; + } + + noffset = fdt_subnode_offset (fit, images_noffset, image_uname); + if (noffset < 0) { + debug ("Can't get node offset for image unit name: '%s' (%s)\n", + image_uname, fdt_strerror (noffset)); + } + + return noffset; +} + +/** + * fit_image_get_os - get os id for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @os: pointer to the uint8_t, will hold os numeric id + * + * fit_image_get_os() finds os property in a given component image node. + * If the property is found, its (string) value is translated to the numeric + * id which is returned to the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_get_os (const void *fit, int noffset, uint8_t *os) +{ + int len; + const void *data; + + /* Get OS name from property data */ + data = fdt_getprop (fit, noffset, FIT_OS_PROP, &len); + if (data == NULL) { + fit_get_debug (fit, noffset, FIT_OS_PROP, len); + *os = -1; + return -1; + } + + /* Translate OS name to id */ + *os = genimg_get_os_id (data); + return 0; +} + +/** + * fit_image_get_arch - get arch id for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @arch: pointer to the uint8_t, will hold arch numeric id + * + * fit_image_get_arch() finds arch property in a given component image node. + * If the property is found, its (string) value is translated to the numeric + * id which is returned to the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_get_arch (const void *fit, int noffset, uint8_t *arch) +{ + int len; + const void *data; + + /* Get architecture name from property data */ + data = fdt_getprop (fit, noffset, FIT_ARCH_PROP, &len); + if (data == NULL) { + fit_get_debug (fit, noffset, FIT_ARCH_PROP, len); + *arch = -1; + return -1; + } + + /* Translate architecture name to id */ + *arch = genimg_get_arch_id (data); + return 0; +} + +/** + * fit_image_get_type - get type id for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @type: pointer to the uint8_t, will hold type numeric id + * + * fit_image_get_type() finds type property in a given component image node. + * If the property is found, its (string) value is translated to the numeric + * id which is returned to the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_get_type (const void *fit, int noffset, uint8_t *type) +{ + int len; + const void *data; + + /* Get image type name from property data */ + data = fdt_getprop (fit, noffset, FIT_TYPE_PROP, &len); + if (data == NULL) { + fit_get_debug (fit, noffset, FIT_TYPE_PROP, len); + *type = -1; + return -1; + } + + /* Translate image type name to id */ + *type = genimg_get_type_id (data); + return 0; +} + +/** + * fit_image_get_comp - get comp id for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @comp: pointer to the uint8_t, will hold comp numeric id + * + * fit_image_get_comp() finds comp property in a given component image node. + * If the property is found, its (string) value is translated to the numeric + * id which is returned to the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_get_comp (const void *fit, int noffset, uint8_t *comp) +{ + int len; + const void *data; + + /* Get compression name from property data */ + data = fdt_getprop (fit, noffset, FIT_COMP_PROP, &len); + if (data == NULL) { + fit_get_debug (fit, noffset, FIT_COMP_PROP, len); + *comp = -1; + return -1; + } + + /* Translate compression name to id */ + *comp = genimg_get_comp_id (data); + return 0; +} + +/** + * fit_image_get_load - get load address property for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @load: pointer to the uint32_t, will hold load address + * + * fit_image_get_load() finds load address property in a given component image node. + * If the property is found, its value is returned to the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_get_load (const void *fit, int noffset, ulong *load) +{ + int len; + const uint32_t *data; + + data = fdt_getprop (fit, noffset, FIT_LOAD_PROP, &len); + if (data == NULL) { + fit_get_debug (fit, noffset, FIT_LOAD_PROP, len); + return -1; + } + + *load = uimage_to_cpu (*data); + return 0; +} + +/** + * fit_image_get_entry - get entry point address property for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @entry: pointer to the uint32_t, will hold entry point address + * + * fit_image_get_entry() finds entry point address property in a given component image node. + * If the property is found, its value is returned to the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_get_entry (const void *fit, int noffset, ulong *entry) +{ + int len; + const uint32_t *data; + + data = fdt_getprop (fit, noffset, FIT_ENTRY_PROP, &len); + if (data == NULL) { + fit_get_debug (fit, noffset, FIT_ENTRY_PROP, len); + return -1; + } + + *entry = uimage_to_cpu (*data); + return 0; +} + +/** + * fit_image_get_data - get data property and its size for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @data: double pointer to void, will hold data property's data address + * @size: pointer to size_t, will hold data property's data size + * + * fit_image_get_data() finds data property in a given component image node. + * If the property is found its data start address and size are returned to + * the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_get_data (const void *fit, int noffset, + const void **data, size_t *size) +{ + int len; + + *data = fdt_getprop (fit, noffset, FIT_DATA_PROP, &len); + if (*data == NULL) { + fit_get_debug (fit, noffset, FIT_DATA_PROP, len); + *size = 0; + return -1; + } + + *size = len; + return 0; +} + +/** + * fit_image_hash_get_algo - get hash algorithm name + * @fit: pointer to the FIT format image header + * @noffset: hash node offset + * @algo: double pointer to char, will hold pointer to the algorithm name + * + * fit_image_hash_get_algo() finds hash algorithm property in a given hash node. + * If the property is found its data start address is returned to the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_hash_get_algo (const void *fit, int noffset, char **algo) +{ + int len; + + *algo = (char *)fdt_getprop (fit, noffset, FIT_ALGO_PROP, &len); + if (*algo == NULL) { + fit_get_debug (fit, noffset, FIT_ALGO_PROP, len); + return -1; + } + + return 0; +} + +/** + * fit_image_hash_get_value - get hash value and length + * @fit: pointer to the FIT format image header + * @noffset: hash node offset + * @value: double pointer to uint8_t, will hold address of a hash value data + * @value_len: pointer to an int, will hold hash data length + * + * fit_image_hash_get_value() finds hash value property in a given hash node. + * If the property is found its data start address and size are returned to + * the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_hash_get_value (const void *fit, int noffset, uint8_t **value, + int *value_len) +{ + int len; + + *value = (uint8_t *)fdt_getprop (fit, noffset, FIT_VALUE_PROP, &len); + if (*value == NULL) { + fit_get_debug (fit, noffset, FIT_VALUE_PROP, len); + *value_len = 0; + return -1; + } + + *value_len = len; + return 0; +} + +/** + * fit_set_timestamp - set node timestamp property + * @fit: pointer to the FIT format image header + * @noffset: node offset + * @timestamp: timestamp value to be set + * + * fit_set_timestamp() attempts to set timestamp property in the requested + * node and returns operation status to the caller. + * + * returns: + * 0, on success + * -1, on property read failure + */ +int fit_set_timestamp (void *fit, int noffset, time_t timestamp) +{ + uint32_t t; + int ret; + + t = cpu_to_uimage (timestamp); + ret = fdt_setprop (fit, noffset, FIT_TIMESTAMP_PROP, &t, + sizeof (uint32_t)); + if (ret) { + printf ("Can't set '%s' property for '%s' node (%s)\n", + FIT_TIMESTAMP_PROP, fit_get_name (fit, noffset, NULL), + fdt_strerror (ret)); + return -1; + } + + return 0; +} + +/** + * calculate_hash - calculate and return hash for provided input data + * @data: pointer to the input data + * @data_len: data length + * @algo: requested hash algorithm + * @value: pointer to the char, will hold hash value data (caller must + * allocate enough free space) + * value_len: length of the calculated hash + * + * calculate_hash() computes input data hash according to the requested algorithm. + * Resulting hash value is placed in caller provided 'value' buffer, length + * of the calculated hash is returned via value_len pointer argument. + * + * returns: + * 0, on success + * -1, when algo is unsupported + */ +static int calculate_hash (const void *data, int data_len, const char *algo, + uint8_t *value, int *value_len) +{ + if (strcmp (algo, "crc32") == 0 ) { + *((uint32_t *)value) = crc32 (0, data, data_len); + *((uint32_t *)value) = cpu_to_uimage (*((uint32_t *)value)); + *value_len = 4; + } else if (strcmp (algo, "sha1") == 0 ) { + sha1_csum ((unsigned char *) data, data_len, + (unsigned char *) value); + *value_len = 20; + } else if (strcmp (algo, "md5") == 0 ) { + md5 ((unsigned char *)data, data_len, value); + *value_len = 16; + } else { + debug ("Unsupported hash alogrithm\n"); + return -1; + } + return 0; +} + +#ifdef USE_HOSTCC +/** + * fit_set_hashes - process FIT component image nodes and calculate hashes + * @fit: pointer to the FIT format image header + * + * fit_set_hashes() adds hash values for all component images in the FIT blob. + * Hashes are calculated for all component images which have hash subnodes + * with algorithm property set to one of the supported hash algorithms. + * + * returns + * 0, on success + * libfdt error code, on failure + */ +int fit_set_hashes (void *fit) +{ + int images_noffset; + int noffset; + int ndepth; + int ret; + + /* Find images parent node offset */ + images_noffset = fdt_path_offset (fit, FIT_IMAGES_PATH); + if (images_noffset < 0) { + printf ("Can't find images parent node '%s' (%s)\n", + FIT_IMAGES_PATH, fdt_strerror (images_noffset)); + return images_noffset; + } + + /* Process its subnodes, print out component images details */ + for (ndepth = 0, noffset = fdt_next_node (fit, images_noffset, &ndepth); + (noffset >= 0) && (ndepth > 0); + noffset = fdt_next_node (fit, noffset, &ndepth)) { + if (ndepth == 1) { + /* + * Direct child node of the images parent node, + * i.e. component image node. + */ + ret = fit_image_set_hashes (fit, noffset); + if (ret) + return ret; + } + } + + return 0; +} + +/** + * fit_image_set_hashes - calculate/set hashes for given component image node + * @fit: pointer to the FIT format image header + * @image_noffset: requested component image node + * + * fit_image_set_hashes() adds hash values for an component image node. All + * existing hash subnodes are checked, if algorithm property is set to one of + * the supported hash algorithms, hash value is computed and corresponding + * hash node property is set, for example: + * + * Input component image node structure: + * + * o image@1 (at image_noffset) + * | - data = [binary data] + * o hash@1 + * |- algo = "sha1" + * + * Output component image node structure: + * + * o image@1 (at image_noffset) + * | - data = [binary data] + * o hash@1 + * |- algo = "sha1" + * |- value = sha1(data) + * + * returns: + * 0 on sucess + * <0 on failure + */ +int fit_image_set_hashes (void *fit, int image_noffset) +{ + const void *data; + size_t size; + char *algo; + uint8_t value[FIT_MAX_HASH_LEN]; + int value_len; + int noffset; + int ndepth; + + /* Get image data and data length */ + if (fit_image_get_data (fit, image_noffset, &data, &size)) { + printf ("Can't get image data/size\n"); + return -1; + } + + /* Process all hash subnodes of the component image node */ + for (ndepth = 0, noffset = fdt_next_node (fit, image_noffset, &ndepth); + (noffset >= 0) && (ndepth > 0); + noffset = fdt_next_node (fit, noffset, &ndepth)) { + if (ndepth == 1) { + /* Direct child node of the component image node */ + + /* + * Check subnode name, must be equal to "hash". + * Multiple hash nodes require unique unit node + * names, e.g. hash@1, hash@2, etc. + */ + if (strncmp (fit_get_name(fit, noffset, NULL), + FIT_HASH_NODENAME, + strlen(FIT_HASH_NODENAME)) != 0) { + /* Not a hash subnode, skip it */ + continue; + } + + if (fit_image_hash_get_algo (fit, noffset, &algo)) { + printf ("Can't get hash algo property for " + "'%s' hash node in '%s' image node\n", + fit_get_name (fit, noffset, NULL), + fit_get_name (fit, image_noffset, NULL)); + return -1; + } + + if (calculate_hash (data, size, algo, value, &value_len)) { + printf ("Unsupported hash algorithm (%s) for " + "'%s' hash node in '%s' image node\n", + algo, fit_get_name (fit, noffset, NULL), + fit_get_name (fit, image_noffset, NULL)); + return -1; + } + + if (fit_image_hash_set_value (fit, noffset, value, + value_len)) { + printf ("Can't set hash value for " + "'%s' hash node in '%s' image node\n", + fit_get_name (fit, noffset, NULL), + fit_get_name (fit, image_noffset, NULL)); + return -1; + } + } + } + + return 0; +} + +/** + * fit_image_hash_set_value - set hash value in requested has node + * @fit: pointer to the FIT format image header + * @noffset: hash node offset + * @value: hash value to be set + * @value_len: hash value length + * + * fit_image_hash_set_value() attempts to set hash value in a node at offset + * given and returns operation status to the caller. + * + * returns + * 0, on success + * -1, on failure + */ +int fit_image_hash_set_value (void *fit, int noffset, uint8_t *value, + int value_len) +{ + int ret; + + ret = fdt_setprop (fit, noffset, FIT_VALUE_PROP, value, value_len); + if (ret) { + printf ("Can't set hash '%s' property for '%s' node (%s)\n", + FIT_VALUE_PROP, fit_get_name (fit, noffset, NULL), + fdt_strerror (ret)); + return -1; + } + + return 0; +} +#endif /* USE_HOSTCC */ + +/** + * fit_image_check_hashes - verify data intergity + * @fit: pointer to the FIT format image header + * @image_noffset: component image node offset + * + * fit_image_check_hashes() goes over component image hash nodes, + * re-calculates each data hash and compares with the value stored in hash + * node. + * + * returns: + * 1, if all hashes are valid + * 0, otherwise (or on error) + */ +int fit_image_check_hashes (const void *fit, int image_noffset) +{ + const void *data; + size_t size; + char *algo; + uint8_t *fit_value; + int fit_value_len; + uint8_t value[FIT_MAX_HASH_LEN]; + int value_len; + int noffset; + int ndepth; + char *err_msg = ""; + + /* Get image data and data length */ + if (fit_image_get_data (fit, image_noffset, &data, &size)) { + printf ("Can't get image data/size\n"); + return 0; + } + + /* Process all hash subnodes of the component image node */ + for (ndepth = 0, noffset = fdt_next_node (fit, image_noffset, &ndepth); + (noffset >= 0) && (ndepth > 0); + noffset = fdt_next_node (fit, noffset, &ndepth)) { + if (ndepth == 1) { + /* Direct child node of the component image node */ + + /* + * Check subnode name, must be equal to "hash". + * Multiple hash nodes require unique unit node + * names, e.g. hash@1, hash@2, etc. + */ + if (strncmp (fit_get_name(fit, noffset, NULL), + FIT_HASH_NODENAME, + strlen(FIT_HASH_NODENAME)) != 0) + continue; + + if (fit_image_hash_get_algo (fit, noffset, &algo)) { + err_msg = "Can't get hash algo property"; + goto error; + } + printf ("%s", algo); + + if (fit_image_hash_get_value (fit, noffset, &fit_value, + &fit_value_len)) { + err_msg = "Can't get hash value property"; + goto error; + } + + if (calculate_hash (data, size, algo, value, &value_len)) { + err_msg = "Unsupported hash algorithm"; + goto error; + } + + if (value_len != fit_value_len) { + err_msg = "Bad hash value len"; + goto error; + } else if (memcmp (value, fit_value, value_len) != 0) { + err_msg = "Bad hash value"; + goto error; + } + printf ("+ "); + } + } + + return 1; + +error: + printf ("%s for '%s' hash node in '%s' image node\n", + err_msg, fit_get_name (fit, noffset, NULL), + fit_get_name (fit, image_noffset, NULL)); + return 0; +} + +/** + * fit_image_check_os - check whether image node is of a given os type + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @os: requested image os + * + * fit_image_check_os() reads image os property and compares its numeric + * id with the requested os. Comparison result is returned to the caller. + * + * returns: + * 1 if image is of given os type + * 0 otherwise (or on error) + */ +int fit_image_check_os (const void *fit, int noffset, uint8_t os) +{ + uint8_t image_os; + + if (fit_image_get_os (fit, noffset, &image_os)) + return 0; + return (os == image_os); +} + +/** + * fit_image_check_arch - check whether image node is of a given arch + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @arch: requested imagearch + * + * fit_image_check_arch() reads image arch property and compares its numeric + * id with the requested arch. Comparison result is returned to the caller. + * + * returns: + * 1 if image is of given arch + * 0 otherwise (or on error) + */ +int fit_image_check_arch (const void *fit, int noffset, uint8_t arch) +{ + uint8_t image_arch; + + if (fit_image_get_arch (fit, noffset, &image_arch)) + return 0; + return (arch == image_arch); +} + +/** + * fit_image_check_type - check whether image node is of a given type + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @type: requested image type + * + * fit_image_check_type() reads image type property and compares its numeric + * id with the requested type. Comparison result is returned to the caller. + * + * returns: + * 1 if image is of given type + * 0 otherwise (or on error) + */ +int fit_image_check_type (const void *fit, int noffset, uint8_t type) +{ + uint8_t image_type; + + if (fit_image_get_type (fit, noffset, &image_type)) + return 0; + return (type == image_type); +} + +/** + * fit_image_check_comp - check whether image node uses given compression + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @comp: requested image compression type + * + * fit_image_check_comp() reads image compression property and compares its + * numeric id with the requested compression type. Comparison result is + * returned to the caller. + * + * returns: + * 1 if image uses requested compression + * 0 otherwise (or on error) + */ +int fit_image_check_comp (const void *fit, int noffset, uint8_t comp) +{ + uint8_t image_comp; + + if (fit_image_get_comp (fit, noffset, &image_comp)) + return 0; + return (comp == image_comp); +} + +/** + * fit_check_format - sanity check FIT image format + * @fit: pointer to the FIT format image header + * + * fit_check_format() runs a basic sanity FIT image verification. + * Routine checks for mandatory properties, nodes, etc. + * + * returns: + * 1, on success + * 0, on failure + */ +int fit_check_format (const void *fit) +{ + /* mandatory / node 'description' property */ + if (fdt_getprop (fit, 0, FIT_DESC_PROP, NULL) == NULL) { + debug ("Wrong FIT format: no description\n"); + return 0; + } + +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) + /* mandatory / node 'timestamp' property */ + if (fdt_getprop (fit, 0, FIT_TIMESTAMP_PROP, NULL) == NULL) { + debug ("Wrong FIT format: no description\n"); + return 0; + } +#endif + + /* mandatory subimages parent '/images' node */ + if (fdt_path_offset (fit, FIT_IMAGES_PATH) < 0) { + debug ("Wrong FIT format: no images parent node\n"); + return 0; + } + + return 1; +} + +/** + * fit_conf_get_node - get node offset for configuration of a given unit name + * @fit: pointer to the FIT format image header + * @conf_uname: configuration node unit name + * + * fit_conf_get_node() finds a configuration (withing the '/configurations' + * parant node) of a provided unit name. If configuration is found its node offset + * is returned to the caller. + * + * When NULL is provided in second argument fit_conf_get_node() will search + * for a default configuration node instead. Default configuration node unit name + * is retrived from FIT_DEFAULT_PROP property of the '/configurations' node. + * + * returns: + * configuration node offset when found (>=0) + * negative number on failure (FDT_ERR_* code) + */ +int fit_conf_get_node (const void *fit, const char *conf_uname) +{ + int noffset, confs_noffset; + int len; + + confs_noffset = fdt_path_offset (fit, FIT_CONFS_PATH); + if (confs_noffset < 0) { + debug ("Can't find configurations parent node '%s' (%s)\n", + FIT_CONFS_PATH, fdt_strerror (confs_noffset)); + return confs_noffset; + } + + if (conf_uname == NULL) { + /* get configuration unit name from the default property */ + debug ("No configuration specified, trying default...\n"); + conf_uname = (char *)fdt_getprop (fit, confs_noffset, FIT_DEFAULT_PROP, &len); + if (conf_uname == NULL) { + fit_get_debug (fit, confs_noffset, FIT_DEFAULT_PROP, len); + return len; + } + debug ("Found default configuration: '%s'\n", conf_uname); + } + + noffset = fdt_subnode_offset (fit, confs_noffset, conf_uname); + if (noffset < 0) { + debug ("Can't get node offset for configuration unit name: '%s' (%s)\n", + conf_uname, fdt_strerror (noffset)); + } + + return noffset; +} + +static int __fit_conf_get_prop_node (const void *fit, int noffset, + const char *prop_name) +{ + char *uname; + int len; + + /* get kernel image unit name from configuration kernel property */ + uname = (char *)fdt_getprop (fit, noffset, prop_name, &len); + if (uname == NULL) + return len; + + return fit_image_get_node (fit, uname); +} + +/** + * fit_conf_get_kernel_node - get kernel image node offset that corresponds to + * a given configuration + * @fit: pointer to the FIT format image header + * @noffset: configuration node offset + * + * fit_conf_get_kernel_node() retrives kernel image node unit name from + * configuration FIT_KERNEL_PROP property and translates it to the node + * offset. + * + * returns: + * image node offset when found (>=0) + * negative number on failure (FDT_ERR_* code) + */ +int fit_conf_get_kernel_node (const void *fit, int noffset) +{ + return __fit_conf_get_prop_node (fit, noffset, FIT_KERNEL_PROP); +} + +/** + * fit_conf_get_ramdisk_node - get ramdisk image node offset that corresponds to + * a given configuration + * @fit: pointer to the FIT format image header + * @noffset: configuration node offset + * + * fit_conf_get_ramdisk_node() retrives ramdisk image node unit name from + * configuration FIT_KERNEL_PROP property and translates it to the node + * offset. + * + * returns: + * image node offset when found (>=0) + * negative number on failure (FDT_ERR_* code) + */ +int fit_conf_get_ramdisk_node (const void *fit, int noffset) +{ + return __fit_conf_get_prop_node (fit, noffset, FIT_RAMDISK_PROP); +} + +/** + * fit_conf_get_fdt_node - get fdt image node offset that corresponds to + * a given configuration + * @fit: pointer to the FIT format image header + * @noffset: configuration node offset + * + * fit_conf_get_fdt_node() retrives fdt image node unit name from + * configuration FIT_KERNEL_PROP property and translates it to the node + * offset. + * + * returns: + * image node offset when found (>=0) + * negative number on failure (FDT_ERR_* code) + */ +int fit_conf_get_fdt_node (const void *fit, int noffset) +{ + return __fit_conf_get_prop_node (fit, noffset, FIT_FDT_PROP); +} + +/** + * fit_conf_print - prints out the FIT configuration details + * @fit: pointer to the FIT format image header + * @noffset: offset of the configuration node + * @p: pointer to prefix string + * + * fit_conf_print() lists all mandatory properies for the processed + * configuration node. + * + * returns: + * no returned results + */ +void fit_conf_print (const void *fit, int noffset, const char *p) +{ + char *desc; + char *uname; + int ret; + + /* Mandatory properties */ + ret = fit_get_desc (fit, noffset, &desc); + printf ("%s Description: ", p); + if (ret) + printf ("unavailable\n"); + else + printf ("%s\n", desc); + + uname = (char *)fdt_getprop (fit, noffset, FIT_KERNEL_PROP, NULL); + printf ("%s Kernel: ", p); + if (uname == NULL) + printf ("unavailable\n"); + else + printf ("%s\n", uname); + + /* Optional properties */ + uname = (char *)fdt_getprop (fit, noffset, FIT_RAMDISK_PROP, NULL); + if (uname) + printf ("%s Init Ramdisk: %s\n", p, uname); + + uname = (char *)fdt_getprop (fit, noffset, FIT_FDT_PROP, NULL); + if (uname) + printf ("%s FDT: %s\n", p, uname); +} + +/** + * fit_check_ramdisk - verify FIT format ramdisk subimage + * @fit_hdr: pointer to the FIT ramdisk header + * @rd_noffset: ramdisk subimage node offset within FIT image + * @arch: requested ramdisk image architecture type + * @verify: data CRC verification flag + * + * fit_check_ramdisk() verifies integrity of the ramdisk subimage and from + * specified FIT image. + * + * returns: + * 1, on success + * 0, on failure + */ +#ifndef USE_HOSTCC +static int fit_check_ramdisk (const void *fit, int rd_noffset, uint8_t arch, int verify) +{ + fit_image_print (fit, rd_noffset, " "); + + if (verify) { + puts (" Verifying Hash Integrity ... "); + if (!fit_image_check_hashes (fit, rd_noffset)) { + puts ("Bad Data Hash\n"); + show_boot_progress (-125); + return 0; + } + puts ("OK\n"); + } + + show_boot_progress (126); + if (!fit_image_check_os (fit, rd_noffset, IH_OS_LINUX) || + !fit_image_check_arch (fit, rd_noffset, arch) || + !fit_image_check_type (fit, rd_noffset, IH_TYPE_RAMDISK)) { + printf ("No Linux %s Ramdisk Image\n", + genimg_get_arch_name(arch)); + show_boot_progress (-126); + return 0; + } + + show_boot_progress (127); + return 1; +} +#endif /* USE_HOSTCC */ +#endif /* CONFIG_FIT */ diff --git a/common/lynxkdi.c b/common/lynxkdi.c index 76a271b966..a5dc88769f 100644 --- a/common/lynxkdi.c +++ b/common/lynxkdi.c @@ -23,45 +23,45 @@ DECLARE_GLOBAL_DATA_PTR; #if defined(CONFIG_MPC8260) || defined(CONFIG_440EP) || defined(CONFIG_440GR) -void lynxkdi_boot ( image_header_t *hdr ) +void lynxkdi_boot (image_header_t *hdr) { - void (*lynxkdi)(void) = (void(*)(void)) ntohl(hdr->ih_ep); + void (*lynxkdi)(void) = (void(*)(void))image_get_ep (hdr); lynxos_bootparms_t *parms = (lynxos_bootparms_t *)0x0020; bd_t *kbd; - u32 *psz = (u32 *)(ntohl(hdr->ih_load) + 0x0204); + u32 *psz = (u32 *)(image_get_load (hdr) + 0x0204); - memset( parms, 0, sizeof(*parms)); + memset (parms, 0, sizeof(*parms)); kbd = gd->bd; parms->clock_ref = kbd->bi_busfreq; parms->dramsz = kbd->bi_memsize; - memcpy(parms->ethaddr, kbd->bi_enetaddr, 6); - mtspr(SPRN_SPRG2, 0x0020); + memcpy (parms->ethaddr, kbd->bi_enetaddr, 6); + mtspr (SPRN_SPRG2, 0x0020); /* Do a simple check for Bluecat so we can pass the * kernel command line parameters. */ - if( le32_to_cpu(*psz) == ntohl(hdr->ih_size) ){ /* FIXME: NOT SURE HERE ! */ - char *args; - char *cmdline = (char *)(ntohl(hdr->ih_load) + 0x020c); - int len; + if (le32_to_cpu (*psz) == image_get_data_size (hdr)) { /* FIXME: NOT SURE HERE ! */ + char *args; + char *cmdline = (char *)(image_get_load (hdr) + 0x020c); + int len; - printf("Booting Bluecat KDI ...\n"); - udelay(200*1000); /* Allow serial port to flush */ - if ((args = getenv("bootargs")) == NULL) - args = ""; - /* Prepend the cmdline */ - len = strlen(args); - if( len && (len + strlen(cmdline) + 2 < (0x0400 - 0x020c))) { - memmove( cmdline + strlen(args) + 1, cmdline, strlen(cmdline) ); - strcpy( cmdline, args ); - cmdline[len] = ' '; - } + printf ("Booting Bluecat KDI ...\n"); + udelay (200*1000); /* Allow serial port to flush */ + if ((args = getenv ("bootargs")) == NULL) + args = ""; + /* Prepend the cmdline */ + len = strlen (args); + if (len && (len + strlen (cmdline) + 2 < (0x0400 - 0x020c))) { + memmove (cmdline + strlen (args) + 1, cmdline, strlen (cmdline)); + strcpy (cmdline, args); + cmdline[len] = ' '; + } } else { - printf("Booting LynxOS KDI ...\n"); + printf ("Booting LynxOS KDI ...\n"); } - lynxkdi(); + lynxkdi (); } #else #error "Lynx KDI support not implemented for configured CPU" diff --git a/cpu/mpc5xxx/cpu.c b/cpu/mpc5xxx/cpu.c index dbfdd97b2a..ace16535ff 100644 --- a/cpu/mpc5xxx/cpu.c +++ b/cpu/mpc5xxx/cpu.c @@ -114,7 +114,7 @@ unsigned long get_tbclk (void) /* ------------------------------------------------------------------------- */ -#ifdef CONFIG_OF_LIBFDT +#if defined(CONFIG_OF_LIBFDT) && defined (CONFIG_OF_BOARD_SETUP) void ft_cpu_setup(void *blob, bd_t *bd) { int div = in_8((void*)CFG_MBAR + 0x204) & 0x0020 ? 8 : 4; diff --git a/cpu/mpc8260/cpu.c b/cpu/mpc8260/cpu.c index 55e61a1887..414759e74c 100644 --- a/cpu/mpc8260/cpu.c +++ b/cpu/mpc8260/cpu.c @@ -300,7 +300,7 @@ void watchdog_reset (void) #endif /* CONFIG_WATCHDOG */ /* ------------------------------------------------------------------------- */ -#if defined(CONFIG_OF_LIBFDT) +#if defined(CONFIG_OF_LIBFDT) && defined (CONFIG_OF_BOARD_SETUP) void ft_cpu_setup (void *blob, bd_t *bd) { char * cpu_path = "/cpus/" OF_CPU; diff --git a/doc/uImage.FIT/command_syntax_extensions.txt b/doc/uImage.FIT/command_syntax_extensions.txt new file mode 100644 index 0000000000..b8b50ffae9 --- /dev/null +++ b/doc/uImage.FIT/command_syntax_extensions.txt @@ -0,0 +1,191 @@ +Command syntax extensions for the new uImage format +=================================================== + +Author: Bartlomiej Sieka <tur@semihalf.com> + +With the introduction of the new uImage format, bootm command (and other +commands as well) have to understand new syntax of the arguments. This is +necessary in order to specify objects contained in the new uImage, on which +bootm has to operate. This note attempts to first summarize bootm usage +scenarios, and then introduces new argument syntax. + + +bootm usage scenarios +--------------------- + +Below is a summary of bootm usage scenarios, focused on booting a PowerPC +Linux kernel. The purpose of the following list is to document a complete list +of supported bootm usages. + +Note: U-Boot supports two methods of booting a PowerPC Linux kernel: old way, +i.e., without passing the Flattened Device Tree (FDT), and new way, where the +kernel is passed a pointer to the FDT. The boot method is indicated for each +scenario. + + +1. bootm boot image at the current address, equivalent to 2,3,8 + +Old uImage: +2. bootm <addr1> /* single image at <addr1> */ +3. bootm <addr1> /* multi-image at <addr1> */ +4. bootm <addr1> - /* multi-image at <addr1> */ +5. bootm <addr1> <addr2> /* single image at <addr1> */ +6. bootm <addr1> <addr2> <addr3> /* single image at <addr1> */ +7. bootm <addr1> - <addr3> /* single image at <addr1> */ + +New uImage: +8. bootm <addr1> +9. bootm [<addr1>]:<subimg1> +10. bootm [<addr1>]#<conf> +11. bootm [<addr1>]:<subimg1> [<addr2>]:<subimg2> +12. bootm [<addr1>]:<subimg1> [<addr2>]:<subimg2> [<addr3>]:<subimg3> +13. bootm [<addr1>]:<subimg1> [<addr2>]:<subimg2> <addr3> +14. bootm [<addr1>]:<subimg1> - [<addr3>]:<subimg3> +15. bootm [<addr1>]:<subimg1> - <addr3> + + +Ad. 1. This is equivalent to cases 2,3,8, depending on the type of image at +the current image address. +- boot method: see cases 2,3,8 + +Ad. 2. Boot kernel image located at <addr1>. +- boot method: non-FDT + +Ad. 3. First and second components of the image at <addr1> are assumed to be a +kernel and a ramdisk, respectively. The kernel is booted with initrd loaded +with the ramdisk from the image. +- boot method: depends on the number of components at <addr1>, and on whether + U-Boot is compiled with OF support: + + | 2 components | 3 components | + | (kernel, initrd) | (kernel, initrd, fdt) | +--------------------------------------------------------------------- +#ifdef CONFIG_OF_* | non-FDT | FDT | +#ifndef CONFIG_OF_* | non-FDT | non-FDT | + +Ad. 4. Similar to case 3, but the kernel is booted without initrd. Second +component of the multi-image is irrelevant (it can be a dummy, 1-byte file). +- boot method: see case 3 + +Ad. 5. Boot kernel image located at <addr1> with initrd loaded with ramdisk +from the image at <addr2>. +- boot method: non-FDT + +Ad. 6. <addr1> is the address of a kernel image, <addr2> is the address of a +ramdisk image, and <addr3> is the address of a FDT binary blob. Kernel is +booted with initrd loaded with ramdisk from the image at <addr2>. +- boot method: FDT + +Ad. 7. <addr1> is the address of a kernel image and <addr3> is the address of +a FDT binary blob. Kernel is booted without initrd. +- boot method: FDT + +Ad. 8. Image at <addr1> is assumed to contain a default configuration, which +is booted. +- boot method: FDT or non-FDT, depending on whether the default configuration + defines FDT + +Ad. 9. Similar to case 2: boot kernel stored in <subimg1> from the image at +address <addr1>. +- boot method: non-FDT + +Ad. 10. Boot configuration <conf> from the image at <addr1>. +- boot method: FDT or non-FDT, depending on whether the configuration given + defines FDT + +Ad. 11. Equivalent to case 5: boot kernel stored in <subimg1> from the image +at <addr1> with initrd loaded with ramdisk <subimg2> from the image at +<addr2>. +- boot method: non-FDT + +Ad. 12. Equivalent to case 6: boot kernel stored in <subimg1> from the image +at <addr1> with initrd loaded with ramdisk <subimg2> from the image at +<addr2>, and pass FDT blob <subimg3> from the image at <addr3>. +- boot method: FDT + +Ad. 13. Similar to case 12, the difference being that <addr3> is the address +of FDT binary blob that is to be passed to the kernel. +- boot method: FDT + +Ad. 14. Equivalent to case 7: boot kernel stored in <subimg1> from the image +at <addr1>, without initrd, and pass FDT blob <subimg3> from the image at +<addr3>. +- boot method: FDT + +Ad. 15. Similar to case 14, the difference being that <addr3> is the address +of the FDT binary blob that is to be passed to the kernel. +- boot method: FDT + + +New uImage argument syntax +-------------------------- + +New uImage support introduces two new forms for bootm arguments, with the +following syntax: + +- new uImage sub-image specification +<addr>:<sub-image unit_name> + +- new uImage configuration specification +<addr>#<configuration unit_name> + + +Examples: + +- boot kernel "kernel@1" stored in a new uImage located at 200000: +bootm 200000:kernel@1 + +- boot configuration "cfg@1" from a new uImage located at 200000: +bootm 200000#cfg@1 + +- boot "kernel@1" from a new uImage at 200000 with initrd "ramdisk@2" found in + some other new uImage stored at address 800000: +bootm 200000:kernel@1 800000:ramdisk@2 + +- boot "kernel@2" from a new uImage at 200000, with initrd "ramdisk@1" and FDT + "fdt@1", both stored in some other new uImage located at 800000: +bootm 200000:kernel@1 800000:ramdisk@1 800000:fdt@1 + +- boot kernel "kernel@2" with initrd "ramdisk@2", both stored in a new uImage + at address 200000, with a raw FDT blob stored at address 600000: +bootm 200000:kernel@2 200000:ramdisk@2 600000 + +- boot kernel "kernel@2" from new uImage at 200000 with FDT "fdt@1" from the + same new uImage: +bootm 200000:kernel@2 - 200000:fdt@1 + + +Note on current image address +----------------------------- + +When bootm is called without arguments, the image at current image address is +booted. The current image address is the address set most recently by a load +command, etc, and is by default equal to CFG_LOAD_ADDR. For example, consider +the following commands: + +tftp 200000 /tftpboot/kernel +bootm +Last command is equivalent to: +bootm 200000 + +In case of the new uImage argument syntax, the address portion of any argument +can be omitted. If <addr3> is omitted, then it is assumed that image at +<addr2> should be used. Similarly, when <addr2> is omitted, is is assumed that +image at <addr1> should be used. If <addr1> is omitted, it is assumed that the +current image address is to be used. For example, consider the following +commands: + +tftp 200000 /tftpboot/uImage +bootm :kernel@1 +Last command is equivalent to: +bootm 200000:kernel@1 + +tftp 200000 /tftpboot/uImage +bootm 400000:kernel@1 :ramdisk@1 +Last command is equivalent to: +bootm 400000:kernel@1 400000:ramdisk@1 + +tftp 200000 /tftpboot/uImage +bootm :kernel@1 400000:ramdisk@1 :fdt@1 +Last command is equivalent to: +bootm 200000:kernel@1 400000:ramdisk@1 400000:fdt@1 diff --git a/doc/uImage.FIT/howto.txt b/doc/uImage.FIT/howto.txt new file mode 100644 index 0000000000..4ae5303b34 --- /dev/null +++ b/doc/uImage.FIT/howto.txt @@ -0,0 +1,297 @@ +How to use images in the new image format +========================================= + +Author: Bartlomiej Sieka <tur@semihalf.com> + + +Overview +-------- + +The new uImage format allows more flexibility in handling images of various +types (kernel, ramdisk, etc.), it also enhances integrity protection of images +with sha1 and md5 checksums. + +Two auxiliary tools are needed on the development host system in order to +create an uImage in the new format: mkimage and dtc, although only one +(mkimage) is invoked directly. dtc is called from within mkimage and operates +behind the scenes, but needs to be present in the $PATH nevertheless. It is +important that the dtc used has support for binary includes -- refer to +www.jdl.com for its latest version. mkimage (together with dtc) takes as input +an image source file, which describes the contents of the image and defines +its various properties used during booting. By convention, image source file +has the ".its" extension, also, the details of its format are given in +doc/source_file_format.txt. The actual data that is to be included in the +uImage (kernel, ramdisk, etc.) is specified in the image source file in the +form of paths to appropriate data files. The outcome of the image creation +process is a binary file (by convention with the ".itb" extension) that +contains all the referenced data (kernel, ramdisk, etc.) and other information +needed by U-Boot to handle the uImage properly. The uImage file is then +transferred to the target (e.g., via tftp) and booted using the bootm command. + +To summarize the prerequisites needed for new uImage creation: +- mkimage +- dtc (with support for binary includes) +- image source file (*.its) +- image data file(s) + + +Here's a graphical overview of the image creation and booting process: + +image source file mkimage + dtc transfer to target + + ---------------> image file --------------------> bootm +image data files(s) + + +Example 1 -- old-style (non-FDT) kernel booting +----------------------------------------------- + +Consider a simple scenario, where a PPC Linux kernel built from sources on the +development host is to be booted old-style (non-FDT) by U-Boot on an embedded +target. Assume that the outcome of the build is vmlinux.bin.gz, a file which +contains a gzip-compressed PPC Linux kernel (the only data file in this case). +The uImage can be produced using the image source file +doc/uImage.FIT/kernel.its (note that kernel.its assumes that vmlinux.bin.gz is +in the current working directory; if desired, an alternative path can be +specified in the kernel.its file). Here's how to create the image and inspect +its contents: + +[on the host system] +$ mkimage -f kernel.its kernel.itb +DTC: dts->dtb on file "kernel.its" +$ +$ mkimage -l kernel.itb +FIT description: Simple image with single Linux kernel +Created: Tue Mar 11 17:26:15 2008 + Image 0 (kernel@1) + Description: Vanilla Linux kernel + Type: Kernel Image + Compression: gzip compressed + Data Size: 943347 Bytes = 921.24 kB = 0.90 MB + Architecture: PowerPC + OS: Linux + Load Address: 0x00000000 + Entry Point: 0x00000000 + Hash algo: crc32 + Hash value: 2ae2bb40 + Hash algo: sha1 + Hash value: 3c200f34e2c226ddc789240cca0c59fc54a67cf4 + Default Configuration: 'config@1' + Configuration 0 (config@1) + Description: Boot Linux kernel + Kernel: kernel@1 + + +The resulting image file kernel.itb can be now transferred to the target, +inspected and booted (note that first three U-Boot commands below are shown +for completeness -- they are part of the standard booting procedure and not +specific to the new image format). + +[on the target system] +=> print nfsargs +nfsargs=setenv bootargs root=/dev/nfs rw nfsroot=${serverip}:${rootpath} +=> print addip +addip=setenv bootargs ${bootargs} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off panic=1 +=> run nfsargs addip +=> tftp 900000 /path/to/tftp/location/kernel.itb +Using FEC ETHERNET device +TFTP from server 192.168.1.1; our IP address is 192.168.160.5 +Filename '/path/to/tftp/location/kernel.itb'. +Load address: 0x900000 +Loading: ################################################################# +done +Bytes transferred = 944464 (e6950 hex) +=> iminfo + +## Checking Image at 00900000 ... + FIT image found + FIT description: Simple image with single Linux kernel + Created: 2008-03-11 16:26:15 UTC + Image 0 (kernel@1) + Description: Vanilla Linux kernel + Type: Kernel Image + Compression: gzip compressed + Data Start: 0x009000e0 + Data Size: 943347 Bytes = 921.2 kB + Architecture: PowerPC + OS: Linux + Load Address: 0x00000000 + Entry Point: 0x00000000 + Hash algo: crc32 + Hash value: 2ae2bb40 + Hash algo: sha1 + Hash value: 3c200f34e2c226ddc789240cca0c59fc54a67cf4 + Default Configuration: 'config@1' + Configuration 0 (config@1) + Description: Boot Linux kernel + Kernel: kernel@1 + +=> bootm +## Booting kernel from FIT Image at 00900000 ... + Using 'config@1' configuration + Trying 'kernel@1' kernel subimage + Description: Vanilla Linux kernel + Type: Kernel Image + Compression: gzip compressed + Data Start: 0x009000e0 + Data Size: 943347 Bytes = 921.2 kB + Architecture: PowerPC + OS: Linux + Load Address: 0x00000000 + Entry Point: 0x00000000 + Hash algo: crc32 + Hash value: 2ae2bb40 + Hash algo: sha1 + Hash value: 3c200f34e2c226ddc789240cca0c59fc54a67cf4 + Verifying Hash Integrity ... crc32+ sha1+ OK + Uncompressing Kernel Image ... OK +Memory BAT mapping: BAT2=256Mb, BAT3=0Mb, residual: 0Mb +Linux version 2.4.25 (m8@hekate) (gcc version 4.0.0 (DENX ELDK 4.0 4.0.0)) #2 czw lip 5 17:56:18 CEST 2007 +On node 0 totalpages: 65536 +zone(0): 65536 pages. +zone(1): 0 pages. +zone(2): 0 pages. +Kernel command line: root=/dev/nfs rw nfsroot=192.168.1.1:/opt/eldk-4.1/ppc_6xx ip=192.168.160.5:192.168.1.1::255.255.0.0:lite5200b:eth0:off panic=1 +Calibrating delay loop... 307.20 BogoMIPS + + +Example 2 -- new-style (FDT) kernel booting +------------------------------------------- + +Consider another simple scenario, where a PPC Linux kernel is to be booted +new-style, i.e., with a FDT blob. In this case there are two prerequisite data +files: vmlinux.bin.gz (Linux kernel) and target.dtb (FDT blob). The uImage can +be produced using image source file doc/uImage.FIT/kernel_fdt.its like this +(note again, that both prerequisite data files are assumed to be present in +the current working directory -- image source file kernel_fdt.its can be +modified to take the files from some other location if needed): + +[on the host system] +$ mkimage -f kernel_fdt.its kernel_fdt.itb +DTC: dts->dtb on file "kernel_fdt.its" +$ +$ mkimage -l kernel_fdt.itb +FIT description: Simple image with single Linux kernel and FDT blob +Created: Tue Mar 11 16:29:22 2008 + Image 0 (kernel@1) + Description: Vanilla Linux kernel + Type: Kernel Image + Compression: gzip compressed + Data Size: 1092037 Bytes = 1066.44 kB = 1.04 MB + Architecture: PowerPC + OS: Linux + Load Address: 0x00000000 + Entry Point: 0x00000000 + Hash algo: crc32 + Hash value: 2c0cc807 + Hash algo: sha1 + Hash value: 264b59935470e42c418744f83935d44cdf59a3bb + Image 1 (fdt@1) + Description: Flattened Device Tree blob + Type: Flat Device Tree + Compression: uncompressed + Data Size: 16384 Bytes = 16.00 kB = 0.02 MB + Architecture: PowerPC + Hash algo: crc32 + Hash value: 0d655d71 + Hash algo: sha1 + Hash value: 25ab4e15cd4b8a5144610394560d9c318ce52def + Default Configuration: 'conf@1' + Configuration 0 (conf@1) + Description: Boot Linux kernel with FDT blob + Kernel: kernel@1 + FDT: fdt@1 + + +The resulting image file kernel_fdt.itb can be now transferred to the target, +inspected and booted: + +[on the target system] +=> tftp 900000 /path/to/tftp/location/kernel_fdt.itb +Using FEC ETHERNET device +TFTP from server 192.168.1.1; our IP address is 192.168.160.5 +Filename '/path/to/tftp/location/kernel_fdt.itb'. +Load address: 0x900000 +Loading: ################################################################# + ########### +done +Bytes transferred = 1109776 (10ef10 hex) +=> iminfo + +## Checking Image at 00900000 ... + FIT image found + FIT description: Simple image with single Linux kernel and FDT blob + Created: 2008-03-11 15:29:22 UTC + Image 0 (kernel@1) + Description: Vanilla Linux kernel + Type: Kernel Image + Compression: gzip compressed + Data Start: 0x009000ec + Data Size: 1092037 Bytes = 1 MB + Architecture: PowerPC + OS: Linux + Load Address: 0x00000000 + Entry Point: 0x00000000 + Hash algo: crc32 + Hash value: 2c0cc807 + Hash algo: sha1 + Hash value: 264b59935470e42c418744f83935d44cdf59a3bb + Image 1 (fdt@1) + Description: Flattened Device Tree blob + Type: Flat Device Tree + Compression: uncompressed + Data Start: 0x00a0abdc + Data Size: 16384 Bytes = 16 kB + Architecture: PowerPC + Hash algo: crc32 + Hash value: 0d655d71 + Hash algo: sha1 + Hash value: 25ab4e15cd4b8a5144610394560d9c318ce52def + Default Configuration: 'conf@1' + Configuration 0 (conf@1) + Description: Boot Linux kernel with FDT blob + Kernel: kernel@1 + FDT: fdt@1 +=> bootm +## Booting kernel from FIT Image at 00900000 ... + Using 'conf@1' configuration + Trying 'kernel@1' kernel subimage + Description: Vanilla Linux kernel + Type: Kernel Image + Compression: gzip compressed + Data Start: 0x009000ec + Data Size: 1092037 Bytes = 1 MB + Architecture: PowerPC + OS: Linux + Load Address: 0x00000000 + Entry Point: 0x00000000 + Hash algo: crc32 + Hash value: 2c0cc807 + Hash algo: sha1 + Hash value: 264b59935470e42c418744f83935d44cdf59a3bb + Verifying Hash Integrity ... crc32+ sha1+ OK + Uncompressing Kernel Image ... OK +## Flattened Device Tree from FIT Image at 00900000 + Using 'conf@1' configuration + Trying 'fdt@1' FDT blob subimage + Description: Flattened Device Tree blob + Type: Flat Device Tree + Compression: uncompressed + Data Start: 0x00a0abdc + Data Size: 16384 Bytes = 16 kB + Architecture: PowerPC + Hash algo: crc32 + Hash value: 0d655d71 + Hash algo: sha1 + Hash value: 25ab4e15cd4b8a5144610394560d9c318ce52def + Verifying Hash Integrity ... crc32+ sha1+ OK + Booting using the fdt blob at 0xa0abdc + Loading Device Tree to 007fc000, end 007fffff ... OK +[ 0.000000] Using lite5200 machine description +[ 0.000000] Linux version 2.6.24-rc6-gaebecdfc (m8@hekate) (gcc version 4.0.0 (DENX ELDK 4.1 4.0.0)) #1 Sat Jan 12 15:38:48 CET 2008 + + +Example 3 -- advanced booting +----------------------------- + +Refer to doc/uImage.FIT/multi.its for an image source file that allows more +sophisticated booting scenarios (multiple kernels, ramdisks and fdt blobs). diff --git a/doc/uImage.FIT/kernel.its b/doc/uImage.FIT/kernel.its new file mode 100644 index 0000000000..d1a5939115 --- /dev/null +++ b/doc/uImage.FIT/kernel.its @@ -0,0 +1,34 @@ +/* + * Simple U-boot uImage source file containing a single kernel + */ +/ { + description = "Simple image with single Linux kernel"; + #address-cells = <1>; + + images { + kernel@1 { + description = "Vanilla Linux kernel"; + data = /incbin/("./vmlinux.bin.gz"); + type = "kernel"; + arch = "ppc"; + os = "linux"; + compression = "gzip"; + load = <00000000>; + entry = <00000000>; + hash@1 { + algo = "crc32"; + }; + hash@2 { + algo = "sha1"; + }; + }; + }; + + configurations { + default = "config@1"; + config@1 { + description = "Boot Linux kernel"; + kernel = "kernel@1"; + }; + }; +}; diff --git a/doc/uImage.FIT/kernel_fdt.its b/doc/uImage.FIT/kernel_fdt.its new file mode 100644 index 0000000000..fd6dee2571 --- /dev/null +++ b/doc/uImage.FIT/kernel_fdt.its @@ -0,0 +1,48 @@ +/* + * Simple U-boot uImage source file containing a single kernel and FDT blob + */ +/ { + description = "Simple image with single Linux kernel and FDT blob"; + #address-cells = <1>; + + images { + kernel@1 { + description = "Vanilla Linux kernel"; + data = /incbin/("./vmlinux.bin.gz"); + type = "kernel"; + arch = "ppc"; + os = "linux"; + compression = "gzip"; + load = <00000000>; + entry = <00000000>; + hash@1 { + algo = "crc32"; + }; + hash@2 { + algo = "sha1"; + }; + }; + fdt@1 { + description = "Flattened Device Tree blob"; + data = /incbin/("./target.dtb"); + type = "flat_dt"; + arch = "ppc"; + compression = "none"; + hash@1 { + algo = "crc32"; + }; + hash@2 { + algo = "sha1"; + }; + }; + }; + + configurations { + default = "conf@1"; + conf@1 { + description = "Boot Linux kernel with FDT blob"; + kernel = "kernel@1"; + fdt = "fdt@1"; + }; + }; +}; diff --git a/doc/uImage.FIT/multi.its b/doc/uImage.FIT/multi.its new file mode 100644 index 0000000000..b9929623b4 --- /dev/null +++ b/doc/uImage.FIT/multi.its @@ -0,0 +1,124 @@ +/* + * U-boot uImage source file with multiple kernels, ramdisks and FDT blobs + */ +/ { + description = "Various kernels, ramdisks and FDT blobs"; + #address-cells = <1>; + + images { + kernel@1 { + description = "vanilla-2.6.23"; + data = /incbin/("./vmlinux.bin.gz"); + type = "kernel"; + arch = "ppc"; + os = "linux"; + compression = "gzip"; + load = <00000000>; + entry = <00000000>; + hash@1 { + algo = "md5"; + }; + hash@2 { + algo = "sha1"; + }; + }; + + kernel@2 { + description = "2.6.23-denx"; + data = /incbin/("./2.6.23-denx.bin.gz"); + type = "kernel"; + arch = "ppc"; + os = "linux"; + compression = "gzip"; + load = <00000000>; + entry = <00000000>; + hash@1 { + algo = "sha1"; + }; + }; + + kernel@3 { + description = "2.4.25-denx"; + data = /incbin/("./2.4.25-denx.bin.gz"); + type = "kernel"; + arch = "ppc"; + os = "linux"; + compression = "gzip"; + load = <00000000>; + entry = <00000000>; + hash@1 { + algo = "md5"; + }; + }; + + ramdisk@1 { + description = "eldk-4.2-ramdisk"; + data = /incbin/("./eldk-4.2-ramdisk"); + type = "ramdisk"; + arch = "ppc"; + compression = "gzip"; + hash@1 { + algo = "sha1"; + }; + }; + + ramdisk@2 { + description = "eldk-3.1-ramdisk"; + data = /incbin/("./eldk-3.1-ramdisk"); + type = "ramdisk"; + arch = "ppc"; + compression = "gzip"; + hash@1 { + algo = "crc32"; + }; + }; + + fdt@1 { + description = "tqm5200-fdt"; + data = /incbin/("./tqm5200.dtb"); + type = "flat_dt"; + arch = "ppc"; + compression = "none"; + hash@1 { + algo = "crc32"; + }; + }; + + fdt@2 { + description = "tqm5200s-fdt"; + data = /incbin/("./tqm5200s.dtb"); + type = "flat_dt"; + arch = "ppc"; + compression = "none"; + load = <00700000>; + hash@1 { + algo = "sha1"; + }; + }; + + }; + + configurations { + default = "config@1"; + + config@1 { + description = "tqm5200 vanilla-2.6.23 configuration"; + kernel = "kernel@1"; + ramdisk = "ramdisk@1"; + fdt = "fdt@1"; + }; + + config@2 { + description = "tqm5200s denx-2.6.23 configuration"; + kernel = "kernel@2"; + ramdisk = "ramdisk@1"; + fdt = "fdt@2"; + }; + + config@3 { + description = "tqm5200s denx-2.4.25 configuration"; + kernel = "kernel@3"; + ramdisk = "ramdisk@2"; + }; + }; +}; diff --git a/doc/uImage.FIT/source_file_format.txt b/doc/uImage.FIT/source_file_format.txt new file mode 100644 index 0000000000..1d7545811b --- /dev/null +++ b/doc/uImage.FIT/source_file_format.txt @@ -0,0 +1,262 @@ +U-boot new uImage source file format (bindings definition) +========================================================== + +Author: Marian Balakowicz <m8@semihalf.com> + +1) Introduction +--------------- + +Evolution of the 2.6 Linux kernel for embedded PowerPC systems introduced new +booting method which requires that hardware description is available to the +kernel in the form of Flattened Device Tree. + +Booting with a Flattened Device Tree is much more flexible and is intended to +replace direct passing of 'struct bd_info' which was used to boot pre-FDT +kernels. + +However, U-boot needs to support both techniques to provide backward +compatibility for platforms which are not FDT ready. Number of elements +playing role in the booting process has increased and now includes the FDT +blob. Kernel image, FDT blob and possibly ramdisk image - all must be placed +in the system memory and passed to bootm as a arguments. Some of them may be +missing: FDT is not present for legacy platforms, ramdisk is always optional. +Additionally, old uImage format has been extended to support multi sub-images +but the support is limited by simple format of the legacy uImage structure. +Single binary header 'struct image_header' is not flexible enough to cover all +possible scenarios. + +All those factors combined clearly show that there is a need for new, more +flexible, multi component uImage format. + + +2) New uImage format assumptions +-------------------------------- + +a) Implementation + +Libfdt has been selected for the new uImage format implementation as (1) it +provides needed functionality, (2) is actively maintained and developed and +(3) increases code reuse as it is already part of the U-boot source tree. + +b) Terminology + +This document defines new uImage structure by providing FDT bindings for new +uImage internals. Bindings are defined from U-boot perspective, i.e. describe +final form of the uImage at the moment when it reaches U-boot. User +perspective may be simpler, as some of the properties (like timestamps and +hashes) will need to be filled in automatically by the U-boot mkimage tool. + +To avoid confusion with the kernel FDT the following naming convention is +proposed for the new uImage format related terms: + +FIT - Flattened uImage Tree + +FIT is formally a flattened device tree (in the libfdt meaning), which +conforms to bindings defined in this document. + +.its - image tree source +.itb - image tree blob + +c) Image building procedure + +The following picture shows how the new uImage is prepared. Input consists of +image source file (.its) and a set of data files. Image is created with the +help of standard U-boot mkimage tool which in turn uses dtc (device tree +compiler) to produce image tree blob (.itb). Resulting .itb file is is the +actual binary of a new uImage. + + +tqm5200.its ++ +vmlinux.bin.gz mkimage + dtc xfer to target +eldk-4.2-ramdisk --------------> tqm5200.itb --------------> bootm +tqm5200.dtb /|\ +... | + 'new uImage' + + - create .its file, automatically filled-in properties are omitted + - call mkimage tool on a .its file + - mkimage calls dtc to create .itb image and assures that + missing properties are added + - .itb (new uImage) is uploaded onto the target and used therein + + +d) Unique identifiers + +To identify FIT sub-nodes representing images, hashes, configurations (which +are defined in the following sections), the "unit name" of the given sub-node +is used as it's identifier as it assures uniqueness without additional +checking required. + + +3) Root node properties +----------------------- + +Root node of the uImage Tree should have the following layout: + +/ o image-tree + |- description = "image description" + |- timestamp = <12399321> + |- #address-cells = <1> + | + o images + | | + | o img@1 {...} + | o img@2 {...} + | ... + | + o configurations + |- default = "cfg@1" + | + o cfg@1 {...} + o cfg@2 {...} + ... + + + Optional property: + - description : Textual description of the uImage + + Mandatory property: + - timestamp : Last image modification time being counted in seconds since + 1970-01-01 00:00:00 - to be automatically calculated by mkimage tool. + + Conditionally mandatory property: + - #address-cells : Number of 32bit cells required to represent entry and + load addresses supplied within sub-image nodes. May be omitted when no + entry or load addresses are used. + + Mandatory node: + - images : This node contains a set of sub-nodes, each of them representing + single component sub-image (like kernel, ramdisk, etc.). At least one + sub-image is required. + + Optional node: + - configurations : Contains a set of available configuration nodes and + defines a default configuration. + + +4) '/images' node +----------------- + +This node is a container node for component sub-image nodes. Each sub-node of +the '/images' node should have the following layout: + + o image@1 + |- description = "component sub-image description" + |- data = /incbin/("path/to/data/file.bin") + |- type = "sub-image type name" + |- arch = "ARCH name" + |- os = "OS name" + |- compression = "compression name" + |- load = <00000000> + |- entry = <00000000> + | + o hash@1 {...} + o hash@2 {...} + ... + + Mandatory properties: + - description : Textual description of the component sub-image + - type : Name of component sub-image type, supported types are: + "standalone", "kernel", "ramdisk", "firmware", "script", "filesystem", + "fdt". + - data : Path to the external file which contains this node's binary data. + - compression : Compression used by included data. Supported compressions + are "gzip" and "bzip2". If no compression is used compression property + should be set to "none". + + Conditionally mandatory property: + - os : OS name, mandatory for type="kernel", valid OS names are: "openbsd", + "netbsd", "freebsd", "4_4bsd", "linux", "svr4", "esix", "solaris", "irix", + "sco", "dell", "ncr", "lynxos", "vxworks", "psos", "qnx", "u_boot", + "rtems", "artos", "unity". + - arch : Architecture name, mandatory for types: "standalone", "kernel", + "firmware", "ramdisk" and "fdt". Valid architecture names are: "alpha", + "arm", "i386", "ia64", "mips", "mips64", "ppc", "s390", "sh", "sparc", + "sparc64", "m68k", "nios", "microblaze", "nios2", "blackfin", "avr32", + "st200". + - entry : entry point address, address size is determined by + '#address-cells' property of the root node. Mandatory for for types: + "standalone" and "kernel". + - load : load address, address size is determined by '#address-cells' + property of the root node. Mandatory for types: "standalone" and "kernel". + + Optional nodes: + - hash@1 : Each hash sub-node represents separate hash or checksum + calculated for node's data according to specified algorithm. + + +5) Hash nodes +------------- + +o hash@1 + |- algo = "hash or checksum algorithm name" + |- value = [hash or checksum value] + + Mandatory properties: + - algo : Algorithm name, supported are "crc32", "md5" and "sha1". + - value : Actual checksum or hash value, correspondingly 4, 16 or 20 bytes + long. + + +6) '/configurations' node +------------------------- + +The 'configurations' node is optional. If present, it allows to create a +convenient, labeled boot configurations, which combine together kernel images +with their ramdisks and fdt blobs. + +The 'configurations' node has has the following structure: + +o configurations + |- default = "default configuration sub-node unit name" + | + o config@1 {...} + o config@2 {...} + ... + + + Optional property: + - default : Selects one of the configuration sub-nodes as a default + configuration. + + Mandatory nodes: + - configuration-sub-node-unit-name : At least one of the configuration + sub-nodes is required. + + +7) Configuration nodes +---------------------- + +Each configuration has the following structure: + +o config@1 + |- description = "configuration description" + |- kernel = "kernel sub-node unit name" + |- ramdisk = "ramdisk sub-node unit name" + |- fdt = "fdt sub-node unit-name" + + + Mandatory properties: + - description : Textual configuration description. + - kernel : Unit name of the corresponding kernel image (image sub-node of a + "kernel" type). + + Optional properties: + - ramdisk : Unit name of the corresponding ramdisk image (component image + node of a "ramdisk" type). + - fdt : Unit name of the corresponding fdt blob (component image node of a + "fdt type"). + +The FDT blob is required to properly boot FDT based kernel, so the minimal +configuration for 2.6 FDT kernel is (kernel, fdt) pair. + +Older, 2.4 kernel and 2.6 non-FDT kernel do not use FDT blob, in such cases +'struct bd_info' must be passed instead of FDT blob, thus fdt property *must +not* be specified in a configuration node. + + +8) Examples +----------- + +Please see doc/uImage.FIT/*.its for actual image source files. diff --git a/examples/eepro100_eeprom.c b/examples/eepro100_eeprom.c index a52e68d4e7..2b15d05adb 100644 --- a/examples/eepro100_eeprom.c +++ b/examples/eepro100_eeprom.c @@ -17,8 +17,9 @@ * and release the resulting code under the GPL. */ -#define _PPC_STRING_H_ /* avoid unnecessary str/mem functions */ -#define _LINUX_STRING_H_ /* avoid unnecessary str/mem functions */ +/* avoid unnecessary memcpy function */ +#define __HAVE_ARCH_MEMCPY +#define _PPC_STRING_H_ #include <common.h> #include <exports.h> diff --git a/fs/cramfs/uncompress.c b/fs/cramfs/uncompress.c index a9c0b7d46e..cf67967904 100644 --- a/fs/cramfs/uncompress.c +++ b/fs/cramfs/uncompress.c @@ -29,24 +29,8 @@ static z_stream stream; -#define ZALLOC_ALIGNMENT 16 - -static void *zalloc (void *x, unsigned items, unsigned size) -{ - void *p; - - size *= items; - size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1); - - p = malloc (size); - - return (p); -} - -static void zfree (void *x, void *addr, unsigned nb) -{ - free (addr); -} +void *zalloc(void *, unsigned, unsigned); +void zfree(void *, void *, unsigned); /* Returns length of decompressed data. */ int cramfs_uncompress_block (void *dst, void *src, int srclen) diff --git a/include/asm-i386/zimage.h b/include/asm-i386/zimage.h index c7103b1f37..b6266e456a 100644 --- a/include/asm-i386/zimage.h +++ b/include/asm-i386/zimage.h @@ -70,6 +70,5 @@ void *load_zimage(char *image, unsigned long kernel_size, int auto_boot); void boot_zimage(void *setup_base); -image_header_t *fake_zimage_header(image_header_t *hdr, void *ptr, int size); #endif diff --git a/include/common.h b/include/common.h index 673afdd150..e03ead10bc 100644 --- a/include/common.h +++ b/include/common.h @@ -222,10 +222,7 @@ int mac_read_from_eeprom(void); void flash_perror (int); /* common/cmd_autoscript.c */ -int autoscript (ulong addr); - -/* common/cmd_bootm.c */ -void print_image_hdr (image_header_t *hdr); +int autoscript (ulong addr, const char *fit_uname); extern ulong load_addr; /* Default Load Address */ diff --git a/include/configs/pcs440ep.h b/include/configs/pcs440ep.h index 893924b4bf..ba6d932249 100644 --- a/include/configs/pcs440ep.h +++ b/include/configs/pcs440ep.h @@ -27,6 +27,12 @@ #ifndef __CONFIG_H #define __CONFIG_H + +/* new uImage format support */ +#define CONFIG_FIT 1 +#define CONFIG_OF_LIBFDT 1 +#define CONFIG_FIT_VERBOSE 1 /* enable fit_format_{error,warning}() */ + /*----------------------------------------------------------------------- * High Level Configuration Options *----------------------------------------------------------------------*/ diff --git a/include/image.h b/include/image.h index 432fa22393..36143e25ac 100644 --- a/include/image.h +++ b/include/image.h @@ -1,4 +1,6 @@ /* + * (C) Copyright 2008 Semihalf + * * (C) Copyright 2000-2005 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * @@ -31,6 +33,34 @@ #ifndef __IMAGE_H__ #define __IMAGE_H__ +#include <asm/byteorder.h> +#include <command.h> + +#ifndef USE_HOSTCC +#include <lmb.h> +#include <linux/string.h> +#include <asm/u-boot.h> + +#else + +/* new uImage format support enabled on host */ +#define CONFIG_FIT 1 +#define CONFIG_OF_LIBFDT 1 +#define CONFIG_FIT_VERBOSE 1 /* enable fit_format_{error,warning}() */ + +#endif /* USE_HOSTCC */ + +#if defined(CONFIG_FIT) && !defined(CONFIG_OF_LIBFDT) +#error "CONFIG_OF_LIBFDT not enabled, required by CONFIG_FIT!" +#endif + +#if defined(CONFIG_FIT) +#include <fdt.h> +#include <libfdt.h> +#include <fdt_support.h> +#define CONFIG_MD5 /* FIT images need MD5 support */ +#endif + /* * Operating System Codes */ @@ -59,25 +89,25 @@ /* * CPU Architecture Codes (supported by Linux) */ -#define IH_CPU_INVALID 0 /* Invalid CPU */ -#define IH_CPU_ALPHA 1 /* Alpha */ -#define IH_CPU_ARM 2 /* ARM */ -#define IH_CPU_I386 3 /* Intel x86 */ -#define IH_CPU_IA64 4 /* IA64 */ -#define IH_CPU_MIPS 5 /* MIPS */ -#define IH_CPU_MIPS64 6 /* MIPS 64 Bit */ -#define IH_CPU_PPC 7 /* PowerPC */ -#define IH_CPU_S390 8 /* IBM S390 */ -#define IH_CPU_SH 9 /* SuperH */ -#define IH_CPU_SPARC 10 /* Sparc */ -#define IH_CPU_SPARC64 11 /* Sparc 64 Bit */ -#define IH_CPU_M68K 12 /* M68K */ -#define IH_CPU_NIOS 13 /* Nios-32 */ -#define IH_CPU_MICROBLAZE 14 /* MicroBlaze */ -#define IH_CPU_NIOS2 15 /* Nios-II */ -#define IH_CPU_BLACKFIN 16 /* Blackfin */ -#define IH_CPU_AVR32 17 /* AVR32 */ -#define IH_CPU_ST200 18 /* STMicroelectronics ST200 */ +#define IH_ARCH_INVALID 0 /* Invalid CPU */ +#define IH_ARCH_ALPHA 1 /* Alpha */ +#define IH_ARCH_ARM 2 /* ARM */ +#define IH_ARCH_I386 3 /* Intel x86 */ +#define IH_ARCH_IA64 4 /* IA64 */ +#define IH_ARCH_MIPS 5 /* MIPS */ +#define IH_ARCH_MIPS64 6 /* MIPS 64 Bit */ +#define IH_ARCH_PPC 7 /* PowerPC */ +#define IH_ARCH_S390 8 /* IBM S390 */ +#define IH_ARCH_SH 9 /* SuperH */ +#define IH_ARCH_SPARC 10 /* Sparc */ +#define IH_ARCH_SPARC64 11 /* Sparc 64 Bit */ +#define IH_ARCH_M68K 12 /* M68K */ +#define IH_ARCH_NIOS 13 /* Nios-32 */ +#define IH_ARCH_MICROBLAZE 14 /* MicroBlaze */ +#define IH_ARCH_NIOS2 15 /* Nios-II */ +#define IH_ARCH_BLACKFIN 16 /* Blackfin */ +#define IH_ARCH_AVR32 17 /* AVR32 */ +#define IH_ARCH_ST200 18 /* STMicroelectronics ST200 */ /* * Image Types @@ -139,9 +169,9 @@ #define IH_NMLEN 32 /* Image Name Length */ /* - * all data in network byte order (aka natural aka bigendian) + * Legacy format image header, + * all data in network byte order (aka natural aka bigendian). */ - typedef struct image_header { uint32_t ih_magic; /* Image Header Magic Number */ uint32_t ih_hcrc; /* Image Header CRC Checksum */ @@ -157,5 +187,412 @@ typedef struct image_header { uint8_t ih_name[IH_NMLEN]; /* Image Name */ } image_header_t; +/* + * Legacy and FIT format headers used by do_bootm() and do_bootm_<os>() + * routines. + */ +typedef struct bootm_headers { + /* + * Legacy os image header, if it is a multi component image + * then boot_get_ramdisk() and get_fdt() will attempt to get + * data from second and third component accordingly. + */ + image_header_t *legacy_hdr_os; + ulong legacy_hdr_valid; + +#if defined(CONFIG_FIT) + const char *fit_uname_cfg; /* configuration node unit name */ + + void *fit_hdr_os; /* os FIT image header */ + const char *fit_uname_os; /* os subimage node unit name */ + int fit_noffset_os; /* os subimage node offset */ + + void *fit_hdr_rd; /* init ramdisk FIT image header */ + const char *fit_uname_rd; /* init ramdisk subimage node unit name */ + int fit_noffset_rd; /* init ramdisk subimage node offset */ + +#if defined(CONFIG_PPC) + void *fit_hdr_fdt; /* FDT blob FIT image header */ + const char *fit_uname_fdt; /* FDT blob subimage node unit name */ + int fit_noffset_fdt;/* FDT blob subimage node offset */ +#endif +#endif + + int verify; /* getenv("verify")[0] != 'n' */ + int autostart; /* getenv("autostart")[0] != 'n' */ + struct lmb *lmb; /* for memory mgmt */ +} bootm_headers_t; + +/* + * Some systems (for example LWMON) have very short watchdog periods; + * we must make sure to split long operations like memmove() or + * crc32() into reasonable chunks. + */ +#define CHUNKSZ (64 * 1024) + +#define uimage_to_cpu(x) ntohl(x) +#define cpu_to_uimage(x) htonl(x) + +const char *genimg_get_os_name (uint8_t os); +const char *genimg_get_arch_name (uint8_t arch); +const char *genimg_get_type_name (uint8_t type); +const char *genimg_get_comp_name (uint8_t comp); +int genimg_get_os_id (const char *name); +int genimg_get_arch_id (const char *name); +int genimg_get_type_id (const char *name); +int genimg_get_comp_id (const char *name); + +#ifndef USE_HOSTCC +/* Image format types, returned by _get_format() routine */ +#define IMAGE_FORMAT_INVALID 0x00 +#define IMAGE_FORMAT_LEGACY 0x01 /* legacy image_header based format */ +#define IMAGE_FORMAT_FIT 0x02 /* new, libfdt based format */ + +int genimg_get_format (void *img_addr); +int genimg_has_config (bootm_headers_t *images); +ulong genimg_get_image (ulong img_addr); + +int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images, + uint8_t arch, ulong *rd_start, ulong *rd_end); + +#if defined(CONFIG_PPC) || defined(CONFIG_M68K) +int boot_ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len, + ulong *initrd_start, ulong *initrd_end); + +int boot_get_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, + ulong bootmap_base); +int boot_get_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base); +#endif /* CONFIG_PPC || CONFIG_M68K */ +#endif /* !USE_HOSTCC */ + +/*******************************************************************/ +/* Legacy format specific code (prefixed with image_) */ +/*******************************************************************/ +static inline uint32_t image_get_header_size (void) +{ + return (sizeof (image_header_t)); +} + +#define image_get_hdr_l(f) \ + static inline uint32_t image_get_##f(image_header_t *hdr) \ + { \ + return uimage_to_cpu (hdr->ih_##f); \ + } +image_get_hdr_l (magic); +image_get_hdr_l (hcrc); +image_get_hdr_l (time); +image_get_hdr_l (size); +image_get_hdr_l (load); +image_get_hdr_l (ep); +image_get_hdr_l (dcrc); + +#define image_get_hdr_b(f) \ + static inline uint8_t image_get_##f(image_header_t *hdr) \ + { \ + return hdr->ih_##f; \ + } +image_get_hdr_b (os); +image_get_hdr_b (arch); +image_get_hdr_b (type); +image_get_hdr_b (comp); + +static inline char *image_get_name (image_header_t *hdr) +{ + return (char *)hdr->ih_name; +} + +static inline uint32_t image_get_data_size (image_header_t *hdr) +{ + return image_get_size (hdr); +} + +/** + * image_get_data - get image payload start address + * @hdr: image header + * + * image_get_data() returns address of the image payload. For single + * component images it is image data start. For multi component + * images it points to the null terminated table of sub-images sizes. + * + * returns: + * image payload data start address + */ +static inline ulong image_get_data (image_header_t *hdr) +{ + return ((ulong)hdr + image_get_header_size ()); +} + +static inline uint32_t image_get_image_size (image_header_t *hdr) +{ + return (image_get_size (hdr) + image_get_header_size ()); +} +static inline ulong image_get_image_end (image_header_t *hdr) +{ + return ((ulong)hdr + image_get_image_size (hdr)); +} + +#define image_set_hdr_l(f) \ + static inline void image_set_##f(image_header_t *hdr, uint32_t val) \ + { \ + hdr->ih_##f = cpu_to_uimage (val); \ + } +image_set_hdr_l (magic); +image_set_hdr_l (hcrc); +image_set_hdr_l (time); +image_set_hdr_l (size); +image_set_hdr_l (load); +image_set_hdr_l (ep); +image_set_hdr_l (dcrc); + +#define image_set_hdr_b(f) \ + static inline void image_set_##f(image_header_t *hdr, uint8_t val) \ + { \ + hdr->ih_##f = val; \ + } +image_set_hdr_b (os); +image_set_hdr_b (arch); +image_set_hdr_b (type); +image_set_hdr_b (comp); + +static inline void image_set_name (image_header_t *hdr, const char *name) +{ + strncpy (image_get_name (hdr), name, IH_NMLEN); +} + +int image_check_hcrc (image_header_t *hdr); +int image_check_dcrc (image_header_t *hdr); +#ifndef USE_HOSTCC +int image_check_dcrc_wd (image_header_t *hdr, ulong chunksize); +int getenv_verify (void); +int getenv_autostart (void); +ulong getenv_bootm_low(void); +ulong getenv_bootm_size(void); +void memmove_wd (void *to, void *from, size_t len, ulong chunksz); +#endif + +static inline int image_check_magic (image_header_t *hdr) +{ + return (image_get_magic (hdr) == IH_MAGIC); +} +static inline int image_check_type (image_header_t *hdr, uint8_t type) +{ + return (image_get_type (hdr) == type); +} +static inline int image_check_arch (image_header_t *hdr, uint8_t arch) +{ + return (image_get_arch (hdr) == arch); +} +static inline int image_check_os (image_header_t *hdr, uint8_t os) +{ + return (image_get_os (hdr) == os); +} + +ulong image_multi_count (image_header_t *hdr); +void image_multi_getimg (image_header_t *hdr, ulong idx, + ulong *data, ulong *len); + +inline void image_print_contents (image_header_t *hdr); +inline void image_print_contents_noindent (image_header_t *hdr); + +#ifndef USE_HOSTCC +static inline int image_check_target_arch (image_header_t *hdr) +{ +#if defined(__ARM__) + if (!image_check_arch (hdr, IH_ARCH_ARM)) +#elif defined(__avr32__) + if (!image_check_arch (hdr, IH_ARCH_AVR32)) +#elif defined(__bfin__) + if (!image_check_arch (hdr, IH_ARCH_BLACKFIN)) +#elif defined(__I386__) + if (!image_check_arch (hdr, IH_ARCH_I386)) +#elif defined(__M68K__) + if (!image_check_arch (hdr, IH_ARCH_M68K)) +#elif defined(__microblaze__) + if (!image_check_arch (hdr, IH_ARCH_MICROBLAZE)) +#elif defined(__mips__) + if (!image_check_arch (hdr, IH_ARCH_MIPS)) +#elif defined(__nios__) + if (!image_check_arch (hdr, IH_ARCH_NIOS)) +#elif defined(__nios2__) + if (!image_check_arch (hdr, IH_ARCH_NIOS2)) +#elif defined(__PPC__) + if (!image_check_arch (hdr, IH_ARCH_PPC)) +#elif defined(__sh__) + if (!image_check_arch (hdr, IH_ARCH_SH)) +#else +# error Unknown CPU type +#endif + return 0; + + return 1; +} +#endif /* USE_HOSTCC */ + +/*******************************************************************/ +/* New uImage format specific code (prefixed with fit_) */ +/*******************************************************************/ +#if defined(CONFIG_FIT) + +#define FIT_IMAGES_PATH "/images" +#define FIT_CONFS_PATH "/configurations" + +/* hash node */ +#define FIT_HASH_NODENAME "hash" +#define FIT_ALGO_PROP "algo" +#define FIT_VALUE_PROP "value" + +/* image node */ +#define FIT_DATA_PROP "data" +#define FIT_TIMESTAMP_PROP "timestamp" +#define FIT_DESC_PROP "description" +#define FIT_ARCH_PROP "arch" +#define FIT_TYPE_PROP "type" +#define FIT_OS_PROP "os" +#define FIT_COMP_PROP "compression" +#define FIT_ENTRY_PROP "entry" +#define FIT_LOAD_PROP "load" + +/* configuration node */ +#define FIT_KERNEL_PROP "kernel" +#define FIT_RAMDISK_PROP "ramdisk" +#define FIT_FDT_PROP "fdt" +#define FIT_DEFAULT_PROP "default" + +#define FIT_MAX_HASH_LEN 20 /* max(crc32_len(4), sha1_len(20)) */ + +/* cmdline argument format parsing */ +inline int fit_parse_conf (const char *spec, ulong addr_curr, + ulong *addr, const char **conf_name); +inline int fit_parse_subimage (const char *spec, ulong addr_curr, + ulong *addr, const char **image_name); + +inline void fit_print_contents (const void *fit); +inline void fit_print_contents_noindent (const void *fit); +void fit_image_print (const void *fit, int noffset, const char *p); +void fit_image_print_hash (const void *fit, int noffset, const char *p); + +/** + * fit_get_end - get FIT image size + * @fit: pointer to the FIT format image header + * + * returns: + * size of the FIT image (blob) in memory + */ +static inline ulong fit_get_size (const void *fit) +{ + return fdt_totalsize (fit); +} + +/** + * fit_get_end - get FIT image end + * @fit: pointer to the FIT format image header + * + * returns: + * end address of the FIT image (blob) in memory + */ +static inline ulong fit_get_end (const void *fit) +{ + return (ulong)fit + fdt_totalsize (fit); +} + +/** + * fit_get_name - get FIT node name + * @fit: pointer to the FIT format image header + * + * returns: + * NULL, on error + * pointer to node name, on success + */ +static inline const char *fit_get_name (const void *fit_hdr, + int noffset, int *len) +{ + return fdt_get_name (fit_hdr, noffset, len); +} + +int fit_get_desc (const void *fit, int noffset, char **desc); +int fit_get_timestamp (const void *fit, int noffset, time_t *timestamp); + +int fit_image_get_node (const void *fit, const char *image_uname); +int fit_image_get_os (const void *fit, int noffset, uint8_t *os); +int fit_image_get_arch (const void *fit, int noffset, uint8_t *arch); +int fit_image_get_type (const void *fit, int noffset, uint8_t *type); +int fit_image_get_comp (const void *fit, int noffset, uint8_t *comp); +int fit_image_get_load (const void *fit, int noffset, ulong *load); +int fit_image_get_entry (const void *fit, int noffset, ulong *entry); +int fit_image_get_data (const void *fit, int noffset, + const void **data, size_t *size); + +int fit_image_hash_get_algo (const void *fit, int noffset, char **algo); +int fit_image_hash_get_value (const void *fit, int noffset, uint8_t **value, + int *value_len); + +int fit_set_timestamp (void *fit, int noffset, time_t timestamp); +int fit_set_hashes (void *fit); +int fit_image_set_hashes (void *fit, int image_noffset); +int fit_image_hash_set_value (void *fit, int noffset, uint8_t *value, + int value_len); + +int fit_image_check_hashes (const void *fit, int noffset); +int fit_image_check_os (const void *fit, int noffset, uint8_t os); +int fit_image_check_arch (const void *fit, int noffset, uint8_t arch); +int fit_image_check_type (const void *fit, int noffset, uint8_t type); +int fit_image_check_comp (const void *fit, int noffset, uint8_t comp); +int fit_check_format (const void *fit); + +int fit_conf_get_node (const void *fit, const char *conf_uname); +int fit_conf_get_kernel_node (const void *fit, int noffset); +int fit_conf_get_ramdisk_node (const void *fit, int noffset); +int fit_conf_get_fdt_node (const void *fit, int noffset); + +void fit_conf_print (const void *fit, int noffset, const char *p); + +#ifndef USE_HOSTCC +static inline int fit_image_check_target_arch (const void *fdt, int node) +{ +#if defined(__ARM__) + if (!fit_image_check_arch (fdt, node, IH_ARCH_ARM)) +#elif defined(__avr32__) + if (!fit_image_check_arch (fdt, node, IH_ARCH_AVR32)) +#elif defined(__bfin__) + if (!fit_image_check_arch (fdt, node, IH_ARCH_BLACKFIN)) +#elif defined(__I386__) + if (!fit_image_check_arch (fdt, node, IH_ARCH_I386)) +#elif defined(__M68K__) + if (!fit_image_check_arch (fdt, node, IH_ARCH_M68K)) +#elif defined(__microblaze__) + if (!fit_image_check_arch (fdt, node, IH_ARCH_MICROBLAZE)) +#elif defined(__mips__) + if (!fit_image_check_arch (fdt, node, IH_ARCH_MIPS)) +#elif defined(__nios__) + if (!fit_image_check_arch (fdt, node, IH_ARCH_NIOS)) +#elif defined(__nios2__) + if (!fit_image_check_arch (fdt, node, IH_ARCH_NIOS2)) +#elif defined(__PPC__) + if (!fit_image_check_arch (fdt, node, IH_ARCH_PPC)) +#elif defined(__sh__) + if (!fit_image_check_arch (fdt, node, IH_ARCH_SH)) +#else +# error Unknown CPU type +#endif + return 0; + + return 1; +} +#endif /* USE_HOSTCC */ + +#ifdef CONFIG_FIT_VERBOSE +#define fit_unsupported(msg) printf ("! %s:%d " \ + "FIT images not supported for '%s'\n", \ + __FILE__, __LINE__, (msg)) + +#define fit_unsupported_reset(msg) printf ("! %s:%d " \ + "FIT images not supported for '%s' " \ + "- must reset board to recover!\n", \ + __FILE__, __LINE__, (msg)) +#else +#define fit_unsupported(msg) +#define fit_unsupported_reset(msg) +#endif /* CONFIG_FIT_VERBOSE */ +#endif /* CONFIG_FIT */ #endif /* __IMAGE_H__ */ diff --git a/include/libfdt_env.h b/include/libfdt_env.h index 78f725830d..98c522ae42 100644 --- a/include/libfdt_env.h +++ b/include/libfdt_env.h @@ -24,7 +24,11 @@ #include <stddef.h> #include <linux/types.h> #include <asm/byteorder.h> +#ifdef USE_HOSTCC +#include <string.h> +#else #include <linux/string.h> +#endif /* USE_HOSTCC */ extern struct fdt_header *fdt; /* Pointer to the working fdt */ diff --git a/include/lmb.h b/include/lmb.h new file mode 100644 index 0000000000..cc64cbbc73 --- /dev/null +++ b/include/lmb.h @@ -0,0 +1,54 @@ +#ifndef _LINUX_LMB_H +#define _LINUX_LMB_H +#ifdef __KERNEL__ + +#include <asm/types.h> +/* + * Logical memory blocks. + * + * Copyright (C) 2001 Peter Bergner, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#define MAX_LMB_REGIONS 8 + +struct lmb_property { + ulong base; + ulong size; +}; + +struct lmb_region { + unsigned long cnt; + ulong size; + struct lmb_property region[MAX_LMB_REGIONS+1]; +}; + +struct lmb { + struct lmb_region memory; + struct lmb_region reserved; +}; + +extern struct lmb lmb; + +extern void lmb_init(struct lmb *lmb); +extern long lmb_add(struct lmb *lmb, ulong base, ulong size); +extern long lmb_reserve(struct lmb *lmb, ulong base, ulong size); +extern ulong lmb_alloc(struct lmb *lmb, ulong size, ulong align); +extern ulong lmb_alloc_base(struct lmb *lmb, ulong size, ulong align, ulong max_addr); +extern ulong __lmb_alloc_base(struct lmb *lmb, ulong size, ulong align, ulong max_addr); +extern int lmb_is_reserved(struct lmb *lmb, ulong addr); + +extern void lmb_dump_all(struct lmb *lmb); + +static inline ulong +lmb_size_bytes(struct lmb_region *type, unsigned long region_nr) +{ + return type->region[region_nr].size; +} +#endif /* __KERNEL__ */ + +#endif /* _LINUX_LMB_H */ diff --git a/include/md5.h b/include/md5.h new file mode 100644 index 0000000000..046d1eee78 --- /dev/null +++ b/include/md5.h @@ -0,0 +1,23 @@ +/* + * This file was transplanted with slight modifications from Linux sources + * (fs/cifs/md5.h) into U-Boot by Bartlomiej Sieka <tur@semihalf.com>. + */ + +#ifndef _MD5_H +#define _MD5_H + +#include <linux/types.h> + +struct MD5Context { + __u32 buf[4]; + __u32 bits[2]; + unsigned char in[64]; +}; + +/* + * Calculate and store in 'output' the MD5 digest of 'len' bytes at + * 'input'. 'output' must have enough space to hold 16 bytes. + */ +void md5 (unsigned char *input, int len, unsigned char output[16]); + +#endif /* _MD5_H */ diff --git a/lib_arm/Makefile b/lib_arm/Makefile index bfd5b0e6f9..12a8748d1c 100644 --- a/lib_arm/Makefile +++ b/lib_arm/Makefile @@ -25,13 +25,21 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(ARCH).a -SOBJS = _ashldi3.o _ashrdi3.o _divsi3.o _modsi3.o _udivsi3.o _umodsi3.o - -COBJS = armlinux.o board.o \ - cache.o div0.o interrupts.o - -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +SOBJS-y += _ashldi3.o +SOBJS-y += _ashrdi3.o +SOBJS-y += _divsi3.o +SOBJS-y += _modsi3.o +SOBJS-y += _udivsi3.o +SOBJS-y += _umodsi3.o + +COBJS-y += board.o +COBJS-y += bootm.o +COBJS-y += cache.o +COBJS-y += div0.o +COBJS-y += interrupts.o + +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) $(LIB): $(obj).depend $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) diff --git a/lib_arm/armlinux.c b/lib_arm/bootm.c index 42098fcd65..c5e8cb3eb6 100644 --- a/lib_arm/armlinux.c +++ b/lib_arm/bootm.c @@ -26,15 +26,9 @@ #include <image.h> #include <zlib.h> #include <asm/byteorder.h> -#ifdef CONFIG_HAS_DATAFLASH -#include <dataflash.h> -#endif DECLARE_GLOBAL_DATA_PTR; -/*cmd_boot.c*/ -extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); - #if defined (CONFIG_SETUP_MEMORY_TAGS) || \ defined (CONFIG_CMDLINE_TAG) || \ defined (CONFIG_INITRD_TAG) || \ @@ -62,165 +56,54 @@ static void setup_end_tag (bd_t *bd); static void setup_videolfb_tag (gd_t *gd); # endif - static struct tag *params; #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */ -extern image_header_t header; /* from cmd_bootm.c */ - +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) + bootm_headers_t *images) { - ulong len = 0, checksum; - ulong initrd_start, initrd_end; - ulong data; - void (*theKernel)(int zero, int arch, uint params); - image_header_t *hdr = &header; - bd_t *bd = gd->bd; - int machid = bd->bi_arch_number; - char *s; + ulong initrd_start, initrd_end; + ulong ep = 0; + bd_t *bd = gd->bd; + char *s; + int machid = bd->bi_arch_number; + void (*theKernel)(int zero, int arch, uint params); + int ret; #ifdef CONFIG_CMDLINE_TAG char *commandline = getenv ("bootargs"); #endif - theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep); - - s = getenv ("machid"); - if (s) { - machid = simple_strtoul (s, NULL, 16); - printf ("Using machid 0x%x from environment\n", machid); - } - - /* - * Check if there is an initrd image - */ - if (argc >= 3) { - show_boot_progress (9); - - addr = simple_strtoul (argv[2], NULL, 16); - - printf ("## Loading Ramdisk Image at %08lx ...\n", addr); - - /* Copy header so we can blank CRC field for re-calculation */ -#ifdef CONFIG_HAS_DATAFLASH - if (addr_dataflash (addr)) { - read_dataflash (addr, sizeof (image_header_t), - (char *) &header); - } else -#endif - memcpy (&header, (char *) addr, - sizeof (image_header_t)); - - if (ntohl (hdr->ih_magic) != IH_MAGIC) { - printf ("Bad Magic Number\n"); - show_boot_progress (-10); - do_reset (cmdtp, flag, argc, argv); - } - - data = (ulong) & header; - len = sizeof (image_header_t); - - checksum = ntohl (hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (unsigned char *) data, len) != checksum) { - printf ("Bad Header Checksum\n"); - show_boot_progress (-11); - do_reset (cmdtp, flag, argc, argv); - } - - show_boot_progress (10); - - print_image_hdr (hdr); - - data = addr + sizeof (image_header_t); - len = ntohl (hdr->ih_size); - -#ifdef CONFIG_HAS_DATAFLASH - if (addr_dataflash (addr)) { - read_dataflash (data, len, (char *) CFG_LOAD_ADDR); - data = CFG_LOAD_ADDR; + /* find kernel entry point */ + if (images->legacy_hdr_valid) { + ep = image_get_ep (images->legacy_hdr_os); +#if defined(CONFIG_FIT) + } else if (images->fit_uname_os) { + ret = fit_image_get_entry (images->fit_hdr_os, + images->fit_noffset_os, &ep); + if (ret) { + puts ("Can't get entry point property!\n"); + goto error; } #endif - - if (verify) { - ulong csum = 0; - - printf (" Verifying Checksum ... "); - csum = crc32 (0, (unsigned char *) data, len); - if (csum != ntohl (hdr->ih_dcrc)) { - printf ("Bad Data CRC\n"); - show_boot_progress (-12); - do_reset (cmdtp, flag, argc, argv); - } - printf ("OK\n"); - } - - show_boot_progress (11); - - if ((hdr->ih_os != IH_OS_LINUX) || - (hdr->ih_arch != IH_CPU_ARM) || - (hdr->ih_type != IH_TYPE_RAMDISK)) { - printf ("No Linux ARM Ramdisk Image\n"); - show_boot_progress (-13); - do_reset (cmdtp, flag, argc, argv); - } - -#if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || \ - defined(CONFIG_ARMADILLO) || defined(CONFIG_M501SK) - /* - *we need to copy the ramdisk to SRAM to let Linux boot - */ - memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len); - data = ntohl(hdr->ih_load); -#endif /* CONFIG_B2 || CONFIG_EVB4510 */ - - /* - * Now check if we have a multifile image - */ - } else if ((hdr->ih_type == IH_TYPE_MULTI) && (len_ptr[1])) { - ulong tail = ntohl (len_ptr[0]) % 4; - int i; - - show_boot_progress (13); - - /* skip kernel length and terminator */ - data = (ulong) (&len_ptr[2]); - /* skip any additional image length fields */ - for (i = 1; len_ptr[i]; ++i) - data += 4; - /* add kernel length, and align */ - data += ntohl (len_ptr[0]); - if (tail) { - data += 4 - tail; - } - - len = ntohl (len_ptr[1]); - } else { - /* - * no initrd image - */ - show_boot_progress (14); - - len = data = 0; + puts ("Could not find kernel entry point!\n"); + goto error; } + theKernel = (void (*)(int, int, uint))ep; -#ifdef DEBUG - if (!data) { - printf ("No initrd\n"); + s = getenv ("machid"); + if (s) { + machid = simple_strtoul (s, NULL, 16); + printf ("Using machid 0x%x from environment\n", machid); } -#endif - if (data) { - initrd_start = data; - initrd_end = initrd_start + len; - } else { - initrd_start = 0; - initrd_end = 0; - } + ret = boot_get_ramdisk (argc, argv, images, IH_ARCH_ARM, + &initrd_start, &initrd_end); + if (ret) + goto error; show_boot_progress (15); @@ -257,6 +140,9 @@ void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], setup_end_tag (bd); #endif + if (!images->autostart) + return ; + /* we assume that the kernel is in place */ printf ("\nStarting kernel ...\n\n"); @@ -270,6 +156,13 @@ void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], cleanup_before_linux (); theKernel (0, machid, bd->bi_boot_params); + /* does not return */ + return; + +error: + if (images->autostart) + do_reset (cmdtp, flag, argc, argv); + return; } diff --git a/lib_avr32/Makefile b/lib_avr32/Makefile index bb2938fe5c..37b80514f3 100644 --- a/lib_avr32/Makefile +++ b/lib_avr32/Makefile @@ -27,12 +27,14 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(ARCH).a -SOBJS = memset.o +SOBJS-y += memset.o -COBJS = board.o interrupts.o avr32_linux.o +COBJS-y += board.o +COBJS-y += bootm.o +COBJS-y += interrupts.o -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) $(LIB): $(obj).depend $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) diff --git a/lib_avr32/avr32_linux.c b/lib_avr32/bootm.c index 62afbd2497..b1c651ab2c 100644 --- a/lib_avr32/avr32_linux.c +++ b/lib_avr32/bootm.c @@ -31,12 +31,10 @@ DECLARE_GLOBAL_DATA_PTR; -extern int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); - /* CPU-specific hook to allow flushing of caches, etc. */ extern void prepare_to_boot(void); -extern image_header_t header; /* from cmd_bootm.c */ +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); static struct tag *setup_start_tag(struct tag *params) { @@ -176,113 +174,37 @@ static void setup_end_tag(struct tag *params) } void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - unsigned long addr, unsigned long *len_ptr, int verify) + bootm_headers_t *images) { - unsigned long data, len = 0; - unsigned long initrd_start, initrd_end; - unsigned long image_start, image_end; - unsigned long checksum; - void (*theKernel)(int magic, void *tagtable); - image_header_t *hdr; - struct tag *params, *params_start; - char *commandline = getenv("bootargs"); - - hdr = (image_header_t *)addr; - image_start = addr; - image_end = addr + hdr->ih_size; - - theKernel = (void *)ntohl(hdr->ih_ep); - - /* - * Check if there is an initrd image - */ - if (argc >= 3) { - show_boot_progress (9); - - addr = simple_strtoul(argv[2], NULL, 16); - - printf("## Loading RAMDISK image at %08lx ...\n", addr); - - memcpy(&header, (char *)addr, sizeof(header)); - hdr = &header; - - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - puts("Bad Magic Number\n"); - show_boot_progress (-10); - do_reset(cmdtp, flag, argc, argv); + ulong initrd_start, initrd_end; + ulong ep = 0; + void (*theKernel)(int magic, void *tagtable); + struct tag *params, *params_start; + char *commandline = getenv("bootargs"); + int ret; + + /* find kernel entry point */ + if (images->legacy_hdr_valid) { + ep = image_get_ep (images->legacy_hdr_os); +#if defined(CONFIG_FIT) + } else if (images->fit_uname_os) { + ret = fit_image_get_entry (images->fit_hdr_os, + images->fit_noffset_os, &ep); + if (ret) { + puts ("Can't get entry point property!\n"); + goto error; } - - data = (unsigned long)hdr; - len = sizeof(*hdr); - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32(0, (unsigned char *)data, len) != checksum) { - puts("Bad Header Checksum\n"); - show_boot_progress (-11); - do_reset(cmdtp, flag, argc, argv); - } - - show_boot_progress (10); - - print_image_hdr(hdr); - - data = addr + sizeof(header); - len = ntohl(hdr->ih_size); - - if (verify) { - unsigned long csum = 0; - - puts(" Verifying Checksum ... "); - csum = crc32(0, (unsigned char *)data, len); - if (csum != ntohl(hdr->ih_dcrc)) { - puts("Bad Data CRC\n"); - show_boot_progress (-12); - do_reset(cmdtp, flag, argc, argv); - } - puts("OK\n"); - } - - show_boot_progress (11); - - if ((hdr->ih_os != IH_OS_LINUX) || - (hdr->ih_arch != IH_CPU_AVR32) || - (hdr->ih_type != IH_TYPE_RAMDISK)) { - puts("Not a Linux/AVR32 RAMDISK image\n"); - show_boot_progress (-13); - do_reset(cmdtp, flag, argc, argv); - } - } else if ((hdr->ih_type == IH_TYPE_MULTI) && (len_ptr[1])) { - ulong tail = ntohl (len_ptr[0]) % 4; - int i; - - show_boot_progress (13); - - /* skip kernel length and terminator */ - data = (ulong) (&len_ptr[2]); - /* skip any additional image length fields */ - for (i = 1; len_ptr[i]; ++i) - data += 4; - /* add kernel length, and align */ - data += ntohl (len_ptr[0]); - if (tail) { - data += 4 - tail; - } - - len = ntohl (len_ptr[1]); +#endif } else { - /* no initrd image */ - show_boot_progress (14); - len = data = 0; + puts ("Could not find kernel entry point!\n"); + goto error; } + theKernel = (void *)ep; - if (data) { - initrd_start = data; - initrd_end = initrd_start + len; - } else { - initrd_start = 0; - initrd_end = 0; - } + ret = boot_get_ramdisk (argc, argv, images, IH_ARCH_AVR32, + &initrd_start, &initrd_end); + if (ret) + goto error; show_boot_progress (15); @@ -299,10 +221,20 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], params = setup_ethernet_tags(params); setup_end_tag(params); + if (!images->autostart) + return ; + printf("\nStarting kernel at %p (params at %p)...\n\n", theKernel, params_start); prepare_to_boot(); theKernel(ATAG_MAGIC, params_start); + /* does not return */ + return; + +error: + if (images->autostart) + do_reset (cmdtp, flag, argc, argv); + return; } diff --git a/lib_blackfin/Makefile b/lib_blackfin/Makefile index a7aaef7a3c..dfaed6d02b 100644 --- a/lib_blackfin/Makefile +++ b/lib_blackfin/Makefile @@ -29,12 +29,21 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(ARCH).a -SOBJS = memcpy.o memcmp.o memset.o memmove.o - -COBJS = post.o tests.o board.o bf533_linux.o bf533_string.o cache.o muldi3.o - -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +SOBJS-y += memcmp.o +SOBJS-y += memcpy.o +SOBJS-y += memmove.o +SOBJS-y += memset.o + +COBJS-y += bf533_string.o +COBJS-y += board.o +COBJS-y += bootm.o +COBJS-y += cache.o +COBJS-y += muldi3.o +COBJS-y += post.o +COBJS-y += tests.o + +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) $(LIB): $(obj).depend $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) diff --git a/lib_blackfin/bf533_linux.c b/lib_blackfin/bootm.c index 80a3dc7d6e..1ea80f4e36 100644 --- a/lib_blackfin/bf533_linux.c +++ b/lib_blackfin/bootm.c @@ -42,22 +42,42 @@ extern void swap_to(int device_id); #endif -extern image_header_t header; extern void flush_instruction_cache(void); extern void flush_data_cache(void); static char *make_command_line(void); void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong * len_ptr, int verify) + bootm_headers_t *images) { - int (*appl) (char *cmdline); - char *cmdline; + int (*appl) (char *cmdline); + char *cmdline; + ulong ep = 0; + + if (!images->autostart) + return ; #ifdef SHARED_RESOURCES swap_to(FLASH); #endif - appl = (int (*)(char *))ntohl(header.ih_ep); + /* find kernel entry point */ + if (images->legacy_hdr_valid) { + ep = image_get_ep (images->legacy_hdr_os); +#if defined(CONFIG_FIT) + } else if (images->fit_uname_os) { + int ret = fit_image_get_entry (images->fit_hdr_os, + images->fit_noffset_os, &ep); + if (ret) { + puts ("Can't get entry point property!\n"); + goto error; + } +#endif + } else { + puts ("Could not find kernel entry point!\n"); + goto error; + } + appl = (int (*)(char *))ep; + printf("Starting Kernel at = %x\n", appl); cmdline = make_command_line(); if (icache_status()) { @@ -69,6 +89,13 @@ void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], dcache_disable(); } (*appl) (cmdline); + /* does not return */ + return; + +error: + if (images->autostart) + do_reset (cmdtp, flag, argc, argv); + return; } char *make_command_line(void) diff --git a/lib_generic/Makefile b/lib_generic/Makefile index 9713353ddf..abee19a2bb 100644 --- a/lib_generic/Makefile +++ b/lib_generic/Makefile @@ -34,7 +34,9 @@ COBJS-y += crc32.o COBJS-y += ctype.o COBJS-y += display_options.o COBJS-y += div64.o +COBJS-y += lmb.o COBJS-y += ldiv.o +COBJS-$(CONFIG_MD5) += md5.o COBJS-y += sha1.o COBJS-y += string.o COBJS-y += vsprintf.o diff --git a/lib_generic/bzlib.c b/lib_generic/bzlib.c index 87e6a6eed6..0d3f9c2d3e 100644 --- a/lib_generic/bzlib.c +++ b/lib_generic/bzlib.c @@ -1592,6 +1592,10 @@ const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum) } #endif +void bz_internal_error(int errcode) +{ + printf ("BZIP2 internal error %d\n", errcode); +} /*-------------------------------------------------------------*/ /*--- end bzlib.c ---*/ diff --git a/lib_generic/lmb.c b/lib_generic/lmb.c new file mode 100644 index 0000000000..3b8c805e88 --- /dev/null +++ b/lib_generic/lmb.c @@ -0,0 +1,280 @@ +/* + * Procedures for maintaining information about logical memory blocks. + * + * Peter Bergner, IBM Corp. June 2001. + * Copyright (C) 2001 Peter Bergner. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <common.h> +#include <lmb.h> + +#define LMB_ALLOC_ANYWHERE 0 + +void lmb_dump_all(struct lmb *lmb) +{ +#ifdef DEBUG + unsigned long i; + + debug("lmb_dump_all:\n"); + debug(" memory.cnt = 0x%lx\n", lmb->memory.cnt); + debug(" memory.size = 0x%08x\n", lmb->memory.size); + for (i=0; i < lmb->memory.cnt ;i++) { + debug(" memory.reg[0x%x].base = 0x%08x\n", i, + lmb->memory.region[i].base); + debug(" .size = 0x%08x\n", + lmb->memory.region[i].size); + } + + debug("\n reserved.cnt = 0x%lx\n", lmb->reserved.cnt); + debug(" reserved.size = 0x%08x\n", lmb->reserved.size); + for (i=0; i < lmb->reserved.cnt ;i++) { + debug(" reserved.reg[0x%x].base = 0x%08x\n", i, + lmb->reserved.region[i].base); + debug(" .size = 0x%08x\n", + lmb->reserved.region[i].size); + } +#endif /* DEBUG */ +} + +static unsigned long lmb_addrs_overlap(ulong base1, + ulong size1, ulong base2, ulong size2) +{ + return ((base1 < (base2+size2)) && (base2 < (base1+size1))); +} + +static long lmb_addrs_adjacent(ulong base1, ulong size1, + ulong base2, ulong size2) +{ + if (base2 == base1 + size1) + return 1; + else if (base1 == base2 + size2) + return -1; + + return 0; +} + +static long lmb_regions_adjacent(struct lmb_region *rgn, + unsigned long r1, unsigned long r2) +{ + ulong base1 = rgn->region[r1].base; + ulong size1 = rgn->region[r1].size; + ulong base2 = rgn->region[r2].base; + ulong size2 = rgn->region[r2].size; + + return lmb_addrs_adjacent(base1, size1, base2, size2); +} + +static void lmb_remove_region(struct lmb_region *rgn, unsigned long r) +{ + unsigned long i; + + for (i = r; i < rgn->cnt - 1; i++) { + rgn->region[i].base = rgn->region[i + 1].base; + rgn->region[i].size = rgn->region[i + 1].size; + } + rgn->cnt--; +} + +/* Assumption: base addr of region 1 < base addr of region 2 */ +static void lmb_coalesce_regions(struct lmb_region *rgn, + unsigned long r1, unsigned long r2) +{ + rgn->region[r1].size += rgn->region[r2].size; + lmb_remove_region(rgn, r2); +} + +void lmb_init(struct lmb *lmb) +{ + /* Create a dummy zero size LMB which will get coalesced away later. + * This simplifies the lmb_add() code below... + */ + lmb->memory.region[0].base = 0; + lmb->memory.region[0].size = 0; + lmb->memory.cnt = 1; + lmb->memory.size = 0; + + /* Ditto. */ + lmb->reserved.region[0].base = 0; + lmb->reserved.region[0].size = 0; + lmb->reserved.cnt = 1; + lmb->reserved.size = 0; +} + +/* This routine called with relocation disabled. */ +static long lmb_add_region(struct lmb_region *rgn, ulong base, ulong size) +{ + unsigned long coalesced = 0; + long adjacent, i; + + if ((rgn->cnt == 1) && (rgn->region[0].size == 0)) { + rgn->region[0].base = base; + rgn->region[0].size = size; + return 0; + } + + /* First try and coalesce this LMB with another. */ + for (i=0; i < rgn->cnt; i++) { + ulong rgnbase = rgn->region[i].base; + ulong rgnsize = rgn->region[i].size; + + if ((rgnbase == base) && (rgnsize == size)) + /* Already have this region, so we're done */ + return 0; + + adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize); + if ( adjacent > 0 ) { + rgn->region[i].base -= size; + rgn->region[i].size += size; + coalesced++; + break; + } + else if ( adjacent < 0 ) { + rgn->region[i].size += size; + coalesced++; + break; + } + } + + if ((i < rgn->cnt-1) && lmb_regions_adjacent(rgn, i, i+1) ) { + lmb_coalesce_regions(rgn, i, i+1); + coalesced++; + } + + if (coalesced) + return coalesced; + if (rgn->cnt >= MAX_LMB_REGIONS) + return -1; + + /* Couldn't coalesce the LMB, so add it to the sorted table. */ + for (i = rgn->cnt-1; i >= 0; i--) { + if (base < rgn->region[i].base) { + rgn->region[i+1].base = rgn->region[i].base; + rgn->region[i+1].size = rgn->region[i].size; + } else { + rgn->region[i+1].base = base; + rgn->region[i+1].size = size; + break; + } + } + + if (base < rgn->region[0].base) { + rgn->region[0].base = base; + rgn->region[0].size = size; + } + + rgn->cnt++; + + return 0; +} + +/* This routine may be called with relocation disabled. */ +long lmb_add(struct lmb *lmb, ulong base, ulong size) +{ + struct lmb_region *_rgn = &(lmb->memory); + + return lmb_add_region(_rgn, base, size); +} + +long lmb_reserve(struct lmb *lmb, ulong base, ulong size) +{ + struct lmb_region *_rgn = &(lmb->reserved); + + return lmb_add_region(_rgn, base, size); +} + +long lmb_overlaps_region(struct lmb_region *rgn, ulong base, + ulong size) +{ + unsigned long i; + + for (i=0; i < rgn->cnt; i++) { + ulong rgnbase = rgn->region[i].base; + ulong rgnsize = rgn->region[i].size; + if ( lmb_addrs_overlap(base,size,rgnbase,rgnsize) ) { + break; + } + } + + return (i < rgn->cnt) ? i : -1; +} + +ulong lmb_alloc(struct lmb *lmb, ulong size, ulong align) +{ + return lmb_alloc_base(lmb, size, align, LMB_ALLOC_ANYWHERE); +} + +ulong lmb_alloc_base(struct lmb *lmb, ulong size, ulong align, ulong max_addr) +{ + ulong alloc; + + alloc = __lmb_alloc_base(lmb, size, align, max_addr); + + if (alloc == 0) + printf("ERROR: Failed to allocate 0x%lx bytes below 0x%lx.\n", + size, max_addr); + + return alloc; +} + +static ulong lmb_align_down(ulong addr, ulong size) +{ + return addr & ~(size - 1); +} + +static ulong lmb_align_up(ulong addr, ulong size) +{ + return (addr + (size - 1)) & ~(size - 1); +} + +ulong __lmb_alloc_base(struct lmb *lmb, ulong size, ulong align, ulong max_addr) +{ + long i, j; + ulong base = 0; + + for (i = lmb->memory.cnt-1; i >= 0; i--) { + ulong lmbbase = lmb->memory.region[i].base; + ulong lmbsize = lmb->memory.region[i].size; + + if (max_addr == LMB_ALLOC_ANYWHERE) + base = lmb_align_down(lmbbase + lmbsize - size, align); + else if (lmbbase < max_addr) { + base = min(lmbbase + lmbsize, max_addr); + base = lmb_align_down(base - size, align); + } else + continue; + + while ((lmbbase <= base) && + ((j = lmb_overlaps_region(&(lmb->reserved), base, size)) >= 0) ) + base = lmb_align_down(lmb->reserved.region[j].base - size, + align); + + if ((base != 0) && (lmbbase <= base)) + break; + } + + if (i < 0) + return 0; + + if (lmb_add_region(&(lmb->reserved), base, lmb_align_up(size, align)) < 0) + return 0; + + return base; +} + +int lmb_is_reserved(struct lmb *lmb, ulong addr) +{ + int i; + + for (i = 0; i < lmb->reserved.cnt; i++) { + ulong upper = lmb->reserved.region[i].base + + lmb->reserved.region[i].size - 1; + if ((addr >= lmb->reserved.region[i].base) && (addr <= upper)) + return 1; + } + return 0; +} diff --git a/lib_generic/md5.c b/lib_generic/md5.c new file mode 100644 index 0000000000..a51da451b7 --- /dev/null +++ b/lib_generic/md5.c @@ -0,0 +1,274 @@ +/* + * This file was transplanted with slight modifications from Linux sources + * (fs/cifs/md5.c) into U-Boot by Bartlomiej Sieka <tur@semihalf.com>. + */ + +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +/* This code slightly modified to fit into Samba by + abartlet@samba.org Jun 2001 + and to fit the cifs vfs by + Steve French sfrench@us.ibm.com */ + +#include <linux/types.h> +#include <linux/string.h> +#include <md5.h> + +static void +MD5Transform(__u32 buf[4], __u32 const in[16]); + +/* + * Note: this code is harmless on little-endian machines. + */ +static void +byteReverse(unsigned char *buf, unsigned longs) +{ + __u32 t; + do { + t = (__u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(__u32 *) buf = t; + buf += 4; + } while (--longs); +} + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +static void +MD5Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +static void +MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) +{ + register __u32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((__u32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memmove(p, buf, len); + return; + } + memmove(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (__u32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memmove(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (__u32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memmove(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +static void +MD5Final(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned int count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (__u32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((__u32 *) ctx->in)[14] = ctx->bits[0]; + ((__u32 *) ctx->in)[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (__u32 *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memmove(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ +} + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void +MD5Transform(__u32 buf[4], __u32 const in[16]) +{ + register __u32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +/* + * Calculate and store in 'output' the MD5 digest of 'len' bytes at + * 'input'. 'output' must have enough space to hold 16 bytes. + */ +void +md5 (unsigned char *input, int len, unsigned char output[16]) +{ + struct MD5Context context; + + MD5Init(&context); + MD5Update(&context, input, len); + MD5Final(output, &context); +} diff --git a/lib_i386/Makefile b/lib_i386/Makefile index e344da5157..4cc29f432a 100644 --- a/lib_i386/Makefile +++ b/lib_i386/Makefile @@ -25,13 +25,22 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(ARCH).a -SOBJS = bios.o bios_pci.o realmode_switch.o - -COBJS = board.o bios_setup.o i386_linux.o zimage.o realmode.o \ - pci_type1.o pci.o video_bios.o video.o - -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +SOBJS-y += bios.o +SOBJS-y += bios_pci.o +SOBJS-y += realmode_switch.o + +COBJS-y += bios_setup.o +COBJS-y += board.o +COBJS-y += bootm.o +COBJS-y += pci.o +COBJS-y += pci_type1.o +COBJS-y += realmode.o +COBJS-y += video_bios.o +COBJS-y += video.o +COBJS-y += zimage.o + +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) $(LIB): $(obj).depend $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) diff --git a/lib_i386/bootm.c b/lib_i386/bootm.c new file mode 100644 index 0000000000..107ebaaa67 --- /dev/null +++ b/lib_i386/bootm.c @@ -0,0 +1,107 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <common.h> +#include <command.h> +#include <image.h> +#include <zlib.h> +#include <asm/byteorder.h> +#include <asm/zimage.h> + +/*cmd_boot.c*/ +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + bootm_headers_t *images) +{ + void *base_ptr; + ulong os_data, os_len; + ulong initrd_start, initrd_end; + ulong ep; + image_header_t *hdr; + int ret; +#if defined(CONFIG_FIT) + const void *data; + size_t len; +#endif + + ret = boot_get_ramdisk (argc, argv, images, IH_ARCH_I386, + &initrd_start, &initrd_end); + if (ret) + goto error; + + if (images->legacy_hdr_valid) { + hdr = images->legacy_hdr_os; + if (image_check_type (hdr, IH_TYPE_MULTI)) { + /* if multi-part image, we need to get first subimage */ + image_multi_getimg (hdr, 0, &os_data, &os_len); + } else { + /* otherwise get image data */ + os_data = image_get_data (hdr); + os_len = image_get_data_size (hdr); + } +#if defined(CONFIG_FIT) + } else if (images->fit_uname_os) { + ret = fit_image_get_data (images->fit_hdr_os, + images->fit_noffset_os, &data, &len); + if (ret) { + puts ("Can't get image data/size!\n"); + goto error; + } + os_data = (ulong)data; + os_len = (ulong)len; +#endif + } else { + puts ("Could not find kernel image!\n"); + goto error; + } + + base_ptr = load_zimage ((void*)os_data, os_len, + initrd_start, initrd_end - initrd_start, 0); + + if (NULL == base_ptr) { + printf ("## Kernel loading failed ...\n"); + goto error; + + } + + if (!images->autostart) + return ; + +#ifdef DEBUG + printf ("## Transferring control to Linux (at address %08x) ...\n", + (u32)base_ptr); +#endif + + /* we assume that the kernel is in place */ + printf("\nStarting kernel ...\n\n"); + + boot_zimage(base_ptr); + /* does not return */ + return; + +error: + if (images->autostart) + do_reset (cmdtp, flag, argc, argv); + return; +} diff --git a/lib_i386/i386_linux.c b/lib_i386/i386_linux.c deleted file mode 100644 index b4a6f5a3cd..0000000000 --- a/lib_i386/i386_linux.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH <www.elinos.com> - * Marius Groeger <mgroeger@sysgo.de> - * - * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <common.h> -#include <command.h> -#include <image.h> -#include <zlib.h> -#include <asm/byteorder.h> -#include <asm/zimage.h> - -/*cmd_boot.c*/ -extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); - -extern image_header_t header; /* from cmd_bootm.c */ - - -image_header_t *fake_header(image_header_t *hdr, void *ptr, int size) -{ - /* try each supported image type in order */ - if (NULL != fake_zimage_header(hdr, ptr, size)) { - return hdr; - } - - return NULL; -} - - -void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) -{ - void *base_ptr; - - ulong len = 0, checksum; - ulong initrd_start, initrd_end; - ulong data; - image_header_t *hdr = &header; - - /* - * Check if there is an initrd image - */ - if (argc >= 3) { - addr = simple_strtoul(argv[2], NULL, 16); - - printf ("## Loading Ramdisk Image at %08lx ...\n", addr); - - /* Copy header so we can blank CRC field for re-calculation */ - memcpy (&header, (char *)addr, sizeof(image_header_t)); - - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - printf ("Bad Magic Number\n"); - do_reset (cmdtp, flag, argc, argv); - } - - data = (ulong)&header; - len = sizeof(image_header_t); - - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (char *)data, len) != checksum) { - printf ("Bad Header Checksum\n"); - do_reset (cmdtp, flag, argc, argv); - } - - print_image_hdr (hdr); - - data = addr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); - - if (verify) { - ulong csum = 0; - - printf (" Verifying Checksum ... "); - csum = crc32 (0, (char *)data, len); - if (csum != ntohl(hdr->ih_dcrc)) { - printf ("Bad Data CRC\n"); - do_reset (cmdtp, flag, argc, argv); - } - printf ("OK\n"); - } - - if ((hdr->ih_os != IH_OS_LINUX) || - (hdr->ih_arch != IH_CPU_I386) || - (hdr->ih_type != IH_TYPE_RAMDISK) ) { - printf ("No Linux i386 Ramdisk Image\n"); - do_reset (cmdtp, flag, argc, argv); - } - - /* - * Now check if we have a multifile image - */ - } else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) { - ulong tail = ntohl(len_ptr[0]) % 4; - int i; - - /* skip kernel length and terminator */ - data = (ulong)(&len_ptr[2]); - /* skip any additional image length fields */ - for (i=1; len_ptr[i]; ++i) - data += 4; - /* add kernel length, and align */ - data += ntohl(len_ptr[0]); - if (tail) { - data += 4 - tail; - } - - len = ntohl(len_ptr[1]); - - } else { - /* - * no initrd image - */ - data = 0; - } - -#ifdef DEBUG - if (!data) { - printf ("No initrd\n"); - } -#endif - - if (data) { - initrd_start = data; - initrd_end = initrd_start + len; - printf (" Loading Ramdisk to %08lx, end %08lx ... ", - initrd_start, initrd_end); - memmove ((void *)initrd_start, (void *)data, len); - printf ("OK\n"); - } else { - initrd_start = 0; - initrd_end = 0; - } - - /* if multi-part image, we need to advance base ptr */ - if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) { - int i; - for (i=0, addr+=sizeof(int); len_ptr[i++]; addr+=sizeof(int)); - } - - base_ptr = load_zimage((void*)addr + sizeof(image_header_t), ntohl(hdr->ih_size), - initrd_start, initrd_end-initrd_start, 0); - - if (NULL == base_ptr) { - printf ("## Kernel loading failed ...\n"); - do_reset(cmdtp, flag, argc, argv); - - } - -#ifdef DEBUG - printf ("## Transferring control to Linux (at address %08x) ...\n", - (u32)base_ptr); -#endif - - /* we assume that the kernel is in place */ - printf("\nStarting kernel ...\n\n"); - - boot_zimage(base_ptr); - -} diff --git a/lib_i386/zimage.c b/lib_i386/zimage.c index 3510f2fd64..c3b4e597aa 100644 --- a/lib_i386/zimage.c +++ b/lib_i386/zimage.c @@ -212,7 +212,6 @@ void *load_zimage(char *image, unsigned long kernel_size, return setup_base; } - void boot_zimage(void *setup_base) { struct pt_regs regs; @@ -224,52 +223,3 @@ void boot_zimage(void *setup_base) regs.eflags = 0; enter_realmode(((u32)setup_base+SETUP_START_OFFSET)>>4, 0, ®s, ®s); } - - -image_header_t *fake_zimage_header(image_header_t *hdr, void *ptr, int size) -{ - /* There is no way to know the size of a zImage ... * - * so we assume that 2MB will be enough for now */ -#define ZIMAGE_SIZE 0x200000 - - /* load a 1MB, the loaded will have to be moved to its final - * position again later... */ -#define ZIMAGE_LOAD 0x100000 - - ulong checksum; - - if (KERNEL_MAGIC != *(u16*)(ptr + BOOT_FLAG_OFF)) { - /* not a zImage or bzImage */ - return NULL; - } - - if (-1 == size) { - size = ZIMAGE_SIZE; - } -#if 0 - checksum = crc32 (0, ptr, size); -#else - checksum = 0; -#endif - memset(hdr, 0, sizeof(image_header_t)); - - /* Build new header */ - hdr->ih_magic = htonl(IH_MAGIC); - hdr->ih_time = 0; - hdr->ih_size = htonl(size); - hdr->ih_load = htonl(ZIMAGE_LOAD); - hdr->ih_ep = 0; - hdr->ih_dcrc = htonl(checksum); - hdr->ih_os = IH_OS_LINUX; - hdr->ih_arch = IH_CPU_I386; - hdr->ih_type = IH_TYPE_KERNEL; - hdr->ih_comp = IH_COMP_NONE; - - strncpy((char *)hdr->ih_name, "(none)", IH_NMLEN); - - checksum = crc32(0,(const char *)hdr,sizeof(image_header_t)); - - hdr->ih_hcrc = htonl(checksum); - - return hdr; -} diff --git a/lib_m68k/Makefile b/lib_m68k/Makefile index 03784fd84e..f6924cd0bd 100644 --- a/lib_m68k/Makefile +++ b/lib_m68k/Makefile @@ -25,12 +25,17 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(ARCH).a -SOBJS = +SOBJS-y += -COBJS = cache.o traps.o time.o interrupts.o board.o m68k_linux.o +COBJS-y += board.o +COBJS-y += bootm.o +COBJS-y += cache.o +COBJS-y += interrupts.o +COBJS-y += time.o +COBJS-y += traps.o -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) $(LIB): $(obj).depend $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) diff --git a/lib_m68k/bootm.c b/lib_m68k/bootm.c new file mode 100644 index 0000000000..6f49c31616 --- /dev/null +++ b/lib_m68k/bootm.c @@ -0,0 +1,171 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <common.h> +#include <command.h> +#include <image.h> +#include <zlib.h> +#include <bzlib.h> +#include <watchdog.h> +#include <environment.h> +#include <asm/byteorder.h> +#ifdef CONFIG_SHOW_BOOT_PROGRESS +# include <status_led.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +#define PHYSADDR(x) x + +#define LINUX_MAX_ENVS 256 +#define LINUX_MAX_ARGS 256 + +static ulong get_sp (void); +static void set_clocks_in_mhz (bd_t *kbd); +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, + int argc, char *argv[], + bootm_headers_t *images) +{ + ulong sp; + + ulong rd_data_start, rd_data_end, rd_len; + ulong initrd_start, initrd_end; + int ret; + + ulong cmd_start, cmd_end; + ulong bootmap_base; + bd_t *kbd; + ulong ep = 0; + void (*kernel) (bd_t *, ulong, ulong, ulong, ulong); + struct lmb *lmb = images->lmb; + + bootmap_base = getenv_bootm_low(); + + /* + * Booting a (Linux) kernel image + * + * Allocate space for command line and board info - the + * address should be as high as possible within the reach of + * the kernel (see CFG_BOOTMAPSZ settings), but in unused + * memory, which means far enough below the current stack + * pointer. + */ + sp = get_sp(); + debug ("## Current stack ends at 0x%08lx ", sp); + + /* adjust sp by 1K to be safe */ + sp -= 1024; + lmb_reserve(lmb, sp, (CFG_SDRAM_BASE + gd->ram_size - sp)); + + /* allocate space and init command line */ + ret = boot_get_cmdline (lmb, &cmd_start, &cmd_end, bootmap_base); + if (ret) { + puts("ERROR with allocation of cmdline\n"); + goto error; + } + + /* allocate space for kernel copy of board info */ + ret = boot_get_kbd (lmb, &kbd, bootmap_base); + if (ret) { + puts("ERROR with allocation of kernel bd\n"); + goto error; + } + set_clocks_in_mhz(kbd); + + /* find kernel entry point */ + if (images->legacy_hdr_valid) { + ep = image_get_ep (images->legacy_hdr_os); +#if defined(CONFIG_FIT) + } else if (images->fit_uname_os) { + ret = fit_image_get_entry (images->fit_hdr_os, + images->fit_noffset_os, &ep); + if (ret) { + puts ("Can't get entry point property!\n"); + goto error; + } +#endif + } else { + puts ("Could not find kernel entry point!\n"); + goto error; + } + kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))ep; + + /* find ramdisk */ + ret = boot_get_ramdisk (argc, argv, images, IH_ARCH_M68K, + &rd_data_start, &rd_data_end); + if (ret) + goto error; + + rd_len = rd_data_end - rd_data_start; + ret = boot_ramdisk_high (lmb, rd_data_start, rd_len, + &initrd_start, &initrd_end); + if (ret) + goto error; + + debug("## Transferring control to Linux (at address %08lx) ...\n", + (ulong) kernel); + + show_boot_progress (15); + + if (!images->autostart) + return; + /* + * Linux Kernel Parameters (passing board info data): + * r3: ptr to board info data + * r4: initrd_start or 0 if no initrd + * r5: initrd_end - unused if r4 is 0 + * r6: Start of command line string + * r7: End of command line string + */ + (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); + /* does not return */ + return ; + +error: + if (images->autostart) + do_reset (cmdtp, flag, argc, argv); + return ; +} + +static ulong get_sp (void) +{ + ulong sp; + + asm("movel %%a7, %%d0\n" + "movel %%d0, %0\n": "=d"(sp): :"%d0"); + + return sp; +} + +static void set_clocks_in_mhz (bd_t *kbd) +{ + char *s; + + if ((s = getenv("clocks_in_mhz")) != NULL) { + /* convert all clock information to MHz */ + kbd->bi_intfreq /= 1000000L; + kbd->bi_busfreq /= 1000000L; + } +} diff --git a/lib_m68k/m68k_linux.c b/lib_m68k/m68k_linux.c deleted file mode 100644 index cc974c2d60..0000000000 --- a/lib_m68k/m68k_linux.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * (C) Copyright 2003 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <common.h> -#include <command.h> -#include <image.h> -#include <zlib.h> -#include <bzlib.h> -#include <watchdog.h> -#include <environment.h> -#include <asm/byteorder.h> - -DECLARE_GLOBAL_DATA_PTR; - -#define PHYSADDR(x) x - -#define LINUX_MAX_ENVS 256 -#define LINUX_MAX_ARGS 256 - -#define CHUNKSZ (64 * 1024) - -#ifdef CONFIG_SHOW_BOOT_PROGRESS -# include <status_led.h> -# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg) -#else -# define SHOW_BOOT_PROGRESS(arg) -#endif - -extern image_header_t header; - -void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, - int argc, char *argv[], - ulong addr, ulong * len_ptr, int verify) -{ - ulong sp; - ulong len, checksum; - ulong initrd_start, initrd_end; - ulong cmd_start, cmd_end; - ulong initrd_high; - ulong data; - int initrd_copy_to_ram = 1; - char *cmdline; - char *s; - bd_t *kbd; - void (*kernel) (bd_t *, ulong, ulong, ulong, ulong); - image_header_t *hdr = &header; - - if ((s = getenv("initrd_high")) != NULL) { - /* a value of "no" or a similar string will act like 0, - * turning the "load high" feature off. This is intentional. - */ - initrd_high = simple_strtoul(s, NULL, 16); - if (initrd_high == ~0) - initrd_copy_to_ram = 0; - } else { /* not set, no restrictions to load high */ - initrd_high = ~0; - } - -#ifdef CONFIG_LOGBUFFER - kbd = gd->bd; - /* Prevent initrd from overwriting logbuffer */ - if (initrd_high < (kbd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD)) - initrd_high = kbd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD; - debug("## Logbuffer at 0x%08lX ", kbd->bi_memsize - LOGBUFF_LEN); -#endif - - /* - * Booting a (Linux) kernel image - * - * Allocate space for command line and board info - the - * address should be as high as possible within the reach of - * the kernel (see CFG_BOOTMAPSZ settings), but in unused - * memory, which means far enough below the current stack - * pointer. - */ - asm("movel %%a7, %%d0\n" - "movel %%d0, %0\n": "=d"(sp): :"%d0"); - - debug("## Current stack ends at 0x%08lX ", sp); - - sp -= 2048; /* just to be sure */ - if (sp > CFG_BOOTMAPSZ) - sp = CFG_BOOTMAPSZ; - sp &= ~0xF; - - debug("=> set upper limit to 0x%08lX\n", sp); - - cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF); - kbd = (bd_t *) (((ulong) cmdline - sizeof(bd_t)) & ~0xF); - - if ((s = getenv("bootargs")) == NULL) - s = ""; - - strcpy(cmdline, s); - - cmd_start = (ulong) & cmdline[0]; - cmd_end = cmd_start + strlen(cmdline); - - *kbd = *(gd->bd); - -#ifdef DEBUG - printf("## cmdline at 0x%08lX ... 0x%08lX\n", cmd_start, cmd_end); - - do_bdinfo(NULL, 0, 0, NULL); -#endif - - if ((s = getenv("clocks_in_mhz")) != NULL) { - /* convert all clock information to MHz */ - kbd->bi_intfreq /= 1000000L; - kbd->bi_busfreq /= 1000000L; - } - - kernel = - (void (*)(bd_t *, ulong, ulong, ulong, ulong))ntohl(hdr->ih_ep); - - /* - * Check if there is an initrd image - */ - - if (argc >= 3) { - debug("Not skipping initrd\n"); - SHOW_BOOT_PROGRESS(9); - - addr = simple_strtoul(argv[2], NULL, 16); - - printf("## Loading RAMDisk Image at %08lx ...\n", addr); - - /* Copy header so we can blank CRC field for re-calculation */ - memmove(&header, (char *)addr, sizeof(image_header_t)); - - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - puts("Bad Magic Number\n"); - SHOW_BOOT_PROGRESS(-10); - do_reset(cmdtp, flag, argc, argv); - } - - data = (ulong) & header; - len = sizeof(image_header_t); - - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32(0, (uchar *) data, len) != checksum) { - puts("Bad Header Checksum\n"); - SHOW_BOOT_PROGRESS(-11); - do_reset(cmdtp, flag, argc, argv); - } - - SHOW_BOOT_PROGRESS(10); - - print_image_hdr(hdr); - - data = addr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); - - if (verify) { - ulong csum = 0; -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - ulong cdata = data, edata = cdata + len; -#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ - - puts(" Verifying Checksum ... "); - -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - - while (cdata < edata) { - ulong chunk = edata - cdata; - - if (chunk > CHUNKSZ) - chunk = CHUNKSZ; - csum = crc32(csum, (uchar *) cdata, chunk); - cdata += chunk; - - WATCHDOG_RESET(); - } -#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ - csum = crc32(0, (uchar *) data, len); -#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ - - if (csum != ntohl(hdr->ih_dcrc)) { - puts("Bad Data CRC\n"); - SHOW_BOOT_PROGRESS(-12); - do_reset(cmdtp, flag, argc, argv); - } - puts("OK\n"); - } - - SHOW_BOOT_PROGRESS(11); - - if ((hdr->ih_os != IH_OS_LINUX) || - (hdr->ih_arch != IH_CPU_M68K) || - (hdr->ih_type != IH_TYPE_RAMDISK)) { - puts("No Linux ColdFire Ramdisk Image\n"); - SHOW_BOOT_PROGRESS(-13); - do_reset(cmdtp, flag, argc, argv); - } - - /* - * Now check if we have a multifile image - */ - } else if ((hdr->ih_type == IH_TYPE_MULTI) && (len_ptr[1])) { - u_long tail = ntohl(len_ptr[0]) % 4; - int i; - - SHOW_BOOT_PROGRESS(13); - - /* skip kernel length and terminator */ - data = (ulong) (&len_ptr[2]); - /* skip any additional image length fields */ - for (i = 1; len_ptr[i]; ++i) - data += 4; - /* add kernel length, and align */ - data += ntohl(len_ptr[0]); - if (tail) { - data += 4 - tail; - } - - len = ntohl(len_ptr[1]); - - } else { - /* - * no initrd image - */ - SHOW_BOOT_PROGRESS(14); - - len = data = 0; - } - - if (!data) { - debug("No initrd\n"); - } - - if (data) { - if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ - initrd_start = data; - initrd_end = initrd_start + len; - } else { - initrd_start = (ulong) kbd - len; - initrd_start &= ~(4096 - 1); /* align on page */ - - if (initrd_high) { - ulong nsp; - - /* - * the inital ramdisk does not need to be within - * CFG_BOOTMAPSZ as it is not accessed until after - * the mm system is initialised. - * - * do the stack bottom calculation again and see if - * the initrd will fit just below the monitor stack - * bottom without overwriting the area allocated - * above for command line args and board info. - */ - asm("movel %%a7, %%d0\n" - "movel %%d0, %0\n": "=d"(nsp): :"%d0"); - - nsp -= 2048; /* just to be sure */ - nsp &= ~0xF; - - if (nsp > initrd_high) /* limit as specified */ - nsp = initrd_high; - - nsp -= len; - nsp &= ~(4096 - 1); /* align on page */ - - if (nsp >= sp) - initrd_start = nsp; - } - - SHOW_BOOT_PROGRESS(12); - - debug - ("## initrd at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", - data, data + len - 1, len, len); - - initrd_end = initrd_start + len; - printf(" Loading Ramdisk to %08lx, end %08lx ... ", - initrd_start, initrd_end); -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - { - size_t l = len; - void *to = (void *)initrd_start; - void *from = (void *)data; - - while (l > 0) { - size_t tail = - (l > CHUNKSZ) ? CHUNKSZ : l; - WATCHDOG_RESET(); - memmove(to, from, tail); - to += tail; - from += tail; - l -= tail; - } - } -#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ - memmove((void *)initrd_start, (void *)data, len); -#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ - puts("OK\n"); - } - } else { - initrd_start = 0; - initrd_end = 0; - } - - debug("## Transferring control to Linux (at address %08lx) ...\n", - (ulong) kernel); - - SHOW_BOOT_PROGRESS(15); - - /* - * Linux Kernel Parameters (passing board info data): - * r3: ptr to board info data - * r4: initrd_start or 0 if no initrd - * r5: initrd_end - unused if r4 is 0 - * r6: Start of command line string - * r7: End of command line string - */ - (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); - /* does not return */ -} diff --git a/lib_microblaze/Makefile b/lib_microblaze/Makefile index 82b7beadb0..141b08280a 100644 --- a/lib_microblaze/Makefile +++ b/lib_microblaze/Makefile @@ -25,12 +25,15 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(ARCH).a -SOBJS = +SOBJS-y += -COBJS = board.o microblaze_linux.o time.o cache.o +COBJS-y += board.o +COBJS-y += bootm.o +COBJS-y += cache.o +COBJS-y += time.o -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) $(LIB): $(obj).depend $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) diff --git a/lib_microblaze/bootm.c b/lib_microblaze/bootm.c new file mode 100644 index 0000000000..fab4a54418 --- /dev/null +++ b/lib_microblaze/bootm.c @@ -0,0 +1,81 @@ +/* + * (C) Copyright 2007 Michal Simek + * (C) Copyright 2004 Atmark Techno, Inc. + * + * Michal SIMEK <monstr@monstr.eu> + * Yasushi SHOJI <yashi@atmark-techno.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <command.h> +#include <image.h> +#include <zlib.h> +#include <asm/byteorder.h> + +DECLARE_GLOBAL_DATA_PTR; + +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], + bootm_headers_t *images) +{ + /* First parameter is mapped to $r5 for kernel boot args */ + void (*theKernel) (char *); + char *commandline = getenv ("bootargs"); + ulong ep = 0; + + /* find kernel entry point */ + if (images->legacy_hdr_valid) { + ep = image_get_ep (images->legacy_hdr_os); +#if defined(CONFIG_FIT) + } else if (images->fit_uname_os) { + int ret = fit_image_get_entry (images->fit_hdr_os, + images->fit_noffset_os, &ep); + if (ret) { + puts ("Can't get entry point property!\n"); + goto error; + } +#endif + } else { + puts ("Could not find kernel entry point!\n"); + goto error; + } + theKernel = (void (*)(char *))ep; + + show_boot_progress (15); + +#ifdef DEBUG + printf ("## Transferring control to Linux (at address %08lx) ...\n", + (ulong) theKernel); +#endif + + if (!images->autostart) + return ; + + theKernel (commandline); + /* does not return */ + return; + +error: + if (images->autostart) + do_reset (cmdtp, flag, argc, argv); + return; +} diff --git a/lib_microblaze/microblaze_linux.c b/lib_microblaze/microblaze_linux.c deleted file mode 100644 index 68b58d4be8..0000000000 --- a/lib_microblaze/microblaze_linux.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * (C) Copyright 2007 Michal Simek - * (C) Copyright 2004 Atmark Techno, Inc. - * - * Michal SIMEK <monstr@monstr.eu> - * Yasushi SHOJI <yashi@atmark-techno.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <command.h> -#include <image.h> -#include <zlib.h> -#include <asm/byteorder.h> - -DECLARE_GLOBAL_DATA_PTR; - -extern image_header_t header; /* from cmd_bootm.c */ -/*cmd_boot.c*/ -extern int do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]); - -void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong * len_ptr, int verify) -{ - ulong len = 0, checksum; - ulong initrd_start, initrd_end; - ulong data; - /* First parameter is mapped to $r5 for kernel boot args */ - void (*theKernel) (char *); - image_header_t *hdr = &header; - char *commandline = getenv ("bootargs"); - int i; - - theKernel = (void (*)(char *))ntohl (hdr->ih_ep); - - /* Check if there is an initrd image */ - if (argc >= 3) { - show_boot_progress (9); - - addr = simple_strtoul (argv[2], NULL, 16); - - printf ("## Loading Ramdisk Image at %08lx ...\n", addr); - - /* Copy header so we can blank CRC field for re-calculation */ - memcpy (&header, (char *)addr, sizeof (image_header_t)); - - if (ntohl (hdr->ih_magic) != IH_MAGIC) { - printf ("Bad Magic Number\n"); - show_boot_progress (-10); - do_reset (cmdtp, flag, argc, argv); - } - - data = (ulong) & header; - len = sizeof (image_header_t); - - checksum = ntohl (hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (char *)data, len) != checksum) { - printf ("Bad Header Checksum\n"); - show_boot_progress (-11); - do_reset (cmdtp, flag, argc, argv); - } - - show_boot_progress (10); - - print_image_hdr (hdr); - - data = addr + sizeof (image_header_t); - len = ntohl (hdr->ih_size); - - if (verify) { - ulong csum = 0; - - printf (" Verifying Checksum ... "); - csum = crc32 (0, (char *)data, len); - if (csum != ntohl (hdr->ih_dcrc)) { - printf ("Bad Data CRC\n"); - show_boot_progress (-12); - do_reset (cmdtp, flag, argc, argv); - } - printf ("OK\n"); - } - - show_boot_progress (11); - - if ((hdr->ih_os != IH_OS_LINUX) || - (hdr->ih_arch != IH_CPU_MICROBLAZE) || - (hdr->ih_type != IH_TYPE_RAMDISK)) { - printf ("No Linux Microblaze Ramdisk Image\n"); - show_boot_progress (-13); - do_reset (cmdtp, flag, argc, argv); - } - - /* - * Now check if we have a multifile image - */ - } else if ((hdr->ih_type == IH_TYPE_MULTI) && (len_ptr[1])) { - ulong tail = ntohl (len_ptr[0]) % 4; - - show_boot_progress (13); - - /* skip kernel length and terminator */ - data = (ulong) (&len_ptr[2]); - /* skip any additional image length fields */ - for (i = 1; len_ptr[i]; ++i) - data += 4; - /* add kernel length, and align */ - data += ntohl (len_ptr[0]); - if (tail) { - data += 4 - tail; - } - - len = ntohl (len_ptr[1]); - - } else { - /* - * no initrd image - */ - show_boot_progress (14); - - data = 0; - } - -#ifdef DEBUG - if (!data) { - printf ("No initrd\n"); - } -#endif - - if (data) { - initrd_start = data; - initrd_end = initrd_start + len; - } else { - initrd_start = 0; - initrd_end = 0; - } - - show_boot_progress (15); - -#ifdef DEBUG - printf ("## Transferring control to Linux (at address %08lx) ...\n", - (ulong) theKernel); -#endif - - theKernel (commandline); -} diff --git a/lib_mips/Makefile b/lib_mips/Makefile index 3163f00e01..799eaf2658 100644 --- a/lib_mips/Makefile +++ b/lib_mips/Makefile @@ -25,12 +25,14 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(ARCH).a -SOBJS = +SOBJS-y += -COBJS = board.o time.o mips_linux.o +COBJS-y += board.o +COBJS-y += bootm.o +COBJS-y += time.o -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) $(LIB): $(obj).depend $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) diff --git a/lib_mips/mips_linux.c b/lib_mips/bootm.c index 556b1804e0..e4c139efab 100644 --- a/lib_mips/mips_linux.c +++ b/lib_mips/bootm.c @@ -33,10 +33,6 @@ DECLARE_GLOBAL_DATA_PTR; #define LINUX_MAX_ENVS 256 #define LINUX_MAX_ARGS 256 -extern image_header_t header; /* from cmd_bootm.c */ - -extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); - static int linux_argc; static char ** linux_argv; @@ -47,126 +43,40 @@ static int linux_env_idx; static void linux_params_init (ulong start, char * commandline); static void linux_env_set (char * env_name, char * env_val); +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong * len_ptr, int verify) + bootm_headers_t *images) { - ulong len = 0, checksum; - ulong initrd_start, initrd_end; - ulong data; - void (*theKernel) (int, char **, char **, int *); - image_header_t *hdr = &header; - char *commandline = getenv ("bootargs"); - char env_buf[12]; - - theKernel = - (void (*)(int, char **, char **, int *)) ntohl (hdr->ih_ep); - - /* - * Check if there is an initrd image - */ - if (argc >= 3) { - show_boot_progress (9); - - addr = simple_strtoul (argv[2], NULL, 16); - - printf ("## Loading Ramdisk Image at %08lx ...\n", addr); - - /* Copy header so we can blank CRC field for re-calculation */ - memcpy (&header, (char *) addr, sizeof (image_header_t)); - - if (ntohl (hdr->ih_magic) != IH_MAGIC) { - printf ("Bad Magic Number\n"); - show_boot_progress (-10); - do_reset (cmdtp, flag, argc, argv); - } - - data = (ulong) & header; - len = sizeof (image_header_t); - - checksum = ntohl (hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (uchar *) data, len) != checksum) { - printf ("Bad Header Checksum\n"); - show_boot_progress (-11); - do_reset (cmdtp, flag, argc, argv); + ulong initrd_start, initrd_end; + ulong ep = 0; + void (*theKernel) (int, char **, char **, int *); + char *commandline = getenv ("bootargs"); + char env_buf[12]; + int ret; + + /* find kernel entry point */ + if (images->legacy_hdr_valid) { + ep = image_get_ep (images->legacy_hdr_os); +#if defined(CONFIG_FIT) + } else if (images->fit_uname_os) { + ret = fit_image_get_entry (images->fit_hdr_os, + images->fit_noffset_os, &ep); + if (ret) { + puts ("Can't get entry point property!\n"); + goto error; } - - show_boot_progress (10); - - print_image_hdr (hdr); - - data = addr + sizeof (image_header_t); - len = ntohl (hdr->ih_size); - - if (verify) { - ulong csum = 0; - - printf (" Verifying Checksum ... "); - csum = crc32 (0, (uchar *) data, len); - if (csum != ntohl (hdr->ih_dcrc)) { - printf ("Bad Data CRC\n"); - show_boot_progress (-12); - do_reset (cmdtp, flag, argc, argv); - } - printf ("OK\n"); - } - - show_boot_progress (11); - - if ((hdr->ih_os != IH_OS_LINUX) || - (hdr->ih_arch != IH_CPU_MIPS) || - (hdr->ih_type != IH_TYPE_RAMDISK)) { - printf ("No Linux MIPS Ramdisk Image\n"); - show_boot_progress (-13); - do_reset (cmdtp, flag, argc, argv); - } - - /* - * Now check if we have a multifile image - */ - } else if ((hdr->ih_type == IH_TYPE_MULTI) && (len_ptr[1])) { - ulong tail = ntohl (len_ptr[0]) % 4; - int i; - - show_boot_progress (13); - - /* skip kernel length and terminator */ - data = (ulong) (&len_ptr[2]); - /* skip any additional image length fields */ - for (i = 1; len_ptr[i]; ++i) - data += 4; - /* add kernel length, and align */ - data += ntohl (len_ptr[0]); - if (tail) { - data += 4 - tail; - } - - len = ntohl (len_ptr[1]); - - } else { - /* - * no initrd image - */ - show_boot_progress (14); - - data = 0; - } - -#ifdef DEBUG - if (!data) { - printf ("No initrd\n"); - } #endif - - if (data) { - initrd_start = data; - initrd_end = initrd_start + len; } else { - initrd_start = 0; - initrd_end = 0; + puts ("Could not find kernel entry point!\n"); + goto error; } + theKernel = (void (*)(int, char **, char **, int *))ep; + + ret = boot_get_ramdisk (argc, argv, images, IH_ARCH_MIPS, + &initrd_start, &initrd_end); + if (ret) + goto error; show_boot_progress (15); @@ -203,10 +113,20 @@ void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], sprintf (env_buf, "0x%X", (uint) (gd->bd->bi_flashsize)); linux_env_set ("flash_size", env_buf); + if (!images->autostart) + return ; + /* we assume that the kernel is in place */ printf ("\nStarting kernel ...\n\n"); theKernel (linux_argc, linux_argv, linux_env, 0); + /* does not return */ + return; + +error: + if (images->autostart) + do_reset (cmdtp, flag, argc, argv); + return; } static void linux_params_init (ulong start, char *line) diff --git a/lib_nios/Makefile b/lib_nios/Makefile index 7c9d62cf7c..c41d981a3e 100644 --- a/lib_nios/Makefile +++ b/lib_nios/Makefile @@ -25,12 +25,17 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(ARCH).a -SOBJS = +SOBJS-y += -COBJS = board.o cache.o divmod.o nios_linux.o mult.o time.o +COBJS-y += board.o +COBJS-y += bootm.o +COBJS-y += cache.o +COBJS-y += divmod.o +COBJS-y += mult.o +COBJS-y += time.o -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) $(LIB): $(obj).depend $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) diff --git a/lib_nios/nios_linux.c b/lib_nios/bootm.c index eef17573f9..fb2e9b5205 100644 --- a/lib_nios/nios_linux.c +++ b/lib_nios/bootm.c @@ -29,6 +29,6 @@ * */ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) + bootm_headers_t *images) { } diff --git a/lib_nios2/Makefile b/lib_nios2/Makefile index 1ff2f29bcb..717aa9bfbe 100644 --- a/lib_nios2/Makefile +++ b/lib_nios2/Makefile @@ -25,12 +25,16 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(ARCH).a -SOBJS = cache.o +SOBJS-y += cache.o -COBJS = board.o divmod.o nios_linux.o mult.o time.o +COBJS-y += board.o +COBJS-y += bootm.o +COBJS-y += divmod.o +COBJS-y += mult.o +COBJS-y += time.o -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) $(LIB): $(obj).depend $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) diff --git a/lib_nios2/nios_linux.c b/lib_nios2/bootm.c index 9eb34264d0..0c89e96358 100644 --- a/lib_nios2/nios_linux.c +++ b/lib_nios2/bootm.c @@ -25,16 +25,43 @@ #include <command.h> #include <asm/byteorder.h> -extern image_header_t header; /* common/cmd_bootm.c */ +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) + bootm_headers_t *images) { - image_header_t *hdr = &header; - void (*kernel)(void) = (void (*)(void))ntohl (hdr->ih_ep); + ulong ep = 0; + + /* find kernel entry point */ + if (images->legacy_hdr_valid) { + ep = image_get_ep (images->legacy_hdr_os); +#if defined(CONFIG_FIT) + } else if (images->fit_uname_os) { + int ret = fit_image_get_entry (images->fit_hdr_os, + images->fit_noffset_os, &ep); + if (ret) { + puts ("Can't get entry point property!\n"); + goto error; + } +#endif + } else { + puts ("Could not find kernel entry point!\n"); + goto error; + } + void (*kernel)(void) = (void (*)(void))ep; + + if (!images->autostart) + return ; /* For now we assume the Microtronix linux ... which only * needs to be called ;-) */ kernel (); + /* does not return */ + return; + +error: + if (images->autostart) + do_reset (cmdtp, flag, argc, argv); + return; } diff --git a/lib_ppc/Makefile b/lib_ppc/Makefile index afbd5caf5a..3d76b700e2 100644 --- a/lib_ppc/Makefile +++ b/lib_ppc/Makefile @@ -25,13 +25,21 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(ARCH).a -SOBJS = ppccache.o ppcstring.o ticks.o - -COBJS = board.o \ - bat_rw.o cache.o extable.o kgdb.o time.o interrupts.o - -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +SOBJS-y += ppccache.o +SOBJS-y += ppcstring.o +SOBJS-y += ticks.o + +COBJS-y += bat_rw.o +COBJS-y += board.o +COBJS-y += bootm.o +COBJS-y += cache.o +COBJS-y += extable.o +COBJS-y += interrupts.o +COBJS-y += kgdb.o +COBJS-y += time.o + +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) $(LIB): $(obj).depend $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c new file mode 100644 index 0000000000..89463e342f --- /dev/null +++ b/lib_ppc/bootm.c @@ -0,0 +1,774 @@ +/* + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include <common.h> +#include <watchdog.h> +#include <command.h> +#include <image.h> +#include <malloc.h> +#include <zlib.h> +#include <bzlib.h> +#include <environment.h> +#include <asm/byteorder.h> + +#if defined(CONFIG_OF_LIBFDT) +#include <fdt.h> +#include <libfdt.h> +#include <fdt_support.h> + +static void fdt_error (const char *msg); +static int boot_get_fdt (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + bootm_headers_t *images, char **of_flat_tree, ulong *of_size); +static int boot_relocate_fdt (struct lmb *lmb, ulong bootmap_base, + cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + char **of_flat_tree, ulong *of_size); +#endif + +#ifdef CFG_INIT_RAM_LOCK +#include <asm/cache.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +extern ulong get_effective_memsize(void); +static ulong get_sp (void); +static void set_clocks_in_mhz (bd_t *kbd); + +#ifndef CFG_LINUX_LOWMEM_MAX_SIZE +#define CFG_LINUX_LOWMEM_MAX_SIZE (768*1024*1024) +#endif + +void __attribute__((noinline)) +do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + bootm_headers_t *images) +{ + ulong sp; + + ulong initrd_start, initrd_end; + ulong rd_data_start, rd_data_end, rd_len; + ulong size; + + ulong cmd_start, cmd_end, bootmap_base; + bd_t *kbd; + ulong ep = 0; + void (*kernel)(bd_t *, ulong, ulong, ulong, ulong); + int ret; + ulong of_size = 0; + struct lmb *lmb = images->lmb; + +#if defined(CONFIG_OF_LIBFDT) + char *of_flat_tree = NULL; +#endif + + bootmap_base = getenv_bootm_low(); + size = getenv_bootm_size(); + +#ifdef DEBUG + if (((u64)bootmap_base + size) > (CFG_SDRAM_BASE + (u64)gd->ram_size)) + puts("WARNING: bootm_low + bootm_size exceed total memory\n"); + if ((bootmap_base + size) > get_effective_memsize()) + puts("WARNING: bootm_low + bootm_size exceed eff. memory\n"); +#endif + + size = min(size, get_effective_memsize()); + size = min(size, CFG_LINUX_LOWMEM_MAX_SIZE); + + if (size < getenv_bootm_size()) { + ulong base = bootmap_base + size; + printf("WARNING: adjusting available memory to %x\n", size); + lmb_reserve(lmb, base, getenv_bootm_size() - size); + } + + /* + * Booting a (Linux) kernel image + * + * Allocate space for command line and board info - the + * address should be as high as possible within the reach of + * the kernel (see CFG_BOOTMAPSZ settings), but in unused + * memory, which means far enough below the current stack + * pointer. + */ + sp = get_sp(); + debug ("## Current stack ends at 0x%08lx\n", sp); + + /* adjust sp by 1K to be safe */ + sp -= 1024; + lmb_reserve(lmb, sp, (CFG_SDRAM_BASE + get_effective_memsize() - sp)); + +#if defined(CONFIG_OF_LIBFDT) + /* find flattened device tree */ + ret = boot_get_fdt (cmdtp, flag, argc, argv, images, &of_flat_tree, &of_size); + + if (ret) + goto error; +#endif + + if (!of_size) { + /* allocate space and init command line */ + ret = boot_get_cmdline (lmb, &cmd_start, &cmd_end, bootmap_base); + if (ret) { + puts("ERROR with allocation of cmdline\n"); + goto error; + } + + /* allocate space for kernel copy of board info */ + ret = boot_get_kbd (lmb, &kbd, bootmap_base); + if (ret) { + puts("ERROR with allocation of kernel bd\n"); + goto error; + } + set_clocks_in_mhz(kbd); + } + + /* find kernel entry point */ + if (images->legacy_hdr_valid) { + ep = image_get_ep (images->legacy_hdr_os); +#if defined(CONFIG_FIT) + } else if (images->fit_uname_os) { + ret = fit_image_get_entry (images->fit_hdr_os, + images->fit_noffset_os, &ep); + if (ret) { + puts ("Can't get entry point property!\n"); + goto error; + } +#endif + } else { + puts ("Could not find kernel entry point!\n"); + goto error; + } + kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))ep; + + /* find ramdisk */ + ret = boot_get_ramdisk (argc, argv, images, IH_ARCH_PPC, + &rd_data_start, &rd_data_end); + if (ret) + goto error; + + rd_len = rd_data_end - rd_data_start; + +#if defined(CONFIG_OF_LIBFDT) + ret = boot_relocate_fdt (lmb, bootmap_base, + cmdtp, flag, argc, argv, &of_flat_tree, &of_size); + + /* + * Add the chosen node if it doesn't exist, add the env and bd_t + * if the user wants it (the logic is in the subroutines). + */ + if (of_size) { + /* pass in dummy initrd info, we'll fix up later */ + if (fdt_chosen(of_flat_tree, rd_data_start, rd_data_end, 0) < 0) { + fdt_error ("/chosen node create failed"); + goto error; + } +#ifdef CONFIG_OF_HAS_UBOOT_ENV + if (fdt_env(of_flat_tree) < 0) { + fdt_error ("/u-boot-env node create failed"); + goto error; + } +#endif +#ifdef CONFIG_OF_HAS_BD_T + if (fdt_bd_t(of_flat_tree) < 0) { + fdt_error ("/bd_t node create failed"); + goto error; + } +#endif +#ifdef CONFIG_OF_BOARD_SETUP + /* Call the board-specific fixup routine */ + ft_board_setup(of_flat_tree, gd->bd); +#endif + } +#endif /* CONFIG_OF_LIBFDT */ + + ret = boot_ramdisk_high (lmb, rd_data_start, rd_len, &initrd_start, &initrd_end); + if (ret) + goto error; + +#if defined(CONFIG_OF_LIBFDT) + /* fixup the initrd now that we know where it should be */ + if ((of_flat_tree) && (initrd_start && initrd_end)) { + uint64_t addr, size; + int total = fdt_num_mem_rsv(of_flat_tree); + int j; + + /* Look for the dummy entry and delete it */ + for (j = 0; j < total; j++) { + fdt_get_mem_rsv(of_flat_tree, j, &addr, &size); + if (addr == rd_data_start) { + fdt_del_mem_rsv(of_flat_tree, j); + break; + } + } + + ret = fdt_add_mem_rsv(of_flat_tree, initrd_start, + initrd_end - initrd_start + 1); + if (ret < 0) { + printf("fdt_chosen: %s\n", fdt_strerror(ret)); + goto error; + } + + do_fixup_by_path_u32(of_flat_tree, "/chosen", + "linux,initrd-start", initrd_start, 0); + do_fixup_by_path_u32(of_flat_tree, "/chosen", + "linux,initrd-end", initrd_end, 0); + } +#endif + debug ("## Transferring control to Linux (at address %08lx) ...\n", + (ulong)kernel); + + show_boot_progress (15); + +#if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500) + unlock_ram_in_cache(); +#endif + if (!images->autostart) + return ; + +#if defined(CONFIG_OF_LIBFDT) + if (of_flat_tree) { /* device tree; boot new style */ + /* + * Linux Kernel Parameters (passing device tree): + * r3: pointer to the fdt, followed by the board info data + * r4: physical pointer to the kernel itself + * r5: NULL + * r6: NULL + * r7: NULL + */ + debug (" Booting using OF flat tree...\n"); + (*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0); + /* does not return */ + } else +#endif + { + /* + * Linux Kernel Parameters (passing board info data): + * r3: ptr to board info data + * r4: initrd_start or 0 if no initrd + * r5: initrd_end - unused if r4 is 0 + * r6: Start of command line string + * r7: End of command line string + */ + debug (" Booting using board info...\n"); + (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); + /* does not return */ + } + return ; + +error: + if (images->autostart) + do_reset (cmdtp, flag, argc, argv); + return ; +} + +static ulong get_sp (void) +{ + ulong sp; + + asm( "mr %0,1": "=r"(sp) : ); + return sp; +} + +static void set_clocks_in_mhz (bd_t *kbd) +{ + char *s; + + if ((s = getenv ("clocks_in_mhz")) != NULL) { + /* convert all clock information to MHz */ + kbd->bi_intfreq /= 1000000L; + kbd->bi_busfreq /= 1000000L; +#if defined(CONFIG_MPC8220) + kbd->bi_inpfreq /= 1000000L; + kbd->bi_pcifreq /= 1000000L; + kbd->bi_pevfreq /= 1000000L; + kbd->bi_flbfreq /= 1000000L; + kbd->bi_vcofreq /= 1000000L; +#endif +#if defined(CONFIG_CPM2) + kbd->bi_cpmfreq /= 1000000L; + kbd->bi_brgfreq /= 1000000L; + kbd->bi_sccfreq /= 1000000L; + kbd->bi_vco /= 1000000L; +#endif +#if defined(CONFIG_MPC5xxx) + kbd->bi_ipbfreq /= 1000000L; + kbd->bi_pcifreq /= 1000000L; +#endif /* CONFIG_MPC5xxx */ + } +} + +#if defined(CONFIG_OF_LIBFDT) +static void fdt_error (const char *msg) +{ + puts ("ERROR: "); + puts (msg); + puts (" - must RESET the board to recover.\n"); +} + +static image_header_t *image_get_fdt (ulong fdt_addr) +{ + image_header_t *fdt_hdr = (image_header_t *)fdt_addr; + + image_print_contents (fdt_hdr); + + puts (" Verifying Checksum ... "); + if (!image_check_hcrc (fdt_hdr)) { + fdt_error ("fdt header checksum invalid"); + return NULL; + } + + if (!image_check_dcrc (fdt_hdr)) { + fdt_error ("fdt checksum invalid"); + return NULL; + } + puts ("OK\n"); + + if (!image_check_type (fdt_hdr, IH_TYPE_FLATDT)) { + fdt_error ("uImage is not a fdt"); + return NULL; + } + if (image_get_comp (fdt_hdr) != IH_COMP_NONE) { + fdt_error ("uImage is compressed"); + return NULL; + } + if (fdt_check_header ((char *)image_get_data (fdt_hdr)) != 0) { + fdt_error ("uImage data is not a fdt"); + return NULL; + } + return fdt_hdr; +} + +/** + * fit_check_fdt - verify FIT format FDT subimage + * @fit_hdr: pointer to the FIT header + * fdt_noffset: FDT subimage node offset within FIT image + * @verify: data CRC verification flag + * + * fit_check_fdt() verifies integrity of the FDT subimage and from + * specified FIT image. + * + * returns: + * 1, on success + * 0, on failure + */ +#if defined(CONFIG_FIT) +static int fit_check_fdt (const void *fit, int fdt_noffset, int verify) +{ + fit_image_print (fit, fdt_noffset, " "); + + if (verify) { + puts (" Verifying Hash Integrity ... "); + if (!fit_image_check_hashes (fit, fdt_noffset)) { + fdt_error ("Bad Data Hash"); + return 0; + } + puts ("OK\n"); + } + + if (!fit_image_check_type (fit, fdt_noffset, IH_TYPE_FLATDT)) { + fdt_error ("Not a FDT image"); + return 0; + } + + if (!fit_image_check_comp (fit, fdt_noffset, IH_COMP_NONE)) { + fdt_error ("FDT image is compressed"); + return 0; + } + + return 1; +} +#endif /* CONFIG_FIT */ + +static int boot_get_fdt (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + bootm_headers_t *images, char **of_flat_tree, ulong *of_size) +{ + ulong fdt_addr; + image_header_t *fdt_hdr; + char *fdt_blob = NULL; + ulong image_start, image_end; + ulong load_start, load_end; +#if defined(CONFIG_FIT) + void *fit_hdr; + const char *fit_uname_config = NULL; + const char *fit_uname_fdt = NULL; + ulong default_addr; + int cfg_noffset; + int fdt_noffset; + const void *data; + size_t size; +#endif + + *of_flat_tree = NULL; + *of_size = 0; + + if (argc > 3 || genimg_has_config (images)) { +#if defined(CONFIG_FIT) + if (argc > 3) { + /* + * If the FDT blob comes from the FIT image and the + * FIT image address is omitted in the command line + * argument, try to use ramdisk or os FIT image + * address or default load address. + */ + if (images->fit_uname_rd) + default_addr = (ulong)images->fit_hdr_rd; + else if (images->fit_uname_os) + default_addr = (ulong)images->fit_hdr_os; + else + default_addr = load_addr; + + if (fit_parse_conf (argv[3], default_addr, + &fdt_addr, &fit_uname_config)) { + debug ("* fdt: config '%s' from image at 0x%08lx\n", + fit_uname_config, fdt_addr); + } else if (fit_parse_subimage (argv[3], default_addr, + &fdt_addr, &fit_uname_fdt)) { + debug ("* fdt: subimage '%s' from image at 0x%08lx\n", + fit_uname_fdt, fdt_addr); + } else +#endif + { + fdt_addr = simple_strtoul(argv[3], NULL, 16); + debug ("* fdt: cmdline image address = 0x%08lx\n", + fdt_addr); + } +#if defined(CONFIG_FIT) + } else { + /* use FIT configuration provided in first bootm + * command argument + */ + fdt_addr = (ulong)images->fit_hdr_os; + fit_uname_config = images->fit_uname_cfg; + debug ("* fdt: using config '%s' from image at 0x%08lx\n", + fit_uname_config, fdt_addr); + + /* + * Check whether configuration has FDT blob defined, + * if not quit silently. + */ + fit_hdr = (void *)fdt_addr; + cfg_noffset = fit_conf_get_node (fit_hdr, + fit_uname_config); + if (cfg_noffset < 0) { + debug ("* fdt: no such config\n"); + return 0; + } + + fdt_noffset = fit_conf_get_fdt_node (fit_hdr, + cfg_noffset); + if (fdt_noffset < 0) { + debug ("* fdt: no fdt in config\n"); + return 0; + } + } +#endif + + debug ("## Checking for 'FDT'/'FDT Image' at %08lx\n", + fdt_addr); + + /* copy from dataflash if needed */ + fdt_addr = genimg_get_image (fdt_addr); + + /* + * Check if there is an FDT image at the + * address provided in the second bootm argument + * check image type, for FIT images get a FIT node. + */ + switch (genimg_get_format ((void *)fdt_addr)) { + case IMAGE_FORMAT_LEGACY: + /* verify fdt_addr points to a valid image header */ + printf ("## Flattened Device Tree from Legacy Image at %08lx\n", + fdt_addr); + fdt_hdr = image_get_fdt (fdt_addr); + if (!fdt_hdr) + goto error; + + /* + * move image data to the load address, + * make sure we don't overwrite initial image + */ + image_start = (ulong)fdt_hdr; + image_end = image_get_image_end (fdt_hdr); + + load_start = image_get_load (fdt_hdr); + load_end = load_start + image_get_data_size (fdt_hdr); + + if ((load_start < image_end) && (load_end > image_start)) { + fdt_error ("fdt overwritten"); + goto error; + } + + debug (" Loading FDT from 0x%08lx to 0x%08lx\n", + image_get_data (fdt_hdr), load_start); + + memmove ((void *)load_start, + (void *)image_get_data (fdt_hdr), + image_get_data_size (fdt_hdr)); + + fdt_blob = (char *)load_start; + break; + case IMAGE_FORMAT_FIT: + /* + * This case will catch both: new uImage format + * (libfdt based) and raw FDT blob (also libfdt + * based). + */ +#if defined(CONFIG_FIT) + /* check FDT blob vs FIT blob */ + if (fit_check_format ((const void *)fdt_addr)) { + /* + * FIT image + */ + fit_hdr = (void *)fdt_addr; + printf ("## Flattened Device Tree from FIT Image at %08lx\n", + fdt_addr); + + if (!fit_uname_fdt) { + /* + * no FDT blob image node unit name, + * try to get config node first. If + * config unit node name is NULL + * fit_conf_get_node() will try to + * find default config node + */ + cfg_noffset = fit_conf_get_node (fit_hdr, + fit_uname_config); + + if (cfg_noffset < 0) { + fdt_error ("Could not find configuration node\n"); + goto error; + } + + fit_uname_config = fdt_get_name (fit_hdr, + cfg_noffset, NULL); + printf (" Using '%s' configuration\n", + fit_uname_config); + + fdt_noffset = fit_conf_get_fdt_node (fit_hdr, + cfg_noffset); + fit_uname_fdt = fit_get_name (fit_hdr, + fdt_noffset, NULL); + } else { + /* get FDT component image node offset */ + fdt_noffset = fit_image_get_node (fit_hdr, + fit_uname_fdt); + } + if (fdt_noffset < 0) { + fdt_error ("Could not find subimage node\n"); + goto error; + } + + printf (" Trying '%s' FDT blob subimage\n", + fit_uname_fdt); + + if (!fit_check_fdt (fit_hdr, fdt_noffset, + images->verify)) + goto error; + + /* get ramdisk image data address and length */ + if (fit_image_get_data (fit_hdr, fdt_noffset, + &data, &size)) { + fdt_error ("Could not find FDT subimage data"); + goto error; + } + + /* verift that image data is a proper FDT blob */ + if (fdt_check_header ((char *)data) != 0) { + fdt_error ("Subimage data is not a FTD"); + goto error; + } + + /* + * move image data to the load address, + * make sure we don't overwrite initial image + */ + image_start = (ulong)fit_hdr; + image_end = fit_get_end (fit_hdr); + + if (fit_image_get_load (fit_hdr, fdt_noffset, + &load_start) == 0) { + load_end = load_start + size; + + if ((load_start < image_end) && + (load_end > image_start)) { + fdt_error ("FDT overwritten"); + goto error; + } + + printf (" Loading FDT from 0x%08lx to 0x%08lx\n", + (ulong)data, load_start); + + memmove ((void *)load_start, + (void *)data, size); + + fdt_blob = (char *)load_start; + } else { + fdt_blob = (char *)data; + } + + images->fit_hdr_fdt = fit_hdr; + images->fit_uname_fdt = fit_uname_fdt; + images->fit_noffset_fdt = fdt_noffset; + break; + } else +#endif + { + /* + * FDT blob + */ + debug ("* fdt: raw FDT blob\n"); + printf ("## Flattened Device Tree blob at %08lx\n", fdt_blob); + fdt_blob = (char *)fdt_addr; + } + break; + default: + fdt_error ("Did not find a cmdline Flattened Device Tree"); + goto error; + } + + printf (" Booting using the fdt blob at 0x%x\n", fdt_blob); + + } else if (images->legacy_hdr_valid && + image_check_type (images->legacy_hdr_os, IH_TYPE_MULTI)) { + + ulong fdt_data, fdt_len; + + /* + * Now check if we have a legacy multi-component image, + * get second entry data start address and len. + */ + printf ("## Flattened Device Tree from multi " + "component Image at %08lX\n", + (ulong)images->legacy_hdr_os); + + image_multi_getimg (images->legacy_hdr_os, 2, &fdt_data, &fdt_len); + if (fdt_len) { + + fdt_blob = (char *)fdt_data; + printf (" Booting using the fdt at 0x%x\n", fdt_blob); + + if (fdt_check_header (fdt_blob) != 0) { + fdt_error ("image is not a fdt"); + goto error; + } + + if (be32_to_cpu (fdt_totalsize (fdt_blob)) != fdt_len) { + fdt_error ("fdt size != image size"); + goto error; + } + } else { + fdt_error ("Did not find a Flattened Device Tree " + "in a legacy multi-component image"); + goto error; + } + } else { + debug ("## No Flattened Device Tree\n"); + return 0; + } + + *of_flat_tree = fdt_blob; + *of_size = be32_to_cpu (fdt_totalsize (fdt_blob)); + debug (" of_flat_tree at 0x%08lx size 0x%08lx\n", + *of_flat_tree, *of_size); + + return 0; + +error: + do_reset (cmdtp, flag, argc, argv); + return 1; +} + +static int boot_relocate_fdt (struct lmb *lmb, ulong bootmap_base, + cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + char **of_flat_tree, ulong *of_size) +{ + char *fdt_blob = *of_flat_tree; + ulong relocate = 0; + ulong of_len = 0; + + /* nothing to do */ + if (*of_size == 0) + return 0; + + if (fdt_check_header (fdt_blob) != 0) { + fdt_error ("image is not a fdt"); + goto error; + } + +#ifndef CFG_NO_FLASH + /* move the blob if it is in flash (set relocate) */ + if (addr2info ((ulong)fdt_blob) != NULL) + relocate = 1; +#endif + + /* + * The blob must be within CFG_BOOTMAPSZ, + * so we flag it to be copied if it is not. + */ + if (fdt_blob >= (char *)CFG_BOOTMAPSZ) + relocate = 1; + + of_len = be32_to_cpu (fdt_totalsize (fdt_blob)); + + /* move flattend device tree if needed */ + if (relocate) { + int err; + ulong of_start; + + /* position on a 4K boundary before the alloc_current */ + of_start = lmb_alloc_base(lmb, of_len, 0x1000, + (CFG_BOOTMAPSZ + bootmap_base)); + + if (of_start == 0) { + puts("device tree - allocation error\n"); + goto error; + } + + debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", + (ulong)fdt_blob, (ulong)fdt_blob + of_len - 1, + of_len, of_len); + + printf (" Loading Device Tree to %08lx, end %08lx ... ", + of_start, of_start + of_len - 1); + + err = fdt_open_into (fdt_blob, (void *)of_start, of_len); + if (err != 0) { + fdt_error ("fdt move failed"); + goto error; + } + puts ("OK\n"); + + *of_flat_tree = (char *)of_start; + } else { + *of_flat_tree = fdt_blob; + lmb_reserve(lmb, (ulong)fdt, of_len); + } + + return 0; + +error: + return 1; +} +#endif diff --git a/lib_sh/Makefile b/lib_sh/Makefile index cf127a826c..a5772a013d 100644 --- a/lib_sh/Makefile +++ b/lib_sh/Makefile @@ -22,12 +22,14 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(ARCH).a -SOBJS = +SOBJS-y += -COBJS = board.o sh_linux.o # time.o +COBJS-y += board.o +COBJS-y += bootm.o +#COBJS-y += time.o -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) $(LIB): $(obj).depend $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) diff --git a/lib_sh/sh_linux.c b/lib_sh/bootm.c index 14b6815cd4..49462c8458 100644 --- a/lib_sh/sh_linux.c +++ b/lib_sh/bootm.c @@ -25,8 +25,6 @@ #include <command.h> #include <asm/byteorder.h> -extern image_header_t header; /* common/cmd_bootm.c */ - /* The SH kernel reads arguments from the empty zero page at location * 0 at the start of SDRAM. The following are copied from * arch/sh/kernel/setup.c and may require tweaking if the kernel sources @@ -45,6 +43,8 @@ extern image_header_t header; /* common/cmd_bootm.c */ #define RAMDISK_IMAGE_START_MASK 0x07FF +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + #ifdef CFG_DEBUG static void hexdump (unsigned char *buf, int len) { @@ -60,15 +60,42 @@ static void hexdump (unsigned char *buf, int len) #endif void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) + bootm_headers_t *images) { - image_header_t *hdr = &header; - char *bootargs = getenv("bootargs"); - void (*kernel) (void) = (void (*)(void)) ntohl (hdr->ih_ep); + ulong ep = 0; + char *bootargs = getenv("bootargs"); + + /* find kernel entry point */ + if (images->legacy_hdr_valid) { + ep = image_get_ep (images->legacy_hdr_os); +#if defined(CONFIG_FIT) + } else if (images->fit_uname_os) { + int ret = fit_image_get_entry (images->fit_hdr_os, + images->fit_noffset_os, &ep); + if (ret) { + puts ("Can't get entry point property!\n"); + goto error; + } +#endif + } else { + puts ("Could not find kernel entry point!\n"); + goto error; + } + void (*kernel) (void) = (void (*)(void))ep; + + if (!images->autostart) + return ; /* Setup parameters */ memset(PARAM, 0, 0x1000); /* Clear zero page */ strcpy(COMMAND_LINE, bootargs); kernel(); + /* does not return */ + return; + +error: + if (images->autostart) + do_reset (cmdtp, flag, argc, argv); + return; } diff --git a/libfdt/fdt.c b/libfdt/fdt.c index bd91712378..cfa1989d8e 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -50,8 +50,12 @@ */ #include "libfdt_env.h" +#ifndef USE_HOSTCC #include <fdt.h> #include <libfdt.h> +#else +#include "fdt_host.h" +#endif #include "libfdt_internal.h" diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 63fa1290be..11d80d2fa2 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -50,8 +50,12 @@ */ #include "libfdt_env.h" +#ifndef USE_HOSTCC #include <fdt.h> #include <libfdt.h> +#else +#include "fdt_host.h" +#endif #include "libfdt_internal.h" diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 0df472bc5e..8609fa7d76 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -50,8 +50,12 @@ */ #include "libfdt_env.h" +#ifndef USE_HOSTCC #include <fdt.h> #include <libfdt.h> +#else +#include "fdt_host.h" +#endif #include "libfdt_internal.h" diff --git a/libfdt/fdt_strerror.c b/libfdt/fdt_strerror.c index f9d32ef536..abf792e7de 100644 --- a/libfdt/fdt_strerror.c +++ b/libfdt/fdt_strerror.c @@ -50,8 +50,12 @@ */ #include "libfdt_env.h" +#ifndef USE_HOSTCC #include <fdt.h> #include <libfdt.h> +#else +#include "fdt_host.h" +#endif #include "libfdt_internal.h" diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c index 88e24b8318..24e172495a 100644 --- a/libfdt/fdt_wip.c +++ b/libfdt/fdt_wip.c @@ -50,8 +50,12 @@ */ #include "libfdt_env.h" +#ifndef USE_HOSTCC #include <fdt.h> #include <libfdt.h> +#else +#include "fdt_host.h" +#endif #include "libfdt_internal.h" diff --git a/tools/.gitignore b/tools/.gitignore index c33679a9d2..979f2dac0d 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -4,6 +4,14 @@ /environment.c /gen_eth_addr /img2srec +/md5.c /mkimage /sha1.c /ubsha1 +/image.c +/fdt.c +/fdt_ro.c +/fdt_rw.c +/fdt_strerror.c +/fdt_wip.c +/libfdt_internal.h diff --git a/tools/Makefile b/tools/Makefile index af0de477cd..9f0dedfa3b 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -23,7 +23,7 @@ BIN_FILES = img2srec$(SFX) mkimage$(SFX) envcrc$(SFX) ubsha1$(SFX) gen_eth_addr$(SFX) bmp_logo$(SFX) -OBJ_LINKS = environment.o crc32.o sha1.o +OBJ_LINKS = environment.o crc32.o md5.o sha1.o image.o OBJ_FILES = img2srec.o mkimage.o envcrc.o ubsha1.o gen_eth_addr.o bmp_logo.o ifeq ($(ARCH),mips) @@ -37,6 +37,8 @@ endif #OBJ_FILES += mpc86x_clk.o #endif +LIBFDT_OBJ_FILES = fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_wip.o + LOGO_H = $(OBJTREE)/include/bmp_logo.h ifeq ($(LOGO_BMP),) @@ -120,6 +122,10 @@ CPPFLAGS = -idirafter $(SRCTREE)/include \ -idirafter $(OBJTREE)/include \ -DTEXT_BASE=$(TEXT_BASE) -DUSE_HOSTCC CFLAGS = $(HOST_CFLAGS) $(CPPFLAGS) -O + +# No -pedantic switch to avoid libfdt compilation warnings +FIT_CFLAGS = -Wall $(CPPFLAGS) -O + AFLAGS = -D__ASSEMBLY__ $(CPPFLAGS) CC = $(HOSTCC) STRIP = $(HOSTSTRIP) @@ -137,7 +143,7 @@ $(obj)img2srec$(SFX): $(obj)img2srec.o $(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^ $(STRIP) $@ -$(obj)mkimage$(SFX): $(obj)mkimage.o $(obj)crc32.o +$(obj)mkimage$(SFX): $(obj)mkimage.o $(obj)crc32.o $(obj)image.o $(obj)md5.o $(obj)sha1.o $(LIBFDT_OBJ_FILES) $(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^ $(STRIP) $@ @@ -170,11 +176,17 @@ $(obj)ubsha1.o: $(src)ubsha1.c $(obj)crc32.o: $(obj)crc32.c $(CC) -g $(CFLAGS) -c -o $@ $< +$(obj)md5.o: $(obj)md5.c + $(CC) -g $(CFLAGS) -c -o $@ $< + $(obj)sha1.o: $(obj)sha1.c $(CC) -g $(CFLAGS) -c -o $@ $< +$(obj)image.o: $(obj)image.c + $(CC) -g $(FIT_CFLAGS) -c -o $@ $< + $(obj)mkimage.o: $(src)mkimage.c - $(CC) -g $(CFLAGS) -c -o $@ $< + $(CC) -g $(FIT_CFLAGS) -c -o $@ $< $(obj)ncb.o: $(src)ncb.c $(CC) -g $(CFLAGS) -c -o $@ $< @@ -188,6 +200,21 @@ $(obj)inca-swap-bytes.o: $(src)inca-swap-bytes.c $(obj)mpc86x_clk.o: $(src)mpc86x_clk.c $(CC) -g $(CFLAGS) -c -o $@ $< +$(obj)fdt.o: $(obj)fdt.c + $(CC) -g $(FIT_CFLAGS) -c -o $@ $< + +$(obj)fdt_ro.o: $(obj)fdt_ro.c + $(CC) -g $(FIT_CFLAGS) -c -o $@ $< + +$(obj)fdt_rw.o: $(obj)fdt_rw.c + $(CC) -g $(FIT_CFLAGS) -c -o $@ $< + +$(obj)fdt_strerror.o: $(obj)fdt_strerror.c + $(CC) -g $(FIT_CFLAGS) -c -o $@ $< + +$(obj)fdt_wip.o: $(obj)fdt_wip.c + $(CC) -g $(FIT_CFLAGS) -c -o $@ $< + subdirs: ifeq ($(TOOLSUBDIRS),) @: @@ -213,10 +240,42 @@ $(obj)crc32.c: @rm -f $(obj)crc32.c ln -s $(src)../lib_generic/crc32.c $(obj)crc32.c +$(obj)md5.c: + @rm -f $(obj)md5.c + ln -s $(src)../lib_generic/md5.c $(obj)md5.c + $(obj)sha1.c: @rm -f $(obj)sha1.c ln -s $(src)../lib_generic/sha1.c $(obj)sha1.c +$(obj)image.c: + @rm -f $(obj)image.c + ln -s $(src)../common/image.c $(obj)image.c + +$(obj)fdt.c: libfdt_internal.h + @rm -f $(obj)fdt.c + ln -s $(src)../libfdt/fdt.c $(obj)fdt.c + +$(obj)fdt_ro.c: libfdt_internal.h + @rm -f $(obj)fdt_ro.c + ln -s $(src)../libfdt/fdt_ro.c $(obj)fdt_ro.c + +$(obj)fdt_rw.c: libfdt_internal.h + @rm -f $(obj)fdt_rw.c + ln -s $(src)../libfdt/fdt_rw.c $(obj)fdt_rw.c + +$(obj)fdt_strerror.c: libfdt_internal.h + @rm -f $(obj)fdt_strerror.c + ln -s $(src)../libfdt/fdt_strerror.c $(obj)fdt_strerror.c + +$(obj)fdt_wip.c: libfdt_internal.h + @rm -f $(obj)fdt_wip.c + ln -s $(src)../libfdt/fdt_wip.c $(obj)fdt_wip.c + +$(obj)libfdt_internal.h: + @rm -f $(obj)libfdt_internal.h + ln -s $(src)../libfdt/libfdt_internal.h $(obj)libfdt_internal.h + $(LOGO_H): $(obj)bmp_logo $(LOGO_BMP) $(obj)./bmp_logo $(LOGO_BMP) >$@ diff --git a/tools/fdt_host.h b/tools/fdt_host.h new file mode 100644 index 0000000000..085013e02e --- /dev/null +++ b/tools/fdt_host.h @@ -0,0 +1,28 @@ +/* + * (C) Copyright 2008 Semihalf + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __FDT_HOST_H__ +#define __FDT_HOST_H__ + +/* Make sure to include u-boot version of libfdt include files */ +#include "../include/fdt.h" +#include "../include/libfdt.h" +#include "../include/fdt_support.h" + +#endif /* __FDT_HOST_H__ */ diff --git a/tools/mkimage.c b/tools/mkimage.c index 21251306ac..6e1ff2b1e2 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -1,4 +1,6 @@ /* + * (C) Copyright 2008 Semihalf + * * (C) Copyright 2000-2004 * DENX Software Engineering * Wolfgang Denk, wd@denx.de @@ -20,44 +22,7 @@ * MA 02111-1307 USA */ -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#ifndef __WIN32__ -#include <netinet/in.h> /* for host / network byte order conversions */ -#endif -#include <sys/mman.h> -#include <sys/stat.h> -#include <time.h> -#include <unistd.h> - -#if defined(__BEOS__) || defined(__NetBSD__) || defined(__APPLE__) -#include <inttypes.h> -#endif - -#ifdef __WIN32__ -typedef unsigned int __u32; - -#define SWAP_LONG(x) \ - ((__u32)( \ - (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ - (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ - (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ - (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; - -#define ntohl(a) SWAP_LONG(a) -#define htonl(a) SWAP_LONG(a) -#endif /* __WIN32__ */ - -#ifndef O_BINARY /* should be define'd on __WIN32__ */ -#define O_BINARY 0 -#endif - +#include "mkimage.h" #include <image.h> extern int errno; @@ -66,110 +31,27 @@ extern int errno; #define MAP_FAILED (-1) #endif -char *cmdname; - -extern unsigned long crc32 (unsigned long crc, const char *buf, unsigned int len); - -typedef struct table_entry { - int val; /* as defined in image.h */ - char *sname; /* short (input) name */ - char *lname; /* long (output) name */ -} table_entry_t; - -table_entry_t arch_name[] = { - { IH_CPU_INVALID, NULL, "Invalid CPU", }, - { IH_CPU_ALPHA, "alpha", "Alpha", }, - { IH_CPU_ARM, "arm", "ARM", }, - { IH_CPU_I386, "x86", "Intel x86", }, - { IH_CPU_IA64, "ia64", "IA64", }, - { IH_CPU_M68K, "m68k", "MC68000", }, - { IH_CPU_MICROBLAZE, "microblaze", "MicroBlaze", }, - { IH_CPU_MIPS, "mips", "MIPS", }, - { IH_CPU_MIPS64, "mips64", "MIPS 64 Bit", }, - { IH_CPU_NIOS, "nios", "NIOS", }, - { IH_CPU_NIOS2, "nios2", "NIOS II", }, - { IH_CPU_PPC, "ppc", "PowerPC", }, - { IH_CPU_S390, "s390", "IBM S390", }, - { IH_CPU_SH, "sh", "SuperH", }, - { IH_CPU_SPARC, "sparc", "SPARC", }, - { IH_CPU_SPARC64, "sparc64", "SPARC 64 Bit", }, - { IH_CPU_BLACKFIN, "blackfin", "Blackfin", }, - { IH_CPU_AVR32, "avr32", "AVR32", }, - { -1, "", "", }, -}; - -table_entry_t os_name[] = { - { IH_OS_INVALID, NULL, "Invalid OS", }, - { IH_OS_4_4BSD, "4_4bsd", "4_4BSD", }, - { IH_OS_ARTOS, "artos", "ARTOS", }, - { IH_OS_DELL, "dell", "Dell", }, - { IH_OS_ESIX, "esix", "Esix", }, - { IH_OS_FREEBSD, "freebsd", "FreeBSD", }, - { IH_OS_IRIX, "irix", "Irix", }, - { IH_OS_LINUX, "linux", "Linux", }, - { IH_OS_LYNXOS, "lynxos", "LynxOS", }, - { IH_OS_NCR, "ncr", "NCR", }, - { IH_OS_NETBSD, "netbsd", "NetBSD", }, - { IH_OS_OPENBSD, "openbsd", "OpenBSD", }, - { IH_OS_PSOS, "psos", "pSOS", }, - { IH_OS_QNX, "qnx", "QNX", }, - { IH_OS_RTEMS, "rtems", "RTEMS", }, - { IH_OS_SCO, "sco", "SCO", }, - { IH_OS_SOLARIS, "solaris", "Solaris", }, - { IH_OS_SVR4, "svr4", "SVR4", }, - { IH_OS_U_BOOT, "u-boot", "U-Boot", }, - { IH_OS_VXWORKS, "vxworks", "VxWorks", }, - { -1, "", "", }, -}; - -table_entry_t type_name[] = { - { IH_TYPE_INVALID, NULL, "Invalid Image", }, - { IH_TYPE_FILESYSTEM, "filesystem", "Filesystem Image", }, - { IH_TYPE_FIRMWARE, "firmware", "Firmware", }, - { IH_TYPE_KERNEL, "kernel", "Kernel Image", }, - { IH_TYPE_MULTI, "multi", "Multi-File Image", }, - { IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", }, - { IH_TYPE_SCRIPT, "script", "Script", }, - { IH_TYPE_STANDALONE, "standalone", "Standalone Program", }, - { IH_TYPE_FLATDT, "flat_dt", "Flat Device Tree", }, - { -1, "", "", }, -}; - -table_entry_t comp_name[] = { - { IH_COMP_NONE, "none", "uncompressed", }, - { IH_COMP_BZIP2, "bzip2", "bzip2 compressed", }, - { IH_COMP_GZIP, "gzip", "gzip compressed", }, - { -1, "", "", }, -}; - -static void copy_file (int, const char *, int); -static void usage (void); -static void print_header (image_header_t *); -static void print_type (image_header_t *); -static char *put_table_entry (table_entry_t *, char *, int); -static char *put_arch (int); -static char *put_type (int); -static char *put_os (int); -static char *put_comp (int); -static int get_table_entry (table_entry_t *, char *, char *); -static int get_arch(char *); -static int get_comp(char *); -static int get_os (char *); -static int get_type(char *); - +extern unsigned long crc32 (unsigned long crc, const char *buf, unsigned int len); +static void copy_file (int, const char *, int); +static void usage (void); +static void image_verify_header (char *, int); +static void fit_handle_file (void); char *datafile; char *imagefile; +char *cmdname; int dflag = 0; int eflag = 0; +int fflag = 0; int lflag = 0; int vflag = 0; int xflag = 0; int opt_os = IH_OS_LINUX; -int opt_arch = IH_CPU_PPC; +int opt_arch = IH_ARCH_PPC; int opt_type = IH_TYPE_KERNEL; int opt_comp = IH_COMP_GZIP; +char *opt_dtc = MKIMAGE_DEFAULT_DTC_OPTIONS; image_header_t header; image_header_t *hdr = &header; @@ -177,7 +59,7 @@ image_header_t *hdr = &header; int main (int argc, char **argv) { - int ifd; + int ifd = -1; uint32_t checksum; uint32_t addr; uint32_t ep; @@ -197,22 +79,28 @@ main (int argc, char **argv) break; case 'A': if ((--argc <= 0) || - (opt_arch = get_arch(*++argv)) < 0) + (opt_arch = genimg_get_arch_id (*++argv)) < 0) usage (); goto NXTARG; case 'C': if ((--argc <= 0) || - (opt_comp = get_comp(*++argv)) < 0) + (opt_comp = genimg_get_comp_id (*++argv)) < 0) + usage (); + goto NXTARG; + case 'D': + if (--argc <= 0) usage (); + opt_dtc = *++argv; goto NXTARG; + case 'O': if ((--argc <= 0) || - (opt_os = get_os(*++argv)) < 0) + (opt_os = genimg_get_os_id (*++argv)) < 0) usage (); goto NXTARG; case 'T': if ((--argc <= 0) || - (opt_type = get_type(*++argv)) < 0) + (opt_type = genimg_get_type_id (*++argv)) < 0) usage (); goto NXTARG; @@ -245,6 +133,12 @@ main (int argc, char **argv) } eflag = 1; goto NXTARG; + case 'f': + if (--argc <= 0) + usage (); + datafile = *++argv; + fflag = 1; + goto NXTARG; case 'n': if (--argc <= 0) usage (); @@ -263,14 +157,17 @@ main (int argc, char **argv) NXTARG: ; } - if ((argc != 1) || ((lflag ^ dflag) == 0)) + if ((argc != 1) || + (dflag && (fflag || lflag)) || + (fflag && (dflag || lflag)) || + (lflag && (dflag || fflag))) usage(); if (!eflag) { ep = addr; /* If XIP, entry point must be after the U-Boot header */ if (xflag) - ep += sizeof(image_header_t); + ep += image_get_header_size (); } /* @@ -278,32 +175,33 @@ NXTARG: ; * the size of the U-Boot header. */ if (xflag) { - if (ep != addr + sizeof(image_header_t)) { + if (ep != addr + image_get_header_size ()) { fprintf (stderr, "%s: For XIP, the entry point must be the load addr + %lu\n", cmdname, - (unsigned long)sizeof(image_header_t)); + (unsigned long)image_get_header_size ()); exit (EXIT_FAILURE); } } imagefile = *argv; - if (lflag) { - ifd = open(imagefile, O_RDONLY|O_BINARY); - } else { - ifd = open(imagefile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666); - } + if (!fflag){ + if (lflag) { + ifd = open (imagefile, O_RDONLY|O_BINARY); + } else { + ifd = open (imagefile, + O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666); + } - if (ifd < 0) { - fprintf (stderr, "%s: Can't open %s: %s\n", - cmdname, imagefile, strerror(errno)); - exit (EXIT_FAILURE); + if (ifd < 0) { + fprintf (stderr, "%s: Can't open %s: %s\n", + cmdname, imagefile, strerror(errno)); + exit (EXIT_FAILURE); + } } if (lflag) { - int len; - char *data; /* * list header information of existing image */ @@ -313,7 +211,7 @@ NXTARG: ; exit (EXIT_FAILURE); } - if ((unsigned)sbuf.st_size < sizeof(image_header_t)) { + if ((unsigned)sbuf.st_size < image_get_header_size ()) { fprintf (stderr, "%s: Bad size: \"%s\" is no valid image\n", cmdname, imagefile); @@ -328,50 +226,24 @@ NXTARG: ; exit (EXIT_FAILURE); } - /* - * create copy of header so that we can blank out the - * checksum field for checking - this can't be done - * on the PROT_READ mapped data. - */ - memcpy (hdr, ptr, sizeof(image_header_t)); - - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - fprintf (stderr, - "%s: Bad Magic Number: \"%s\" is no valid image\n", - cmdname, imagefile); - exit (EXIT_FAILURE); - } - - data = (char *)hdr; - len = sizeof(image_header_t); - - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = htonl(0); /* clear for re-calculation */ - - if (crc32 (0, data, len) != checksum) { - fprintf (stderr, - "%s: ERROR: \"%s\" has bad header checksum!\n", - cmdname, imagefile); - exit (EXIT_FAILURE); + if (fdt_check_header (ptr)) { + /* old-style image */ + image_verify_header ((char *)ptr, sbuf.st_size); + image_print_contents_noindent ((image_header_t *)ptr); + } else { + /* FIT image */ + fit_print_contents_noindent (ptr); } - data = (char *)(ptr + sizeof(image_header_t)); - len = sbuf.st_size - sizeof(image_header_t) ; - - if (crc32 (0, data, len) != ntohl(hdr->ih_dcrc)) { - fprintf (stderr, - "%s: ERROR: \"%s\" has corrupted data!\n", - cmdname, imagefile); - exit (EXIT_FAILURE); - } - - /* for multi-file images we need the data part, too */ - print_header ((image_header_t *)ptr); - (void) munmap((void *)ptr, sbuf.st_size); (void) close (ifd); exit (EXIT_SUCCESS); + } else if (fflag) { + /* Flattened Image Tree (FIT) format handling */ + debug ("FIT format handling\n"); + fit_handle_file (); + exit (EXIT_SUCCESS); } /* @@ -379,9 +251,9 @@ NXTARG: ; * * write dummy header, to be fixed later */ - memset (hdr, 0, sizeof(image_header_t)); + memset (hdr, 0, image_get_header_size ()); - if (write(ifd, hdr, sizeof(image_header_t)) != sizeof(image_header_t)) { + if (write(ifd, hdr, image_get_header_size ()) != image_get_header_size ()) { fprintf (stderr, "%s: Write error on %s: %s\n", cmdname, imagefile, strerror(errno)); exit (EXIT_FAILURE); @@ -404,7 +276,7 @@ NXTARG: ; cmdname, file, strerror(errno)); exit (EXIT_FAILURE); } - size = htonl(sbuf.st_size); + size = cpu_to_uimage (sbuf.st_size); } else { size = 0; } @@ -469,29 +341,29 @@ NXTARG: ; hdr = (image_header_t *)ptr; checksum = crc32 (0, - (const char *)(ptr + sizeof(image_header_t)), - sbuf.st_size - sizeof(image_header_t) + (const char *)(ptr + image_get_header_size ()), + sbuf.st_size - image_get_header_size () ); /* Build new header */ - hdr->ih_magic = htonl(IH_MAGIC); - hdr->ih_time = htonl(sbuf.st_mtime); - hdr->ih_size = htonl(sbuf.st_size - sizeof(image_header_t)); - hdr->ih_load = htonl(addr); - hdr->ih_ep = htonl(ep); - hdr->ih_dcrc = htonl(checksum); - hdr->ih_os = opt_os; - hdr->ih_arch = opt_arch; - hdr->ih_type = opt_type; - hdr->ih_comp = opt_comp; + image_set_magic (hdr, IH_MAGIC); + image_set_time (hdr, sbuf.st_mtime); + image_set_size (hdr, sbuf.st_size - image_get_header_size ()); + image_set_load (hdr, addr); + image_set_ep (hdr, ep); + image_set_dcrc (hdr, checksum); + image_set_os (hdr, opt_os); + image_set_arch (hdr, opt_arch); + image_set_type (hdr, opt_type); + image_set_comp (hdr, opt_comp); - strncpy((char *)hdr->ih_name, name, IH_NMLEN); + image_set_name (hdr, name); - checksum = crc32(0,(const char *)hdr,sizeof(image_header_t)); + checksum = crc32 (0, (const char *)hdr, image_get_header_size ()); - hdr->ih_hcrc = htonl(checksum); + image_set_hcrc (hdr, checksum); - print_header (hdr); + image_print_contents_noindent (hdr); (void) munmap((void *)ptr, sbuf.st_size); @@ -554,14 +426,14 @@ copy_file (int ifd, const char *datafile, int pad) * reserved for it. */ - if ((unsigned)sbuf.st_size < sizeof(image_header_t)) { + if ((unsigned)sbuf.st_size < image_get_header_size ()) { fprintf (stderr, "%s: Bad size: \"%s\" is too small for XIP\n", cmdname, datafile); exit (EXIT_FAILURE); } - for (p=ptr; p < ptr+sizeof(image_header_t); p++) { + for (p = ptr; p < ptr + image_get_header_size (); p++) { if ( *p != 0xff ) { fprintf (stderr, "%s: Bad file: \"%s\" has invalid buffer for XIP\n", @@ -570,7 +442,7 @@ copy_file (int ifd, const char *datafile, int pad) } } - offset = sizeof(image_header_t); + offset = image_get_header_size (); } size = sbuf.st_size - offset; @@ -597,11 +469,11 @@ void usage () { fprintf (stderr, "Usage: %s -l image\n" - " -l ==> list image header information\n" - " %s [-x] -A arch -O os -T type -C comp " - "-a addr -e ep -n name -d data_file[:data_file...] image\n", - cmdname, cmdname); - fprintf (stderr, " -A ==> set architecture to 'arch'\n" + " -l ==> list image header information\n", + cmdname); + fprintf (stderr, " %s [-x] -A arch -O os -T type -C comp " + "-a addr -e ep -n name -d data_file[:data_file...] image\n" + " -A ==> set architecture to 'arch'\n" " -O ==> set operating system to 'os'\n" " -T ==> set image type to 'type'\n" " -C ==> set compression type 'comp'\n" @@ -609,143 +481,158 @@ usage () " -e ==> set entry point to 'ep' (hex)\n" " -n ==> set image name to 'name'\n" " -d ==> use image data from 'datafile'\n" - " -x ==> set XIP (execute in place)\n" - ); + " -x ==> set XIP (execute in place)\n", + cmdname); + fprintf (stderr, " %s [-D dtc_options] -f fit-image.its fit-image\n", + cmdname); + exit (EXIT_FAILURE); } static void -print_header (image_header_t *hdr) +image_verify_header (char *ptr, int image_size) { - time_t timestamp; - uint32_t size; - - timestamp = (time_t)ntohl(hdr->ih_time); - size = ntohl(hdr->ih_size); - - printf ("Image Name: %.*s\n", IH_NMLEN, hdr->ih_name); - printf ("Created: %s", ctime(×tamp)); - printf ("Image Type: "); print_type(hdr); - printf ("Data Size: %d Bytes = %.2f kB = %.2f MB\n", - size, (double)size / 1.024e3, (double)size / 1.048576e6 ); - printf ("Load Address: 0x%08X\n", ntohl(hdr->ih_load)); - printf ("Entry Point: 0x%08X\n", ntohl(hdr->ih_ep)); - - if (hdr->ih_type == IH_TYPE_MULTI || hdr->ih_type == IH_TYPE_SCRIPT) { - int i, ptrs; - uint32_t pos; - uint32_t *len_ptr = (uint32_t *) ( - (unsigned long)hdr + sizeof(image_header_t) - ); - - /* determine number of images first (to calculate image offsets) */ - for (i=0; len_ptr[i]; ++i) /* null pointer terminates list */ - ; - ptrs = i; /* null pointer terminates list */ - - pos = sizeof(image_header_t) + ptrs * sizeof(long); - printf ("Contents:\n"); - for (i=0; len_ptr[i]; ++i) { - size = ntohl(len_ptr[i]); - - printf (" Image %d: %8d Bytes = %4d kB = %d MB\n", - i, size, size>>10, size>>20); - if (hdr->ih_type == IH_TYPE_SCRIPT && i > 0) { - /* - * the user may need to know offsets - * if planning to do something with - * multiple files - */ - printf (" Offset = %08X\n", pos); - } - /* copy_file() will pad the first files to even word align */ - size += 3; - size &= ~3; - pos += size; - } - } -} + int len; + char *data; + uint32_t checksum; + image_header_t header; + image_header_t *hdr = &header; + /* + * create copy of header so that we can blank out the + * checksum field for checking - this can't be done + * on the PROT_READ mapped data. + */ + memcpy (hdr, ptr, sizeof(image_header_t)); -static void -print_type (image_header_t *hdr) -{ - printf ("%s %s %s (%s)\n", - put_arch (hdr->ih_arch), - put_os (hdr->ih_os ), - put_type (hdr->ih_type), - put_comp (hdr->ih_comp) - ); -} + if (ntohl(hdr->ih_magic) != IH_MAGIC) { + fprintf (stderr, + "%s: Bad Magic Number: \"%s\" is no valid image\n", + cmdname, imagefile); + exit (EXIT_FAILURE); + } -static char *put_arch (int arch) -{ - return (put_table_entry(arch_name, "Unknown Architecture", arch)); -} + data = (char *)hdr; + len = sizeof(image_header_t); -static char *put_os (int os) -{ - return (put_table_entry(os_name, "Unknown OS", os)); -} + checksum = ntohl(hdr->ih_hcrc); + hdr->ih_hcrc = htonl(0); /* clear for re-calculation */ -static char *put_type (int type) -{ - return (put_table_entry(type_name, "Unknown Image", type)); -} + if (crc32 (0, data, len) != checksum) { + fprintf (stderr, + "%s: ERROR: \"%s\" has bad header checksum!\n", + cmdname, imagefile); + exit (EXIT_FAILURE); + } -static char *put_comp (int comp) -{ - return (put_table_entry(comp_name, "Unknown Compression", comp)); -} + data = ptr + sizeof(image_header_t); + len = image_size - sizeof(image_header_t) ; -static char *put_table_entry (table_entry_t *table, char *msg, int type) -{ - for (; table->val>=0; ++table) { - if (table->val == type) - return (table->lname); + if (crc32 (0, data, len) != ntohl(hdr->ih_dcrc)) { + fprintf (stderr, + "%s: ERROR: \"%s\" has corrupted data!\n", + cmdname, imagefile); + exit (EXIT_FAILURE); } - return (msg); } -static int get_arch(char *name) +/** + * fit_handle_file - main FIT file processing function + * + * fit_handle_file() runs dtc to convert .its to .itb, includes + * binary data, updates timestamp property and calculates hashes. + * + * datafile - .its file + * imagefile - .itb file + * + * returns: + * only on success, otherwise calls exit (EXIT_FAILURE); + */ +static void fit_handle_file (void) { - return (get_table_entry(arch_name, "CPU", name)); -} + char tmpfile[MKIMAGE_MAX_TMPFILE_LEN]; + char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN]; + int tfd; + struct stat sbuf; + unsigned char *ptr; + /* call dtc to include binary properties into the tmp file */ + if (strlen (imagefile) + strlen (MKIMAGE_TMPFILE_SUFFIX) + 1 > + sizeof (tmpfile)) { + fprintf (stderr, "%s: Image file name (%s) too long, " + "can't create tmpfile", + imagefile, cmdname); + exit (EXIT_FAILURE); + } + sprintf (tmpfile, "%s%s", imagefile, MKIMAGE_TMPFILE_SUFFIX); + + /* dtc -I dts -O -p 200 datafile > tmpfile */ + sprintf (cmd, "%s %s %s > %s", + MKIMAGE_DTC, opt_dtc, datafile, tmpfile); + debug ("Trying to execute \"%s\"\n", cmd); + if (system (cmd) == -1) { + fprintf (stderr, "%s: system(%s) failed: %s\n", + cmdname, cmd, strerror(errno)); + unlink (tmpfile); + exit (EXIT_FAILURE); + } -static int get_comp(char *name) -{ - return (get_table_entry(comp_name, "Compression", name)); -} + /* load FIT blob into memory */ + tfd = open (tmpfile, O_RDWR|O_BINARY); + if (tfd < 0) { + fprintf (stderr, "%s: Can't open %s: %s\n", + cmdname, tmpfile, strerror(errno)); + unlink (tmpfile); + exit (EXIT_FAILURE); + } -static int get_os (char *name) -{ - return (get_table_entry(os_name, "OS", name)); -} + if (fstat (tfd, &sbuf) < 0) { + fprintf (stderr, "%s: Can't stat %s: %s\n", + cmdname, tmpfile, strerror(errno)); + unlink (tmpfile); + exit (EXIT_FAILURE); + } + ptr = (unsigned char *)mmap (0, sbuf.st_size, + PROT_READ|PROT_WRITE, MAP_SHARED, tfd, 0); + if ((caddr_t)ptr == (caddr_t)-1) { + fprintf (stderr, "%s: Can't read %s: %s\n", + cmdname, tmpfile, strerror(errno)); + unlink (tmpfile); + exit (EXIT_FAILURE); + } -static int get_type(char *name) -{ - return (get_table_entry(type_name, "Image", name)); -} + /* check if ptr has a valid blob */ + if (fdt_check_header (ptr)) { + fprintf (stderr, "%s: Invalid FIT blob\n", cmdname); + unlink (tmpfile); + exit (EXIT_FAILURE); + } -static int get_table_entry (table_entry_t *table, char *msg, char *name) -{ - table_entry_t *t; - int first = 1; + /* set hashes for images in the blob */ + if (fit_set_hashes (ptr)) { + fprintf (stderr, "%s Can't add hashes to FIT blob", cmdname); + unlink (tmpfile); + exit (EXIT_FAILURE); + } - for (t=table; t->val>=0; ++t) { - if (t->sname && strcasecmp(t->sname, name)==0) - return (t->val); + /* add a timestamp at offset 0 i.e., root */ + if (fit_set_timestamp (ptr, 0, sbuf.st_mtime)) { + fprintf (stderr, "%s: Can't add image timestamp\n", cmdname); + unlink (tmpfile); + exit (EXIT_FAILURE); } - fprintf (stderr, "\nInvalid %s Type - valid names are", msg); - for (t=table; t->val>=0; ++t) { - if (t->sname == NULL) - continue; - fprintf (stderr, "%c %s", (first) ? ':' : ',', t->sname); - first = 0; + debug ("Added timestamp successfully\n"); + + munmap ((void *)ptr, sbuf.st_size); + close (tfd); + + if (rename (tmpfile, imagefile) == -1) { + fprintf (stderr, "%s: Can't rename %s to %s: %s\n", + cmdname, tmpfile, imagefile, strerror (errno)); + unlink (tmpfile); + unlink (imagefile); + exit (EXIT_FAILURE); } - fprintf (stderr, "\n"); - return (-1); } diff --git a/tools/mkimage.h b/tools/mkimage.h new file mode 100644 index 0000000000..a2d5248943 --- /dev/null +++ b/tools/mkimage.h @@ -0,0 +1,75 @@ +/* + * (C) Copyright 2000-2004 + * DENX Software Engineering + * Wolfgang Denk, wd@denx.de + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifndef __WIN32__ +#include <netinet/in.h> /* for host / network byte order conversions */ +#endif +#include <sys/mman.h> +#include <sys/stat.h> +#include <time.h> +#include <unistd.h> +#include <sha1.h> +#include "fdt_host.h" + +#define MKIMAGE_DEBUG + +#ifdef MKIMAGE_DEBUG +#define debug(fmt,args...) printf (fmt ,##args) +#else +#define debug(fmt,args...) +#endif /* MKIMAGE_DEBUG */ + +#define MKIMAGE_TMPFILE_SUFFIX ".tmp" +#define MKIMAGE_MAX_TMPFILE_LEN 256 +#define MKIMAGE_DEFAULT_DTC_OPTIONS "-I dts -O dtb -p 500" +#define MKIMAGE_MAX_DTC_CMDLINE_LEN 512 +#define MKIMAGE_DTC "dtc" /* assume dtc is in $PATH */ + +#if defined(__BEOS__) || defined(__NetBSD__) || defined(__APPLE__) +#include <inttypes.h> +#endif + +#ifdef __WIN32__ +typedef unsigned int __u32; + +#define SWAP_LONG(x) \ + ((__u32)( \ + (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ + (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ + (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ + (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + +#define ntohl(a) SWAP_LONG(a) +#define htonl(a) SWAP_LONG(a) +#endif /* __WIN32__ */ + +#ifndef O_BINARY /* should be define'd on __WIN32__ */ +#define O_BINARY 0 +#endif |