[U-Boot] [PATCH 1/2] bootm: Add subcommands

Add the ability to break the steps of the bootm command into several subcommands: start, loados, ramdisk, fdt, bdt, cmdline, prep, go.
This allows us to do things like manipulate device trees before they are passed to a booting kernel or setup memory for a secondary core in multicore situations.
Not all OS types support all subcommands (currently only start, loados, ramdisk, fdt, and go are supported).
Signed-off-by: Kumar Gala galak@kernel.crashing.org --- common/cmd_bootm.c | 168 +++++++++++++++++++++++++++++++++++++++++++++++- include/image.h | 20 ++++++- lib_arm/bootm.c | 3 + lib_avr32/bootm.c | 3 + lib_blackfin/bootm.c | 3 + lib_i386/bootm.c | 3 + lib_m68k/bootm.c | 3 + lib_microblaze/bootm.c | 3 + lib_mips/bootm.c | 3 + lib_nios2/bootm.c | 3 + lib_ppc/bootm.c | 3 + lib_sh/bootm.c | 3 + lib_sparc/bootm.c | 3 + 13 files changed, 219 insertions(+), 2 deletions(-)
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 956e1a0..1b2dfc4 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) @@ -296,7 +297,7 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) }
images.os.start = (ulong)os_hdr; - images.valid = 1; + images.state = BOOTM_STATE_START;
return 0; } @@ -399,6 +400,121 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) return 0; }
+/* we overload the cmd field with our state machine info instead of a + * function pointer */ +cmd_tbl_t cmd_bootm_sub[] = { + U_BOOT_CMD_MKENT(start, 0, 1, (void *)BOOTM_STATE_START, "", ""), + U_BOOT_CMD_MKENT(loados, 0, 1, (void *)BOOTM_STATE_LOADOS, "", ""), +#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC) + U_BOOT_CMD_MKENT(ramdisk, 0, 1, (void *)BOOTM_STATE_RAMDISK, "", ""), +#endif +#ifdef CONFIG_OF_LIBFDT + U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)BOOTM_STATE_FDT, "", ""), +#endif + U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""), + U_BOOT_CMD_MKENT(cmdline, 0, 1, (void *)BOOTM_STATE_OS_CMDLINE, "", ""), + U_BOOT_CMD_MKENT(prep, 0, 1, (void *)BOOTM_STATE_OS_PREP, "", ""), + U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""), +}; + +int do_bootm_subcommand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int ret = 0; + int state; + cmd_tbl_t *c; + boot_os_fn *boot_fn; + + c = find_cmd_tbl(argv[1], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub)); + + if (c) { + state = (int)c->cmd; + + /* treat start special since it resets the state machine */ + if (state == BOOTM_STATE_START) { + argc--; + argv++; + return bootm_start(cmdtp, flag, argc, argv); + } + } + /* Unrecognized command */ + else { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + if (images.state >= state) { + printf ("Trying to execute a command out of order\n"); + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + images.state |= state; + boot_fn = boot_os[images.os.os]; + + switch (state) { + ulong load_end; + case BOOTM_STATE_START: + /* should never occur */ + break; + case BOOTM_STATE_LOADOS: + 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)); + break; +#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC) + case BOOTM_STATE_RAMDISK: + { + 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); + } + break; +#endif +#ifdef CONFIG_OF_LIBFDT + case BOOTM_STATE_FDT: + { + ulong bootmap_base = getenv_bootm_low(); + ret = boot_relocate_fdt(&images.lmb, bootmap_base, + &images.ft_addr, &images.ft_len); + break; + } +#endif + case BOOTM_STATE_OS_CMDLINE: + ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, &images); + if (ret) + printf ("cmdline subcommand not supported\n"); + break; + case BOOTM_STATE_OS_BD_T: + ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, &images); + if (ret) + printf ("bdt subcommand not supported\n"); + break; + case BOOTM_STATE_OS_PREP: + ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, &images); + if (ret) + printf ("prep subcommand not supported\n"); + break; + case BOOTM_STATE_OS_GO: + disable_interrupts(); + boot_fn(BOOTM_STATE_OS_GO, argc, argv, &images); + break; + } + + return ret; +} + /*******************************************************************/ /* bootm - boot application image from image in memory */ /*******************************************************************/ @@ -419,6 +535,23 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) relocated = 1; }
+ /* determine if we have a sub command */ + if (argc > 1) { + char *endp; + + simple_strtoul(argv[1], &endp, 16); + /* endp pointing to NULL means that argv[1] was just a + * valid number, pass it along to the normal bootm processing + * + * If endp is ':' or '#' assume a FIT identifier so pass + * along for normal processing. + * + * Right now we assume the first arg should never be '-' + */ + if ((*endp != 0) && (*endp != ':') && (*endp != '#')) + return do_bootm_subcommand(cmdtp, flag, argc, argv); + } + if (bootm_start(cmdtp, flag, argc, argv)) return 1;
@@ -783,6 +916,21 @@ U_BOOT_CMD( "\tUse iminfo command to get the list of existing component\n" "\timages and configurations.\n" #endif + "\nSub-commands to do part of the bootm sequence. The sub-commands " + "must be\n" + "issued in the order below (it's ok to not issue all sub-commands):\n" + "\tstart [addr [arg ...]]\n" + "\tloados - load OS image\n" +#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC) + "\tramdisk - relocate initrd, set env initrd_start/initrd_end\n" +#endif +#if defined(CONFIG_OF_LIBFDT) + "\tfdt - relocate flat device tree\n" +#endif + "\tbdt - OS specific bd_t processing\n" + "\tcmdline - OS specific command line processing/setup\n" + "\tprep - OS specific prep before relocation or go\n" + "\tgo - start OS\n" );
/*******************************************************************/ @@ -1022,6 +1170,9 @@ static int do_bootm_netbsd (int flag, int argc, char *argv[], char *consdev; char *cmdline;
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + #if defined(CONFIG_FIT) if (!images->legacy_hdr_valid) { fit_unsupported_reset ("NetBSD"); @@ -1102,6 +1253,9 @@ static int do_bootm_lynxkdi (int flag, int argc, char *argv[], { image_header_t *hdr = &images->legacy_hdr_os_copy;
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + #if defined(CONFIG_FIT) if (!images->legacy_hdr_valid) { fit_unsupported_reset ("Lynx"); @@ -1120,6 +1274,9 @@ static int do_bootm_rtems (int flag, int argc, char *argv[], { void (*entry_point)(bd_t *);
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + #if defined(CONFIG_FIT) if (!images->legacy_hdr_valid) { fit_unsupported_reset ("RTEMS"); @@ -1149,6 +1306,9 @@ static int do_bootm_vxworks (int flag, int argc, char *argv[], { char str[80];
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + #if defined(CONFIG_FIT) if (!images->legacy_hdr_valid) { fit_unsupported_reset ("VxWorks"); @@ -1169,6 +1329,9 @@ static int do_bootm_qnxelf(int flag, int argc, char *argv[], char *local_args[2]; char str[16];
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + #if defined(CONFIG_FIT) if (!images->legacy_hdr_valid) { fit_unsupported_reset ("QNX"); @@ -1191,6 +1354,9 @@ static int do_bootm_integrity (int flag, int argc, char *argv[], { void (*entry_point)(void);
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + #if defined(CONFIG_FIT) if (!images->legacy_hdr_valid) { fit_unsupported_reset ("INTEGRITY"); diff --git a/include/image.h b/include/image.h index 82e6345..557e72a 100644 --- a/include/image.h +++ b/include/image.h @@ -228,6 +228,7 @@ typedef struct bootm_headers { #endif #endif
+#ifndef USE_HOSTCC image_info_t os; /* os image info */ ulong ep; /* entry point of OS */
@@ -238,8 +239,25 @@ 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 */ + +#define BOOTM_STATE_START (0x00000001) +#define BOOTM_STATE_LOADOS (0x00000002) +#define BOOTM_STATE_RAMDISK (0x00000004) +#define BOOTM_STATE_FDT (0x00000008) +#define BOOTM_STATE_OS_CMDLINE (0x00000010) +#define BOOTM_STATE_OS_BD_T (0x00000020) +#define BOOTM_STATE_OS_PREP (0x00000040) +#define BOOTM_STATE_OS_GO (0x00000080) + int state; + #ifndef USE_HOSTCC struct lmb lmb; /* for memory mgmt */ #endif diff --git a/lib_arm/bootm.c b/lib_arm/bootm.c index 772fa7f..8e264ce 100644 --- a/lib_arm/bootm.c +++ b/lib_arm/bootm.c @@ -67,6 +67,9 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) char *commandline = getenv ("bootargs"); #endif
+ if ((flag != 0) || (flag != BOOTM_STATE_OS_GO)) + return 1; + theKernel = (void (*)(int, int, uint))images->ep;
s = getenv ("machid"); diff --git a/lib_avr32/bootm.c b/lib_avr32/bootm.c index 35240e2..556e3ea 100644 --- a/lib_avr32/bootm.c +++ b/lib_avr32/bootm.c @@ -178,6 +178,9 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) char *commandline = getenv("bootargs"); int ret;
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + theKernel = (void *)images->ep;
show_boot_progress (15); diff --git a/lib_blackfin/bootm.c b/lib_blackfin/bootm.c index 9938ae5..195eb9c 100644 --- a/lib_blackfin/bootm.c +++ b/lib_blackfin/bootm.c @@ -36,6 +36,9 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) int (*appl) (char *cmdline); char *cmdline;
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + #ifdef SHARED_RESOURCES swap_to(FLASH); #endif diff --git a/lib_i386/bootm.c b/lib_i386/bootm.c index 613e339..ea19b3d 100644 --- a/lib_i386/bootm.c +++ b/lib_i386/bootm.c @@ -40,6 +40,9 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) size_t len; #endif
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + if (images->legacy_hdr_valid) { hdr = images->legacy_hdr_os; if (image_check_type (hdr, IH_TYPE_MULTI)) { diff --git a/lib_m68k/bootm.c b/lib_m68k/bootm.c index c52dd2f..0798e07 100644 --- a/lib_m68k/bootm.c +++ b/lib_m68k/bootm.c @@ -76,6 +76,9 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) void (*kernel) (bd_t *, ulong, ulong, ulong, ulong); struct lmb *lmb = &images->lmb;
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + bootmap_base = getenv_bootm_low();
/* allocate space and init command line */ diff --git a/lib_microblaze/bootm.c b/lib_microblaze/bootm.c index 52fe068..e97aae6 100644 --- a/lib_microblaze/bootm.c +++ b/lib_microblaze/bootm.c @@ -38,6 +38,9 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) void (*theKernel) (char *); char *commandline = getenv ("bootargs");
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + theKernel = (void (*)(char *))images->ep;
show_boot_progress (15); diff --git a/lib_mips/bootm.c b/lib_mips/bootm.c index dced28c..3db22ea 100644 --- a/lib_mips/bootm.c +++ b/lib_mips/bootm.c @@ -50,6 +50,9 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) char env_buf[12]; char *cp;
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + /* find kernel entry point */ theKernel = (void (*)(int, char **, char **, int *))images->ep;
diff --git a/lib_nios2/bootm.c b/lib_nios2/bootm.c index 34f5b8f..53fd569 100644 --- a/lib_nios2/bootm.c +++ b/lib_nios2/bootm.c @@ -29,6 +29,9 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) { void (*kernel)(void) = (void (*)(void))images->ep;
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + /* For now we assume the Microtronix linux ... which only * needs to be called ;-) */ diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c index 1f3501a..6c9cf9e 100644 --- a/lib_ppc/bootm.c +++ b/lib_ppc/bootm.c @@ -117,6 +117,9 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) char *of_flat_tree = images->ft_addr; #endif
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong, ulong, ulong))images->ep;
diff --git a/lib_sh/bootm.c b/lib_sh/bootm.c index 078a24d..ae1f869 100644 --- a/lib_sh/bootm.c +++ b/lib_sh/bootm.c @@ -56,6 +56,9 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) unsigned long size = images->ep - (unsigned long)param; char *bootargs = getenv("bootargs");
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + /* Setup parameters */ memset(param, 0, size); /* Clear zero page */ strcpy(cmdline, bootargs); diff --git a/lib_sparc/bootm.c b/lib_sparc/bootm.c index 565b41c..4975759 100644 --- a/lib_sparc/bootm.c +++ b/lib_sparc/bootm.c @@ -102,6 +102,9 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t * images) struct lmb *lmb = &images->lmb; int ret;
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + /* Get virtual address of kernel start */ linux_hdr = (void *)images->os.load;

Add support for 'bdt', 'cmdline', 'prep' to the linux PPC bootm.
Signed-off-by: Kumar Gala galak@kernel.crashing.org --- lib_ppc/bootm.c | 271 +++++++++++++++++++++++++++++++++++-------------------- 1 files changed, 175 insertions(+), 96 deletions(-)
diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c index 6c9cf9e..fce4eff 100644 --- a/lib_ppc/bootm.c +++ b/lib_ppc/bootm.c @@ -47,6 +47,7 @@
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); @@ -55,6 +56,74 @@ static void set_clocks_in_mhz (bd_t *kbd); #define CONFIG_SYS_LINUX_LOWMEM_MAX_SIZE (768*1024*1024) #endif
+static void boot_jump_linux(bootm_headers_t *images) +{ + void (*kernel)(bd_t *, ulong r4, ulong r5, ulong r6, + ulong r7, ulong r8, ulong r9); +#ifdef CONFIG_OF_LIBFDT + char *of_flat_tree = images->ft_addr; +#endif + + 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(CONFIG_SYS_INIT_RAM_LOCK) && !defined(CONFIG_E500) + unlock_ram_in_cache(); +#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 + + debug (" Booting using OF flat tree...\n"); + (*kernel) ((bd_t *)of_flat_tree, 0, 0, EPAPR_MAGIC, + CONFIG_SYS_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 ; +} + void arch_lmb_reserve(struct lmb *lmb) { phys_size_t bootm_size; @@ -99,153 +168,163 @@ void arch_lmb_reserve(struct lmb *lmb) return ; }
-__attribute__((noinline)) -int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) +static void boot_prep_linux(void) { - ulong initrd_start, initrd_end; - ulong rd_len; - - 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; - -#if defined(CONFIG_OF_LIBFDT) - char *of_flat_tree = images->ft_addr; +#if (CONFIG_NUM_CPUS > 1) + /* if we are MP make sure to flush the dcache() to any changes are made + * visibile to all other cores */ + flush_dcache(); #endif + return ; +}
- if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) - return 1; - - kernel = (void (*)(bd_t *, ulong, ulong, ulong, - ulong, ulong, ulong))images->ep; +static int boot_cmdline_linux(bootm_headers_t *images) +{ + ulong bootmap_base = getenv_bootm_low(); + ulong of_size = images->ft_len; + struct lmb *lmb = &images->lmb; + ulong *cmd_start = &images->cmdline_start; + ulong *cmd_end = &images->cmdline_end;
- bootmap_base = getenv_bootm_low(); + int ret = 0;
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; } + } + + return ret; +} + +static int boot_bd_t_linux(bootm_headers_t *images) +{ + ulong bootmap_base = getenv_bootm_low(); + ulong of_size = images->ft_len; + struct lmb *lmb = &images->lmb; + bd_t **kbd = &images->kbd; + + int ret = 0;
+ if (!of_size) { /* 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); }
+ return ret; +} + +static int boot_body_linux(bootm_headers_t *images) +{ + ulong rd_len, bootmap_base = getenv_bootm_low(); + ulong of_size = images->ft_len; + struct lmb *lmb = &images->lmb; + ulong *initrd_start = &images->initrd_start; + ulong *initrd_end = &images->initrd_end; +#if defined(CONFIG_OF_LIBFDT) + char **of_flat_tree = &images->ft_addr; +#endif + + int ret; + + /* allocate space and init command line */ + ret = boot_cmdline_linux(images); + if (ret) + return ret; + + /* allocate space for kernel copy of board info */ + ret = boot_bd_t_linux(images); + if (ret) + return ret; + 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) { - if (fdt_chosen(of_flat_tree, 1) < 0) { + if (fdt_chosen(*of_flat_tree, 1) < 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 */ - ft_board_setup(of_flat_tree, gd->bd); + 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)); + lmb_free(lmb, (phys_addr_t)(u32)*of_flat_tree, + (phys_size_t)fdt_totalsize(*of_flat_tree));
- ret = fdt_resize(of_flat_tree); + ret = fdt_resize(*of_flat_tree); if (ret < 0) - goto error; + return ret; of_size = ret;
- if ((of_flat_tree) && (initrd_start && initrd_end)) + if (*initrd_start && *initrd_end) of_size += FDT_RAMDISK_OVERHEAD; /* Create a new LMB reservation */ - lmb_reserve(lmb, (ulong)of_flat_tree, of_size); + lmb_reserve(lmb, (ulong)*of_flat_tree, of_size); + + /* fixup the initrd now that we know where it should be */ + if (*initrd_start && *initrd_end) + fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1); } #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); +__attribute__((noinline)) +int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) +{ + int ret;
- show_boot_progress (15); + if (flag & BOOTM_STATE_OS_CMDLINE) { + boot_cmdline_linux(images); + return 0; + }
-#if defined(CONFIG_SYS_INIT_RAM_LOCK) && !defined(CONFIG_E500) - unlock_ram_in_cache(); -#endif + if (flag & BOOTM_STATE_OS_BD_T) { + boot_bd_t_linux(images); + return 0; + }
-#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 & BOOTM_STATE_OS_PREP) { + boot_prep_linux(); + return 0; + }
- debug (" Booting using OF flat tree...\n"); - (*kernel) ((bd_t *)of_flat_tree, 0, 0, EPAPR_MAGIC, - CONFIG_SYS_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 & BOOTM_STATE_OS_GO) { + boot_jump_linux(images); + return 0; } - return 1;
-error: - return 1; + boot_prep_linux(); + ret = boot_body_linux(images); + if (ret) + return ret; + boot_jump_linux(images); + + return 0; }
static ulong get_sp (void)

Dear Kumar Gala,
In message 1224520091-26756-1-git-send-email-galak@kernel.crashing.org you wrote:
Add the ability to break the steps of the bootm command into several subcommands: start, loados, ramdisk, fdt, bdt, cmdline, prep, go.
This allows us to do things like manipulate device trees before they are passed to a booting kernel or setup memory for a secondary core in multicore situations.
Not all OS types support all subcommands (currently only start, loados, ramdisk, fdt, and go are supported).
Signed-off-by: Kumar Gala galak@kernel.crashing.org
This looks mostly OK to me, but I haven't actually tested any of this code yet - can you please comment to what extend you tested it?
--- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c
...
@@ -1022,6 +1170,9 @@ static int do_bootm_netbsd (int flag, int argc, char *argv[], char *consdev; char *cmdline;
- if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
return 1;
This is a test that repeats quite often... Maybe e can optimize this as
if ((flag ^ BOOTM_STATE_OS_GO) != 0) return 1;
?
Best regards,
Wolfgang Denk

On Oct 21, 2008, at 2:30 PM, Wolfgang Denk wrote:
Dear Kumar Gala,
In message <1224520091-26756-1-git-send-email-galak@kernel.crashing.org
you wrote: Add the ability to break the steps of the bootm command into several subcommands: start, loados, ramdisk, fdt, bdt, cmdline, prep, go.
This allows us to do things like manipulate device trees before they are passed to a booting kernel or setup memory for a secondary core in multicore situations.
Not all OS types support all subcommands (currently only start, loados, ramdisk, fdt, and go are supported).
Signed-off-by: Kumar Gala galak@kernel.crashing.org
This looks mostly OK to me, but I haven't actually tested any of this code yet - can you please comment to what extend you tested it?
I've tested this on FSL 85xx HW. I'm able to boot using a sequence of bootm subcommands + a few other commands as well as plain old bootm.
--- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c
...
@@ -1022,6 +1170,9 @@ static int do_bootm_netbsd (int flag, int argc, char *argv[], char *consdev; char *cmdline;
- if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
return 1;
This is a test that repeats quite often... Maybe e can optimize this as
if ((flag ^ BOOTM_STATE_OS_GO) != 0) return 1;
Hmm, this isn't equivalent:
0 ^ BOOTM_STATE_OS_GO => BOOTM_STATE_OS_GO BOOTM_STATE_OS_GO != 0 return 1.
- k

Kumar Gala wrote:
On Oct 21, 2008, at 2:30 PM, Wolfgang Denk wrote:
Dear Kumar Gala,
In message <1224520091-26756-1-git-send-email-galak@kernel.crashing.org
you wrote: Add the ability to break the steps of the bootm command into several subcommands: start, loados, ramdisk, fdt, bdt, cmdline, prep, go.
This allows us to do things like manipulate device trees before they are passed to a booting kernel or setup memory for a secondary core in multicore situations.
Not all OS types support all subcommands (currently only start, loados, ramdisk, fdt, and go are supported).
Signed-off-by: Kumar Gala galak@kernel.crashing.org
This looks mostly OK to me, but I haven't actually tested any of this code yet - can you please comment to what extend you tested it?
I've tested this on FSL 85xx HW. I'm able to boot using a sequence of bootm subcommands + a few other commands as well as plain old bootm.
Ditto for the MPC8360.
Best regards, gvb

Kumar Gala wrote:
Add the ability to break the steps of the bootm command into several subcommands: start, loados, ramdisk, fdt, bdt, cmdline, prep, go.
This allows us to do things like manipulate device trees before they are passed to a booting kernel or setup memory for a secondary core in multicore situations.
Not all OS types support all subcommands (currently only start, loados, ramdisk, fdt, and go are supported).
Signed-off-by: Kumar Gala galak@kernel.crashing.org
Hi Kumar,
I've been hacking at cmd_bootm.c and image.c. The direction I'm hacking in is: * Move boot_* stuff from image.c into cmd_bootm.c - Calling out to another file to a function unused in that file? Ugly. * Move the FIT stuff out of image.c into a new file fit_image.c - The resulting files are more cohesive and less BIG. * Move the im* commands out of cmd_bootm.c into a new file cmd_image.c - At one time, I was of the opinion that "bootm (loados|ramdisk|fdt)" should be "ldimage (os|ramdisk|fdt)". I'm less sure of myself, but have not totally discarded the opinion. - Looking in cmd_bootm.c for im* commands is rather unintuitive.
My intent is to do this hacking based on your bootm subcommand changes, so we can do a two-step cleanup.
Do you have a git repo I can clone rather than trying to keep up with the master repo + your patches? My tracking of your work is falling apart. I see you have an out-of-date repo on git.kernel.org, can you update that perhaps?
Thanks, gvb

Dear Jerry Van Baren,
In message 48FE3114.3040908@ge.com you wrote:
Do you have a git repo I can clone rather than trying to keep up with the master repo + your patches? My tracking of your work is falling apart. I see you have an out-of-date repo on git.kernel.org, can you update that perhaps?
If it helps, we can use a branch in u-boot-testing for this.
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
Dear Jerry Van Baren,
In message 48FE3114.3040908@ge.com you wrote:
Do you have a git repo I can clone rather than trying to keep up with the master repo + your patches? My tracking of your work is falling apart. I see you have an out-of-date repo on git.kernel.org, can you update that perhaps?
If it helps, we can use a branch in u-boot-testing for this.
Best regards,
Wolfgang Denk
Sounds good to me.
Thanks, gvb

Dear Jerry Van Baren,
In message 48FE32DC.7000705@ge.com you wrote:
If it helps, we can use a branch in u-boot-testing for this.
...
Sounds good to me.
Please just drop me a note which patches (in which versions) should go in. I kind of lost track...
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
Dear Jerry Van Baren,
In message 48FE32DC.7000705@ge.com you wrote:
If it helps, we can use a branch in u-boot-testing for this.
...
Sounds good to me.
Please just drop me a note which patches (in which versions) should go in. I kind of lost track...
Best regards,
Wolfgang Denk
Dear Kumar Gala,
I kind of lost track too. :-/
gvb

On Oct 21, 2008, at 2:44 PM, Jerry Van Baren wrote:
I've been hacking at cmd_bootm.c and image.c. The direction I'm hacking in is:
- Move boot_* stuff from image.c into cmd_bootm.c
- Calling out to another file to a function unused in that file?
Ugly.
- Move the FIT stuff out of image.c into a new file fit_image.c
- The resulting files are more cohesive and less BIG.
- Move the im* commands out of cmd_bootm.c into a new file cmd_image.c
- At one time, I was of the opinion that "bootm (loados|ramdisk|fdt)" should be "ldimage (os|ramdisk|fdt)". I'm less sure of myself, but have not totally discarded the opinion.
- Looking in cmd_bootm.c for im* commands is rather unintuitive.
these all sound like good things. I've posted a "clean" patchset for Wolfgang to apply to 'master' or 'testing'
- k

Kumar Gala wrote:
On Oct 21, 2008, at 2:44 PM, Jerry Van Baren wrote:
I've been hacking at cmd_bootm.c and image.c. The direction I'm hacking in is:
- Move boot_* stuff from image.c into cmd_bootm.c
- Calling out to another file to a function unused in that file? Ugly.
- Move the FIT stuff out of image.c into a new file fit_image.c
- The resulting files are more cohesive and less BIG.
- Move the im* commands out of cmd_bootm.c into a new file cmd_image.c
- At one time, I was of the opinion that "bootm (loados|ramdisk|fdt)" should be "ldimage (os|ramdisk|fdt)". I'm less sure of myself, but have not totally discarded the opinion.
- Looking in cmd_bootm.c for im* commands is rather unintuitive.
these all sound like good things. I've posted a "clean" patchset for Wolfgang to apply to 'master' or 'testing'
- k
Thanks, that was helpful. I cloned the testing branch and am hacking merrily.
gvb
participants (3)
-
Jerry Van Baren
-
Kumar Gala
-
Wolfgang Denk