X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=common%2Fimage.c;h=3a2f25e5af4de7f64e9e3e31bc61ef456e9e97c3;hb=458379d674f256d32132e29c20a223a3c39b9e34;hp=c3545a7c766f5cdc2d7025c5eb2858e3ea64ea1b;hpb=cd5b7d4a1e651e9197a5ac9e9e957d70b126d16d;p=u-boot diff --git a/common/image.c b/common/image.c index c3545a7c76..3a2f25e5af 100644 --- a/common/image.c +++ b/common/image.c @@ -60,12 +60,12 @@ static int fit_check_ramdisk (const void *fit, int os_noffset, #endif #ifdef CONFIG_CMD_BDI -extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); #endif DECLARE_GLOBAL_DATA_PTR; -static image_header_t* image_get_ramdisk (ulong rd_addr, uint8_t arch, +static const image_header_t* image_get_ramdisk (ulong rd_addr, uint8_t arch, int verify); #else #include "mkimage.h" @@ -74,12 +74,6 @@ static image_header_t* image_get_ramdisk (ulong rd_addr, uint8_t arch, #include #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", }, @@ -90,7 +84,6 @@ static table_entry_t uimage_arch[] = { { 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, "powerpc", "PowerPC", }, { IH_ARCH_PPC, "ppc", "PowerPC", }, @@ -105,20 +98,21 @@ static table_entry_t uimage_arch[] = { 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_OSE, "ose", "Enea OSE", }, { 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 +#if defined(CONFIG_INTEGRITY) || defined(USE_HOSTCC) + { IH_OS_INTEGRITY,"integrity", "INTEGRITY", }, +#endif #ifdef USE_HOSTCC { IH_OS_4_4BSD, "4_4bsd", "4_4BSD", }, { IH_OS_DELL, "dell", "Dell", }, @@ -145,6 +139,8 @@ static table_entry_t uimage_type[] = { { IH_TYPE_SCRIPT, "script", "Script", }, { IH_TYPE_STANDALONE, "standalone", "Standalone Program", }, { IH_TYPE_FLATDT, "flat_dt", "Flat Device Tree", }, + { IH_TYPE_KWBIMAGE, "kwbimage", "Kirkwood Boot Image",}, + { IH_TYPE_IMXIMAGE, "imximage", "Freescale i.MX Boot Image",}, { -1, "", "", }, }; @@ -152,12 +148,13 @@ static table_entry_t uimage_comp[] = { { IH_COMP_NONE, "none", "uncompressed", }, { IH_COMP_BZIP2, "bzip2", "bzip2 compressed", }, { IH_COMP_GZIP, "gzip", "gzip compressed", }, + { IH_COMP_LZMA, "lzma", "lzma compressed", }, + { IH_COMP_LZO, "lzo", "lzo compressed", }, { -1, "", "", }, }; uint32_t crc32 (uint32_t, const unsigned char *, uint); uint32_t crc32_wd (uint32_t, const unsigned char *, uint, uint); -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 @@ -165,7 +162,7 @@ static void genimg_print_time (time_t timestamp); /*****************************************************************************/ /* Legacy format routines */ /*****************************************************************************/ -int image_check_hcrc (image_header_t *hdr) +int image_check_hcrc (const image_header_t *hdr) { ulong hcrc; ulong len = image_get_header_size (); @@ -180,7 +177,7 @@ int image_check_hcrc (image_header_t *hdr) return (hcrc == image_get_hcrc (hdr)); } -int image_check_dcrc (image_header_t *hdr) +int image_check_dcrc (const image_header_t *hdr) { ulong data = image_get_data (hdr); ulong len = image_get_data_size (hdr); @@ -189,7 +186,6 @@ int image_check_dcrc (image_header_t *hdr) return (dcrc == image_get_dcrc (hdr)); } - /** * image_multi_count - get component (sub-image) count * @hdr: pointer to the header of the multi component image @@ -203,7 +199,7 @@ int image_check_dcrc (image_header_t *hdr) * returns: * number of components */ -ulong image_multi_count (image_header_t *hdr) +ulong image_multi_count (const image_header_t *hdr) { ulong i, count = 0; uint32_t *size; @@ -236,7 +232,7 @@ ulong image_multi_count (image_header_t *hdr) * 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, +void image_multi_getimg (const image_header_t *hdr, ulong idx, ulong *data, ulong *len) { int i; @@ -272,7 +268,7 @@ void image_multi_getimg (image_header_t *hdr, ulong idx, } } -static void image_print_type (image_header_t *hdr) +static void image_print_type (const image_header_t *hdr) { const char *os, *arch, *type, *comp; @@ -286,7 +282,7 @@ static void image_print_type (image_header_t *hdr) /** * image_print_contents - prints out the contents of the legacy format image - * @hdr: pointer to the legacy format image header + * @ptr: pointer to the legacy format image header * @p: pointer to prefix string * * image_print_contents() formats a multi line legacy image contents description. @@ -296,8 +292,9 @@ static void image_print_type (image_header_t *hdr) * returns: * no returned results */ -void image_print_contents (image_header_t *hdr) +void image_print_contents (const void *ptr) { + const image_header_t *hdr = (const image_header_t *)ptr; const char *p; #ifdef USE_HOSTCC @@ -363,10 +360,10 @@ void image_print_contents (image_header_t *hdr) * 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, +static const image_header_t *image_get_ramdisk (ulong rd_addr, uint8_t arch, int verify) { - image_header_t *rd_hdr = (image_header_t *)rd_addr; + const image_header_t *rd_hdr = (const image_header_t *)rd_addr; if (!image_check_magic (rd_hdr)) { puts ("Bad Magic Number\n"); @@ -426,8 +423,8 @@ ulong getenv_bootm_low(void) return tmp; } -#if defined(CFG_SDRAM_BASE) - return CFG_SDRAM_BASE; +#if defined(CONFIG_SYS_SDRAM_BASE) + return CONFIG_SYS_SDRAM_BASE; #elif defined(CONFIG_ARM) return gd->bd->bi_dram[0].start; #else @@ -437,26 +434,31 @@ ulong getenv_bootm_low(void) phys_size_t getenv_bootm_size(void) { + phys_size_t tmp; char *s = getenv ("bootm_size"); if (s) { - phys_size_t tmp; -#ifdef CFG_64BIT_STRTOUL tmp = (phys_size_t)simple_strtoull (s, NULL, 16); -#else - tmp = (phys_size_t)simple_strtoul (s, NULL, 16); -#endif return tmp; } + s = getenv("bootm_low"); + if (s) + tmp = (phys_size_t)simple_strtoull (s, NULL, 16); + else + tmp = 0; + #if defined(CONFIG_ARM) - return gd->bd->bi_dram[0].size; + return gd->bd->bi_dram[0].size - tmp; #else - return gd->bd->bi_memsize; + return gd->bd->bi_memsize - tmp; #endif } void memmove_wd (void *to, void *from, size_t len, ulong chunksz) { + if (to == from) + return; + #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) while (len > 0) { size_t tail = (len > chunksz) ? chunksz : len; @@ -472,7 +474,7 @@ void memmove_wd (void *to, void *from, size_t len, ulong chunksz) } #endif /* !USE_HOSTCC */ -static void genimg_print_size (uint32_t size) +void genimg_print_size (uint32_t size) { #ifndef USE_HOSTCC printf ("%d Bytes = ", size); @@ -514,11 +516,15 @@ static void genimg_print_time (time_t timestamp) * long entry name if translation succeeds * msg otherwise */ -static char *get_table_entry_name (table_entry_t *table, char *msg, int id) +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); +#if defined(USE_HOSTCC) || defined(CONFIG_RELOC_FIXUP_WORKS) + return table->lname; +#else + return table->lname + gd->reloc_off; +#endif } return (msg); } @@ -557,7 +563,7 @@ const char *genimg_get_comp_name (uint8_t comp) * entry id if translation succeeds * -1 otherwise */ -static int get_table_entry_id (table_entry_t *table, +int get_table_entry_id (table_entry_t *table, const char *table_name, const char *name) { table_entry_t *t; @@ -579,7 +585,11 @@ static int get_table_entry_id (table_entry_t *table, fprintf (stderr, "\n"); #else for (t = table; t->id >= 0; ++t) { +#ifdef CONFIG_RELOC_FIXUP_WORKS if (t->sname && strcmp(t->sname, name) == 0) +#else + if (t->sname && strcmp(t->sname + gd->reloc_off, name) == 0) +#endif return (t->id); } debug ("Invalid %s Type: %s\n", table_name, name); @@ -624,13 +634,13 @@ int genimg_get_comp_id (const char *name) */ int genimg_get_format (void *img_addr) { - ulong format = IMAGE_FORMAT_INVALID; - image_header_t *hdr; + ulong format = IMAGE_FORMAT_INVALID; + const image_header_t *hdr; #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) - char *fit_hdr; + char *fit_hdr; #endif - hdr = (image_header_t *)img_addr; + hdr = (const image_header_t *)img_addr; if (image_check_magic(hdr)) format = IMAGE_FORMAT_LEGACY; #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) @@ -663,7 +673,7 @@ ulong genimg_get_image (ulong img_addr) if (addr_dataflash (img_addr)){ /* ger RAM address */ - ram_addr = CFG_LOAD_ADDR; + ram_addr = CONFIG_SYS_LOAD_ADDR; /* get header size */ h_size = image_get_header_size (); @@ -681,7 +691,7 @@ ulong genimg_get_image (ulong img_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); + d_size = image_get_data_size ((const image_header_t *)ram_addr); debug (" Legacy format image found at 0x%08lx, size 0x%08lx\n", ram_addr, d_size); break; @@ -750,15 +760,15 @@ int genimg_has_config (bootm_headers_t *images) * 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 + * 1, if ramdisk image is found but corrupted, or invalid * 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, +int boot_get_ramdisk (int argc, char * const 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; + const image_header_t *rd_hdr; #if defined(CONFIG_FIT) void *fit_hdr; const char *fit_uname_config = NULL; @@ -937,6 +947,7 @@ int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images, default: puts ("Wrong Ramdisk Image Format\n"); rd_data = rd_len = rd_load = 0; + return 1; } #if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO) @@ -1070,7 +1081,514 @@ int boot_ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len, error: return -1; } +#endif /* defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC) */ + +#ifdef CONFIG_OF_LIBFDT +static void fdt_error (const char *msg) +{ + puts ("ERROR: "); + puts (msg); + puts (" - must RESET the board to recover.\n"); +} + +static const image_header_t *image_get_fdt (ulong fdt_addr) +{ + const image_header_t *fdt_hdr = (const 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 */ + +#ifndef CONFIG_SYS_FDT_PAD +#define CONFIG_SYS_FDT_PAD 0x3000 +#endif + +/** + * boot_relocate_fdt - relocate flat device tree + * @lmb: pointer to lmb handle, will be used for memory mgmt + * @bootmap_base: base address of the bootmap region + * @of_flat_tree: pointer to a char* variable, will hold fdt start address + * @of_size: pointer to a ulong variable, will hold fdt length + * + * boot_relocate_fdt() determines if the of_flat_tree address is within + * the bootmap and if not relocates it into that region + * + * of_flat_tree and of_size are set to final (after relocation) values + * + * returns: + * 0 - success + * 1 - failure + */ +#if defined(CONFIG_SYS_BOOTMAPSZ) +int boot_relocate_fdt (struct lmb *lmb, ulong bootmap_base, + 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 CONFIG_SYS_NO_FLASH + /* move the blob if it is in flash (set relocate) */ + if (addr2info ((ulong)fdt_blob) != NULL) + relocate = 1; +#endif + + /* + * The blob needs to be inside the boot mapping. + */ + if (fdt_blob < (char *)bootmap_base) + relocate = 1; + + if ((fdt_blob + *of_size + CONFIG_SYS_FDT_PAD) >= + ((char *)CONFIG_SYS_BOOTMAPSZ + bootmap_base)) + relocate = 1; + + /* move flattend device tree if needed */ + if (relocate) { + int err; + ulong of_start = 0; + + /* position on a 4K boundary before the alloc_current */ + /* Pad the FDT by a specified amount */ + of_len = *of_size + CONFIG_SYS_FDT_PAD; + of_start = (unsigned long)lmb_alloc_base(lmb, of_len, 0x1000, + (CONFIG_SYS_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_size - 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; + *of_size = of_len; + } else { + *of_flat_tree = fdt_blob; + of_len = (CONFIG_SYS_BOOTMAPSZ + bootmap_base) - (ulong)fdt_blob; + lmb_reserve(lmb, (ulong)fdt_blob, of_len); + fdt_set_totalsize(*of_flat_tree, of_len); + + *of_size = of_len; + } + + set_working_fdt_addr(*of_flat_tree); + return 0; + +error: + return 1; +} +#endif /* CONFIG_SYS_BOOTMAPSZ */ + +/** + * boot_get_fdt - main fdt handling routine + * @argc: command argument count + * @argv: command argument list + * @images: pointer to the bootm images structure + * @of_flat_tree: pointer to a char* variable, will hold fdt start address + * @of_size: pointer to a ulong variable, will hold fdt length + * + * boot_get_fdt() is responsible for finding a valid flat device tree image. + * Curently supported are the following ramdisk sources: + * - multicomponent kernel/ramdisk image, + * - commandline provided address of decicated ramdisk image. + * + * returns: + * 0, if fdt image was found and valid, or skipped + * of_flat_tree and of_size are set to fdt start address and length if + * fdt image is found and valid + * + * 1, if fdt image is found but corrupted + * of_flat_tree and of_size are set to 0 if no fdt exists + */ +int boot_get_fdt (int flag, int argc, char * const argv[], bootm_headers_t *images, + char **of_flat_tree, ulong *of_size) +{ + const image_header_t *fdt_hdr; + ulong fdt_addr; + 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 + */ + fdt_blob = (char *)fdt_addr; + debug ("* fdt: raw FDT blob\n"); + printf ("## Flattened Device Tree blob at %08lx\n", (long)fdt_blob); + } + break; + default: + puts ("ERROR: Did not find a cmdline Flattened Device Tree\n"); + goto error; + } + + printf (" Booting using the fdt blob at 0x%x\n", (int)fdt_blob); + + } else if (images->legacy_hdr_valid && + image_check_type (&images->legacy_hdr_os_copy, 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", (int)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 { + debug ("## No Flattened Device Tree\n"); + return 0; + } + } 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", + (ulong)*of_flat_tree, *of_size); + + return 0; + +error: + *of_flat_tree = 0; + *of_size = 0; + return 1; +} +#endif /* CONFIG_OF_LIBFDT */ +#if defined(CONFIG_PPC) || defined(CONFIG_M68K) /** * boot_get_cmdline - allocate and initialize kernel cmdline * @lmb: pointer to lmb handle, will be used for memory mgmt @@ -1094,8 +1612,8 @@ int boot_get_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, char *cmdline; char *s; - cmdline = (char *)(ulong)lmb_alloc_base(lmb, CFG_BARGSIZE, 0xf, - CFG_BOOTMAPSZ + bootmap_base); + cmdline = (char *)(ulong)lmb_alloc_base(lmb, CONFIG_SYS_BARGSIZE, 0xf, + CONFIG_SYS_BOOTMAPSZ + bootmap_base); if (cmdline == NULL) return -1; @@ -1131,7 +1649,7 @@ int boot_get_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, int boot_get_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base) { *kbd = (bd_t *)(ulong)lmb_alloc_base(lmb, sizeof(bd_t), 0xf, - CFG_BOOTMAPSZ + bootmap_base); + CONFIG_SYS_BOOTMAPSZ + bootmap_base); if (*kbd == NULL) return -1; @@ -1348,7 +1866,10 @@ void fit_print_contents (const void *fit) * @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. + * image. If present, hash nodes are printed out as well. Load + * address for images of type firmware is also printed out. Since the load + * address is not mandatory for firmware images, it will be output as + * "unavailable" when not present. * * returns: * no returned results @@ -1407,14 +1928,17 @@ void fit_image_print (const void *fit, int image_noffset, const char *p) printf ("%s OS: %s\n", p, genimg_get_os_name (os)); } - if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE)) { + if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || + (type == IH_TYPE_FIRMWARE)) { 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); + } + if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE)) { fit_image_get_entry (fit, image_noffset, &entry); printf ("%s Entry Point: ", p); if (ret) @@ -2142,27 +2666,29 @@ int fit_image_check_hashes (const void *fit, int image_noffset) continue; if (fit_image_hash_get_algo (fit, noffset, &algo)) { - err_msg = "Can't get hash algo property"; + err_msg = " error!\nCan'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"; + err_msg = " error!\nCan't get hash value " + "property"; goto error; } if (calculate_hash (data, size, algo, value, &value_len)) { - err_msg = "Unsupported hash algorithm"; + err_msg = " error!\nUnsupported hash algorithm"; goto error; } if (value_len != fit_value_len) { - err_msg = "Bad hash value len"; + err_msg = " error !\nBad hash value len"; goto error; } else if (memcmp (value, fit_value, value_len) != 0) { - err_msg = "Bad hash value"; + err_msg = " error!\nBad hash value"; goto error; } printf ("+ "); @@ -2178,6 +2704,55 @@ error: return 0; } +/** + * fit_all_image_check_hashes - verify data intergity for all images + * @fit: pointer to the FIT format image header + * + * fit_all_image_check_hashes() goes over all images in the FIT and + * for every images checks if all it's hashes are valid. + * + * returns: + * 1, if all hashes of all images are valid + * 0, otherwise (or on error) + */ +int fit_all_image_check_hashes (const void *fit) +{ + int images_noffset; + int noffset; + int ndepth; + int count; + + /* 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 0; + } + + /* Process all image subnodes, check hashes for each */ + printf ("## Checking hash(es) for FIT Image at %08lx ...\n", + (ulong)fit); + 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 (" Hash(es) for Image %u (%s): ", count++, + fit_get_name (fit, noffset, NULL)); + + if (!fit_image_check_hashes (fit, noffset)) + return 0; + printf ("\n"); + } + } + return 1; +} + /** * fit_image_check_os - check whether image node is of a given os type * @fit: pointer to the FIT format image header @@ -2289,7 +2864,7 @@ int fit_check_format (const void *fit) #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"); + debug ("Wrong FIT format: no timestamp\n"); return 0; } #endif