15a2072
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
15a2072
From: Javier Martinez Canillas <javierm@redhat.com>
15a2072
Date: Wed, 18 Jul 2018 08:08:02 +0200
15a2072
Subject: [PATCH] blscfg: Expand the BLS options field instead of showing its
15a2072
 variables
15a2072
15a2072
The values of the BLS fragment fields can either be string literals or
15a2072
grub2 environment variables, the latter will be expanded by grub2 when
15a2072
the boot entry is selected.
15a2072
15a2072
But from a usability point of view, is much more convenient if the BLS
15a2072
parse code expand any variables that are present in the options field.
15a2072
15a2072
That will allow users to select an entry in the menu by pressing the e
15a2072
key and edit the kernel command line parameters. So for example instead
15a2072
of showing the following:
15a2072
15a2072
kernel /boot/vmlinuz-4.17.0 $kernelopts
15a2072
15a2072
It would show something like the following:
15a2072
15a2072
kernel /boot/vmlinuz-4.17.0 root=UUID=cec677c9-c890-4103-b94a-bcc191642935
15a2072
15a2072
Suggested-by: Hans de Goede <hdegoede@redhat.com>
15a2072
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
15a2072
---
15a2072
 grub-core/commands/blscfg.c | 69 ++++++++++++++++++++++++++++++++++++++++++++-
15a2072
 1 file changed, 68 insertions(+), 1 deletion(-)
15a2072
15a2072
diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
15a2072
index c6addc4dc12..80d8814fc3f 100644
15a2072
--- a/grub-core/commands/blscfg.c
15a2072
+++ b/grub-core/commands/blscfg.c
15a2072
@@ -32,6 +32,8 @@
15a2072
 #include <grub/normal.h>
15a2072
 #include <grub/lib/envblk.h>
15a2072
 
15a2072
+#include <stdbool.h>
15a2072
+
15a2072
 GRUB_MOD_LICENSE ("GPLv3+");
15a2072
 
15a2072
 #include "loadenv.h"
15a2072
@@ -506,6 +508,70 @@ static char **bls_make_list (struct bls_entry *entry, const char *key, int *num)
15a2072
   return list;
15a2072
 }
15a2072
 
15a2072
+static char *field_append(bool is_var, char *buffer, char *start, char *end)
15a2072
+{
15a2072
+  char *temp = grub_strndup(start, end - start + 1);
15a2072
+  const char *field = temp;
15a2072
+
15a2072
+  if (is_var) {
15a2072
+    field = grub_env_get (temp);
15a2072
+    if (!field)
15a2072
+      return buffer;
15a2072
+  }
15a2072
+
15a2072
+  if (!buffer) {
15a2072
+    buffer = grub_strdup(field);
15a2072
+    if (!buffer)
15a2072
+      return NULL;
15a2072
+  } else {
15a2072
+    buffer = grub_realloc (buffer, grub_strlen(buffer) + grub_strlen(field));
15a2072
+    if (!buffer)
15a2072
+      return NULL;
15a2072
+
15a2072
+    grub_stpcpy (buffer + grub_strlen(buffer), field);
15a2072
+  }
15a2072
+
15a2072
+  return buffer;
15a2072
+}
15a2072
+
15a2072
+static char *expand_val(char *value)
15a2072
+{
15a2072
+  char *buffer = NULL;
15a2072
+  char *start = value;
15a2072
+  char *end = value;
15a2072
+  bool is_var = false;
15a2072
+
15a2072
+  while (*value) {
15a2072
+    if (*value == '$') {
15a2072
+      if (start != end) {
15a2072
+	buffer = field_append(is_var, buffer, start, end);
15a2072
+	if (!buffer)
15a2072
+	  return NULL;
15a2072
+      }
15a2072
+
15a2072
+      is_var = true;
15a2072
+      start = value + 1;
15a2072
+    } else if (is_var) {
15a2072
+      if (!grub_isalnum(*value) && *value != '_') {
15a2072
+	buffer = field_append(is_var, buffer, start, end);
15a2072
+	is_var = false;
15a2072
+	start = value;
15a2072
+      }
15a2072
+    }
15a2072
+
15a2072
+    end = value;
15a2072
+    value++;
15a2072
+  }
15a2072
+
15a2072
+  if (start != end) {
15a2072
+    buffer = field_append(is_var, buffer, start, end);
15a2072
+    if (!buffer)
15a2072
+      return NULL;
15a2072
+  }
15a2072
+
15a2072
+  return buffer;
15a2072
+}
15a2072
+
15a2072
 static void create_entry (struct bls_entry *entry)
15a2072
 {
15a2072
   int argc = 0;
15a2072
@@ -536,7 +602,7 @@ static void create_entry (struct bls_entry *entry)
15a2072
     }
15a2072
 
15a2072
   title = bls_get_val (entry, "title", NULL);
15a2072
-  options = bls_get_val (entry, "options", NULL);
15a2072
+  options = expand_val (bls_get_val (entry, "options", NULL));
15a2072
   initrds = bls_make_list (entry, "initrd", NULL);
15a2072
 
15a2072
   hotkey = bls_get_val (entry, "grub_hotkey", NULL);
15a2072
@@ -594,6 +660,7 @@ static void create_entry (struct bls_entry *entry)
15a2072
 finish:
15a2072
   grub_free (initrd);
15a2072
   grub_free (initrds);
15a2072
+  grub_free (options);
15a2072
   grub_free (classes);
15a2072
   grub_free (args);
15a2072
   grub_free (argv);