Merge patch series "Complete decoupling of bootm logic from commands"

Simon Glass <sjg@chromium.org> says:

This series continues refactoring the bootm code to allow it to be used
with CONFIG_COMMAND disabled. The OS-handling code is refactored and
a new bootm_run() function is created to run through the bootm stages.
This completes the work.

A booti_go() function is created also, in case it proves useful, but at
last for now standard boot does not use this.

This is cmdd (part d of CMDLINE refactoring)
It depends on dm/bootstda-working
which depends on dm/cmdc-working
This commit is contained in:
Tom Rini 2023-12-21 16:10:00 -05:00
commit 7c4647b8fb
27 changed files with 444 additions and 202 deletions

View file

@ -3,6 +3,7 @@
* Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
*/
#include <bootm.h>
#include <bootstage.h>
#include <env.h>
#include <image.h>
@ -78,8 +79,10 @@ static void boot_jump_linux(struct bootm_headers *images, int flag)
board_jump_and_run(kernel_entry, r0, 0, r2);
}
int do_bootm_linux(int flag, int argc, char *argv[], struct bootm_headers *images)
int do_bootm_linux(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
/* No need for those on ARC */
if ((flag & BOOTM_STATE_OS_BD_T) || (flag & BOOTM_STATE_OS_CMDLINE))
return -1;

View file

@ -12,6 +12,7 @@
*/
#include <common.h>
#include <bootm.h>
#include <bootstage.h>
#include <command.h>
#include <cpu_func.h>
@ -378,9 +379,10 @@ static void boot_jump_linux(struct bootm_headers *images, int flag)
* DIFFERENCE: Instead of calling prep and go at the end
* they are called if subcommand is equal 0.
*/
int do_bootm_linux(int flag, int argc, char *const argv[],
struct bootm_headers *images)
int do_bootm_linux(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
/* No need for those on ARM */
if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
return -1;

View file

@ -4,6 +4,7 @@
*/
#include <common.h>
#include <bootm.h>
#include <command.h>
#include <dfu.h>
#include <image.h>
@ -124,35 +125,41 @@ static int do_stm32prog(struct cmd_tbl *cmdtp, int flag, int argc,
char boot_addr_start[20];
char dtb_addr[20];
char initrd_addr[40];
char *bootm_argv[5] = {
"bootm", boot_addr_start, "-", dtb_addr, NULL
};
char *fdt_arg, *initrd_arg;
const void *uimage = (void *)data->uimage;
const void *dtb = (void *)data->dtb;
const void *initrd = (void *)data->initrd;
struct bootm_info bmi;
fdt_arg = dtb_addr;
if (!dtb)
bootm_argv[3] = env_get("fdtcontroladdr");
fdt_arg = env_get("fdtcontroladdr");
else
snprintf(dtb_addr, sizeof(dtb_addr) - 1,
"0x%p", dtb);
snprintf(dtb_addr, sizeof(dtb_addr) - 1, "0x%p", dtb);
snprintf(boot_addr_start, sizeof(boot_addr_start) - 1,
"0x%p", uimage);
initrd_arg = NULL;
if (initrd) {
snprintf(initrd_addr, sizeof(initrd_addr) - 1, "0x%p:0x%zx",
initrd, data->initrd_size);
bootm_argv[2] = initrd_addr;
snprintf(initrd_addr, sizeof(initrd_addr) - 1,
"0x%p:0x%zx", initrd, data->initrd_size);
initrd_arg = initrd_addr;
}
printf("Booting kernel at %s %s %s...\n\n\n",
boot_addr_start, bootm_argv[2], bootm_argv[3]);
printf("Booting kernel at %s %s %s...\n\n\n", boot_addr_start,
initrd_arg ?: "-", fdt_arg);
bootm_init(&bmi);
bmi.addr_img = boot_addr_start;
bmi.conf_ramdisk = initrd_arg;
bmi.conf_fdt = fdt_arg;
/* Try bootm for legacy and FIT format image */
if (genimg_get_format(uimage) != IMAGE_FORMAT_INVALID)
do_bootm(cmdtp, 0, 4, bootm_argv);
bootm_run(&bmi);
else if (IS_ENABLED(CONFIG_CMD_BOOTZ))
do_bootz(cmdtp, 0, 4, bootm_argv);
bootz_run(&bmi);
}
if (data->script)
cmd_source_script(data->script, NULL, NULL);

View file

@ -4,6 +4,7 @@
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*/
#include <bootm.h>
#include <bootstage.h>
#include <command.h>
#include <env.h>
@ -34,9 +35,9 @@ void arch_lmb_reserve(struct lmb *lmb)
arch_lmb_reserve_generic(lmb, get_sp(), gd->ram_top, 1024);
}
int do_bootm_linux(int flag, int argc, char *const argv[],
struct bootm_headers *images)
int do_bootm_linux(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
int ret;
struct bd_info *kbd;
void (*kernel) (struct bd_info *, ulong, ulong, ulong, ulong);

View file

@ -8,6 +8,7 @@
*/
#include <config.h>
#include <cpu_func.h>
#include <init.h>
#include <watchdog.h>
#include <command.h>
@ -66,3 +67,9 @@ int arch_initr_trap(void)
return 0;
}
void reset_cpu(void)
{
/* TODO: Refactor all the do_reset calls to be reset_cpu() instead */
do_reset(NULL, 0, 0, NULL);
}

View file

@ -7,6 +7,7 @@
* Yasushi SHOJI <yashi@atmark-techno.com>
*/
#include <bootm.h>
#include <bootstage.h>
#include <command.h>
#include <cpu_func.h>
@ -81,9 +82,10 @@ static void boot_prep_linux(struct bootm_headers *images)
}
}
int do_bootm_linux(int flag, int argc, char *const argv[],
struct bootm_headers *images)
int do_bootm_linux(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
images->cmdline_start = (ulong)env_get("bootargs");
/* cmdline init is the part of 'prep' and nothing to do for 'bdt' */

View file

@ -4,6 +4,7 @@
* Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
*/
#include <cpu_func.h>
#include <command.h>
#include <init.h>
#include <linux/compiler.h>
@ -20,9 +21,14 @@ void __weak _machine_restart(void)
/* NOP */;
}
int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
void reset_cpu(void)
{
_machine_restart();
}
int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
reset_cpu();
return 0;
}

View file

@ -4,6 +4,7 @@
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*/
#include <bootm.h>
#include <bootstage.h>
#include <env.h>
#include <image.h>
@ -216,7 +217,7 @@ static int boot_reloc_fdt(struct bootm_headers *images)
{
/*
* In case of legacy uImage's, relocation of FDT is already done
* by do_bootm_states() and should not repeated in 'bootm prep'.
* by bootm_run_states() and should not repeated in 'bootm prep'.
*/
if (images->state & BOOTM_STATE_FDT) {
debug("## FDT already relocated\n");
@ -300,9 +301,10 @@ static void boot_jump_linux(struct bootm_headers *images)
linux_extra);
}
int do_bootm_linux(int flag, int argc, char *const argv[],
struct bootm_headers *images)
int do_bootm_linux(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
/* No need for those on MIPS */
if (flag & BOOTM_STATE_OS_BD_T)
return -1;

View file

@ -35,11 +35,17 @@ int checkboard(void)
}
#endif
int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
void reset_cpu(void)
{
disable_interrupts();
/* indirect call to go beyond 256MB limitation of toolchain */
nios2_callr(gd->arch.reset_addr);
}
int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
reset_cpu();
return 0;
}

View file

@ -5,6 +5,7 @@
*/
#include <common.h>
#include <bootm.h>
#include <cpu_func.h>
#include <env.h>
#include <image.h>
@ -16,9 +17,9 @@ DECLARE_GLOBAL_DATA_PTR;
#define NIOS_MAGIC 0x534f494e /* enable command line and initrd passing */
int do_bootm_linux(int flag, int argc, char *const argv[],
struct bootm_headers *images)
int do_bootm_linux(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
void (*kernel)(int, int, int, char *) = (void *)images->ep;
char *commandline = env_get("bootargs");
ulong initrd_start = images->rd_start;
@ -29,8 +30,9 @@ int do_bootm_linux(int flag, int argc, char *const argv[],
if (images->ft_len)
of_flat_tree = images->ft_addr;
#endif
if (!of_flat_tree && argc > 1)
of_flat_tree = (char *)hextoul(argv[1], NULL);
/* TODO: Clean this up - the DT should already be set up */
if (!of_flat_tree && bmi->argc > 1)
of_flat_tree = (char *)hextoul(bmi->argv[1], NULL);
if (of_flat_tree)
initrd_end = (ulong)of_flat_tree;

View file

@ -8,6 +8,7 @@
#include <common.h>
#include <bootm.h>
#include <bootstage.h>
#include <cpu_func.h>
#include <env.h>
@ -223,9 +224,9 @@ static int boot_body_linux(struct bootm_headers *images)
return 0;
}
noinline int do_bootm_linux(int flag, int argc, char *const argv[],
struct bootm_headers *images)
int do_bootm_linux(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
int ret;
if (flag & BOOTM_STATE_OS_CMDLINE) {

View file

@ -4,6 +4,8 @@
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*/
#include <command.h>
#include <cpu_func.h>
#include <init.h>
#include <asm/global_data.h>
@ -17,3 +19,11 @@ int arch_initr_trap(void)
return 0;
}
#ifndef CONFIG_SYSRESET
void reset_cpu(void)
{
/* TODO: Refactor all the do_reset calls to be reset_cpu() instead */
do_reset(NULL, 0, 0, NULL);
}
#endif

View file

@ -3,10 +3,13 @@
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
*/
#include <command.h>
#include <cpu.h>
#include <cpu_func.h>
#include <dm.h>
#include <dm/lists.h>
#include <event.h>
#include <hang.h>
#include <init.h>
#include <log.h>
#include <asm/encoding.h>
@ -162,3 +165,13 @@ int arch_early_init_r(void)
__weak void harts_early_init(void)
{
}
#if !CONFIG_IS_ENABLED(SYSRESET)
void reset_cpu(void)
{
printf("resetting ...\n");
printf("reset not supported yet\n");
hang();
}
#endif

View file

@ -7,6 +7,7 @@
*/
#include <bootstage.h>
#include <bootm.h>
#include <command.h>
#include <dm.h>
#include <fdt_support.h>
@ -105,9 +106,10 @@ static void boot_jump_linux(struct bootm_headers *images, int flag)
}
}
int do_bootm_linux(int flag, int argc, char *const argv[],
struct bootm_headers *images)
int do_bootm_linux(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
/* No need for those on RISC-V */
if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
return -1;
@ -127,10 +129,9 @@ int do_bootm_linux(int flag, int argc, char *const argv[],
return 0;
}
int do_bootm_vxworks(int flag, int argc, char *const argv[],
struct bootm_headers *images)
int do_bootm_vxworks(int flag, struct bootm_info *bmi)
{
return do_bootm_linux(flag, argc, argv, images);
return do_bootm_linux(flag, bmi);
}
static ulong get_sp(void)

View file

@ -4,14 +4,11 @@
*/
#include <command.h>
#include <hang.h>
#include <cpu_func.h>
int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
printf("resetting ...\n");
printf("reset not supported yet\n");
hang();
reset_cpu();
return 0;
}

View file

@ -285,6 +285,14 @@ void sandbox_set_enable_pci_map(int enable)
enable_pci_map = enable;
}
void dcache_enable(void)
{
}
void dcache_disable(void)
{
}
int dcache_status(void)
{
return 1;

View file

@ -4,6 +4,7 @@
* Copyright (c) 2015 Sjoerd Simons <sjoerd.simons@collabora.co.uk>
*/
#include <bootm.h>
#include <bootstage.h>
#include <image.h>
#include <asm/io.h>
@ -63,8 +64,10 @@ static int boot_prep_linux(struct bootm_headers *images)
return 0;
}
int do_bootm_linux(int flag, int argc, char *argv[], struct bootm_headers *images)
int do_bootm_linux(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
if (flag & BOOTM_STATE_OS_PREP)
return boot_prep_linux(images);

View file

@ -8,6 +8,7 @@
*/
#include <common.h>
#include <bootm.h>
#include <command.h>
#include <env.h>
#include <image.h>
@ -39,9 +40,10 @@ static unsigned long sh_check_cmd_arg(char *cmdline, char *key, int base)
return val;
}
int do_bootm_linux(int flag, int argc, char *const argv[],
struct bootm_headers *images)
int do_bootm_linux(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
/* Linux kernel load address */
void (*kernel) (void) = (void (*)(void))images->ep;
/* empty_zero_page */

View file

@ -8,6 +8,7 @@
*/
#include <common.h>
#include <bootm.h>
#include <bootstage.h>
#include <command.h>
#include <efi.h>
@ -237,9 +238,10 @@ static int boot_jump_linux(struct bootm_headers *images)
images->os.arch == IH_ARCH_X86_64);
}
int do_bootm_linux(int flag, int argc, char *const argv[],
struct bootm_headers *images)
int do_bootm_linux(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
/* No need for those on x86 */
if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
return -1;

View file

@ -5,6 +5,7 @@
*/
#include <common.h>
#include <bootm.h>
#include <bootstage.h>
#include <command.h>
#include <cpu_func.h>
@ -134,8 +135,9 @@ static struct bp_tag *setup_fdt_tag(struct bp_tag *params, void *fdt_start)
* Boot Linux.
*/
int do_bootm_linux(int flag, int argc, char *argv[], struct bootm_headers *images)
int do_bootm_linux(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
struct bp_tag *params, *params_start;
ulong initrd_start, initrd_end;
char *commandline = env_get("bootargs");

View file

@ -6,6 +6,7 @@
#ifndef USE_HOSTCC
#include <common.h>
#include <bootm.h>
#include <bootstage.h>
#include <cli.h>
#include <command.h>
@ -989,35 +990,9 @@ unmap_image:
return ret;
}
/**
* Execute selected states of the bootm command.
*
* Note the arguments to this state must be the first argument, Any 'bootm'
* or sub-command arguments must have already been taken.
*
* Note that if states contains more than one flag it MUST contain
* BOOTM_STATE_START, since this handles and consumes the command line args.
*
* Also note that aside from boot_os_fn functions and bootm_load_os no other
* functions we store the return value of in 'ret' may use a negative return
* value, without special handling.
*
* @param cmdtp Pointer to bootm command table entry
* @param flag Command flags (CMD_FLAG_...)
* @param argc Number of subcommand arguments (0 = no arguments)
* @param argv Arguments
* @param states Mask containing states to run (BOOTM_STATE_...)
* @param images Image header information
* @param boot_progress 1 to show boot progress, 0 to not do this
* Return: 0 if ok, something else on error. Some errors will cause this
* function to perform a reboot! If states contains BOOTM_STATE_OS_GO
* then the intent is to boot an OS, so this function will not return
* unless the image type is standalone.
*/
int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[], int states, struct bootm_headers *images,
int boot_progress)
int bootm_run_states(struct bootm_info *bmi, int states)
{
struct bootm_headers *images = bmi->images;
boot_os_fn *boot_fn;
ulong iflag = 0;
int ret = 0, need_boot_fn;
@ -1032,17 +1007,18 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
ret = bootm_start();
if (!ret && (states & BOOTM_STATE_PRE_LOAD))
ret = bootm_pre_load(argv[0]);
ret = bootm_pre_load(bmi->addr_img);
if (!ret && (states & BOOTM_STATE_FINDOS))
ret = bootm_find_os(cmdtp->name, argv[0]);
ret = bootm_find_os(bmi->cmd_name, bmi->addr_img);
if (!ret && (states & BOOTM_STATE_FINDOTHER)) {
ulong img_addr;
img_addr = argc ? hextoul(argv[0], NULL) : image_load_addr;
ret = bootm_find_other(img_addr, cmd_arg1(argc, argv),
cmd_arg2(argc, argv));
img_addr = bmi->addr_img ? hextoul(bmi->addr_img, NULL)
: image_load_addr;
ret = bootm_find_other(img_addr, bmi->conf_ramdisk,
bmi->conf_fdt);
}
if (IS_ENABLED(CONFIG_MEASURED_BOOT) && !ret &&
@ -1096,12 +1072,11 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
return 1;
}
/* Call various other states that are not generally used */
if (!ret && (states & BOOTM_STATE_OS_CMDLINE))
ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images);
ret = boot_fn(BOOTM_STATE_OS_CMDLINE, bmi);
if (!ret && (states & BOOTM_STATE_OS_BD_T))
ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images);
ret = boot_fn(BOOTM_STATE_OS_BD_T, bmi);
if (!ret && (states & BOOTM_STATE_OS_PREP)) {
int flags = 0;
/* For Linux OS do all substitutions at console processing */
@ -1113,7 +1088,7 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
ret = CMD_RET_FAILURE;
goto err;
}
ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images);
ret = boot_fn(BOOTM_STATE_OS_PREP, bmi);
}
#ifdef CONFIG_TRACE
@ -1121,10 +1096,9 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) {
char *cmd_list = env_get("fakegocmd");
ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_FAKE_GO,
images, boot_fn);
ret = boot_selected_os(BOOTM_STATE_OS_FAKE_GO, bmi, boot_fn);
if (!ret && cmd_list)
ret = run_command_list(cmd_list, -1, flag);
ret = run_command_list(cmd_list, -1, 0);
}
#endif
@ -1136,37 +1110,61 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
/* Now run the OS! We hope this doesn't return */
if (!ret && (states & BOOTM_STATE_OS_GO))
ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO,
images, boot_fn);
ret = boot_selected_os(BOOTM_STATE_OS_GO, bmi, boot_fn);
/* Deal with any fallout */
err:
if (iflag)
enable_interrupts();
if (ret == BOOTM_ERR_UNIMPLEMENTED)
if (ret == BOOTM_ERR_UNIMPLEMENTED) {
bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL);
else if (ret == BOOTM_ERR_RESET)
do_reset(cmdtp, flag, argc, argv);
} else if (ret == BOOTM_ERR_RESET) {
printf("Resetting the board...\n");
reset_cpu();
}
return ret;
}
int boot_run(struct bootm_info *bmi, const char *cmd, int extra_states)
{
int states;
bmi->cmd_name = cmd;
states = BOOTM_STATE_MEASURE | BOOTM_STATE_OS_PREP |
BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO;
if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH))
states |= BOOTM_STATE_RAMDISK;
states |= extra_states;
return bootm_run_states(bmi, states);
}
int bootm_run(struct bootm_info *bmi)
{
return boot_run(bmi, "bootm", BOOTM_STATE_START | BOOTM_STATE_FINDOS |
BOOTM_STATE_PRE_LOAD | BOOTM_STATE_FINDOTHER |
BOOTM_STATE_LOADOS);
}
int bootz_run(struct bootm_info *bmi)
{
return boot_run(bmi, "bootz", 0);
}
int booti_run(struct bootm_info *bmi)
{
return boot_run(bmi, "booti", 0);
}
int bootm_boot_start(ulong addr, const char *cmdline)
{
static struct cmd_tbl cmd = {"bootm"};
char addr_str[30];
char *argv[] = {addr_str, NULL};
struct bootm_info bmi;
int states;
int ret;
/*
* TODO(sjg@chromium.org): This uses the command-line interface, but
* should not. To clean this up, the various bootm states need to be
* passed an info structure instead of cmdline flags. Then this can
* set up the required info and move through the states without needing
* the command line.
*/
states = BOOTM_STATE_START | BOOTM_STATE_FINDOS | BOOTM_STATE_PRE_LOAD |
BOOTM_STATE_FINDOTHER | BOOTM_STATE_LOADOS |
BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
@ -1184,11 +1182,22 @@ int bootm_boot_start(ulong addr, const char *cmdline)
printf("Failed to set cmdline\n");
return ret;
}
ret = do_bootm_states(&cmd, 0, 1, argv, states, &images, 1);
bootm_init(&bmi);
bmi.addr_img = addr_str;
bmi.cmd_name = "bootm";
ret = bootm_run_states(&bmi, states);
return ret;
}
void bootm_init(struct bootm_info *bmi)
{
memset(bmi, '\0', sizeof(struct bootm_info));
bmi->boot_progress = true;
if (IS_ENABLED(CONFIG_CMD_BOOTM))
bmi->images = &images;
}
/**
* switch_to_non_secure_mode() - switch to non-secure mode
*

View file

@ -23,9 +23,9 @@
DECLARE_GLOBAL_DATA_PTR;
static int do_bootm_standalone(int flag, int argc, char *const argv[],
struct bootm_headers *images)
static int do_bootm_standalone(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
int (*appl)(int, char *const[]);
if (!env_get_autostart()) {
@ -33,7 +33,7 @@ static int do_bootm_standalone(int flag, int argc, char *const argv[],
return 0;
}
appl = (int (*)(int, char * const []))images->ep;
appl(argc, argv);
appl(bmi->argc, bmi->argv);
return 0;
}
@ -64,9 +64,9 @@ static void __maybe_unused fit_unsupported_reset(const char *msg)
}
#ifdef CONFIG_BOOTM_NETBSD
static int do_bootm_netbsd(int flag, int argc, char *const argv[],
struct bootm_headers *images)
static int do_bootm_netbsd(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
void (*loader)(struct bd_info *bd, struct legacy_img_hdr *hdr,
char *console, char *cmdline);
struct legacy_img_hdr *os_hdr, *hdr;
@ -102,14 +102,14 @@ static int do_bootm_netbsd(int flag, int argc, char *const argv[],
os_hdr = hdr;
}
if (argc > 0) {
if (bmi->argc > 0) {
ulong len;
int i;
for (i = 0, len = 0; i < argc; i += 1)
len += strlen(argv[i]) + 1;
for (i = 0, len = 0; i < bmi->argc; i += 1)
len += strlen(bmi->argv[i]) + 1;
cmdline = malloc(len);
copy_args(cmdline, argc, argv, ' ');
copy_args(cmdline, bmi->argc, bmi->argv, ' ');
} else {
cmdline = env_get("bootargs");
if (cmdline == NULL)
@ -137,9 +137,9 @@ static int do_bootm_netbsd(int flag, int argc, char *const argv[],
#endif /* CONFIG_BOOTM_NETBSD*/
#ifdef CONFIG_BOOTM_RTEMS
static int do_bootm_rtems(int flag, int argc, char *const argv[],
struct bootm_headers *images)
static int do_bootm_rtems(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
void (*entry_point)(struct bd_info *);
if (flag != BOOTM_STATE_OS_GO)
@ -170,9 +170,9 @@ static int do_bootm_rtems(int flag, int argc, char *const argv[],
#endif /* CONFIG_BOOTM_RTEMS */
#if defined(CONFIG_BOOTM_OSE)
static int do_bootm_ose(int flag, int argc, char *const argv[],
struct bootm_headers *images)
static int do_bootm_ose(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
void (*entry_point)(void);
if (flag != BOOTM_STATE_OS_GO)
@ -203,9 +203,9 @@ static int do_bootm_ose(int flag, int argc, char *const argv[],
#endif /* CONFIG_BOOTM_OSE */
#if defined(CONFIG_BOOTM_PLAN9)
static int do_bootm_plan9(int flag, int argc, char *const argv[],
struct bootm_headers *images)
static int do_bootm_plan9(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
void (*entry_point)(void);
char *s;
@ -224,8 +224,8 @@ static int do_bootm_plan9(int flag, int argc, char *const argv[],
if (s != NULL) {
char *confaddr = (char *)hextoul(s, NULL);
if (argc > 0) {
copy_args(confaddr, argc, argv, '\n');
if (bmi->argc) {
copy_args(confaddr, bmi->argc, bmi->argv, '\n');
} else {
s = env_get("bootargs");
if (s != NULL)
@ -311,9 +311,10 @@ static void do_bootvx_fdt(struct bootm_headers *images)
puts("## vxWorks terminated\n");
}
static int do_bootm_vxworks_legacy(int flag, int argc, char *const argv[],
struct bootm_headers *images)
static int do_bootm_vxworks_legacy(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
if (flag != BOOTM_STATE_OS_GO)
return 0;
@ -322,8 +323,7 @@ static int do_bootm_vxworks_legacy(int flag, int argc, char *const argv[],
return 1;
}
int do_bootm_vxworks(int flag, int argc, char *const argv[],
struct bootm_headers *images)
int do_bootm_vxworks(int flag, struct bootm_info *bmi)
{
char *bootargs;
int pos;
@ -348,19 +348,19 @@ int do_bootm_vxworks(int flag, int argc, char *const argv[],
if (std_dtb) {
if (flag & BOOTM_STATE_OS_PREP)
printf(" Using standard DTB\n");
return do_bootm_linux(flag, argc, argv, images);
return do_bootm_linux(flag, bmi);
} else {
if (flag & BOOTM_STATE_OS_PREP)
printf(" !!! WARNING !!! Using legacy DTB\n");
return do_bootm_vxworks_legacy(flag, argc, argv, images);
return do_bootm_vxworks_legacy(flag, bmi);
}
}
#endif
#if defined(CONFIG_CMD_ELF)
static int do_bootm_qnxelf(int flag, int argc, char *const argv[],
struct bootm_headers *images)
static int do_bootm_qnxelf(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
char *local_args[2];
char str[16];
int dcache;
@ -376,7 +376,7 @@ static int do_bootm_qnxelf(int flag, int argc, char *const argv[],
#endif
sprintf(str, "%lx", images->ep); /* write entry-point into string */
local_args[0] = argv[0];
local_args[0] = bmi->argv[0];
local_args[1] = str; /* and provide it via the arguments */
/*
@ -396,9 +396,9 @@ static int do_bootm_qnxelf(int flag, int argc, char *const argv[],
#endif
#ifdef CONFIG_INTEGRITY
static int do_bootm_integrity(int flag, int argc, char *const argv[],
struct bootm_headers *images)
static int do_bootm_integrity(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
void (*entry_point)(void);
if (flag != BOOTM_STATE_OS_GO)
@ -429,9 +429,9 @@ static int do_bootm_integrity(int flag, int argc, char *const argv[],
#endif
#ifdef CONFIG_BOOTM_OPENRTOS
static int do_bootm_openrtos(int flag, int argc, char *const argv[],
struct bootm_headers *images)
static int do_bootm_openrtos(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
void (*entry_point)(void);
if (flag != BOOTM_STATE_OS_GO)
@ -455,9 +455,9 @@ static int do_bootm_openrtos(int flag, int argc, char *const argv[],
#endif
#ifdef CONFIG_BOOTM_OPTEE
static int do_bootm_tee(int flag, int argc, char *const argv[],
struct bootm_headers *images)
static int do_bootm_tee(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
int ret;
/* Validate OPTEE header */
@ -468,14 +468,14 @@ static int do_bootm_tee(int flag, int argc, char *const argv[],
return ret;
/* From here we can run the regular linux boot path */
return do_bootm_linux(flag, argc, argv, images);
return do_bootm_linux(flag, bmi);
}
#endif
#ifdef CONFIG_BOOTM_EFI
static int do_bootm_efi(int flag, int argc, char *const argv[],
struct bootm_headers *images)
static int do_bootm_efi(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
int ret;
void *image_buf;
@ -550,15 +550,15 @@ __weak void board_preboot_os(void)
/* please define board specific board_preboot_os() */
}
int boot_selected_os(int argc, char *const argv[], int state,
struct bootm_headers *images, boot_os_fn *boot_fn)
int boot_selected_os(int state, struct bootm_info *bmi, boot_os_fn *boot_fn)
{
arch_preboot_os();
board_preboot_os();
boot_fn(state, argc, argv, images);
boot_fn(state, bmi);
/* Stand-alone may return when 'autostart' is 'no' */
if (images->os.type == IH_TYPE_STANDALONE ||
if (bmi->images->os.type == IH_TYPE_STANDALONE ||
IS_ENABLED(CONFIG_SANDBOX) ||
state == BOOTM_STATE_OS_FAKE_GO) /* We expect to return */
return 0;

View file

@ -20,9 +20,9 @@ DECLARE_GLOBAL_DATA_PTR;
/*
* Image booting support
*/
static int booti_start(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[], struct bootm_headers *images)
static int booti_start(struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
int ret;
ulong ld;
ulong relocated_addr;
@ -34,16 +34,15 @@ static int booti_start(struct cmd_tbl *cmdtp, int flag, int argc,
unsigned long decomp_len;
int ctype;
ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
images, 1);
ret = bootm_run_states(bmi, BOOTM_STATE_START);
/* Setup Linux kernel Image entry point */
if (!argc) {
if (!bmi->addr_img) {
ld = image_load_addr;
debug("* kernel: default image load address = 0x%08lx\n",
image_load_addr);
} else {
ld = hextoul(argv[0], NULL);
ld = hextoul(bmi->addr_img, NULL);
debug("* kernel: cmdline image address = 0x%08lx\n", ld);
}
@ -95,9 +94,8 @@ static int booti_start(struct cmd_tbl *cmdtp, int flag, int argc,
* Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
* have a header that provide this informaiton.
*/
if (bootm_find_images(image_load_addr, cmd_arg1(argc, argv),
cmd_arg2(argc, argv), relocated_addr,
image_size))
if (bootm_find_images(image_load_addr, bmi->conf_ramdisk, bmi->conf_fdt,
relocated_addr, image_size))
return 1;
return 0;
@ -105,12 +103,25 @@ static int booti_start(struct cmd_tbl *cmdtp, int flag, int argc,
int do_booti(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
struct bootm_info bmi;
int states;
int ret;
/* Consume 'booti' */
argc--; argv++;
if (booti_start(cmdtp, flag, argc, argv, &images))
bootm_init(&bmi);
if (argc)
bmi.addr_img = argv[0];
if (argc > 1)
bmi.conf_ramdisk = argv[1];
if (argc > 2)
bmi.conf_fdt = argv[2];
bmi.boot_progress = true;
bmi.cmd_name = "booti";
/* do not set up argc and argv[] since nothing uses them */
if (booti_start(&bmi))
return 1;
/*
@ -120,19 +131,17 @@ int do_booti(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
bootm_disable_interrupts();
images.os.os = IH_OS_LINUX;
#ifdef CONFIG_RISCV_SMODE
images.os.arch = IH_ARCH_RISCV;
#elif CONFIG_ARM64
images.os.arch = IH_ARCH_ARM64;
#endif
ret = do_bootm_states(cmdtp, flag, argc, argv,
#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
BOOTM_STATE_RAMDISK |
#endif
BOOTM_STATE_MEASURE |
BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
BOOTM_STATE_OS_GO,
&images, 1);
if (IS_ENABLED(CONFIG_RISCV_SMODE))
images.os.arch = IH_ARCH_RISCV;
else if (IS_ENABLED(CONFIG_ARM64))
images.os.arch = IH_ARCH_ARM64;
states = BOOTM_STATE_MEASURE | BOOTM_STATE_OS_PREP |
BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO;
if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH))
states |= BOOTM_STATE_RAMDISK;
ret = bootm_run_states(&bmi, states);
return ret;
}

View file

@ -76,6 +76,7 @@ static ulong bootm_get_addr(int argc, char *const argv[])
static int do_bootm_subcommand(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
struct bootm_info bmi;
int ret = 0;
long state;
struct cmd_tbl *c;
@ -103,7 +104,21 @@ static int do_bootm_subcommand(struct cmd_tbl *cmdtp, int flag, int argc,
return CMD_RET_USAGE;
}
ret = do_bootm_states(cmdtp, flag, argc, argv, state, &images, 0);
bootm_init(&bmi);
if (argc)
bmi.addr_img = argv[0];
if (argc > 1)
bmi.conf_ramdisk = argv[1];
if (argc > 2)
bmi.conf_fdt = argv[2];
bmi.cmd_name = "bootm";
bmi.boot_progress = false;
/* set up argc and argv[] since some OSes use them */
bmi.argc = argc;
bmi.argv = argv;
ret = bootm_run_states(&bmi, state);
#if defined(CONFIG_CMD_BOOTM_PRE_LOAD)
if (!ret && (state & BOOTM_STATE_PRE_LOAD))
@ -120,7 +135,7 @@ static int do_bootm_subcommand(struct cmd_tbl *cmdtp, int flag, int argc,
int do_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
int states;
struct bootm_info bmi;
int ret;
/* determine if we have a sub command */
@ -141,17 +156,19 @@ int do_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
return do_bootm_subcommand(cmdtp, flag, argc, argv);
}
states = BOOTM_STATE_START | BOOTM_STATE_FINDOS | BOOTM_STATE_PRE_LOAD |
BOOTM_STATE_FINDOTHER | BOOTM_STATE_LOADOS |
BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
BOOTM_STATE_OS_GO;
if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH))
states |= BOOTM_STATE_RAMDISK;
if (IS_ENABLED(CONFIG_MEASURED_BOOT))
states |= BOOTM_STATE_MEASURE;
if (IS_ENABLED(CONFIG_PPC) || IS_ENABLED(CONFIG_MIPS))
states |= BOOTM_STATE_OS_CMDLINE;
ret = do_bootm_states(cmdtp, flag, argc, argv, states, &images, 1);
bootm_init(&bmi);
if (argc)
bmi.addr_img = argv[0];
if (argc > 1)
bmi.conf_ramdisk = argv[1];
if (argc > 2)
bmi.conf_fdt = argv[2];
/* set up argc and argv[] since some OSes use them */
bmi.argc = argc;
bmi.argv = argv;
ret = bootm_run(&bmi);
return ret ? CMD_RET_FAILURE : 0;
}

View file

@ -27,11 +27,20 @@ int __weak bootz_setup(ulong image, ulong *start, ulong *end)
static int bootz_start(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[], struct bootm_headers *images)
{
int ret;
ulong zi_start, zi_end;
struct bootm_info bmi;
int ret;
ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
images, 1);
bootm_init(&bmi);
if (argc)
bmi.addr_img = argv[0];
if (argc > 1)
bmi.conf_ramdisk = argv[1];
if (argc > 2)
bmi.conf_fdt = argv[2];
/* do not set up argc and argv[] since nothing uses them */
ret = bootm_run_states(&bmi, BOOTM_STATE_START);
/* Setup Linux kernel zImage entry point */
if (!argc) {
@ -64,6 +73,7 @@ static int bootz_start(struct cmd_tbl *cmdtp, int flag, int argc,
int do_bootz(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
struct bootm_info bmi;
int ret;
/* Consume 'bootz' */
@ -79,14 +89,17 @@ int do_bootz(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
bootm_disable_interrupts();
images.os.os = IH_OS_LINUX;
ret = do_bootm_states(cmdtp, flag, argc, argv,
#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
BOOTM_STATE_RAMDISK |
#endif
BOOTM_STATE_MEASURE |
BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
BOOTM_STATE_OS_GO,
&images, 1);
bootm_init(&bmi);
if (argc)
bmi.addr_img = argv[0];
if (argc > 1)
bmi.conf_ramdisk = argv[1];
if (argc > 2)
bmi.conf_fdt = argv[2];
bmi.cmd_name = "bootz";
ret = bootz_run(&bmi);
return ret;
}

View file

@ -44,10 +44,11 @@ CONFIG_CMD_CPU=y
CONFIG_CMD_LICENSE=y
CONFIG_CMD_BOOTM_PRE_LOAD=y
CONFIG_CMD_BOOTZ=y
CONFIG_BOOTM_OPENRTOS=y
CONFIG_BOOTM_OSE=y
CONFIG_CMD_BOOTEFI_HELLO=y
CONFIG_CMD_BOOTMENU=y
CONFIG_CMD_ABOOTIMG=y
# CONFIG_CMD_ELF is not set
CONFIG_CMD_ASKENV=y
CONFIG_CMD_GREPENV=y
CONFIG_CMD_ERASEENV=y

View file

@ -16,6 +16,55 @@ struct cmd_tbl;
#define BOOTM_ERR_OVERLAP (-2)
#define BOOTM_ERR_UNIMPLEMENTED (-3)
/**
* struct bootm_info() - information used when processing images to boot
*
* These mirror the first three arguments of the bootm command. They are
* designed to handle any type of image, but typically it is a FIT.
*
* @addr_img: Address of image to bootm, as passed to
* genimg_get_kernel_addr_fit() for processing:
*
* NULL: Usees default load address, i.e. image_load_addr
* <addr>: Uses hex address
*
* For FIT:
* "[<addr>]#<conf>": Uses address (or image_load_addr) and also specifies
* the FIT configuration to use
* "[<addr>]:<subimage>": Uses address (or image_load_addr) and also
* specifies the subimage name containing the OS
*
* @conf_ramdisk: Address (or with FIT, the name) of the ramdisk image, as
* passed to boot_get_ramdisk() for processing, or NULL for none
* @conf_fdt: Address (or with FIT, the name) of the FDT image, as passed to
* boot_get_fdt() for processing, or NULL for none
* @boot_progress: true to show boot progress
* @images: images information
* @cmd_name: command which invoked this operation, e.g. "bootm"
* @argc: Number of arguments to the command (excluding the actual command).
* This is 0 if there are no arguments
* @argv: NULL-terminated list of arguments, or NULL if there are no arguments
*/
struct bootm_info {
const char *addr_img;
const char *conf_ramdisk;
const char *conf_fdt;
bool boot_progress;
struct bootm_headers *images;
const char *cmd_name;
int argc;
char *const *argv;
};
/**
* bootm_init() - Set up a bootm_info struct with useful defaults
*
* Set up the struct with default values for all members:
* @boot_progress is set to true and @images is set to the global images
* variable. Everything else is set to NULL except @argc which is 0
*/
void bootm_init(struct bootm_info *bmi);
/*
* Continue booting an OS image; caller already has:
* - copied image header to global variable `header'
@ -25,21 +74,16 @@ struct cmd_tbl;
* - disabled interrupts.
*
* @flag: Flags indicating what to do (BOOTM_STATE_...)
* @argc: Number of arguments. Note that the arguments are shifted down
* so that 0 is the first argument not processed by U-Boot, and
* argc is adjusted accordingly. This avoids confusion as to how
* many arguments are available for the OS.
* @images: Pointers to os/initrd/fdt
* bmi: Bootm information
* Return: 1 on error. On success the OS boots so this function does
* not return.
*/
typedef int boot_os_fn(int flag, int argc, char *const argv[],
struct bootm_headers *images);
typedef int boot_os_fn(int flag, struct bootm_info *bmi);
extern boot_os_fn do_bootm_linux;
extern boot_os_fn do_bootm_vxworks;
int do_bootelf(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
int do_bootelf(struct cmd_tbl *cmdtp, int fglag, int argc, char *const argv[]);
boot_os_fn *bootm_os_get_boot_func(int os);
@ -47,8 +91,7 @@ boot_os_fn *bootm_os_get_boot_func(int os);
int bootm_host_load_images(const void *fit, int cfg_noffset);
#endif
int boot_selected_os(int argc, char *const argv[], int state,
struct bootm_headers *images, boot_os_fn *boot_fn);
int boot_selected_os(int state, struct bootm_info *bmi, boot_os_fn *boot_fn);
ulong bootm_disable_interrupts(void);
@ -87,9 +130,82 @@ int bootm_find_images(ulong img_addr, const char *conf_ramdisk,
*/
int bootm_measure(struct bootm_headers *images);
int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[], int states, struct bootm_headers *images,
int boot_progress);
/**
* bootm_run_states() - Execute selected states of the bootm command.
*
* Note that if states contains more than one flag it MUST contain
* BOOTM_STATE_START, since this handles the addr_fit, conf_ramdisk and conf_fit
* members of @bmi
*
* Also note that aside from boot_os_fn functions and bootm_load_os, no other
* functions store the return value of in 'ret' may use a negative return
* value, without special handling.
*
* @bmi: bootm information
* @states Mask containing states to run (BOOTM_STATE_...)
* Return: 0 if ok, something else on error. Some errors will cause this
* function to perform a reboot! If states contains BOOTM_STATE_OS_GO
* then the intent is to boot an OS, so this function will not return
* unless the image type is standalone.
*/
int bootm_run_states(struct bootm_info *bmi, int states);
/**
* boot_run() - Run the entire bootm/booti/bootz process
*
* This runs through the boot process from start to finish, with a base set of
* states, along with the extra ones supplied.
*
* This uses bootm_run_states().
*
* Note that it is normally easier to use bootm_run(), etc. since they handle
* the extra states correctly.
*
* @bmi: bootm information
* @cmd: command being run, NULL if none
* @extra_states: Mask of extra states to use for the boot
* Return: 0 if ok, something else on error
*/
int boot_run(struct bootm_info *bmi, const char *cmd, int extra_states);
/**
* bootm_run() - Run the entire bootm process
*
* This runs through the bootm process from start to finish, using the default
* set of states.
*
* This uses bootm_run_states().
*
* @bmi: bootm information
* Return: 0 if ok, something else on error
*/
int bootm_run(struct bootm_info *bmi);
/**
* bootz_run() - Run the entire bootz process
*
* This runs through the bootz process from start to finish, using the default
* set of states.
*
* This uses bootm_run_states().
*
* @bmi: bootm information
* Return: 0 if ok, something else on error
*/
int bootz_run(struct bootm_info *bmi);
/**
* booti_run() - Run the entire booti process
*
* This runs through the booti process from start to finish, using the default
* set of states.
*
* This uses bootm_run_states().
*
* @bmi: bootm information
* Return: 0 if ok, something else on error
*/
int booti_run(struct bootm_info *bmi);
void arch_preboot_os(void);