summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/lib/image.c9
-rw-r--r--arch/riscv/lib/image.c9
-rw-r--r--arch/sandbox/lib/bootm.c5
-rw-r--r--arch/x86/include/asm/zimage.h57
-rw-r--r--arch/x86/lib/zimage.c102
-rw-r--r--boot/Makefile2
-rw-r--r--boot/bootm.c77
-rw-r--r--boot/bootmeth_cros.c6
-rw-r--r--boot/image-board.c36
-rw-r--r--boot/pxe_utils.c417
-rw-r--r--cmd/bootflow.c8
-rw-r--r--cmd/net.c92
-rw-r--r--cmd/x86/zboot.c33
-rw-r--r--include/bootm.h63
-rw-r--r--include/image.h48
-rw-r--r--include/net-common.h30
-rw-r--r--net/net.c44
17 files changed, 661 insertions, 377 deletions
diff --git a/arch/arm/lib/image.c b/arch/arm/lib/image.c
index 1f672eee2c8..d78d704cb58 100644
--- a/arch/arm/lib/image.c
+++ b/arch/arm/lib/image.c
@@ -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;
}
diff --git a/arch/riscv/lib/image.c b/arch/riscv/lib/image.c
index a82f48e9a50..859326cbac8 100644
--- a/arch/riscv/lib/image.c
+++ b/arch/riscv/lib/image.c
@@ -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;
}
diff --git a/arch/sandbox/lib/bootm.c b/arch/sandbox/lib/bootm.c
index 44ba8b52e13..8ed923750f4 100644
--- a/arch/sandbox/lib/bootm.c
+++ b/arch/sandbox/lib/bootm.c
@@ -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;
+}
diff --git a/arch/x86/include/asm/zimage.h b/arch/x86/include/asm/zimage.h
index 8b542605170..4ed6d8d5cc2 100644
--- a/arch/x86/include/asm/zimage.h
+++ b/arch/x86/include/asm/zimage.h
@@ -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 */
@@ -43,64 +45,27 @@ enum {
};
/**
- * 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
*
* Load the zimage into the correct place
*
* 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
diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c
index 2eece34a073..ba7a008fec7 100644
--- a/arch/x86/lib/zimage.c
+++ b/arch/x86/lib/zimage.c
@@ -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);
- version = zimage_get_kernel_version(base_ptr,
- (void *)state.bzimage_addr);
- if (version)
- printf(" @%p: %s\n", version, version);
+ if (bmi->bzimage_addr) {
+ const char *version;
+
+ version = zimage_get_kernel_version(base_ptr,
+ (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);
}
diff --git a/boot/Makefile b/boot/Makefile
index 34bac26c4e2..f1e4444aa0a 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -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
diff --git a/boot/bootm.c b/boot/bootm.c
index 854ac7ec738..8a1aac7515f 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -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;
}
diff --git a/boot/bootmeth_cros.c b/boot/bootmeth_cros.c
index c7b862e512a..ea4c9ed830f 100644
--- a/boot/bootmeth_cros.c
+++ b/boot/bootmeth_cros.c
@@ -446,9 +446,9 @@ 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),
- bflow->cmdline);
+ 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),
bflow->cmdline);
diff --git a/boot/image-board.c b/boot/image-board.c
index 514f8e63f9c..a2bafba7ae1 100644
--- a/boot/image-board.c
+++ b/boot/image-board.c
@@ -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) {
diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index 82f217aaf86..c606da9e96b 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -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,169 +433,42 @@ skip_overlay:
}
#endif
-/**
- * label_boot() - Boot according to the contents of a pxe_label
+/*
+ * label_process_fdt() - Process FDT for the label
*
- * If we can't boot for any reason, we return. A successful boot never
- * returns.
+ * @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
*
- * The kernel will be stored in the location given by the 'kernel_addr_r'
- * environment variable.
+ * fdt usage is optional:
+ * It handles the following scenarios.
*
- * If the label specifies an initrd file, it will be stored in the location
- * given by the 'ramdisk_addr_r' environment variable.
+ * 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 the label specifies an 'append' line, its contents will overwrite that
- * of the 'bootargs' environment variable.
+ * If retrieve fails and no exact fdt blob is specified in pxe file with
+ * "fdt" label, try Scenario 2.
*
- * @ctx: PXE context
- * @label: Label to process
- * Returns does not return on success, otherwise returns 0 if a localboot
- * label was processed, or 1 on error
+ * 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_boot(struct pxe_context *ctx, struct pxe_label *label)
+static int label_process_fdt(struct pxe_context *ctx, struct pxe_label *label,
+ char *kernel_addr, const char **fdt_argp)
{
- 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];
- char initrd_str[28];
- 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);
-
- label->attempted = 1;
-
- if (label->localboot) {
- if (label->localboot_val >= 0)
- label_localboot(label);
- return 0;
- }
-
- if (!label->kernel) {
- printf("No kernel given, skipping %s\n",
- label->name);
- return 1;
- }
-
- if (get_relfile_envaddr(ctx, label->kernel, "kernel_addr_r",
- (enum bootflow_img_t)IH_TYPE_KERNEL, NULL)
- < 0) {
- printf("Skipping %s for failure retrieving kernel\n",
- label->name);
- return 1;
- }
-
- kernel_addr = env_get("kernel_addr_r");
- /* for FIT, append the configuration identifier */
- if (label->config) {
- int len = strlen(kernel_addr) + strlen(label->config) + 1;
-
- fit_addr = malloc(len);
- if (!fit_addr) {
- printf("malloc fail (FIT address)\n");
- return 1;
- }
- snprintf(fit_addr, len, "%s%s", kernel_addr, label->config);
- kernel_addr = fit_addr;
- }
-
- /* For FIT, the label can be identical to kernel one */
- if (label->initrd && !strcmp(label->kernel_label, label->initrd)) {
- initrd_addr_str = kernel_addr;
- } else if (label->initrd) {
- ulong size;
- if (get_relfile_envaddr(ctx, label->initrd, "ramdisk_addr_r",
- (enum bootflow_img_t)IH_TYPE_RAMDISK,
- &size) < 0) {
- printf("Skipping %s for failure retrieving initrd\n",
- label->name);
- goto cleanup;
- }
- strcpy(initrd_filesize, simple_xtoa(size));
- initrd_addr_str = env_get("ramdisk_addr_r");
- size = snprintf(initrd_str, sizeof(initrd_str), "%s:%lx",
- initrd_addr_str, size);
- if (size >= sizeof(initrd_str))
- goto cleanup;
- }
-
- if (label->ipappend & 0x1) {
- sprintf(ip_str, " ip=%s:%s:%s:%s",
- env_get("ipaddr"), env_get("serverip"),
- env_get("gatewayip"), env_get("netmask"));
- }
-
- if (IS_ENABLED(CONFIG_CMD_NET)) {
- if (label->ipappend & 0x2) {
- int err;
-
- strcpy(mac_str, " BOOTIF=");
- err = format_mac_pxe(mac_str + 8, sizeof(mac_str) - 8);
- if (err < 0)
- mac_str[0] = '\0';
- }
- }
-
- if ((label->ipappend & 0x3) || label->append) {
- char bootargs[CONFIG_SYS_CBSIZE] = "";
- char finalbootargs[CONFIG_SYS_CBSIZE];
-
- if (strlen(label->append ?: "") +
- strlen(ip_str) + strlen(mac_str) + 1 > sizeof(bootargs)) {
- printf("bootarg overflow %zd+%zd+%zd+1 > %zd\n",
- strlen(label->append ?: ""),
- strlen(ip_str), strlen(mac_str),
- sizeof(bootargs));
- goto cleanup;
- }
-
- if (label->append)
- strncpy(bootargs, label->append, sizeof(bootargs));
-
- strcat(bootargs, ip_str);
- strcat(bootargs, mac_str);
-
- cli_simple_process_macros(bootargs, finalbootargs,
- sizeof(finalbootargs));
- env_set("bootargs", finalbootargs);
- 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;
+ *fdt_argp = kernel_addr;
/* if fdt label is defined then get fdt from server */
- } else if (bootm_argv[3]) {
+ } else if (*fdt_argp) {
char *fdtfile = NULL;
char *fdtfilefree = NULL;
@@ -607,6 +481,7 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
}
} else if (label->fdtdir) {
char *f1, *f2, *f3, *f4, *slash;
+ int len;
f1 = env_get("fdtfile");
if (f1) {
@@ -649,7 +524,7 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
fdtfilefree = malloc(len);
if (!fdtfilefree) {
printf("malloc fail (FDT filename)\n");
- goto cleanup;
+ return -ENOMEM;
}
snprintf(fdtfilefree, len, "%s%s%s%s%s%s",
@@ -664,12 +539,12 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
free(fdtfilefree);
if (err < 0) {
- bootm_argv[3] = NULL;
+ *fdt_argp = NULL;
if (label->fdt) {
printf("Skipping %s for failure retrieving FDT\n",
label->name);
- goto cleanup;
+ return -ENOENT;
}
if (label->fdtdir) {
@@ -686,74 +561,236 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
label_boot_fdtoverlay(ctx, label);
#endif
} else {
- bootm_argv[3] = NULL;
+ *fdt_argp = NULL;
}
}
- bootm_argv[1] = kernel_addr;
- zboot_argv[1] = kernel_addr;
+ return 0;
+}
- if (initrd_addr_str) {
- bootm_argv[2] = initrd_str;
- bootm_argc = 3;
+/**
+ * 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));
- zboot_argv[3] = initrd_addr_str;
- zboot_argv[4] = initrd_filesize;
- zboot_argc = 5;
+ 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 (!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");
- }
+ 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 (!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;
+ 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");
- do_bootm(ctx->cmdtp, 0, bootm_argc, bootm_argv);
+ ret = bootm_run(&bmi);
/* 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);
+ ret = booti_run(&bmi);
/* 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);
+ ret = bootz_run(&bmi);
/* 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);
+ ret = zboot_run(&bmi);
}
unmap_sysmem(buf);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+/**
+ * label_boot() - Boot according to the contents of a pxe_label
+ *
+ * If we can't boot for any reason, we return. A successful boot never
+ * returns.
+ *
+ * The kernel will be stored in the location given by the 'kernel_addr_r'
+ * environment variable.
+ *
+ * If the label specifies an initrd file, it will be stored in the location
+ * given by the 'ramdisk_addr_r' environment variable.
+ *
+ * If the label specifies an 'append' line, its contents will overwrite that
+ * of the 'bootargs' environment variable.
+ *
+ * @ctx: PXE context
+ * @label: Label to process
+ * Returns does not return on success, otherwise returns 0 if a localboot
+ * label was processed, or 1 on error
+ */
+static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
+{
+ char *kernel_addr = NULL;
+ char *initrd_addr_str = NULL;
+ char initrd_filesize[10];
+ char initrd_str[28];
+ char mac_str[29] = "";
+ char ip_str[68] = "";
+ char *fit_addr = NULL;
+
+ label_print(label);
+
+ label->attempted = 1;
+
+ if (label->localboot) {
+ if (label->localboot_val >= 0)
+ label_localboot(label);
+ return 0;
+ }
+
+ if (!label->kernel) {
+ printf("No kernel given, skipping %s\n",
+ label->name);
+ return 1;
+ }
+
+ if (get_relfile_envaddr(ctx, label->kernel, "kernel_addr_r",
+ (enum bootflow_img_t)IH_TYPE_KERNEL, NULL)
+ < 0) {
+ printf("Skipping %s for failure retrieving kernel\n",
+ label->name);
+ return 1;
+ }
+
+ kernel_addr = env_get("kernel_addr_r");
+ /* for FIT, append the configuration identifier */
+ if (label->config) {
+ int len = strlen(kernel_addr) + strlen(label->config) + 1;
+
+ fit_addr = malloc(len);
+ if (!fit_addr) {
+ printf("malloc fail (FIT address)\n");
+ return 1;
+ }
+ snprintf(fit_addr, len, "%s%s", kernel_addr, label->config);
+ kernel_addr = fit_addr;
+ }
+
+ /* For FIT, the label can be identical to kernel one */
+ if (label->initrd && !strcmp(label->kernel_label, label->initrd)) {
+ initrd_addr_str = kernel_addr;
+ } else if (label->initrd) {
+ ulong size;
+ int ret;
+
+ ret = get_relfile_envaddr(ctx, label->initrd, "ramdisk_addr_r",
+ (enum bootflow_img_t)IH_TYPE_RAMDISK,
+ &size);
+ if (ret < 0) {
+ printf("Skipping %s for failure retrieving initrd\n",
+ label->name);
+ goto cleanup;
+ }
+ strcpy(initrd_filesize, simple_xtoa(size));
+ initrd_addr_str = env_get("ramdisk_addr_r");
+ size = snprintf(initrd_str, sizeof(initrd_str), "%s:%lx",
+ initrd_addr_str, size);
+ if (size >= sizeof(initrd_str))
+ goto cleanup;
+ }
+
+ if (label->ipappend & 0x1) {
+ sprintf(ip_str, " ip=%s:%s:%s:%s",
+ env_get("ipaddr"), env_get("serverip"),
+ env_get("gatewayip"), env_get("netmask"));
+ }
+
+ if (IS_ENABLED(CONFIG_CMD_NET)) {
+ if (label->ipappend & 0x2) {
+ int err;
+
+ strcpy(mac_str, " BOOTIF=");
+ err = format_mac_pxe(mac_str + 8, sizeof(mac_str) - 8);
+ if (err < 0)
+ mac_str[0] = '\0';
+ }
+ }
+
+ if ((label->ipappend & 0x3) || label->append) {
+ char bootargs[CONFIG_SYS_CBSIZE] = "";
+ char finalbootargs[CONFIG_SYS_CBSIZE];
+
+ if (strlen(label->append ?: "") +
+ strlen(ip_str) + strlen(mac_str) + 1 > sizeof(bootargs)) {
+ printf("bootarg overflow %zd+%zd+%zd+1 > %zd\n",
+ strlen(label->append ?: ""),
+ strlen(ip_str), strlen(mac_str),
+ sizeof(bootargs));
+ goto cleanup;
+ }
+
+ if (label->append)
+ strlcpy(bootargs, label->append, sizeof(bootargs));
+
+ strcat(bootargs, ip_str);
+ strcat(bootargs, mac_str);
+
+ cli_simple_process_macros(bootargs, finalbootargs,
+ sizeof(finalbootargs));
+ env_set("bootargs", finalbootargs);
+ printf("append: %s\n", finalbootargs);
+ }
+
+ 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 */
diff --git a/cmd/bootflow.c b/cmd/bootflow.c
index f88995a478f..6d0be320bdb 100644
--- a/cmd/bootflow.c
+++ b/cmd/bootflow.c
@@ -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;
}
diff --git a/cmd/net.c b/cmd/net.c
index 79525f73a51..8f33c9f55d5 100644
--- a/cmd/net.c
+++ b/cmd/net.c
@@ -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))
- return 1;
- net_boot_file_name_explicit = true;
- copy_filename(net_boot_file_name, argv[3],
- sizeof(net_boot_file_name));
- break;
-#endif
+ if (IS_ENABLED(CONFIG_CMD_TFTPPUT)) {
+ if (parse_addr_size(argv, addrp, sizep))
+ return 1;
+ *fnamep = argv[3];
+ break;
+ }
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();
diff --git a/cmd/x86/zboot.c b/cmd/x86/zboot.c
index 94e602b8a5b..ee099ca041b 100644
--- a/cmd/x86/zboot.c
+++ b/cmd/x86/zboot.c
@@ -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,8 +124,8 @@ 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,
- char *const argv[], int state_mask)
+static int do_zboot_states(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[], int state_mask)
{
int ret = 0;
diff --git a/include/bootm.h b/include/bootm.h
index 61160705215..465577a66f5 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -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,8 +341,8 @@ 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,
- ulong base, char *cmdline);
+int zboot_run_args(ulong addr, ulong size, ulong initrd, ulong initrd_size,
+ ulong base, char *cmdline);
/*
* zimage_get_kernel_version() - Get the version string from a kernel
@@ -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
diff --git a/include/image.h b/include/image.h
index c1db8383459..2455baa6667 100644
--- a/include/image.h
+++ b/include/image.h
@@ -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,10 +633,43 @@ 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
*
* @images: Information about images being loaded
diff --git a/include/net-common.h b/include/net-common.h
index 1d507b13b06..6a39091a5d4 100644
--- a/include/net-common.h
+++ b/include/net-common.h
@@ -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
*
diff --git a/net/net.c b/net/net.c
index 1828f1cca36..ef97377cdec 100644
--- a/net/net.c
+++ b/net/net.c
@@ -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)