From 06a09918f3903450313e2047a9cc258bf5872f46 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 15 Aug 2008 08:24:38 -0500 Subject: bootm: refactor fdt locating and relocation code Move the code that handles finding a device tree blob and relocating it (if needed) into common code so all arch's have access to it. Signed-off-by: Kumar Gala --- common/cmd_bootm.c | 10 ++ common/image.c | 502 +++++++++++++++++++++++++++++++++++++++++++++++++++++ include/image.h | 13 ++ lib_ppc/bootm.c | 492 +-------------------------------------------------- 4 files changed, 533 insertions(+), 484 deletions(-) diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 56236b9..9a745f1 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -258,6 +258,16 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) puts ("Ramdisk image is corrupt\n"); return 1; } + +#if defined(CONFIG_OF_LIBFDT) + /* find flattened device tree */ + ret = boot_get_fdt (flag, argc, argv, &images, + &images.ft_addr, &images.ft_len); + if (ret) { + puts ("Could not find a valid device tree\n"); + return 1; + } +#endif } image_start = (ulong)os_hdr; diff --git a/common/image.c b/common/image.c index 6d2ce32..18d667d 100644 --- a/common/image.c +++ b/common/image.c @@ -1070,6 +1070,508 @@ error: return -1; } +#ifdef 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 */ + +#ifndef CFG_FDT_PAD +#define CFG_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 + */ +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 CFG_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 + CFG_FDT_PAD) >= + ((char *)CFG_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 + CFG_FDT_PAD; + of_start = (unsigned long)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_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 = (CFG_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; + } + + return 0; + +error: + return 1; +} + +/** + * 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 *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 + */ + fdt_blob = (char *)fdt_addr; + debug ("* fdt: raw FDT blob\n"); + printf ("## Flattened Device Tree blob at %08lx\n", (long)fdt_blob); + } + break; + default: + fdt_error ("Did not find a cmdline Flattened Device Tree"); + 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", + *of_flat_tree, *of_size); + + return 0; + +error: + *of_flat_tree = 0; + *of_size = 0; + return 1; +} +#endif /* CONFIG_OF_LIBFDT */ + /** * boot_get_cmdline - allocate and initialize kernel cmdline * @lmb: pointer to lmb handle, will be used for memory mgmt diff --git a/include/image.h b/include/image.h index b8577a0..653cbc6 100644 --- a/include/image.h +++ b/include/image.h @@ -223,6 +223,11 @@ typedef struct bootm_headers { ulong rd_start, rd_end;/* ramdisk start/end */ +#ifdef CONFIG_OF_LIBFDT + char *ft_addr; /* flat dev tree address */ +#endif + ulong ft_len; /* length of flat device tree */ + int verify; /* getenv("verify")[0] != 'n' */ struct lmb *lmb; /* for memory mgmt */ } bootm_headers_t; @@ -273,6 +278,14 @@ 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); + +#ifdef CONFIG_OF_LIBFDT +int boot_get_fdt (int flag, int argc, char *argv[], bootm_headers_t *images, + char **of_flat_tree, ulong *of_size); +int boot_relocate_fdt (struct lmb *lmb, ulong bootmap_base, + char **of_flat_tree, ulong *of_size); +#endif + #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); diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c index e6a6e44..a3e632f 100644 --- a/lib_ppc/bootm.c +++ b/lib_ppc/bootm.c @@ -39,22 +39,12 @@ #include #include -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 #endif -#ifndef CFG_FDT_PAD -#define CFG_FDT_PAD 0x3000 -#endif - DECLARE_GLOBAL_DATA_PTR; extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); @@ -82,11 +72,11 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], void (*kernel)(bd_t *, ulong r4, ulong r5, ulong r6, ulong r7, ulong r8, ulong r9); int ret; - ulong of_size = 0; + ulong of_size = images->ft_len; struct lmb *lmb = images->lmb; #if defined(CONFIG_OF_LIBFDT) - char *of_flat_tree = NULL; + char *of_flat_tree = images->ft_addr; #endif kernel = (void (*)(bd_t *, ulong, ulong, ulong, @@ -128,14 +118,6 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], 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); @@ -156,8 +138,9 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], rd_len = images->rd_end - images->rd_start; #if defined(CONFIG_OF_LIBFDT) - ret = boot_relocate_fdt (lmb, bootmap_base, - cmdtp, flag, argc, argv, &of_flat_tree, &of_size); + ret = boot_relocate_fdt(lmb, bootmap_base, &of_flat_tree, &of_size); + if (ret) + goto error; /* * Add the chosen node if it doesn't exist, add the env and bd_t @@ -166,7 +149,9 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], if (of_size) { /* pass in dummy initrd info, we'll fix up later */ if (fdt_chosen(of_flat_tree, images->rd_start, images->rd_end, 0) < 0) { - fdt_error ("/chosen node create failed"); + puts ("ERROR: "); + puts ("/chosen node create failed"); + puts (" - must RESET the board to recover.\n"); goto error; } #ifdef CONFIG_OF_BOARD_SETUP @@ -339,464 +324,3 @@ static void set_clocks_in_mhz (bd_t *kbd) #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 - */ - fdt_blob = (char *)fdt_addr; - debug ("* fdt: raw FDT blob\n"); - printf ("## Flattened Device Tree blob at %08lx\n", (long)fdt_blob); - } - break; - default: - fdt_error ("Did not find a cmdline Flattened Device Tree"); - 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", - *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 needs to be inside the boot mapping. - */ - if (fdt_blob < (char *)bootmap_base) - relocate = 1; - - if ((fdt_blob + *of_size + CFG_FDT_PAD) >= - ((char *)CFG_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 + CFG_FDT_PAD; - of_start = (unsigned long)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_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 = (CFG_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; - } - - return 0; - -error: - return 1; -} -#endif -- cgit v1.1