diff options
| author | Tom Rini <[email protected]> | 2023-01-17 08:55:40 -0500 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2023-01-17 08:55:40 -0500 |
| commit | 5b958dea5c678dbdb2aeb6ac3c0c8cc8dfea065c (patch) | |
| tree | 172424111d1a39640cf5245eefd080fae3b5fb27 /cmd | |
| parent | 6d03688e75041a7bae4d33815de28da781c37dd6 (diff) | |
| parent | b5c8fea7b830c0304051237ad1501431a958b0e6 (diff) | |
Merge branch '2022-01-16-bootstd-updates'
To quote the author:
So far standard boot lacks a boot menu, although it is possible to create
a rudimentary one using the existing 'bootmenu' command.
Even then, this text-based menu offer only basic functionality and does
not take full advantage of the displays which are common on many devices.
This series provides a 'bootflow menu' command which allows the user to
select from the available bootflows. An attempt is made to show the name
of the available operating systems, by reading more information into the
bootflow. A logo can be read also, where supported, so that this can be
presented to the user when an option is highlighted.
Full use is made of TrueType fonts, if enabled. For cases where only a
serial console is available, it falls back to a simple text-based menu.
All of this is implementing using a new 'expo' construct, a collection of
scenes (like menu screens) which can be navigated by the user to view
information and select options. This is fairly general and should be able
to cope with a wider array of use cases, with less hacking of the menu
code, such as is currently needed for CMD_BOOTEFI_BOOTMGR.
Of course it would be possible to enhance the existing menu rather than
creating a new setup. Instead it seems better to make the existing menu
use expo, if code space permits. It avoids the event-loop problem and
should be more extensible, given its loosely coupled components and use of
IDs instead of pointers. Further motivation is provided in the
documentation.
For now the CLI keypress-decoding code is split out to be used by the new
menu. The key codes defined by menu.h are reused also.
This is of course just a starting point. Some ideas for future work are
included in the documentation.
Diffstat (limited to 'cmd')
| -rw-r--r-- | cmd/bootflow.c | 44 | ||||
| -rw-r--r-- | cmd/bootmenu.c | 19 | ||||
| -rw-r--r-- | cmd/eficonfig.c | 38 | ||||
| -rw-r--r-- | cmd/font.c | 11 | ||||
| -rw-r--r-- | cmd/source.c | 166 |
5 files changed, 84 insertions, 194 deletions
diff --git a/cmd/bootflow.c b/cmd/bootflow.c index 313103d2775..2b6ed26fdcb 100644 --- a/cmd/bootflow.c +++ b/cmd/bootflow.c @@ -337,6 +337,13 @@ static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc, printf("Filename: %s\n", bflow->fname); printf("Buffer: %lx\n", (ulong)map_to_sysmem(bflow->buf)); printf("Size: %x (%d bytes)\n", bflow->size, bflow->size); + printf("OS: %s\n", bflow->os_name ? bflow->os_name : "(none)"); + printf("Logo: %s\n", bflow->logo ? + simple_xtoa((ulong)map_to_sysmem(bflow->logo)) : "(none)"); + if (bflow->logo) { + printf("Logo size: %x (%d bytes)\n", bflow->logo_size, + bflow->logo_size); + } printf("Error: %d\n", bflow->err); if (dump && bflow->buf) { /* Set some sort of maximum on the size */ @@ -382,6 +389,37 @@ static int do_bootflow_boot(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } + +static int do_bootflow_menu(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct bootstd_priv *std; + struct bootflow *bflow; + bool text_mode = false; + int ret; + + if (argc > 1 && *argv[1] == '-') + text_mode = strchr(argv[1], 't'); + + ret = bootstd_get_priv(&std); + if (ret) + return CMD_RET_FAILURE; + + ret = bootflow_menu_run(std, text_mode, &bflow); + if (ret) { + if (ret == -EAGAIN) + printf("Nothing chosen\n"); + else + printf("Menu failed (err=%d)\n", ret); + + return CMD_RET_FAILURE; + } + + printf("Selected: %s\n", bflow->os_name ? bflow->os_name : bflow->name); + std->cur_bootflow = bflow; + + return 0; +} #endif /* CONFIG_CMD_BOOTFLOW_FULL */ #ifdef CONFIG_SYS_LONGHELP @@ -391,7 +429,8 @@ static char bootflow_help_text[] = "bootflow list [-e] - list scanned bootflows (-e errors)\n" "bootflow select [<num>|<name>] - select a bootflow\n" "bootflow info [-d] - show info on current bootflow (-d dump bootflow)\n" - "bootflow boot - boot current bootflow (or first available if none selected)"; + "bootflow boot - boot current bootflow (or first available if none selected)\n" + "bootflow menu [-t] - show a menu of available bootflows"; #else "scan - boot first available bootflow\n"; #endif @@ -403,6 +442,7 @@ U_BOOT_CMD_WITH_SUBCMDS(bootflow, "Boot flows", bootflow_help_text, U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootflow_list), U_BOOT_SUBCMD_MKENT(select, 2, 1, do_bootflow_select), U_BOOT_SUBCMD_MKENT(info, 2, 1, do_bootflow_info), - U_BOOT_SUBCMD_MKENT(boot, 1, 1, do_bootflow_boot) + U_BOOT_SUBCMD_MKENT(boot, 1, 1, do_bootflow_boot), + U_BOOT_SUBCMD_MKENT(menu, 2, 1, do_bootflow_menu), #endif ); diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c index e5a10f5d5c4..3236ca5d799 100644 --- a/cmd/bootmenu.c +++ b/cmd/bootmenu.c @@ -4,6 +4,7 @@ */ #include <charset.h> +#include <cli.h> #include <common.h> #include <command.h> #include <ansi.h> @@ -84,38 +85,40 @@ static void bootmenu_print_entry(void *data) static char *bootmenu_choice_entry(void *data) { + struct cli_ch_state s_cch, *cch = &s_cch; struct bootmenu_data *menu = data; struct bootmenu_entry *iter; - enum bootmenu_key key = KEY_NONE; - int esc = 0; + enum bootmenu_key key = BKEY_NONE; int i; + cli_ch_init(cch); + while (1) { if (menu->delay >= 0) { /* Autoboot was not stopped */ - bootmenu_autoboot_loop(menu, &key, &esc); + key = bootmenu_autoboot_loop(menu, cch); } else { /* Some key was pressed, so autoboot was stopped */ - bootmenu_loop(menu, &key, &esc); + key = bootmenu_loop(menu, cch); } switch (key) { - case KEY_UP: + case BKEY_UP: if (menu->active > 0) --menu->active; /* no menu key selected, regenerate menu */ return NULL; - case KEY_DOWN: + case BKEY_DOWN: if (menu->active < menu->count - 1) ++menu->active; /* no menu key selected, regenerate menu */ return NULL; - case KEY_SELECT: + case BKEY_SELECT: iter = menu->first; for (i = 0; i < menu->active; ++i) iter = iter->next; return iter->key; - case KEY_QUIT: + case BKEY_QUIT: /* Quit by choosing the last entry - U-Boot console */ iter = menu->first; while (iter->next) diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c index ce7175a5666..d830e4af53b 100644 --- a/cmd/eficonfig.c +++ b/cmd/eficonfig.c @@ -6,6 +6,7 @@ */ #include <ansi.h> +#include <cli.h> #include <common.h> #include <charset.h> #include <efi_loader.h> @@ -184,34 +185,36 @@ static void eficonfig_display_statusline(struct menu *m) */ static char *eficonfig_choice_entry(void *data) { - int esc = 0; + struct cli_ch_state s_cch, *cch = &s_cch; struct list_head *pos, *n; struct eficonfig_entry *entry; - enum bootmenu_key key = KEY_NONE; + enum bootmenu_key key = BKEY_NONE; struct efimenu *efi_menu = data; + cli_ch_init(cch); + while (1) { - bootmenu_loop((struct bootmenu_data *)efi_menu, &key, &esc); + key = bootmenu_loop((struct bootmenu_data *)efi_menu, cch); switch (key) { - case KEY_UP: + case BKEY_UP: if (efi_menu->active > 0) --efi_menu->active; /* no menu key selected, regenerate menu */ return NULL; - case KEY_DOWN: + case BKEY_DOWN: if (efi_menu->active < efi_menu->count - 1) ++efi_menu->active; /* no menu key selected, regenerate menu */ return NULL; - case KEY_SELECT: + case BKEY_SELECT: list_for_each_safe(pos, n, &efi_menu->list) { entry = list_entry(pos, struct eficonfig_entry, list); if (entry->num == efi_menu->active) return entry->key; } break; - case KEY_QUIT: + case BKEY_QUIT: /* Quit by choosing the last entry */ entry = list_last_entry(&efi_menu->list, struct eficonfig_entry, list); return entry->key; @@ -1862,16 +1865,17 @@ static void eficonfig_display_change_boot_order(struct efimenu *efi_menu) */ static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu) { - int esc = 0; + struct cli_ch_state s_cch, *cch = &s_cch; struct list_head *pos, *n; - enum bootmenu_key key = KEY_NONE; + enum bootmenu_key key = BKEY_NONE; struct eficonfig_entry *entry, *tmp; + cli_ch_init(cch); while (1) { - bootmenu_loop(NULL, &key, &esc); + key = bootmenu_loop(NULL, cch); switch (key) { - case KEY_PLUS: + case BKEY_PLUS: if (efi_menu->active > 0) { list_for_each_safe(pos, n, &efi_menu->list) { entry = list_entry(pos, struct eficonfig_entry, list); @@ -1885,11 +1889,11 @@ static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu) list_add(&tmp->list, &entry->list); } fallthrough; - case KEY_UP: + case BKEY_UP: if (efi_menu->active > 0) --efi_menu->active; return EFI_NOT_READY; - case KEY_MINUS: + case BKEY_MINUS: if (efi_menu->active < efi_menu->count - 3) { list_for_each_safe(pos, n, &efi_menu->list) { entry = list_entry(pos, struct eficonfig_entry, list); @@ -1905,11 +1909,11 @@ static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu) ++efi_menu->active; } return EFI_NOT_READY; - case KEY_DOWN: + case BKEY_DOWN: if (efi_menu->active < efi_menu->count - 1) ++efi_menu->active; return EFI_NOT_READY; - case KEY_SELECT: + case BKEY_SELECT: /* "Save" */ if (efi_menu->active == efi_menu->count - 2) return EFI_SUCCESS; @@ -1919,7 +1923,7 @@ static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu) return EFI_ABORTED; break; - case KEY_SPACE: + case BKEY_SPACE: if (efi_menu->active < efi_menu->count - 2) { list_for_each_safe(pos, n, &efi_menu->list) { entry = list_entry(pos, struct eficonfig_entry, list); @@ -1932,7 +1936,7 @@ static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu) } } break; - case KEY_QUIT: + case BKEY_QUIT: return EFI_ABORTED; default: /* Pressed key is not valid, no need to regenerate the menu */ diff --git a/cmd/font.c b/cmd/font.c index 3e522f3aaa1..7b4347f32b5 100644 --- a/cmd/font.c +++ b/cmd/font.c @@ -15,7 +15,11 @@ static int do_font_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - vidconsole_list_fonts(); + struct udevice *dev; + + if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev)) + return CMD_RET_FAILURE; + vidconsole_list_fonts(dev); return 0; } @@ -47,6 +51,7 @@ static int do_font_select(struct cmd_tbl *cmdtp, int flag, int argc, static int do_font_size(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { + const char *font_name; struct udevice *dev; uint size; int ret; @@ -56,9 +61,11 @@ static int do_font_size(struct cmd_tbl *cmdtp, int flag, int argc, if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev)) return CMD_RET_FAILURE; + font_name = vidconsole_get_font_size(dev, &size); size = dectoul(argv[1], NULL); - ret = vidconsole_select_font(dev, NULL, size); + + ret = vidconsole_select_font(dev, font_name, size); if (ret) { printf("Failed (error %d)\n", ret); return CMD_RET_FAILURE; diff --git a/cmd/source.c b/cmd/source.c index 94da5d8d6ad..92c7835bf50 100644 --- a/cmd/source.c +++ b/cmd/source.c @@ -24,169 +24,6 @@ #include <asm/byteorder.h> #include <asm/io.h> -#if defined(CONFIG_FIT) -/** - * get_default_image() - Return default property from /images - * - * Return: Pointer to value of default property (or NULL) - */ -static const char *get_default_image(const void *fit) -{ - int images_noffset; - - images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); - if (images_noffset < 0) - return NULL; - - return fdt_getprop(fit, images_noffset, FIT_DEFAULT_PROP, NULL); -} -#endif - -int image_source_script(ulong addr, const char *fit_uname, const char *confname) -{ - ulong len; -#if defined(CONFIG_LEGACY_IMAGE_FORMAT) - const struct legacy_img_hdr *hdr; -#endif - u32 *data; - int verify; - void *buf; -#if defined(CONFIG_FIT) - const void* fit_hdr; - int noffset; - const void *fit_data; - size_t fit_len; -#endif - - verify = env_get_yesno("verify"); - - buf = map_sysmem(addr, 0); - switch (genimg_get_format(buf)) { -#if defined(CONFIG_LEGACY_IMAGE_FORMAT) - case IMAGE_FORMAT_LEGACY: - hdr = buf; - - if (!image_check_magic (hdr)) { - puts ("Bad magic number\n"); - return 1; - } - - if (!image_check_hcrc (hdr)) { - puts ("Bad header crc\n"); - return 1; - } - - if (verify) { - if (!image_check_dcrc (hdr)) { - puts ("Bad data crc\n"); - return 1; - } - } - - if (!image_check_type (hdr, IH_TYPE_SCRIPT)) { - puts ("Bad image type\n"); - return 1; - } - - /* get length of script */ - data = (u32 *)image_get_data (hdr); - - if ((len = uimage_to_cpu (*data)) == 0) { - puts ("Empty Script\n"); - return 1; - } - - /* - * scripts are just multi-image files with one component, seek - * past the zero-terminated sequence of image lengths to get - * to the actual image data - */ - while (*data++); - break; -#endif -#if defined(CONFIG_FIT) - case IMAGE_FORMAT_FIT: - fit_hdr = buf; - if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) { - puts ("Bad FIT image format\n"); - return 1; - } - - if (!fit_uname) { - /* If confname is empty, use the default */ - if (confname && *confname) - noffset = fit_conf_get_node(fit_hdr, confname); - else - noffset = fit_conf_get_node(fit_hdr, NULL); - if (noffset < 0) { - if (!confname) - goto fallback; - printf("Could not find config %s\n", confname); - return 1; - } - - if (verify && fit_config_verify(fit_hdr, noffset)) - return 1; - - noffset = fit_conf_get_prop_node(fit_hdr, noffset, - FIT_SCRIPT_PROP, - IH_PHASE_NONE); - if (noffset < 0) { - if (!confname) - goto fallback; - printf("Could not find script in %s\n", confname); - return 1; - } - } else { -fallback: - if (!fit_uname || !*fit_uname) - fit_uname = get_default_image(fit_hdr); - if (!fit_uname) { - puts("No FIT subimage unit name\n"); - return 1; - } - - /* get script component image node offset */ - noffset = fit_image_get_node(fit_hdr, fit_uname); - if (noffset < 0) { - printf("Can't find '%s' FIT subimage\n", - fit_uname); - return 1; - } - } - - if (!fit_image_check_type (fit_hdr, noffset, IH_TYPE_SCRIPT)) { - puts("Not a script image\n"); - return 1; - } - - /* verify integrity */ - if (verify && !fit_image_verify(fit_hdr, noffset)) { - puts("Bad Data Hash\n"); - return 1; - } - - /* get script subimage data address and length */ - if (fit_image_get_data (fit_hdr, noffset, &fit_data, &fit_len)) { - puts ("Could not find script subimage data\n"); - return 1; - } - - data = (u32 *)fit_data; - len = (ulong)fit_len; - break; -#endif - default: - puts ("Wrong image format for \"source\" command\n"); - return 1; - } - - debug("** Script length: %ld\n", len); - return run_command_list((char *)data, len, 0); -} - -/**************************************************/ -#if defined(CONFIG_CMD_SOURCE) static int do_source(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { @@ -213,7 +50,7 @@ static int do_source(struct cmd_tbl *cmdtp, int flag, int argc, } printf ("## Executing script at %08lx\n", addr); - rcode = image_source_script(addr, fit_uname, confname); + rcode = cmd_source_script(addr, fit_uname, confname); return rcode; } @@ -235,4 +72,3 @@ U_BOOT_CMD( source, 2, 0, do_source, "run script from memory", source_help_text ); -#endif |
