Merge patch series "pxe: Precursor series for supporting read_all() in extlinux / PXE"

Simon Glass <sjg@chromium.org> says:

This series includes some patches related to allowing read_all() to be
used with the extlinux / PXE bootmeths.

These patches were split out from the stb4 series, since it will need to
have additional patches for LWIP, to avoid breaking PXE booting when
LWIP is used.

Link: https://lore.kernel.org/r/20250306002533.2380866-1-sjg@chromium.org
This commit is contained in:
Tom Rini 2025-03-18 13:12:51 -06:00
commit 8bc3542384
17 changed files with 663 additions and 379 deletions

View file

@ -28,6 +28,13 @@ struct Image_header {
uint32_t res5;
};
bool booti_is_valid(const void *img)
{
const struct Image_header *ih = img;
return ih->magic == le32_to_cpu(LINUX_ARM64_IMAGE_MAGIC);
}
int booti_setup(ulong image, ulong *relocated_addr, ulong *size,
bool force_reloc)
{
@ -39,7 +46,7 @@ int booti_setup(ulong image, ulong *relocated_addr, ulong *size,
ih = (struct Image_header *)map_sysmem(image, 0);
if (ih->magic != le32_to_cpu(LINUX_ARM64_IMAGE_MAGIC)) {
if (!booti_is_valid(ih)) {
puts("Bad Linux ARM64 Image magic!\n");
return 1;
}

View file

@ -32,6 +32,13 @@ struct linux_image_h {
uint32_t res4; /* reserved */
};
bool booti_is_valid(const void *img)
{
const struct linux_image_h *lhdr = img;
return lhdr->magic == LINUX_RISCV_IMAGE_MAGIC;
}
int booti_setup(ulong image, ulong *relocated_addr, ulong *size,
bool force_reloc)
{
@ -39,7 +46,7 @@ int booti_setup(ulong image, ulong *relocated_addr, ulong *size,
lhdr = (struct linux_image_h *)map_sysmem(image, 0);
if (lhdr->magic != LINUX_RISCV_IMAGE_MAGIC) {
if (!booti_is_valid(lhdr)) {
puts("Bad Linux RISCV Image magic!\n");
return -EINVAL;
}

View file

@ -89,3 +89,8 @@ int booti_setup(ulong image, ulong *relocated_addr, ulong *size,
return 1;
}
bool booti_is_valid(const void *img)
{
return false;
}

View file

@ -10,6 +10,8 @@
#include <asm/bootparam.h>
#include <asm/e820.h>
struct bootm_info;
/* linux i386 zImage/bzImage header. Offsets relative to
* the start of the image */
@ -42,43 +44,6 @@ enum {
ZBOOT_STATE_COUNT = 5,
};
/**
* struct zboot_state - Current state of the boot
*
* @bzimage_addr: Address of the bzImage to boot, or 0 if the image has already
* been loaded and does not exist (as a cohesive whole) in memory
* @bzimage_size: Size of the bzImage, or 0 to detect this
* @initrd_addr: Address of the initial ramdisk, or 0 if none
* @initrd_size: Size of the initial ramdisk, or 0 if none
* @load_address: Address where the bzImage is moved before booting, either
* BZIMAGE_LOAD_ADDR or ZIMAGE_LOAD_ADDR
* This is set up when loading the zimage
* @base_ptr: Pointer to the boot parameters, typically at address
* DEFAULT_SETUP_BASE
* This is set up when loading the zimage
* @cmdline: Environment variable containing the 'override' command line, or
* NULL to use the one in the setup block
*/
struct zboot_state {
ulong bzimage_addr;
ulong bzimage_size;
ulong initrd_addr;
ulong initrd_size;
ulong load_address;
struct boot_params *base_ptr;
const char *cmdline;
};
extern struct zboot_state state;
/**
* zimage_dump() - Dump information about a zimage
*
* @base_ptr: Pointer to the boot parameters
* @show_cmdline: true to show the kernel command line
*/
void zimage_dump(struct boot_params *base_ptr, bool show_cmdline);
/**
* zboot_load() - Load a zimage
*
@ -86,21 +51,21 @@ void zimage_dump(struct boot_params *base_ptr, bool show_cmdline);
*
* Return: 0 if OK, -ve on error
*/
int zboot_load(void);
int zboot_load(struct bootm_info *bmi);
/**
* zboot_setup() - Set up the zboot image reeady for booting
*
* Return: 0 if OK, -ve on error
*/
int zboot_setup(void);
int zboot_setup(struct bootm_info *bmi);
/**
* zboot_go() - Start the image
*
* Return: 0 if OK, -ve on error
*/
int zboot_go(void);
int zboot_go(struct bootm_info *bmi);
/**
* load_zimage() - Load a zImage or bzImage
@ -139,6 +104,7 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
*
* Record information about a zimage so it can be booted
*
* @bmi: Bootm information
* @bzimage_addr: Address of the bzImage to boot
* @bzimage_size: Size of the bzImage, or 0 to detect this
* @initrd_addr: Address of the initial ramdisk, or 0 if none
@ -149,14 +115,17 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
* @cmdline: Environment variable containing the 'override' command line, or
* NULL to use the one in the setup block
*/
void zboot_start(ulong bzimage_addr, ulong bzimage_size, ulong initrd_addr,
ulong initrd_size, ulong base_addr, const char *cmdline);
void zboot_start(struct bootm_info *bmi, ulong bzimage_addr, ulong bzimage_size,
ulong initrd_addr, ulong initrd_size, ulong base_addr,
const char *cmdline);
/**
* zboot_info() - Show simple info about a zimage
*
* Shows wherer the kernel was loaded and also the setup base
* Shows where the kernel was loaded and also the setup base
*
* @bmi: Bootm information
*/
void zboot_info(void);
void zboot_info(struct bootm_info *bmi);
#endif

View file

@ -55,9 +55,6 @@ DECLARE_GLOBAL_DATA_PTR;
#define COMMAND_LINE_SIZE 2048
/* Current state of the boot */
struct zboot_state state;
static void build_command_line(char *command_line, int auto_boot)
{
char *env_command_line;
@ -366,13 +363,13 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
return 0;
}
int zboot_load(void)
int zboot_load(struct bootm_info *bmi)
{
struct boot_params *base_ptr;
int ret;
if (state.base_ptr) {
struct boot_params *from = (struct boot_params *)state.base_ptr;
if (bmi->base_ptr) {
struct boot_params *from = (struct boot_params *)bmi->base_ptr;
base_ptr = (struct boot_params *)DEFAULT_SETUP_BASE;
log_debug("Building boot_params at 0x%8.8lx\n",
@ -380,41 +377,41 @@ int zboot_load(void)
memset(base_ptr, '\0', sizeof(*base_ptr));
base_ptr->hdr = from->hdr;
} else {
base_ptr = load_zimage((void *)state.bzimage_addr, state.bzimage_size,
&state.load_address);
base_ptr = load_zimage((void *)bmi->bzimage_addr,
bmi->bzimage_size, &bmi->load_address);
if (!base_ptr) {
puts("## Kernel loading failed ...\n");
return -EINVAL;
}
}
state.base_ptr = base_ptr;
bmi->base_ptr = base_ptr;
ret = env_set_hex("zbootbase", map_to_sysmem(state.base_ptr));
ret = env_set_hex("zbootbase", map_to_sysmem(bmi->base_ptr));
if (!ret)
ret = env_set_hex("zbootaddr", state.load_address);
ret = env_set_hex("zbootaddr", bmi->load_address);
if (ret)
return ret;
return 0;
}
int zboot_setup(void)
int zboot_setup(struct bootm_info *bmi)
{
struct boot_params *base_ptr = state.base_ptr;
struct boot_params *base_ptr = bmi->base_ptr;
int ret;
ret = setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET,
0, state.initrd_addr, state.initrd_size,
(ulong)state.cmdline);
0, bmi->initrd_addr, bmi->initrd_size,
(ulong)bmi->cmdline);
if (ret)
return -EINVAL;
return 0;
}
int zboot_go(void)
int zboot_go(struct bootm_info *bmi)
{
struct boot_params *params = state.base_ptr;
struct boot_params *params = bmi->base_ptr;
struct setup_header *hdr = &params->hdr;
bool image_64bit;
ulong entry;
@ -422,7 +419,7 @@ int zboot_go(void)
disable_interrupts();
entry = state.load_address;
entry = bmi->load_address;
image_64bit = false;
if (IS_ENABLED(CONFIG_X86_RUN_64BIT) &&
(hdr->xloadflags & XLF_KERNEL_64)) {
@ -430,30 +427,43 @@ int zboot_go(void)
}
/* we assume that the kernel is in place */
ret = boot_linux_kernel((ulong)state.base_ptr, entry, image_64bit);
ret = boot_linux_kernel((ulong)bmi->base_ptr, entry, image_64bit);
return ret;
}
int zboot_run(ulong addr, ulong size, ulong initrd, ulong initrd_size,
ulong base, char *cmdline)
int zboot_run(struct bootm_info *bmi)
{
int ret;
zboot_start(addr, size, initrd, initrd_size, base, cmdline);
ret = zboot_load();
ret = zboot_load(bmi);
if (ret)
return log_msg_ret("ld", ret);
ret = zboot_setup();
ret = zboot_setup(bmi);
if (ret)
return log_msg_ret("set", ret);
ret = zboot_go();
ret = zboot_go(bmi);
if (ret)
return log_msg_ret("go", ret);
return -EFAULT;
}
int zboot_run_args(ulong addr, ulong size, ulong initrd, ulong initrd_size,
ulong base, char *cmdline)
{
struct bootm_info bmi;
int ret;
bootm_init(&bmi);
zboot_start(&bmi, addr, size, initrd, initrd_size, base, cmdline);
ret = zboot_run(&bmi);
if (ret)
return log_msg_ret("zra", ret);
return 0;
}
static void print_num(const char *name, ulong value)
{
printf("%-20s: %lx\n", name, value);
@ -555,12 +565,13 @@ static void show_loader(struct setup_header *hdr)
printf("\n");
}
void zimage_dump(struct boot_params *base_ptr, bool show_cmdline)
void zimage_dump(struct bootm_info *bmi, bool show_cmdline)
{
struct boot_params *base_ptr;
struct setup_header *hdr;
const char *version;
int i;
base_ptr = bmi->base_ptr;
printf("Setup located at %p:\n\n", base_ptr);
print_num64("ACPI RSDP addr", base_ptr->acpi_rsdp_addr);
@ -595,10 +606,14 @@ void zimage_dump(struct boot_params *base_ptr, bool show_cmdline)
print_num("Real mode switch", hdr->realmode_swtch);
print_num("Start sys seg", hdr->start_sys_seg);
print_num("Kernel version", hdr->kernel_version);
if (bmi->bzimage_addr) {
const char *version;
version = zimage_get_kernel_version(base_ptr,
(void *)state.bzimage_addr);
(void *)bmi->bzimage_addr);
if (version)
printf(" @%p: %s\n", version, version);
}
print_num("Type of loader", hdr->type_of_loader);
show_loader(hdr);
print_num("Load flags", hdr->loadflags);
@ -639,25 +654,24 @@ void zimage_dump(struct boot_params *base_ptr, bool show_cmdline)
print_num("Kernel info offset", hdr->kernel_info_offset);
}
void zboot_start(ulong bzimage_addr, ulong bzimage_size, ulong initrd_addr,
ulong initrd_size, ulong base_addr, const char *cmdline)
void zboot_start(struct bootm_info *bmi, ulong bzimage_addr, ulong bzimage_size,
ulong initrd_addr, ulong initrd_size, ulong base_addr,
const char *cmdline)
{
memset(&state, '\0', sizeof(state));
state.bzimage_size = bzimage_size;
state.initrd_addr = initrd_addr;
state.initrd_size = initrd_size;
bmi->bzimage_size = bzimage_size;
bmi->initrd_addr = initrd_addr;
bmi->initrd_size = initrd_size;
if (base_addr) {
state.base_ptr = map_sysmem(base_addr, 0);
state.load_address = bzimage_addr;
bmi->base_ptr = map_sysmem(base_addr, 0);
bmi->load_address = bzimage_addr;
} else {
state.bzimage_addr = bzimage_addr;
bmi->bzimage_addr = bzimage_addr;
}
state.cmdline = cmdline;
bmi->cmdline = cmdline;
}
void zboot_info(void)
void zboot_info(struct bootm_info *bmi)
{
printf("Kernel loaded at %08lx, setup_base=%p\n",
state.load_address, state.base_ptr);
bmi->load_address, bmi->base_ptr);
}

View file

@ -10,7 +10,7 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o bootm_os.o
obj-$(CONFIG_CMD_BOOTZ) += bootm.o bootm_os.o
obj-$(CONFIG_CMD_BOOTI) += bootm.o bootm_os.o
obj-$(CONFIG_PXE_UTILS) += pxe_utils.o
obj-$(CONFIG_PXE_UTILS) += bootm.o pxe_utils.o
endif

View file

@ -146,7 +146,7 @@ static int boot_get_kernel(const char *addr_fit, struct bootm_headers *images,
/* check image type, for FIT images get FIT kernel node */
*os_data = *os_len = 0;
buf = map_sysmem(img_addr, 0);
switch (genimg_get_format(buf)) {
switch (genimg_get_format_comp(buf)) {
#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
case IMAGE_FORMAT_LEGACY:
printf("## Booting kernel from Legacy Image at %08lx ...\n",
@ -227,6 +227,9 @@ static int boot_get_kernel(const char *addr_fit, struct bootm_headers *images,
break;
}
#endif
case IMAGE_FORMAT_BOOTI:
*os_data = img_addr;
break;
default:
bootstage_error(BOOTSTAGE_ID_CHECK_IMAGETYPE);
return -EPROTOTYPE;
@ -286,6 +289,35 @@ static int bootm_pre_load(const char *addr_str)
return ret;
}
static int found_booti_os(enum image_comp_t comp)
{
images.os.load = images.os.image_start;
images.os.type = IH_TYPE_KERNEL;
images.os.os = IH_OS_LINUX;
images.os.comp = comp;
if (IS_ENABLED(CONFIG_RISCV_SMODE))
images.os.arch = IH_ARCH_RISCV;
else if (IS_ENABLED(CONFIG_ARM64))
images.os.arch = IH_ARCH_ARM64;
log_debug("load %lx start %lx len %lx ep %lx os %x comp %x\n",
images.os.load, images.os.image_start, images.os.image_len,
images.ep, images.os.os, images.os.comp);
if (comp != IH_COMP_NONE) {
images.os.load = env_get_hex("kernel_comp_addr_r", 0);
images.os.image_len = env_get_ulong("kernel_comp_size", 16, 0);
if (!images.os.load || !images.os.image_len) {
puts("kernel_comp_addr_r or kernel_comp_size is not provided!\n");
return -ENOTSUPP;
}
if (lmb_reserve(images.os.load, images.os.image_len, LMB_NONE)
< 0)
return -EXDEV;
}
return 0;
}
/**
* bootm_find_os(): Find the OS to boot
*
@ -390,7 +422,28 @@ static int bootm_find_os(const char *cmd_name, const char *addr_fit)
}
break;
#endif
case IMAGE_FORMAT_BOOTI:
if (IS_ENABLED(CONFIG_CMD_BOOTI)) {
if (found_booti_os(IH_COMP_NONE))
return 1;
ep_found = true;
break;
}
fallthrough;
default:
/* any compressed image is probably a booti image */
if (IS_ENABLED(CONFIG_CMD_BOOTI)) {
int comp;
comp = image_decomp_type(os_hdr, 2);
if (comp != IH_COMP_NONE) {
if (found_booti_os(comp))
return 1;
ep_found = true;
}
break;
}
puts("ERROR: unknown image format type!\n");
return 1;
}
@ -541,6 +594,7 @@ int bootm_find_images(ulong img_addr, const char *conf_ramdisk,
static int bootm_find_other(ulong img_addr, const char *conf_ramdisk,
const char *conf_fdt)
{
log_debug("find_other type %x os %x\n", images.os.type, images.os.os);
if ((images.os.type == IH_TYPE_KERNEL ||
images.os.type == IH_TYPE_KERNEL_NOLOAD ||
images.os.type == IH_TYPE_MULTI) &&
@ -629,15 +683,17 @@ static int bootm_load_os(struct bootm_headers *images, int boot_progress)
debug("Allocated %lx bytes at %lx for kernel (size %lx) decompression\n",
req_size, load, image_len);
}
log_debug("load_os load %lx image_start %lx image_len %lx\n", load,
image_start, image_len);
load_buf = map_sysmem(load, 0);
image_buf = map_sysmem(os.image_start, image_len);
err = image_decomp(os.comp, load, os.image_start, os.type,
load_buf, image_buf, image_len,
CONFIG_SYS_BOOTM_LEN, &load_end);
load_buf, image_buf, image_len, bootm_len(),
&load_end);
if (err) {
err = handle_decomp_error(os.comp, load_end - load,
CONFIG_SYS_BOOTM_LEN, err);
err = handle_decomp_error(os.comp, load_end - load, bootm_len(),
err);
bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
return err;
}
@ -1110,6 +1166,10 @@ int boot_run(struct bootm_info *bmi, const char *cmd, int extra_states)
states |= BOOTM_STATE_RAMDISK;
states |= extra_states;
log_debug("cmd '%s' states %x addr_img '%s' conf_ramdisk '%s' conf_fdt '%s' images %p\n",
cmd, states, bmi->addr_img, bmi->conf_ramdisk, bmi->conf_fdt,
bmi->images);
return bootm_run_states(bmi, states);
}
@ -1127,7 +1187,9 @@ int bootz_run(struct bootm_info *bmi)
int booti_run(struct bootm_info *bmi)
{
return boot_run(bmi, "booti", 0);
return boot_run(bmi, "booti", BOOTM_STATE_START | BOOTM_STATE_FINDOS |
BOOTM_STATE_PRE_LOAD | BOOTM_STATE_FINDOTHER |
BOOTM_STATE_LOADOS);
}
int bootm_boot_start(ulong addr, const char *cmdline)
@ -1166,7 +1228,8 @@ void bootm_init(struct bootm_info *bmi)
{
memset(bmi, '\0', sizeof(struct bootm_info));
bmi->boot_progress = true;
if (IS_ENABLED(CONFIG_CMD_BOOTM))
if (IS_ENABLED(CONFIG_CMD_BOOTM) || IS_ENABLED(CONFIG_CMD_BOOTZ) ||
IS_ENABLED(CONFIG_CMD_BOOTI) || IS_ENABLED(CONFIG_PXE_UTILS))
bmi->images = &images;
}

View file

@ -446,8 +446,8 @@ static int cros_boot(struct udevice *dev, struct bootflow *bflow)
}
if (IS_ENABLED(CONFIG_X86)) {
ret = zboot_run(map_to_sysmem(bflow->buf), bflow->size, 0, 0,
map_to_sysmem(bflow->x86_setup),
ret = zboot_run_args(map_to_sysmem(bflow->buf), bflow->size, 0,
0, map_to_sysmem(bflow->x86_setup),
bflow->cmdline);
} else {
ret = bootm_boot_start(map_to_sysmem(bflow->buf),

View file

@ -234,21 +234,7 @@ ulong genimg_get_kernel_addr(char * const img_addr)
&fit_uname_kernel);
}
/**
* genimg_get_format - get image format type
* @img_addr: image start address
*
* genimg_get_format() checks whether provided address points to a valid
* legacy or FIT image.
*
* New uImage format and FDT blob are based on a libfdt. FDT blob
* may be passed directly or embedded in a FIT image. In both situations
* genimg_get_format() must be able to dectect libfdt header.
*
* returns:
* image format type or IMAGE_FORMAT_INVALID if no image is present
*/
int genimg_get_format(const void *img_addr)
enum image_fmt_t genimg_get_format(const void *img_addr)
{
if (CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)) {
const struct legacy_img_hdr *hdr;
@ -264,10 +250,24 @@ int genimg_get_format(const void *img_addr)
if (IS_ENABLED(CONFIG_ANDROID_BOOT_IMAGE) &&
is_android_boot_image_header(img_addr))
return IMAGE_FORMAT_ANDROID;
if (IS_ENABLED(CONFIG_CMD_BOOTI) &&
booti_is_valid(img_addr))
return IMAGE_FORMAT_BOOTI;
return IMAGE_FORMAT_INVALID;
}
enum image_fmt_t genimg_get_format_comp(const void *img_addr)
{
enum image_fmt_t fmt = genimg_get_format(img_addr);
if (IS_ENABLED(CONFIG_CMD_BOOTI) && fmt == IMAGE_FORMAT_INVALID &&
image_decomp_type(img_addr, 2) != IH_COMP_NONE)
fmt = IMAGE_FORMAT_BOOTI;
return fmt;
}
/**
* fit_has_config - check if there is a valid FIT configuration
* @images: pointer to the bootm command headers structure
@ -364,7 +364,7 @@ static int select_ramdisk(struct bootm_headers *images, const char *select, u8 a
* check image type, for FIT images get FIT node.
*/
buf = map_sysmem(rd_addr, 0);
switch (genimg_get_format(buf)) {
switch (genimg_get_format_comp(buf)) {
case IMAGE_FORMAT_LEGACY:
if (CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)) {
const struct legacy_img_hdr *rd_hdr;
@ -434,6 +434,10 @@ static int select_ramdisk(struct bootm_headers *images, const char *select, u8 a
done = true;
}
break;
case IMAGE_FORMAT_BOOTI:
break;
case IMAGE_FORMAT_INVALID:
break;
}
if (!done) {

View file

@ -7,6 +7,7 @@
#define LOG_CATEGORY LOGC_BOOT
#include <bootflow.h>
#include <bootm.h>
#include <command.h>
#include <dm.h>
#include <env.h>
@ -432,6 +433,223 @@ skip_overlay:
}
#endif
/*
* label_process_fdt() - Process FDT for the label
*
* @ctx: PXE context
* @label: Label to process
* @kernel_addr: String containing kernel address
* @fdt_argp: bootm argument to fill in, for FDT
* Return: 0 if OK, -ENOMEM if out of memory, -ENOENT if FDT file could not be
* loaded
*
* fdt usage is optional:
* It handles the following scenarios.
*
* Scenario 1: If fdt_addr_r specified and "fdt" or "fdtdir" label is
* defined in pxe file, retrieve fdt blob from server. Pass fdt_addr_r to
* bootm, and adjust argc appropriately.
*
* If retrieve fails and no exact fdt blob is specified in pxe file with
* "fdt" label, try Scenario 2.
*
* Scenario 2: If there is an fdt_addr specified, pass it along to
* bootm, and adjust argc appropriately.
*
* Scenario 3: If there is an fdtcontroladdr specified, pass it along to
* bootm, and adjust argc appropriately, unless the image type is fitImage.
*
* Scenario 4: fdt blob is not available.
*/
static int label_process_fdt(struct pxe_context *ctx, struct pxe_label *label,
char *kernel_addr, const char **fdt_argp)
{
/* For FIT, the label can be identical to kernel one */
if (label->fdt && !strcmp(label->kernel_label, label->fdt)) {
*fdt_argp = kernel_addr;
/* if fdt label is defined then get fdt from server */
} else if (*fdt_argp) {
char *fdtfile = NULL;
char *fdtfilefree = NULL;
if (label->fdt) {
if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) {
if (strcmp("-", label->fdt))
fdtfile = label->fdt;
} else {
fdtfile = label->fdt;
}
} else if (label->fdtdir) {
char *f1, *f2, *f3, *f4, *slash;
int len;
f1 = env_get("fdtfile");
if (f1) {
f2 = "";
f3 = "";
f4 = "";
} else {
/*
* For complex cases where this code doesn't
* generate the correct filename, the board
* code should set $fdtfile during early boot,
* or the boot scripts should set $fdtfile
* before invoking "pxe" or "sysboot".
*/
f1 = env_get("soc");
f2 = "-";
f3 = env_get("board");
f4 = ".dtb";
if (!f1) {
f1 = "";
f2 = "";
}
if (!f3) {
f2 = "";
f3 = "";
}
}
len = strlen(label->fdtdir);
if (!len)
slash = "./";
else if (label->fdtdir[len - 1] != '/')
slash = "/";
else
slash = "";
len = strlen(label->fdtdir) + strlen(slash) +
strlen(f1) + strlen(f2) + strlen(f3) +
strlen(f4) + 1;
fdtfilefree = malloc(len);
if (!fdtfilefree) {
printf("malloc fail (FDT filename)\n");
return -ENOMEM;
}
snprintf(fdtfilefree, len, "%s%s%s%s%s%s",
label->fdtdir, slash, f1, f2, f3, f4);
fdtfile = fdtfilefree;
}
if (fdtfile) {
int err = get_relfile_envaddr(ctx, fdtfile,
"fdt_addr_r",
(enum bootflow_img_t)IH_TYPE_FLATDT, NULL);
free(fdtfilefree);
if (err < 0) {
*fdt_argp = NULL;
if (label->fdt) {
printf("Skipping %s for failure retrieving FDT\n",
label->name);
return -ENOENT;
}
if (label->fdtdir) {
printf("Skipping fdtdir %s for failure retrieving dts\n",
label->fdtdir);
}
}
if (label->kaslrseed)
label_boot_kaslrseed();
#ifdef CONFIG_OF_LIBFDT_OVERLAY
if (label->fdtoverlays)
label_boot_fdtoverlay(ctx, label);
#endif
} else {
*fdt_argp = NULL;
}
}
return 0;
}
/**
* label_run_boot() - Set up the FDT and call the appropriate bootm/z/i command
*
* @ctx: PXE context
* @label: Label to process
* @kernel_addr: String containing kernel address (cannot be NULL)
* @initrd_addr_str: String containing initrd address (NULL if none)
* @initrd_filesize: String containing initrd size (only used if
* @initrd_addr_str)
* @initrd_str: initrd string to process (only used if @initrd_addr_str)
* Return: does not return on success, or returns 0 if the boot command
* returned, or -ve error value on error
*/
static int label_run_boot(struct pxe_context *ctx, struct pxe_label *label,
char *kernel_addr, char *initrd_addr_str,
char *initrd_filesize, char *initrd_str)
{
struct bootm_info bmi;
ulong kernel_addr_r;
void *buf;
int ret;
bootm_init(&bmi);
bmi.conf_fdt = env_get("fdt_addr_r");
ret = label_process_fdt(ctx, label, kernel_addr, &bmi.conf_fdt);
if (ret)
return ret;
bmi.addr_img = kernel_addr;
bootm_x86_set(&bmi, bzimage_addr, hextoul(kernel_addr, NULL));
if (initrd_addr_str) {
bmi.conf_ramdisk = initrd_str;
bootm_x86_set(&bmi, initrd_addr,
hextoul(initrd_addr_str, NULL));
bootm_x86_set(&bmi, initrd_size,
hextoul(initrd_filesize, NULL));
}
if (!bmi.conf_fdt) {
if (!IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS) ||
strcmp("-", label->fdt))
bmi.conf_fdt = env_get("fdt_addr");
}
kernel_addr_r = genimg_get_kernel_addr(kernel_addr);
buf = map_sysmem(kernel_addr_r, 0);
if (!bmi.conf_fdt && genimg_get_format(buf) != IMAGE_FORMAT_FIT) {
if (!IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS) ||
strcmp("-", label->fdt))
bmi.conf_fdt = env_get("fdtcontroladdr");
}
/* Try bootm for legacy and FIT format image */
if (genimg_get_format(buf) != IMAGE_FORMAT_INVALID &&
IS_ENABLED(CONFIG_CMD_BOOTM)) {
log_debug("using bootm\n");
ret = bootm_run(&bmi);
/* Try booting an AArch64 Linux kernel image */
} else if (IS_ENABLED(CONFIG_CMD_BOOTI)) {
log_debug("using booti\n");
ret = booti_run(&bmi);
/* Try booting a Image */
} else if (IS_ENABLED(CONFIG_CMD_BOOTZ)) {
log_debug("using bootz\n");
ret = bootz_run(&bmi);
/* Try booting an x86_64 Linux kernel image */
} else if (IS_ENABLED(CONFIG_CMD_ZBOOT)) {
log_debug("using zboot\n");
ret = zboot_run(&bmi);
}
unmap_sysmem(buf);
if (ret)
return ret;
return 0;
}
/**
* label_boot() - Boot according to the contents of a pxe_label
*
@ -454,8 +672,6 @@ skip_overlay:
*/
static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
{
char *bootm_argv[] = { "bootm", NULL, NULL, NULL, NULL };
char *zboot_argv[] = { "zboot", NULL, "0", NULL, NULL };
char *kernel_addr = NULL;
char *initrd_addr_str = NULL;
char initrd_filesize[10];
@ -463,11 +679,6 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
char mac_str[29] = "";
char ip_str[68] = "";
char *fit_addr = NULL;
int bootm_argc = 2;
int zboot_argc = 3;
int len = 0;
ulong kernel_addr_r;
void *buf;
label_print(label);
@ -512,9 +723,12 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
initrd_addr_str = kernel_addr;
} else if (label->initrd) {
ulong size;
if (get_relfile_envaddr(ctx, label->initrd, "ramdisk_addr_r",
int ret;
ret = get_relfile_envaddr(ctx, label->initrd, "ramdisk_addr_r",
(enum bootflow_img_t)IH_TYPE_RAMDISK,
&size) < 0) {
&size);
if (ret < 0) {
printf("Skipping %s for failure retrieving initrd\n",
label->name);
goto cleanup;
@ -558,7 +772,7 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
}
if (label->append)
strncpy(bootargs, label->append, sizeof(bootargs));
strlcpy(bootargs, label->append, sizeof(bootargs));
strcat(bootargs, ip_str);
strcat(bootargs, mac_str);
@ -569,191 +783,14 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
printf("append: %s\n", finalbootargs);
}
/*
* fdt usage is optional:
* It handles the following scenarios.
*
* Scenario 1: If fdt_addr_r specified and "fdt" or "fdtdir" label is
* defined in pxe file, retrieve fdt blob from server. Pass fdt_addr_r to
* bootm, and adjust argc appropriately.
*
* If retrieve fails and no exact fdt blob is specified in pxe file with
* "fdt" label, try Scenario 2.
*
* Scenario 2: If there is an fdt_addr specified, pass it along to
* bootm, and adjust argc appropriately.
*
* Scenario 3: If there is an fdtcontroladdr specified, pass it along to
* bootm, and adjust argc appropriately, unless the image type is fitImage.
*
* Scenario 4: fdt blob is not available.
*/
bootm_argv[3] = env_get("fdt_addr_r");
/* For FIT, the label can be identical to kernel one */
if (label->fdt && !strcmp(label->kernel_label, label->fdt)) {
bootm_argv[3] = kernel_addr;
/* if fdt label is defined then get fdt from server */
} else if (bootm_argv[3]) {
char *fdtfile = NULL;
char *fdtfilefree = NULL;
if (label->fdt) {
if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) {
if (strcmp("-", label->fdt))
fdtfile = label->fdt;
} else {
fdtfile = label->fdt;
}
} else if (label->fdtdir) {
char *f1, *f2, *f3, *f4, *slash;
f1 = env_get("fdtfile");
if (f1) {
f2 = "";
f3 = "";
f4 = "";
} else {
/*
* For complex cases where this code doesn't
* generate the correct filename, the board
* code should set $fdtfile during early boot,
* or the boot scripts should set $fdtfile
* before invoking "pxe" or "sysboot".
*/
f1 = env_get("soc");
f2 = "-";
f3 = env_get("board");
f4 = ".dtb";
if (!f1) {
f1 = "";
f2 = "";
}
if (!f3) {
f2 = "";
f3 = "";
}
}
len = strlen(label->fdtdir);
if (!len)
slash = "./";
else if (label->fdtdir[len - 1] != '/')
slash = "/";
else
slash = "";
len = strlen(label->fdtdir) + strlen(slash) +
strlen(f1) + strlen(f2) + strlen(f3) +
strlen(f4) + 1;
fdtfilefree = malloc(len);
if (!fdtfilefree) {
printf("malloc fail (FDT filename)\n");
goto cleanup;
}
snprintf(fdtfilefree, len, "%s%s%s%s%s%s",
label->fdtdir, slash, f1, f2, f3, f4);
fdtfile = fdtfilefree;
}
if (fdtfile) {
int err = get_relfile_envaddr(ctx, fdtfile,
"fdt_addr_r",
(enum bootflow_img_t)IH_TYPE_FLATDT, NULL);
free(fdtfilefree);
if (err < 0) {
bootm_argv[3] = NULL;
if (label->fdt) {
printf("Skipping %s for failure retrieving FDT\n",
label->name);
goto cleanup;
}
if (label->fdtdir) {
printf("Skipping fdtdir %s for failure retrieving dts\n",
label->fdtdir);
}
}
if (label->kaslrseed)
label_boot_kaslrseed();
#ifdef CONFIG_OF_LIBFDT_OVERLAY
if (label->fdtoverlays)
label_boot_fdtoverlay(ctx, label);
#endif
} else {
bootm_argv[3] = NULL;
}
}
bootm_argv[1] = kernel_addr;
zboot_argv[1] = kernel_addr;
if (initrd_addr_str) {
bootm_argv[2] = initrd_str;
bootm_argc = 3;
zboot_argv[3] = initrd_addr_str;
zboot_argv[4] = initrd_filesize;
zboot_argc = 5;
}
if (!bootm_argv[3]) {
if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) {
if (strcmp("-", label->fdt))
bootm_argv[3] = env_get("fdt_addr");
} else {
bootm_argv[3] = env_get("fdt_addr");
}
}
kernel_addr_r = genimg_get_kernel_addr(kernel_addr);
buf = map_sysmem(kernel_addr_r, 0);
if (!bootm_argv[3] && genimg_get_format(buf) != IMAGE_FORMAT_FIT) {
if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) {
if (strcmp("-", label->fdt))
bootm_argv[3] = env_get("fdtcontroladdr");
} else {
bootm_argv[3] = env_get("fdtcontroladdr");
}
}
if (bootm_argv[3]) {
if (!bootm_argv[2])
bootm_argv[2] = "-";
bootm_argc = 4;
}
/* Try bootm for legacy and FIT format image */
if (genimg_get_format(buf) != IMAGE_FORMAT_INVALID &&
IS_ENABLED(CONFIG_CMD_BOOTM)) {
log_debug("using bootm\n");
do_bootm(ctx->cmdtp, 0, bootm_argc, bootm_argv);
/* Try booting an AArch64 Linux kernel image */
} else if (IS_ENABLED(CONFIG_CMD_BOOTI)) {
log_debug("using booti\n");
do_booti(ctx->cmdtp, 0, bootm_argc, bootm_argv);
/* Try booting a Image */
} else if (IS_ENABLED(CONFIG_CMD_BOOTZ)) {
log_debug("using bootz\n");
do_bootz(ctx->cmdtp, 0, bootm_argc, bootm_argv);
/* Try booting an x86_64 Linux kernel image */
} else if (IS_ENABLED(CONFIG_CMD_ZBOOT)) {
log_debug("using zboot\n");
do_zboot_parent(ctx->cmdtp, 0, zboot_argc, zboot_argv, NULL);
}
unmap_sysmem(buf);
label_run_boot(ctx, label, kernel_addr, initrd_addr_str,
initrd_filesize, initrd_str);
/* ignore the error value since we are going to fail anyway */
cleanup:
free(fit_addr);
return 1;
return 1; /* returning is always failure */
}
/** enum token_type - Tokens for the pxe file parser */

View file

@ -380,7 +380,13 @@ static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc,
bflow = std->cur_bootflow;
if (IS_ENABLED(CONFIG_X86) && x86_setup) {
zimage_dump(bflow->x86_setup, false);
struct bootm_info bmi;
bootm_init(&bmi);
/* we don't know this at present */
bootm_x86_set(&bmi, bzimage_addr, 0);
bootm_x86_set(&bmi, base_ptr, bflow->x86_setup);
zimage_dump(&bmi, false);
return 0;
}

View file

@ -297,13 +297,15 @@ static void netboot_update_env(void)
/**
* parse_addr_size() - parse address and size arguments for tftpput
*
* @argv: command line arguments
* @argv: command line arguments (argv[1] and argv[2] must be valid)
* @addrp: returns the address, on success
* @sizep: returns the size, on success
* Return: 0 on success
*/
static int parse_addr_size(char * const argv[])
static int parse_addr_size(char * const argv[], ulong *addrp, ulong *sizep)
{
if (strict_strtoul(argv[1], 16, &image_save_addr) < 0 ||
strict_strtoul(argv[2], 16, &image_save_size) < 0) {
if (strict_strtoul(argv[1], 16, addrp) < 0 ||
strict_strtoul(argv[2], 16, sizep) < 0) {
printf("Invalid address/size\n");
return CMD_RET_USAGE;
}
@ -313,24 +315,31 @@ static int parse_addr_size(char * const argv[])
/**
* parse_args() - parse command line arguments
*
* Sets:
* - image_save_addr and image_save_size, if proto == TFTPPUT
*
* @proto: command prototype
* @argc: number of arguments
* @argv: command line arguments
* @argc: number of arguments, include the command, which has already been
* parsed
* @argv: command line arguments, with argv[0] being the command
* @fnamep: set to the filename, if provided, else NULL
* @addrp: returns the load/save address, if any is provided, else it is
* left unchanged
* @sizep: returns the save size, if any is provided, else it is left
* unchanged
* Return: 0 on success
*/
static int parse_args(enum proto_t proto, int argc, char *const argv[])
static int parse_args(enum proto_t proto, int argc, char *const argv[],
const char **fnamep, ulong *addrp, ulong *sizep)
{
ulong addr;
char *end;
*fnamep = NULL;
switch (argc) {
case 1:
if (IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT)
return 1;
/* refresh bootfile name from env */
copy_filename(net_boot_file_name, env_get("bootfile"),
sizeof(net_boot_file_name));
break;
case 2:
@ -343,48 +352,42 @@ static int parse_args(enum proto_t proto, int argc, char *const argv[])
* mis-interpreted as a valid number.
*/
addr = hextoul(argv[1], &end);
if (end == (argv[1] + strlen(argv[1]))) {
image_load_addr = addr;
/* refresh bootfile name from env */
copy_filename(net_boot_file_name, env_get("bootfile"),
sizeof(net_boot_file_name));
} else {
net_boot_file_name_explicit = true;
copy_filename(net_boot_file_name, argv[1],
sizeof(net_boot_file_name));
}
if (end == (argv[1] + strlen(argv[1])))
*addrp = addr;
else
*fnamep = argv[1];
break;
case 3:
if (IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) {
if (parse_addr_size(argv))
if (parse_addr_size(argv, addrp, sizep))
return 1;
} else {
image_load_addr = hextoul(argv[1], NULL);
net_boot_file_name_explicit = true;
copy_filename(net_boot_file_name, argv[2],
sizeof(net_boot_file_name));
*addrp = hextoul(argv[1], NULL);
*fnamep = argv[2];
}
break;
#ifdef CONFIG_CMD_TFTPPUT
case 4:
if (parse_addr_size(argv))
if (IS_ENABLED(CONFIG_CMD_TFTPPUT)) {
if (parse_addr_size(argv, addrp, sizep))
return 1;
net_boot_file_name_explicit = true;
copy_filename(net_boot_file_name, argv[3],
sizeof(net_boot_file_name));
*fnamep = argv[3];
break;
#endif
}
default:
return 1;
}
return 0;
}
static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc,
char *const argv[])
{
ulong addr, save_size;
bool fname_explicit;
const char *fname;
char *s;
int rcode = 0;
int size;
@ -392,10 +395,10 @@ static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc,
net_boot_file_name_explicit = false;
*net_boot_file_name = '\0';
/* pre-set image_load_addr */
/* pre-set addr */
s = env_get("loadaddr");
if (s != NULL)
image_load_addr = hextoul(s, NULL);
addr = hextoul(s, NULL);
if (IS_ENABLED(CONFIG_IPV6)) {
use_ip6 = false;
@ -408,12 +411,17 @@ static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc,
}
}
if (parse_args(proto, argc, argv)) {
if (parse_args(proto, argc, argv, &fname, &addr, &save_size)) {
bootstage_error(BOOTSTAGE_ID_NET_START);
return CMD_RET_USAGE;
}
bootstage_mark(BOOTSTAGE_ID_NET_START);
if (fname) {
fname_explicit = true;
} else {
fname_explicit = false;
fname = env_get("bootfile");
}
if (IS_ENABLED(CONFIG_IPV6) && !use_ip6) {
char *s, *e;
@ -428,12 +436,10 @@ static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc,
}
}
size = net_loop(proto);
if (size < 0) {
bootstage_error(BOOTSTAGE_ID_NET_NETLOOP_OK);
size = netboot_run_(proto, addr, fname, save_size, fname_explicit,
IS_ENABLED(CONFIG_IPV6) && use_ip6);
if (size < 0)
return CMD_RET_FAILURE;
}
bootstage_mark(BOOTSTAGE_ID_NET_NETLOOP_OK);
/* net_loop ok, update environment */
netboot_update_env();

View file

@ -7,11 +7,15 @@
#define LOG_CATEGORY LOGC_BOOT
#include <bootm.h>
#include <command.h>
#include <mapmem.h>
#include <vsprintf.h>
#include <asm/zimage.h>
/* Current state of the boot */
static struct bootm_info bmi;
static int do_zboot_start(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
@ -20,6 +24,8 @@ static int do_zboot_start(struct cmd_tbl *cmdtp, int flag, int argc,
ulong base_addr;
int i;
bootm_init(&bmi);
log_debug("argc %d:", argc);
for (i = 0; i < argc; i++)
log_debug(" %s", argv[i]);
@ -35,7 +41,7 @@ static int do_zboot_start(struct cmd_tbl *cmdtp, int flag, int argc,
base_addr = argc > 5 ? hextoul(argv[5], NULL) : 0;
cmdline = argc > 6 ? env_get(argv[6]) : NULL;
zboot_start(bzimage_addr, bzimage_size, initrd_addr, initrd_size,
zboot_start(&bmi, bzimage_addr, bzimage_size, initrd_addr, initrd_size,
base_addr, cmdline);
return 0;
@ -46,7 +52,7 @@ static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc,
{
int ret;
ret = zboot_load();
ret = zboot_load(&bmi);
if (ret)
return ret;
@ -56,16 +62,17 @@ static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc,
static int do_zboot_setup(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
if (!state.base_ptr) {
if (!bmi.base_ptr) {
printf("base is not set: use 'zboot load' first\n");
return CMD_RET_FAILURE;
}
if (zboot_setup()) {
if (zboot_setup(&bmi)) {
puts("Setting up boot parameters failed ...\n");
return CMD_RET_FAILURE;
}
if (zboot_setup())
if (zboot_setup(&bmi))
return CMD_RET_FAILURE;
return 0;
@ -74,7 +81,7 @@ static int do_zboot_setup(struct cmd_tbl *cmdtp, int flag, int argc,
static int do_zboot_info(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
zboot_info();
zboot_info(&bmi);
return 0;
}
@ -84,7 +91,7 @@ static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc,
{
int ret;
ret = zboot_go();
ret = zboot_go(&bmi);
if (ret) {
printf("Kernel returned! (err=%d)\n", ret);
return CMD_RET_FAILURE;
@ -96,15 +103,13 @@ static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc,
static int do_zboot_dump(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
struct boot_params *base_ptr = state.base_ptr;
if (argc > 1)
base_ptr = (void *)hextoul(argv[1], NULL);
if (!base_ptr) {
bmi.base_ptr = (void *)hextoul(argv[1], NULL);
if (!bmi.base_ptr) {
printf("No zboot setup_base\n");
return CMD_RET_FAILURE;
}
zimage_dump(base_ptr, true);
zimage_dump(&bmi, true);
return 0;
}
@ -119,7 +124,7 @@ U_BOOT_SUBCMDS(zboot,
U_BOOT_CMD_MKENT(dump, 2, 1, do_zboot_dump, "", ""),
)
int do_zboot_states(struct cmd_tbl *cmdtp, int flag, int argc,
static int do_zboot_states(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[], int state_mask)
{
int ret = 0;

View file

@ -44,6 +44,21 @@ struct cmd_tbl;
* @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
*
* For zboot:
* @bzimage_addr: Address of the bzImage to boot, or 0 if the image has already
* been loaded and does not exist (as a cohesive whole) in memory
* @bzimage_size: Size of the bzImage, or 0 to detect this
* @initrd_addr: Address of the initial ramdisk, or 0 if none
* @initrd_size: Size of the initial ramdisk, or 0 if none
* @load_address: Address where the bzImage is moved before booting, either
* BZIMAGE_LOAD_ADDR or ZIMAGE_LOAD_ADDR
* This is set up when loading the zimage
* @base_ptr: Pointer to the boot parameters, typically at address
* DEFAULT_SETUP_BASE
* This is set up when loading the zimage
* @cmdline: Environment variable containing the 'override' command line, or
* NULL to use the one in the setup block
*/
struct bootm_info {
const char *addr_img;
@ -54,11 +69,39 @@ struct bootm_info {
const char *cmd_name;
int argc;
char *const *argv;
/* zboot items */
#ifdef CONFIG_X86
ulong bzimage_addr;
ulong bzimage_size;
ulong initrd_addr;
ulong initrd_size;
ulong load_address;
struct boot_params *base_ptr;
const char *cmdline;
#endif
};
/* macro to allow setting fields in generic code */
#ifdef CONFIG_X86
#define bootm_x86_set(_bmi, _field, _val) (_bmi)->_field = (_val)
#else
#define bootm_x86_set(_bmi, _field, _val)
#endif
static inline ulong bootm_len(void)
{
#ifdef CONFIG_SYS_BOOTM_LEN
return CONFIG_SYS_BOOTM_LEN;
#endif
return 0;
}
/**
* bootm_init() - Set up a bootm_info struct with useful defaults
*
* @bmi: Bootm information
*
* 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
@ -74,7 +117,7 @@ void bootm_init(struct bootm_info *bmi);
* - disabled interrupts.
*
* @flag: Flags indicating what to do (BOOTM_STATE_...)
* bmi: Bootm information
* @bmi: Bootm information
* Return: 1 on error. On success the OS boots so this function does
* not return.
*/
@ -275,6 +318,15 @@ int bootm_process_cmdline_env(int flags);
/**
* zboot_run() - Run through the various steps to boot a zimage
*
* @bmi: Bootm information, with bzimage_size, initrd_addr, initrd_size and
* cmdline set up. If base_ptr is 0, then bzimage_addr must be set to the start
* of the bzImage. Otherwise base_ptr and load_address must be provided.
*/
int zboot_run(struct bootm_info *bmi);
/**
* zboot_run_args() - Run through the various steps to boot a zimage
*
* Boot a zimage, given the component parts
*
* @addr: Address where the bzImage is moved before booting, either
@ -289,7 +341,7 @@ int bootm_process_cmdline_env(int flags);
* to use for booting
* Return: -EFAULT on error (normally it does not return)
*/
int zboot_run(ulong addr, ulong size, ulong initrd, ulong initrd_size,
int zboot_run_args(ulong addr, ulong size, ulong initrd, ulong initrd_size,
ulong base, char *cmdline);
/*
@ -307,11 +359,10 @@ const char *zimage_get_kernel_version(struct boot_params *params,
*
* This shows all available information in a zimage that has been loaded.
*
* @base_ptr: Pointer to the boot parameters, typically at address
* DEFAULT_SETUP_BASE
* @bmi: Bootm information, with valid base_ptr
* @show_cmdline: true to show the full command line
*/
void zimage_dump(struct boot_params *base_ptr, bool show_cmdline);
void zimage_dump(struct bootm_info *bmi, bool show_cmdline);
/*
* bootm_boot_start() - Boot an image at the given address

View file

@ -244,7 +244,7 @@ enum image_type_t {
* New IDs *MUST* be appended at the end of the list and *NEVER*
* inserted for backward compatibility.
*/
enum {
enum image_comp_t {
IH_COMP_NONE = 0, /* No Compression Used */
IH_COMP_GZIP, /* gzip Compression Used */
IH_COMP_BZIP2, /* bzip2 Compression Used */
@ -598,10 +598,13 @@ int boot_get_setup(struct bootm_headers *images, uint8_t arch, ulong *setup_star
ulong *setup_len);
/* Image format types, returned by _get_format() routine */
#define IMAGE_FORMAT_INVALID 0x00
#define IMAGE_FORMAT_LEGACY 0x01 /* legacy image_header based format */
#define IMAGE_FORMAT_FIT 0x02 /* new, libfdt based format */
#define IMAGE_FORMAT_ANDROID 0x03 /* Android boot image */
enum image_fmt_t {
IMAGE_FORMAT_INVALID,
IMAGE_FORMAT_LEGACY, /* legacy image_header based format */
IMAGE_FORMAT_FIT, /* new, libfdt based format */
IMAGE_FORMAT_ANDROID, /* Android boot image */
IMAGE_FORMAT_BOOTI, /* Arm64/RISC-V boot image */
};
/**
* genimg_get_kernel_addr_fit() - Parse FIT specifier
@ -630,9 +633,42 @@ ulong genimg_get_kernel_addr_fit(const char *const img_addr,
const char **fit_uname_kernel);
ulong genimg_get_kernel_addr(char * const img_addr);
int genimg_get_format(const void *img_addr);
/**
* genimg_get_format - get image format type
* @img_addr: image start address
* Return: image format type or IMAGE_FORMAT_INVALID if no image is present
*
* genimg_get_format() checks whether provided address points to a valid
* legacy or FIT image.
*
* New uImage format and FDT blob are based on a libfdt. FDT blob
* may be passed directly or embedded in a FIT image. In both situations
* genimg_get_format() must be able to dectect libfdt header.
*/
enum image_fmt_t genimg_get_format(const void *img_addr);
/**
* genimg_get_format_comp() - Like genimg_get_format() but adds compressed booti
*
* If a compressed file is detected (with image_decomp_type()) and
* CONFIG_CMD_BOOTI is enabled, then this returns IMAGE_FORMAT_BOOTI
*
* @img_addr: image start address
* Return: image format type or IMAGE_FORMAT_INVALID if no image is present
*/
enum image_fmt_t genimg_get_format_comp(const void *img_addr);
int genimg_has_config(struct bootm_headers *images);
/**
* booti_is_valid() - Check if an image appears to be an Arm64 image
*
* @img: Pointer to image
* Return: true if the image has the Arm64 magic
*/
bool booti_is_valid(const void *img);
/**
* boot_get_fpga() - Locate the FPGA image
*

View file

@ -475,6 +475,36 @@ int net_init(void);
enum proto_t;
int net_loop(enum proto_t protocol);
/* internal function: do not use! */
int netboot_run_(enum proto_t proto, ulong addr, const char *fname, ulong size,
bool fname_explicit, bool ipv6);
/**
* netboot_run() - Run a network operation
*
* The following proto values are NOT supported:
* PING, since net_ping_ip cannot be set
* NETCONS, since its parameters cannot bet set
* RS, since first_call cannot be set, along with perhaps other things
* UDP, since udp_ops cannot be set
* DNS, since net_dns_resolve and net_dns_env_var cannot be set
* WGET, since DNS must be done first and that is not supported
* DHCP6, since the required parameters cannot be passed in
*
* To support one of these, either add the required arguments or perhaps a
* separate function and a struct to hold the information.
*
* @proto: Operation to run: TFTPGET, FASTBOOT_UDP, FASTBOOT_TCP, BOOTP,
* TFTPPUT, RARP, NFS, DHCP
* @addr: Load/save address
* @fname: Filename
* @size: Save size (not used for TFTPGET)
* @ipv6: true to use IPv6, false to use IPv4
* Return 0 on success, else -ve error code
*/
int netboot_run(enum proto_t proto, ulong addr, const char *fname, ulong size,
bool ipv6);
/**
* dhcp_run() - Run DHCP on the current ethernet device
*

View file

@ -775,6 +775,50 @@ done:
return ret;
}
int netboot_run_(enum proto_t proto, ulong addr, const char *fname, ulong size,
bool fname_explicit, bool ipv6)
{
int ret;
bootstage_mark(BOOTSTAGE_ID_NET_START);
/*
* For now we use the global variables as that is the only way to
* control the network stack. At some point, perhaps, the state could be
* in a struct
*/
if (IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT)
image_save_addr = addr;
else
image_load_addr = addr;
net_boot_file_name_explicit = fname_explicit;
copy_filename(net_boot_file_name, fname, sizeof(net_boot_file_name));
if (IS_ENABLED(CONFIG_IPV6))
use_ip6 = ipv6;
if (IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) {
image_save_addr = addr;
image_save_size = size;
} else {
image_load_addr = addr;
}
ret = net_loop(proto);
if (ret < 0) {
bootstage_error(BOOTSTAGE_ID_NET_NETLOOP_OK);
return ret;
}
bootstage_mark(BOOTSTAGE_ID_NET_NETLOOP_OK);
return 0;
}
int netboot_run(enum proto_t proto, ulong addr, const char *fname, ulong size,
bool ipv6)
{
return netboot_run_(proto, addr, fname, size, true, ipv6);
}
/**********************************************************************/
static void start_again_timeout_handler(void)