mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-24 20:54:24 +08:00
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>
This commit is contained in:
parent
be08315933
commit
49c3a861d1
@ -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");
|
||||
|
@ -230,6 +230,7 @@ typedef struct bootm_headers {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
image_info_t os; /* os image info */
|
||||
ulong ep; /* entry point of OS */
|
||||
|
||||
@ -240,8 +241,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
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)) {
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 ;-)
|
||||
*/
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user