summaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
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/fdt_support.c39
-rw-r--r--boot/image-board.c36
-rw-r--r--boot/image-fdt.c7
-rw-r--r--boot/pxe_utils.c417
7 files changed, 366 insertions, 218 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/fdt_support.c b/boot/fdt_support.c
index 49efeec3681..92f2f534ee0 100644
--- a/boot/fdt_support.c
+++ b/boot/fdt_support.c
@@ -18,6 +18,7 @@
#include <dm/ofnode.h>
#include <linux/ctype.h>
#include <linux/types.h>
+#include <linux/sizes.h>
#include <asm/global_data.h>
#include <asm/unaligned.h>
#include <linux/libfdt.h>
@@ -464,7 +465,6 @@ void do_fixup_by_compat_u32(void *fdt, const char *compat,
do_fixup_by_compat(fdt, compat, prop, &tmp, 4, create);
}
-#ifdef CONFIG_ARCH_FIXUP_FDT_MEMORY
/*
* fdt_pack_reg - pack address and size array into the "reg"-suitable stream
*/
@@ -493,6 +493,7 @@ static int fdt_pack_reg(const void *fdt, void *buf, u64 *address, u64 *size,
return p - (char *)buf;
}
+#ifdef CONFIG_ARCH_FIXUP_FDT_MEMORY
#if CONFIG_NR_DRAM_BANKS > 4
#define MEMORY_BANKS_MAX CONFIG_NR_DRAM_BANKS
#else
@@ -2222,3 +2223,39 @@ int fdt_valid(struct fdt_header **blobp)
}
return 1;
}
+
+int fdt_fixup_pmem_region(void *fdt, u64 pmem_start, u64 pmem_size)
+{
+ char node_name[32];
+ int nodeoffset, len;
+ int err;
+ u8 tmp[4 * 16]; /* Up to 64-bit address + 64-bit size */
+
+ if (!IS_ALIGNED(pmem_start, SZ_2M) ||
+ !IS_ALIGNED(pmem_start + pmem_size, SZ_2M)) {
+ printf("Start and end address must be 2MiB aligned\n");
+ return -1;
+ }
+
+ snprintf(node_name, sizeof(node_name), "pmem@%llx", pmem_start);
+ nodeoffset = fdt_find_or_add_subnode(fdt, 0, node_name);
+ if (nodeoffset < 0)
+ return nodeoffset;
+
+ err = fdt_setprop_string(fdt, nodeoffset, "compatible", "pmem-region");
+ if (err)
+ return err;
+ err = fdt_setprop_empty(fdt, nodeoffset, "volatile");
+ if (err)
+ return err;
+
+ len = fdt_pack_reg(fdt, tmp, &pmem_start, &pmem_size, 1);
+ err = fdt_setprop(fdt, nodeoffset, "reg", tmp, len);
+ if (err < 0) {
+ printf("WARNING: could not set pmem %s %s.\n", "reg",
+ fdt_strerror(err));
+ return err;
+ }
+
+ return 0;
+}
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/image-fdt.c b/boot/image-fdt.c
index 9d1598b1a93..8f718ad29f6 100644
--- a/boot/image-fdt.c
+++ b/boot/image-fdt.c
@@ -11,6 +11,7 @@
#include <command.h>
#include <fdt_support.h>
#include <fdtdec.h>
+#include <efi.h>
#include <env.h>
#include <errno.h>
#include <image.h>
@@ -649,6 +650,12 @@ int image_setup_libfdt(struct bootm_headers *images, void *blob, bool lmb)
if (!ft_verify_fdt(blob))
goto err;
+ if (CONFIG_IS_ENABLED(BLKMAP) && CONFIG_IS_ENABLED(EFI_LOADER)) {
+ fdt_ret = fdt_efi_pmem_setup(blob);
+ if (fdt_ret)
+ goto err;
+ }
+
/* after here we are using a livetree */
if (!of_live_active() && CONFIG_IS_ENABLED(EVENT)) {
struct event_ft_fixup fixup;
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 */