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

Heinrich Schuchardt xypron.glpk at gmx.de
Fri Apr 29 21:51:31 CEST 2022


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



More information about the U-Boot mailing list