diff options
author | Tom Rini | 2024-04-10 17:06:27 -0600 |
---|---|---|
committer | Tom Rini | 2024-04-10 17:06:27 -0600 |
commit | 777c28460947371ada40868dc994dfe8537d7115 (patch) | |
tree | ed76982806de141ac6bcbc303b3167f90e8877e7 /boot | |
parent | ab3453e7b12daef47b9e91da2a2a3d48615dc6fc (diff) | |
parent | cf70f75447133c497f9e5c56f2b33c8f2d3f08b5 (diff) |
Merge patch series "pxe: Allow extlinux booting without CMDLINE enabled"
Simon Glass <sjg@chromium.org> says:
This series is the culmanation of the current line of refactoring
series. It adjusts pxe to call the booting functionality directly
rather than going through the command-line interface.
With this is is possible to boot using the extlinux bootmeth without
the command line enabled.
It also updates fastboot to do a similar thing.
Diffstat (limited to 'boot')
-rw-r--r-- | boot/Kconfig | 129 | ||||
-rw-r--r-- | boot/Makefile | 2 | ||||
-rw-r--r-- | boot/pxe_utils.c | 404 |
3 files changed, 317 insertions, 218 deletions
diff --git a/boot/Kconfig b/boot/Kconfig index d9a6c270059..777e408e243 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -2,39 +2,6 @@ menu "Boot options" menu "Boot images" -config ANDROID_BOOT_IMAGE - bool "Android Boot Images" - default y if FASTBOOT - help - This enables support for booting images which use the Android - image format header. - -config TIMESTAMP - bool "Show image date and time when displaying image information" - default y if CMD_DATE - help - When CONFIG_TIMESTAMP is selected, the timestamp (date and time) of - an image is printed by image commands like bootm or iminfo. This - is shown as 'Timestamp: xxx' and 'Created: xxx'. If this option is - enabled, then U-Boot requires FITs to have a timestamp. If a FIT is - loaded that does not, the message 'Wrong FIT format: no timestamp' - is shown. - -config BUTTON_CMD - bool "Support for running a command if a button is held during boot" - depends on CMDLINE - depends on BUTTON - help - For many embedded devices it's useful to enter a special flashing mode - such as fastboot mode when a button is held during boot. This option - allows arbitrary commands to be assigned to specific buttons. These will - be run after "preboot" if the button is held. Configuration is done via - the environment variables "button_cmd_N_name" and "button_cmd_N" where n is - the button number (starting from 0). e.g: - - "button_cmd_0_name=vol_down" - "button_cmd_0=fastboot usb 0" - menuconfig FIT bool "Flattened Image Tree (FIT)" select HASH @@ -721,6 +688,100 @@ config BOOTMETH_SCRIPT endif # BOOTSTD +config BOOTM + bool "Support booting an application image from memory" + default y + help + This is the main boot implementation in U-Boot, supporting a wide + variety of features including FIT and legacy-image boot, kernel and + FDT selection, setting up of the command line for the OS and many + other features. + + This option should normally be enabled. It is used to implement the + 'bootm' command. + +config BOOTM_LINUX + bool "Support booting Linux OS images" + depends on BOOTM || CMD_BOOTZ || CMD_BOOTI + default y + help + Support booting the Linux kernel directly via a command such as bootm + or booti or bootz. + +config BOOTM_NETBSD + bool "Support booting NetBSD (non-EFI) loader images" + depends on BOOTM + default y + help + Support booting NetBSD via the bootm command. + +config BOOTM_OPENRTOS + bool "Support booting OPENRTOS / FreeRTOS images" + depends on BOOTM + help + Support booting OPENRTOS / FreeRTOS via the bootm command. + +config BOOTM_OSE + bool "Support booting Enea OSE images" + depends on (ARM && (ARM64 || CPU_V7A || CPU_V7R) || SANDBOX || PPC || X86) + depends on BOOTM + help + Support booting Enea OSE images via the bootm command. + +config BOOTM_PLAN9 + bool "Support booting Plan9 OS images" + depends on BOOTM + default y + help + Support booting Plan9 images via the bootm command. + +config BOOTM_RTEMS + bool "Support booting RTEMS OS images" + depends on BOOTM + default y + help + Support booting RTEMS images via the bootm command. + +config BOOTM_VXWORKS + bool "Support booting VxWorks OS images" + depends on BOOTM + default y + help + Support booting VxWorks images via the bootm command. + +config ANDROID_BOOT_IMAGE + bool "Android Boot Images" + default y if FASTBOOT + help + This enables support for booting images which use the Android + image format header. + +config TIMESTAMP + bool "Show image date and time when displaying image information" + default y if CMD_DATE + help + When CONFIG_TIMESTAMP is selected, the timestamp (date and time) of + an image is printed by image commands like bootm or iminfo. This + is shown as 'Timestamp: xxx' and 'Created: xxx'. If this option is + enabled, then U-Boot requires FITs to have a timestamp. If a FIT is + loaded that does not, the message 'Wrong FIT format: no timestamp' + is shown. + +config BUTTON_CMD + bool "Support for running a command if a button is held during boot" + depends on CMDLINE + depends on BUTTON + help + For many embedded devices it's useful to enter a special flashing mode + such as fastboot mode when a button is held during boot. This option + allows arbitrary commands to be assigned to specific buttons. These will + be run after "preboot" if the button is held. Configuration is done via + the environment variables "button_cmd_N_name" and "button_cmd_N" where n is + the button number (starting from 0). e.g: + + "button_cmd_0_name=vol_down" + "button_cmd_0=fastboot usb 0" + config LEGACY_IMAGE_FORMAT bool "Enable support for the legacy image format" default y if !FIT_SIGNATURE && !TI_SECURE_DEVICE @@ -765,7 +826,7 @@ endif # MEASURED_BOOT config SYS_BOOTM_LEN hex "Maximum size of a decompresed OS image" - depends on CMD_BOOTM || CMD_BOOTI || CMD_BOOTZ || \ + depends on BOOTM || CMD_BOOTI || CMD_BOOTZ || \ LEGACY_IMAGE_FORMAT || SPL_LEGACY_IMAGE_FORMAT default 0x4000000 if PPC || ARM64 default 0x1000000 if X86 || ARCH_MX6 || ARCH_MX7 diff --git a/boot/Makefile b/boot/Makefile index 84ccfeaecec..bf767fd5356 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -6,7 +6,7 @@ ifndef CONFIG_SPL_BUILD obj-$(CONFIG_BOOT_RETRY) += bootretry.o -obj-$(CONFIG_CMD_BOOTM) += bootm.o bootm_os.o +obj-$(CONFIG_BOOTM) += bootm.o bootm_os.o obj-$(CONFIG_CMD_BOOTZ) += bootm.o bootm_os.o obj-$(CONFIG_CMD_BOOTI) += bootm.o bootm_os.o diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c index 96205626750..d5e1bead125 100644 --- a/boot/pxe_utils.c +++ b/boot/pxe_utils.c @@ -5,6 +5,7 @@ */ #include <common.h> +#include <bootm.h> #include <command.h> #include <dm.h> #include <env.h> @@ -470,6 +471,220 @@ skip_overlay: #endif /** + * calc_fdt_fname() - Figure out the filename to use for the FDT + * + * Determine the path to the FDT filename, based on the "fdtfile" environment + * variable. Use <soc>-<board>.dtb as a fallback + * + * @fdtdir: Directory to use for the FDT file + * Return: allocated filename (including directory), or NULL if out of memory + */ +static char *calc_fdt_fname(const char *fdtdir) +{ + char *fdtfile; + char *f1, *f2, *f3, *f4, *slash; + int len; + + f1 = env_get("fdtfile"); + if (f1) { + f2 = ""; + f3 = ""; + f4 = ""; + } else { + /* + * For complex cases where this code doesn't generate the + * correct filename, the board code should set $fdtfile during + * early boot, or the boot scripts should set $fdtfile before + * invoking "pxe" or "sysboot". + */ + f1 = env_get("soc"); + f2 = "-"; + f3 = env_get("board"); + f4 = ".dtb"; + if (!f1) { + f1 = ""; + f2 = ""; + } + if (!f3) { + f2 = ""; + f3 = ""; + } + } + + len = strlen(fdtdir); + if (!len) + slash = "./"; + else if (fdtdir[len - 1] != '/') + slash = "/"; + else + slash = ""; + + len = strlen(fdtdir) + strlen(slash) + strlen(f1) + strlen(f2) + + strlen(f3) + strlen(f4) + 1; + fdtfile = malloc(len); + if (!fdtfile) { + printf("malloc fail (FDT filename)\n"); + return NULL; + } + + snprintf(fdtfile, len, "%s%s%s%s%s%s", fdtdir, slash, f1, f2, f3, f4); + + return fdtfile; +} + +/** + * label_run_boot() - Run the correct boot procedure + * + * 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. + * + * @ctx: PXE context + * @label: Label to process + * @kernel_addr: string containing the kernel address / config + * @initrd_str: string containing the initrd address / size + * @initrd_addr_str: initrd address, or NULL if none + * @initrd_filesize: initrd size in bytes; only valid if initrd_addr_str is not + * NULL + * Returns does not return on success, otherwise returns 0 if a localboot + * label was processed, or 1 on error + */ +static int label_run_boot(struct pxe_context *ctx, struct pxe_label *label, + char *kernel_addr, char *initrd_str, + char *initrd_addr_str, char *initrd_filesize) +{ + struct bootm_info bmi; + const char *fdt_addr; + ulong kernel_addr_r; + void *buf; + int ret; + + if (IS_ENABLED(CONFIG_BOOTM)) + bootm_init(&bmi); + + fdt_addr = env_get("fdt_addr_r"); + + /* For FIT, the label can be identical to kernel one */ + if (label->fdt && !strcmp(label->kernel_label, label->fdt)) { + fdt_addr = kernel_addr; + /* if fdt label is defined then get fdt from server */ + } else if (fdt_addr) { + char *fdtfile = NULL; + char *fdtfilefree = NULL; + + if (label->fdt) { + if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) { + if (strcmp("-", label->fdt)) + fdtfile = label->fdt; + } else { + fdtfile = label->fdt; + } + } else if (label->fdtdir) { + fdtfilefree = calc_fdt_fname(label->fdtdir); + if (!fdtfilefree) + return -ENOMEM; + fdtfile = fdtfilefree; + } + + if (fdtfile) { + int err = get_relfile_envaddr(ctx, fdtfile, + "fdt_addr_r", NULL); + + free(fdtfilefree); + if (err < 0) { + fdt_addr = NULL; + + if (label->fdt) { + printf("Skipping %s for failure retrieving FDT\n", + label->name); + return -ENOENT; + } + + if (label->fdtdir) { + printf("Skipping fdtdir %s for failure retrieving dts\n", + label->fdtdir); + } + } + + if (label->kaslrseed) + label_boot_kaslrseed(); + +#ifdef CONFIG_OF_LIBFDT_OVERLAY + if (label->fdtoverlays) + label_boot_fdtoverlay(ctx, label); +#endif + } else { + fdt_addr = NULL; + } + } + + bmi.addr_img = kernel_addr; + + if (initrd_addr_str) + bmi.conf_ramdisk = initrd_str; + + if (!fdt_addr) { + if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) { + if (strcmp("-", label->fdt)) + fdt_addr = env_get("fdt_addr"); + } else { + fdt_addr = env_get("fdt_addr"); + } + } + + kernel_addr_r = genimg_get_kernel_addr(kernel_addr); + buf = map_sysmem(kernel_addr_r, 0); + + if (!fdt_addr && genimg_get_format(buf) != IMAGE_FORMAT_FIT) { + if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) { + if (strcmp("-", label->fdt)) + fdt_addr = env_get("fdtcontroladdr"); + } else { + fdt_addr = env_get("fdtcontroladdr"); + } + } + + bmi.conf_fdt = fdt_addr; + + /* Try bootm for legacy and FIT format image */ + if (genimg_get_format(buf) != IMAGE_FORMAT_INVALID && + IS_ENABLED(CONFIG_BOOTM)) + ret = bootm_run(&bmi); + /* Try booting an AArch64 Linux kernel image */ + else if (IS_ENABLED(CONFIG_BOOTM)) + ret = booti_run(&bmi); + /* Try booting a Image */ + else if (IS_ENABLED(CONFIG_BOOTM)) + ret = bootz_run(&bmi); + /* Try booting an x86_64 Linux kernel image */ + else if (IS_ENABLED(CONFIG_ZBOOT)) + ret = zboot_run(hextoul(kernel_addr, NULL), 0, + initrd_addr_str ? + hextoul(initrd_addr_str, NULL) : 0, + initrd_addr_str ? + hextoul(initrd_filesize, NULL) : 0, + 0, NULL); + + unmap_sysmem(buf); + + 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 @@ -491,8 +706,6 @@ skip_overlay: */ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) { - char *bootm_argv[] = { "bootm", NULL, NULL, NULL, NULL }; - char *zboot_argv[] = { "zboot", NULL, "0", NULL, NULL }; char *kernel_addr = NULL; char *initrd_addr_str = NULL; char initrd_filesize[10]; @@ -500,11 +713,7 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) char mac_str[29] = ""; char ip_str[68] = ""; char *fit_addr = NULL; - int bootm_argc = 2; - int zboot_argc = 3; - int len = 0; - ulong kernel_addr_r; - void *buf; + int ret; label_print(label); @@ -545,9 +754,10 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) /* For FIT, the label can be identical to kernel one */ if (label->initrd && !strcmp(label->kernel_label, label->initrd)) { - initrd_addr_str = kernel_addr; + initrd_addr_str = kernel_addr; } else if (label->initrd) { ulong size; + if (get_relfile_envaddr(ctx, label->initrd, "ramdisk_addr_r", &size) < 0) { printf("Skipping %s for failure retrieving initrd\n", @@ -593,7 +803,7 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) } if (label->append) - strncpy(bootargs, label->append, sizeof(bootargs)); + strlcpy(bootargs, label->append, sizeof(bootargs)); strcat(bootargs, ip_str); strcat(bootargs, mac_str); @@ -604,180 +814,8 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) printf("append: %s\n", finalbootargs); } - /* - * fdt usage is optional: - * It handles the following scenarios. - * - * Scenario 1: If fdt_addr_r specified and "fdt" or "fdtdir" label is - * defined in pxe file, retrieve fdt blob from server. Pass fdt_addr_r to - * bootm, and adjust argc appropriately. - * - * If retrieve fails and no exact fdt blob is specified in pxe file with - * "fdt" label, try Scenario 2. - * - * Scenario 2: If there is an fdt_addr specified, pass it along to - * bootm, and adjust argc appropriately. - * - * Scenario 3: If there is an fdtcontroladdr specified, pass it along to - * bootm, and adjust argc appropriately, unless the image type is fitImage. - * - * Scenario 4: fdt blob is not available. - */ - bootm_argv[3] = env_get("fdt_addr_r"); - - /* For FIT, the label can be identical to kernel one */ - if (label->fdt && !strcmp(label->kernel_label, label->fdt)) { - bootm_argv[3] = kernel_addr; - /* if fdt label is defined then get fdt from server */ - } else if (bootm_argv[3]) { - char *fdtfile = NULL; - char *fdtfilefree = NULL; - - if (label->fdt) { - if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) { - if (strcmp("-", label->fdt)) - fdtfile = label->fdt; - } else { - fdtfile = label->fdt; - } - } else if (label->fdtdir) { - char *f1, *f2, *f3, *f4, *slash; - - f1 = env_get("fdtfile"); - if (f1) { - f2 = ""; - f3 = ""; - f4 = ""; - } else { - /* - * For complex cases where this code doesn't - * generate the correct filename, the board - * code should set $fdtfile during early boot, - * or the boot scripts should set $fdtfile - * before invoking "pxe" or "sysboot". - */ - f1 = env_get("soc"); - f2 = "-"; - f3 = env_get("board"); - f4 = ".dtb"; - if (!f1) { - f1 = ""; - f2 = ""; - } - if (!f3) { - f2 = ""; - f3 = ""; - } - } - - len = strlen(label->fdtdir); - if (!len) - slash = "./"; - else if (label->fdtdir[len - 1] != '/') - slash = "/"; - else - slash = ""; - - len = strlen(label->fdtdir) + strlen(slash) + - strlen(f1) + strlen(f2) + strlen(f3) + - strlen(f4) + 1; - fdtfilefree = malloc(len); - if (!fdtfilefree) { - printf("malloc fail (FDT filename)\n"); - goto cleanup; - } - - snprintf(fdtfilefree, len, "%s%s%s%s%s%s", - label->fdtdir, slash, f1, f2, f3, f4); - fdtfile = fdtfilefree; - } - - if (fdtfile) { - int err = get_relfile_envaddr(ctx, fdtfile, - "fdt_addr_r", NULL); - - free(fdtfilefree); - if (err < 0) { - bootm_argv[3] = NULL; - - if (label->fdt) { - printf("Skipping %s for failure retrieving FDT\n", - label->name); - goto cleanup; - } - - if (label->fdtdir) { - printf("Skipping fdtdir %s for failure retrieving dts\n", - label->fdtdir); - } - } - - if (label->kaslrseed) - label_boot_kaslrseed(); - -#ifdef CONFIG_OF_LIBFDT_OVERLAY - if (label->fdtoverlays) - label_boot_fdtoverlay(ctx, label); -#endif - } else { - bootm_argv[3] = NULL; - } - } - - bootm_argv[1] = kernel_addr; - zboot_argv[1] = kernel_addr; - - if (initrd_addr_str) { - bootm_argv[2] = initrd_str; - bootm_argc = 3; - - zboot_argv[3] = initrd_addr_str; - zboot_argv[4] = initrd_filesize; - zboot_argc = 5; - } - - if (!bootm_argv[3]) { - if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) { - if (strcmp("-", label->fdt)) - bootm_argv[3] = env_get("fdt_addr"); - } else { - bootm_argv[3] = env_get("fdt_addr"); - } - } - - kernel_addr_r = genimg_get_kernel_addr(kernel_addr); - buf = map_sysmem(kernel_addr_r, 0); - - if (!bootm_argv[3] && genimg_get_format(buf) != IMAGE_FORMAT_FIT) { - if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) { - if (strcmp("-", label->fdt)) - bootm_argv[3] = env_get("fdtcontroladdr"); - } else { - bootm_argv[3] = env_get("fdtcontroladdr"); - } - } - - if (bootm_argv[3]) { - if (!bootm_argv[2]) - bootm_argv[2] = "-"; - bootm_argc = 4; - } - - /* Try bootm for legacy and FIT format image */ - if (genimg_get_format(buf) != IMAGE_FORMAT_INVALID && - IS_ENABLED(CONFIG_CMD_BOOTM)) - do_bootm(ctx->cmdtp, 0, bootm_argc, bootm_argv); - /* Try booting an AArch64 Linux kernel image */ - else if (IS_ENABLED(CONFIG_CMD_BOOTI)) - do_booti(ctx->cmdtp, 0, bootm_argc, bootm_argv); - /* Try booting a Image */ - else if (IS_ENABLED(CONFIG_CMD_BOOTZ)) - do_bootz(ctx->cmdtp, 0, bootm_argc, bootm_argv); - /* Try booting an x86_64 Linux kernel image */ - else if (IS_ENABLED(CONFIG_CMD_ZBOOT)) - do_zboot_parent(ctx->cmdtp, 0, zboot_argc, zboot_argv, NULL); - - unmap_sysmem(buf); + ret = label_run_boot(ctx, label, kernel_addr, initrd_str, + initrd_addr_str, initrd_filesize); cleanup: free(fit_addr); |