diff options
-rw-r--r-- | arch/arm/lib/image.c | 9 | ||||
-rw-r--r-- | arch/riscv/lib/image.c | 9 | ||||
-rw-r--r-- | arch/sandbox/lib/bootm.c | 5 | ||||
-rw-r--r-- | arch/x86/include/asm/zimage.h | 57 | ||||
-rw-r--r-- | arch/x86/lib/zimage.c | 102 | ||||
-rw-r--r-- | boot/Makefile | 2 | ||||
-rw-r--r-- | boot/bootm.c | 77 | ||||
-rw-r--r-- | boot/bootmeth_cros.c | 6 | ||||
-rw-r--r-- | boot/image-board.c | 36 | ||||
-rw-r--r-- | boot/pxe_utils.c | 417 | ||||
-rw-r--r-- | cmd/bootflow.c | 8 | ||||
-rw-r--r-- | cmd/net.c | 92 | ||||
-rw-r--r-- | cmd/x86/zboot.c | 33 | ||||
-rw-r--r-- | include/bootm.h | 63 | ||||
-rw-r--r-- | include/image.h | 48 | ||||
-rw-r--r-- | include/net-common.h | 30 | ||||
-rw-r--r-- | net/net.c | 44 |
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 = ¶ms->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) |