X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=lib_ppc%2Fbootm.c;h=38266e1da2176f94ce3bfae1c39866728f9d4a61;hb=56844a22b76c719e600047e23b80465a44d76abd;hp=81803ddef3dd0aca138359374bf123a4641595b9;hpb=ac5ba41c2234dd513ed2c879914e964cc05a0135;p=u-boot diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c index 81803ddef3..38266e1da2 100644 --- a/lib_ppc/bootm.c +++ b/lib_ppc/bootm.c @@ -39,25 +39,14 @@ #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[]); extern ulong get_effective_memsize(void); static ulong get_sp (void); static void set_clocks_in_mhz (bd_t *kbd); @@ -66,29 +55,31 @@ static void set_clocks_in_mhz (bd_t *kbd); #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) +__attribute__((noinline)) +int do_bootm_linux(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 rd_len; ulong size; phys_size_t bootm_size; ulong cmd_start, cmd_end, bootmap_base; bd_t *kbd; - ulong ep = 0; - void (*kernel)(bd_t *, ulong, ulong, ulong, ulong); + void (*kernel)(bd_t *, ulong r4, ulong r5, ulong r6, + ulong r7, ulong r8, ulong r9); int ret; - ulong of_size = 0; - struct lmb *lmb = images->lmb; + 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, + ulong, ulong, ulong))images->ep; + bootmap_base = getenv_bootm_low(); bootm_size = getenv_bootm_size(); @@ -125,14 +116,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); @@ -150,44 +133,22 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], set_clocks_in_mhz(kbd); } - /* find kernel entry point */ - if (images->legacy_hdr_valid) { - ep = image_get_ep (&images->legacy_hdr_os_copy); -#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; + rd_len = images->rd_end - images->rd_start; - /* find ramdisk */ - ret = boot_get_ramdisk (argc, argv, images, IH_ARCH_PPC, - &rd_data_start, &rd_data_end); +#if defined(CONFIG_OF_LIBFDT) + ret = boot_relocate_fdt(lmb, bootmap_base, &of_flat_tree, &of_size); 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"); + if (fdt_chosen(of_flat_tree, 0) < 0) { + puts ("ERROR: "); + puts ("/chosen node create failed"); + puts (" - must RESET the board to recover.\n"); goto error; } #ifdef CONFIG_OF_BOARD_SETUP @@ -198,76 +159,30 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], /* Fixup the fdt memreserve now that we know how big it is */ if (of_flat_tree) { - int j; - uint64_t addr, size; - int total = fdt_num_mem_rsv(of_flat_tree); - uint actualsize; - - for (j = 0; j < total; j++) { - fdt_get_mem_rsv(of_flat_tree, j, &addr, &size); - if (addr == (uint64_t)(u32)of_flat_tree) { - fdt_del_mem_rsv(of_flat_tree, j); - break; - } - } - /* Delete the old LMB reservation */ lmb_free(lmb, (phys_addr_t)(u32)of_flat_tree, (phys_size_t)fdt_totalsize(of_flat_tree)); - /* Calculate the actual size of the fdt */ - actualsize = fdt_off_dt_strings(of_flat_tree) + - fdt_size_dt_strings(of_flat_tree); - - /* Make it so the fdt ends on a page boundary */ - actualsize = ALIGN(actualsize, 0x1000); - actualsize = actualsize - ((uint)of_flat_tree & 0xfff); - - /* Change the fdt header to reflect the correct size */ - fdt_set_totalsize(of_flat_tree, actualsize); - of_size = actualsize; - - /* Add the new reservation */ - ret = fdt_add_mem_rsv(of_flat_tree, (uint)of_flat_tree, - of_size); + ret = fdt_resize(of_flat_tree); + if (ret < 0) + goto error; + of_size = ret; + if ((of_flat_tree) && (initrd_start && initrd_end)) + of_size += FDT_RAMDISK_OVERHEAD; /* Create a new LMB reservation */ lmb_reserve(lmb, (ulong)of_flat_tree, of_size); } #endif /* CONFIG_OF_LIBFDT */ - ret = boot_ramdisk_high (lmb, rd_data_start, rd_len, &initrd_start, &initrd_end); + ret = boot_ramdisk_high (lmb, images->rd_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); - } + if ((of_flat_tree) && (initrd_start && initrd_end)) + fdt_initrd(of_flat_tree, initrd_start, initrd_end, 1); #endif debug ("## Transferring control to Linux (at address %08lx) ...\n", (ulong)kernel); @@ -277,21 +192,28 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], #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 + * r3: pointer to the fdt + * r4: 0 + * r5: 0 + * r6: epapr magic + * r7: size of IMA in bytes + * r8: 0 + * r9: 0 */ +#if defined(CONFIG_85xx) || defined(CONFIG_440) + #define EPAPR_MAGIC (0x45504150) +#else + #define EPAPR_MAGIC (0x65504150) +#endif + debug (" Booting using OF flat tree...\n"); - (*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0); + (*kernel) ((bd_t *)of_flat_tree, 0, 0, EPAPR_MAGIC, + CFG_BOOTMAPSZ, 0, 0); /* does not return */ } else #endif @@ -303,17 +225,18 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], * r5: initrd_end - unused if r4 is 0 * r6: Start of command line string * r7: End of command line string + * r8: 0 + * r9: 0 */ debug (" Booting using board info...\n"); - (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); + (*kernel) (kbd, initrd_start, initrd_end, + cmd_start, cmd_end, 0, 0); /* does not return */ } - return ; + return 1; error: - if (images->autostart) - do_reset (cmdtp, flag, argc, argv); - return ; + return 1; } static ulong get_sp (void) @@ -351,464 +274,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