diff mbox series

[v5,08/17] bootmenu: update bootmenu_entry structure

Message ID 20220428080950.23509-9-masahisa.kojima@linaro.org
State New
Headers show
Series enable menu-driven boot device selection | expand

Commit Message

Masahisa Kojima April 28, 2022, 8:09 a.m. UTC
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(-)

Comments

Heinrich Schuchardt April 29, 2022, 7:51 p.m. UTC | #1
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);
Heinrich Schuchardt May 1, 2022, 8:54 p.m. UTC | #2
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);
>
Masahisa Kojima May 9, 2022, 8:54 a.m. UTC | #3
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 mbox series

Patch

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);