Signed-off-by: Kumar Gala <[EMAIL PROTECTED]> --- Got rid of unique boots command and just made sub commands part of bootm.
- k common/cmd_bootm.c | 106 +++++++++++++++++++++++++++- include/image.h | 12 +++- lib_ppc/bootm.c | 201 +++++++++++++++++++++++++++++----------------------- 3 files changed, 228 insertions(+), 91 deletions(-) diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 0343ab1..f2a3c94 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -34,6 +34,7 @@ #include <bzlib.h> #include <environment.h> #include <lmb.h> +#include <linux/ctype.h> #include <asm/byteorder.h> #if defined(CONFIG_CMD_USB) @@ -97,7 +98,7 @@ 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; +extern int do_bootm_linux(int flag, bootm_headers_t *images); static boot_os_fn do_bootm_netbsd; #if defined(CONFIG_LYNXKDI) static boot_os_fn do_bootm_lynxkdi; @@ -353,6 +354,87 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) return 0; } +int do_bootm_subcommand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int ret = 0; + + /* start */ + if (argv[1][0] == 's') { + argc--; + argv++; + return bootm_start(cmdtp, flag, argc, argv); + } + + if (!images.valid) { + printf("Need to call %s start first\n", argv[0]); + return 1; + } + + /* load os */ + if (argv[1][0] == 'l') { + ulong load_end; + ret = bootm_load_os(images.os, &load_end, 0); + if (ret) + return ret; + + lmb_reserve(&images.lmb, images.os.load, + (load_end - images.os.load)); + + return ret; + } + /* initrd relocate */ + else if (argv[1][0] == 'i') { + ulong rd_len = images.rd_end - images.rd_start; + char str[17]; + + ret = boot_ramdisk_high(&images.lmb, images.rd_start, + rd_len, &images.initrd_start, &images.initrd_end); + if (ret) + return ret; + + sprintf(str, "%lx", images.initrd_start); + setenv("initrd_start", str); + sprintf(str, "%lx", images.initrd_end); + setenv("initrd_end", str); + + return ret; + } +#ifdef CONFIG_OF_LIBFDT + /* fdt relocate */ + else if (argv[1][0] == 'f') { + ulong bootmap_base = getenv_bootm_low(); + ret = boot_relocate_fdt(&images.lmb, bootmap_base, + &images.ft_addr, &images.ft_len); + } +#endif +#if 0 +are these really common ??? or is there any harm?? + /* bd_t setup */ + else if (argv[1][0] == 'p') { + } + /* cmd setup */ + else if (argv[1][0] == 'c') { + } +#endif + /* prep os */ + else if (argv[1][0] == 'p') { + return do_bootm_linux(BOOT_OS_PREP, &images); + } + /* go */ + else if (argv[1][0] == 'g') { + disable_interrupts(); + do_bootm_linux(BOOT_OS_GO, &images); + return 0; + } + else { + /* Unrecognized command */ + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + return ret; +} + /*******************************************************************/ /* bootm - boot application image from image in memory */ /*******************************************************************/ @@ -363,6 +445,16 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ulong load_end = 0; int ret; + /* determine if we have a sub command */ + if (argc > 1) { + char *endp; + + simple_strtoul(argv[1], &endp, 16); + /* all of argv[1] wasn't a number, assume its a sub command */ + if (*endp != 0) + return do_bootm_subcommand(cmdtp, flag, argc, argv); + } + bootm_start(cmdtp, flag, argc, argv); /* @@ -429,7 +521,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #ifdef CONFIG_SILENT_CONSOLE fixup_silent_linux(); #endif - do_bootm_linux (cmdtp, flag, argc, argv, &images); + do_bootm_linux (0, &images); break; case IH_OS_NETBSD: @@ -462,6 +554,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) break; #endif } + do_reset (cmdtp, flag, argc, argv); show_boot_progress (-9); #ifdef DEBUG @@ -760,6 +853,15 @@ U_BOOT_CMD( "\tUse iminfo command to get the list of existing component\n" "\timages and configurations.\n" #endif + "\t\nSub-commands to do part of the bootm sequence:\n" + "\tstart [addr [arg ...]]\n" + "\tloados - load OS image\n" + "\tprepos - OS specific prep before relocation or go\n" + "\tinitrd - relocate initrd, set env initrd_start/initrd_end\n" +#if defined(CONFIG_OF_LIBFDT) + "\tfdt - relocate initrd\n" +#endif + "\tgo - start os\n" ); /*******************************************************************/ diff --git a/include/image.h b/include/image.h index 80af404..905b1eb 100644 --- a/include/image.h +++ b/include/image.h @@ -40,7 +40,6 @@ #include <lmb.h> #include <linux/string.h> #include <asm/u-boot.h> - #else /* new uImage format support enabled on host */ @@ -226,6 +225,7 @@ typedef struct bootm_headers { #endif #endif +#ifndef USE_HOSTCC image_info_t os; /* os image info */ ulong ep; /* entry point of OS */ @@ -236,6 +236,13 @@ typedef struct bootm_headers { #endif ulong ft_len; /* length of flat device tree */ + ulong initrd_start; + ulong initrd_end; + ulong cmdline_start; + ulong cmdline_end; + bd_t *kbd; +#endif + int verify; /* getenv("verify")[0] != 'n' */ int valid; /* set to 1 if we've set values in the header */ #ifndef USE_HOSTCC @@ -637,4 +644,7 @@ static inline int fit_image_check_target_arch (const void *fdt, int node) #endif /* CONFIG_FIT_VERBOSE */ #endif /* CONFIG_FIT */ +#define BOOT_OS_PREP 0x01 +#define BOOT_OS_GO 0x02 + #endif /* __IMAGE_H__ */ diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c index d4c3a33..cddf3fd 100644 --- a/lib_ppc/bootm.c +++ b/lib_ppc/bootm.c @@ -56,31 +56,75 @@ 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) +static void boot_jump_linux(bootm_headers_t *images, char *of_flat_tree) { - ulong sp; - - ulong initrd_start, initrd_end; - ulong rd_len; - ulong size; - phys_size_t bootm_size; - - ulong cmd_start, cmd_end, bootmap_base; - bd_t *kbd; void (*kernel)(bd_t *, ulong r4, ulong r5, ulong r6, ulong r7, ulong r8, ulong r9); - int ret; - ulong of_size = images->ft_len; - struct lmb *lmb = &images->lmb; + + kernel = (void (*)(bd_t *, ulong, ulong, ulong, + ulong, ulong, ulong))images->ep; + 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 defined(CONFIG_OF_LIBFDT) - char *of_flat_tree = images->ft_addr; + if (of_flat_tree) { /* device tree; boot new style */ + /* + * Linux Kernel Parameters (passing device tree): + * 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 - kernel = (void (*)(bd_t *, ulong, ulong, ulong, - ulong, ulong, ulong))images->ep; + debug (" Booting using OF flat tree...\n"); + (*kernel) ((bd_t *)of_flat_tree, 0, 0, EPAPR_MAGIC, + CFG_BOOTMAPSZ, 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 + * r8: 0 + * r9: 0 + */ + ulong cmd_start = images->cmdline_start; + ulong cmd_end = images->cmdline_end; + ulong initrd_start = images->initrd_start; + ulong initrd_end = images->initrd_end; + bd_t *kbd = images->kbd; + + debug (" Booting using board info...\n"); + (*kernel) (kbd, initrd_start, initrd_end, + cmd_start, cmd_end, 0, 0); + /* does not return */ + } + return ; +} + +static void boot_prep_linux(struct lmb *lmb) +{ + phys_size_t bootm_size; + ulong size, sp, bootmap_base; bootmap_base = getenv_bootm_low(); bootm_size = getenv_bootm_size(); @@ -118,128 +162,109 @@ 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)); + return ; +} + +static int boot_body_linux(bootm_headers_t *images, char **of_flat_tree) +{ + ulong rd_len, bootmap_base = getenv_bootm_low(); + ulong of_size = images->ft_len; + struct lmb *lmb = &images->lmb; + bd_t **kbd = &images->kbd; + ulong *cmd_start = &images->cmdline_start; + ulong *cmd_end = &images->cmdline_end; + ulong *initrd_start = &images->initrd_start; + ulong *initrd_end = &images->initrd_end; + + int ret; + if (!of_size) { /* allocate space and init command line */ - ret = boot_get_cmdline (lmb, &cmd_start, &cmd_end, bootmap_base); + ret = boot_get_cmdline (lmb, cmd_start, cmd_end, bootmap_base); if (ret) { puts("ERROR with allocation of cmdline\n"); - goto error; + return ret; } /* allocate space for kernel copy of board info */ - ret = boot_get_kbd (lmb, &kbd, bootmap_base); + ret = boot_get_kbd (lmb, kbd, bootmap_base); if (ret) { puts("ERROR with allocation of kernel bd\n"); - goto error; + return ret; } - set_clocks_in_mhz(kbd); + set_clocks_in_mhz(*kbd); } rd_len = images->rd_end - images->rd_start; + ret = boot_ramdisk_high (lmb, images->rd_start, rd_len, initrd_start, initrd_end); + if (ret) + return ret; #if defined(CONFIG_OF_LIBFDT) - ret = boot_relocate_fdt(lmb, bootmap_base, &of_flat_tree, &of_size); + ret = boot_relocate_fdt(lmb, bootmap_base, of_flat_tree, &of_size); if (ret) - goto error; + return ret; /* * 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, images->rd_start, images->rd_end, 0) < 0) { puts ("ERROR: "); puts ("/chosen node create failed"); puts (" - must RESET the board to recover.\n"); - goto error; + return -1; } #ifdef CONFIG_OF_BOARD_SETUP /* Call the board-specific fixup routine */ if (!getenv("no_ft_board_setup")) ft_board_setup(of_flat_tree, gd->bd); #endif - } - /* Fixup the fdt memreserve now that we know how big it is */ - if (of_flat_tree) { /* Delete the old LMB reservation */ lmb_free(lmb, (phys_addr_t)(u32)of_flat_tree, (phys_size_t)fdt_totalsize(of_flat_tree)); ret = fdt_resize(of_flat_tree); if (ret < 0) - goto error; + return ret; of_size = ret; /* Create a new LMB reservation */ lmb_reserve(lmb, (ulong)of_flat_tree, of_size); } #endif /* CONFIG_OF_LIBFDT */ + return 0; +} - 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)) - fdt_initrd(of_flat_tree, initrd_start, initrd_end, 1); -#endif - debug ("## Transferring control to Linux (at address %08lx) ...\n", - (ulong)kernel); - - show_boot_progress (15); +int __attribute__((noinline)) +do_bootm_linux(int flag, bootm_headers_t *images) +{ + int ret; + char *of_flat_tree = NULL; -#if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500) - unlock_ram_in_cache(); +#ifdef CONFIG_OF_LIBFDT + of_flat_tree = images->ft_addr; #endif -#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 - * 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 + if (flag & BOOT_OS_PREP) { + boot_prep_linux(&images->lmb); + return 0; + } - debug (" Booting using OF flat tree...\n"); - (*kernel) ((bd_t *)of_flat_tree, 0, 0, EPAPR_MAGIC, - CFG_BOOTMAPSZ, 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 - * r8: 0 - * r9: 0 - */ - debug (" Booting using board info...\n"); - (*kernel) (kbd, initrd_start, initrd_end, - cmd_start, cmd_end, 0, 0); - /* does not return */ + if (flag & BOOT_OS_GO) { + boot_jump_linux(images, of_flat_tree); + return 0; } - return ; -error: - do_reset (cmdtp, flag, argc, argv); - return ; + boot_prep_linux(&images->lmb); + ret = boot_body_linux(images, &of_flat_tree); + if (ret) + return ret; + boot_jump_linux(images, of_flat_tree); + + return 0; } static ulong get_sp (void) -- 1.5.5.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot