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.

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


Reply via email to