Message ID | 20220428080950.23509-9-masahisa.kojima@linaro.org |
---|---|
State | New |
Headers | show |
Series | enable menu-driven boot device selection | expand |
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.kojima@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 <pali@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); > + 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. We need a testcase for this. 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);
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.kojima@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 <pali@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. > > We need a testcase for this. I have already provided a patch with this. 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); >
On Mon, 2 May 2022 at 05:54, Heinrich Schuchardt <xypron.glpk@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.kojima@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 <pali@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); > > >
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 <pali@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); + 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); 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);
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.kojima@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(-)