summaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2025-03-18 13:12:51 -0600
committerTom Rini <[email protected]>2025-03-18 13:12:51 -0600
commit8bc3542384e3a1219e5ffb62b79d16dddc1b1fb9 (patch)
tree8473478696b9a12d2db424afcec705dcce58c580 /boot
parent698edd63eca090a2e299cd3facf90a0b97bed677 (diff)
parent0f094b8b146679c3980cd2febde4e902bbc4405d (diff)
Merge patch series "pxe: Precursor series for supporting read_all() in extlinux / PXE"
Simon Glass <[email protected]> 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/[email protected]
Diffstat (limited to 'boot')
-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
5 files changed, 321 insertions, 217 deletions
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 */