On Mon, 2 May 2022 at 05:54, Heinrich Schuchardt <xypron.g...@gmx.de> wrote: > > On 4/29/22 21:51, Heinrich Schuchardt wrote: > > On 4/28/22 10:09, Masahisa Kojima wrote: > >> This is a preparation for succeeding addition of uefi boot > >> and distro boot menu entries into bootmenu. > >> The bootmenu_entry title is updated to u16 string because > >> uefi use u16 string. This commit also factors out the function > >> to prepare the entries generated by "bootmenu_x" U-Boot environment > >> variable. > >> > >> This commit also updates the bootmenu entry title. > >> The entry derived from "bootmenu_x" U-Boot environment variable > >> has the "bootmenu_xx" prefix as below. > >> > >> *** U-Boot Boot Menu *** > >> > >> bootmenu_00 : Boot 1. kernel > >> bootmenu_01 : Boot 2. kernel > >> bootmenu_02 : Reset board > >> > >> Signed-off-by: Masahisa Kojima <masahisa.koj...@linaro.org> > >> --- > >> Changes in v5: > >> - split into the separate patch > >> - add function description comment > >> > >> cmd/bootmenu.c | 110 +++++++++++++++++++++++++++++++++++-------------- > >> 1 file changed, 78 insertions(+), 32 deletions(-) > >> > >> diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c > >> index 9a32a18b19..15ad621c9f 100644 > >> --- a/cmd/bootmenu.c > >> +++ b/cmd/bootmenu.c > >> @@ -3,6 +3,7 @@ > >> * (C) Copyright 2011-2013 Pali Rohár <p...@kernel.org> > >> */ > >> > >> +#include <charset.h> > >> #include <common.h> > >> #include <command.h> > >> #include <ansi.h> > >> @@ -24,11 +25,18 @@ > >> */ > >> #define MAX_ENV_SIZE (9 + 2 + 1) > >> > >> +enum boot_type { > >> + BOOTMENU_TYPE_NONE = 0, > >> + BOOTMENU_TYPE_BOOTMENU, > >> +}; > >> + > >> struct bootmenu_entry { > >> unsigned short int num; /* unique number 0 .. MAX_COUNT */ > >> char key[3]; /* key identifier of number */ > >> - char *title; /* title of entry */ > >> + u16 *title; /* title of entry */ > >> char *command; /* hush command of entry */ > >> + enum boot_type type; /* boot type of entry */ > >> + u16 bootorder; /* order for each boot type */ > >> struct bootmenu_data *menu; /* this bootmenu */ > >> struct bootmenu_entry *next; /* next menu entry (num+1) */ > >> }; > >> @@ -75,7 +83,10 @@ static void bootmenu_print_entry(void *data) > >> if (reverse) > >> puts(ANSI_COLOR_REVERSE); > >> > >> - puts(entry->title); > >> + if (entry->type == BOOTMENU_TYPE_BOOTMENU) > >> + printf("bootmenu_%02d : %ls", entry->bootorder, entry->title); > > This "bootmen_%02d" strings conveys not information of interest. Please > remove this hunk. > > >> + else > >> + printf("%ls", entry->title); > >> > >> if (reverse) > >> puts(ANSI_COLOR_RESET); > >> @@ -279,31 +290,32 @@ static void bootmenu_destroy(struct > >> bootmenu_data *menu) > >> free(menu); > >> } > >> > >> -static struct bootmenu_data *bootmenu_create(int delay) > >> +/** > >> + * prepare_bootmenu_entry() - generate the bootmenu_xx entries > >> + * > >> + * This function read the "bootmenu_x" U-Boot environment variable > >> + * and generate the bootmenu entries. > >> + * > >> + * @menu: pointer to the bootmenu structure > >> + * @current: pointer to the last bootmenu entry list > >> + * @index: pointer to the index of the last bootmenu entry, > >> + * the number of bootmenu entry is added by this function > >> + * Return: 1 on success, negative value on error > >> + */ > >> +static int prepare_bootmenu_entry(struct bootmenu_data *menu, > >> + struct bootmenu_entry **current, > >> + unsigned short int *index) > >> { > >> - unsigned short int i = 0; > >> - const char *option; > >> - struct bootmenu_data *menu; > >> - struct bootmenu_entry *iter = NULL; > >> - > >> int len; > >> char *sep; > >> - char *default_str; > >> - struct bootmenu_entry *entry; > >> - > >> - menu = malloc(sizeof(struct bootmenu_data)); > >> - if (!menu) > >> - return NULL; > >> - > >> - menu->delay = delay; > >> - menu->active = 0; > >> - menu->first = NULL; > >> - > >> - default_str = env_get("bootmenu_default"); > >> - if (default_str) > >> - menu->active = (int)simple_strtol(default_str, NULL, 10); > >> + const char *option; > >> + unsigned short int i = *index; > >> + struct bootmenu_entry *entry = NULL; > >> + struct bootmenu_entry *iter = *current; > >> > >> while ((option = bootmenu_getoption(i))) { > >> + u16 *buf; > >> + > >> sep = strchr(option, '='); > >> if (!sep) { > >> printf("Invalid bootmenu entry: %s\n", option); > >> @@ -312,23 +324,23 @@ static struct bootmenu_data *bootmenu_create(int > >> delay) > >> > >> entry = malloc(sizeof(struct bootmenu_entry)); > >> if (!entry) > >> - goto cleanup; > >> + return -ENOMEM; > >> > >> len = sep-option; > >> - entry->title = malloc(len + 1); > >> + buf = calloc(1, (len + 1) * sizeof(u16)); > >> + entry->title = buf; > >> if (!entry->title) { > >> free(entry); > >> - goto cleanup; > >> + return -ENOMEM; > >> } > >> - memcpy(entry->title, option, len); > >> - entry->title[len] = 0; > >> + utf8_utf16_strncpy(&buf, option, len); > >> > >> len = strlen(sep + 1); > >> entry->command = malloc(len + 1); > >> if (!entry->command) { > >> free(entry->title); > >> free(entry); > >> - goto cleanup; > >> + return -ENOMEM; > >> } > >> memcpy(entry->command, sep + 1, len); > >> entry->command[len] = 0; > >> @@ -337,6 +349,8 @@ static struct bootmenu_data *bootmenu_create(int > >> delay) > >> > >> entry->num = i; > >> entry->menu = menu; > >> + entry->type = BOOTMENU_TYPE_BOOTMENU; > >> + entry->bootorder = i; > >> entry->next = NULL; > >> > >> if (!iter) > >> @@ -351,13 +365,44 @@ static struct bootmenu_data *bootmenu_create(int > >> delay) > >> break; > >> } > >> > >> + *index = i; > >> + *current = iter; > >> + > >> + return 1; > >> +} > >> + > >> +static struct bootmenu_data *bootmenu_create(int delay) > >> +{ > >> + int ret; > >> + unsigned short int i = 0; > >> + struct bootmenu_data *menu; > >> + struct bootmenu_entry *iter = NULL; > >> + struct bootmenu_entry *entry; > >> + char *default_str; > >> + > >> + menu = malloc(sizeof(struct bootmenu_data)); > >> + if (!menu) > >> + return NULL; > >> + > >> + menu->delay = delay; > >> + menu->active = 0; > >> + menu->first = NULL; > >> + > >> + default_str = env_get("bootmenu_default"); > >> + if (default_str) > >> + menu->active = (int)simple_strtol(default_str, NULL, 10); > >> + > >> + ret = prepare_bootmenu_entry(menu, &iter, &i); > >> + if (ret < 0) > >> + goto cleanup; > >> + > >> /* Add U-Boot console entry at the end */ > >> if (i <= MAX_COUNT - 1) { > >> entry = malloc(sizeof(struct bootmenu_entry)); > >> if (!entry) > >> goto cleanup; > >> > >> - entry->title = strdup("U-Boot console"); > >> + entry->title = u16_strdup(u"U-Boot console"); > >> if (!entry->title) { > >> free(entry); > >> goto cleanup; > >> @@ -374,6 +419,7 @@ static struct bootmenu_data *bootmenu_create(int > >> delay) > >> > >> entry->num = i; > >> entry->menu = menu; > >> + entry->type = BOOTMENU_TYPE_NONE; > >> entry->next = NULL; > >> > >> if (!iter) > >> @@ -431,7 +477,7 @@ static void bootmenu_show(int delay) > >> { > >> int init = 0; > >> void *choice = NULL; > >> - char *title = NULL; > >> + u16 *title = NULL; > >> char *command = NULL; > >> struct menu *menu; > >> struct bootmenu_data *bootmenu; > >> @@ -482,7 +528,7 @@ static void bootmenu_show(int delay) > >> > >> if (menu_get_choice(menu, &choice) == 1) { > >> iter = choice; > >> - title = strdup(iter->title); > >> + title = u16_strdup(iter->title); > > > > We must still be able to use the bootmenu command outside of the UEFI > > sub-system. There wide strings will not be used.
OK, I will consider supporting a non-UEFI system. > > > > We need a testcase for this. > > I have already provided a patch with this. Thank you very much for adding test cases. Regards, Masahisa Kojima > > Best regards > > Heinrich > > > > > Best regards > > > > Heinrich > > > >> command = strdup(iter->command); > >> } > >> > >> @@ -497,7 +543,7 @@ cleanup: > >> } > >> > >> if (title && command) { > >> - debug("Starting entry '%s'\n", title); > >> + debug("Starting entry '%ls'\n", title); > >> free(title); > >> run_command(command, 0); > >> free(command); > > >