grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] grub: add grub variable update functionality


From: Prarit Bhargava
Subject: [PATCH] grub: add grub variable update functionality
Date: Fri, 4 Jan 2019 07:53:42 -0500

Please be aware I am NOT subscribed to grub-devel.

P.

---8<---

Customers and users of the kernel are commenting that there is no way to update
a grub variable without copy and pasting the existing data.

For example,

[10:57 AM address@hidden grub-2.02]# ./grub-editenv list
saved_entry=0
next_entry=
kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro 
crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap 
rd.lvm.lv=rhel_intel-wildcatpass-07/root 
rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81  
ignore_loglevel
[10:57 AM address@hidden grub-2.02]# ./grub-editenv - set 
kernelopts="root=/dev/mapper/rhel_intel--wildcatpass--07-root ro 
crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap 
rd.lvm.lv=rhel_intel-wildcatpass-07/root 
rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81  
ignore_loglevel newarg"
[10:57 AM address@hidden grub-2.02]# ./grub-editenv list
saved_entry=0
next_entry=
kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro 
crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap 
rd.lvm.lv=rhel_intel-wildcatpass-07/root 
rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81  
ignore_loglevel newarg

which is cumbersome.

Add functionality to add to an existing variable.  For example,

[10:58 AM address@hidden grub-2.02]# ./grub-editenv list
saved_entry=0
next_entry=
kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro 
crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap 
rd.lvm.lv=rhel_intel-wildcatpass-07/root 
rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81  
ignore_loglevel
[10:58 AM address@hidden grub-2.02]# ./grub-editenv - set kernelopts+="newarg"
[10:59 AM address@hidden grub-2.02]# ./grub-editenv list
saved_entry=0
next_entry=
kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro 
crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap 
rd.lvm.lv=rhel_intel-wildcatpass-07/root 
rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81  
ignore_loglevel newarg

Signed-off-by: Prarit Bhargava <address@hidden>
Cc: address@hidden
Cc: address@hidden
Cc: address@hidden
Cc: address@hidden
---
 grub-core/lib/envblk.c    | 61 +++++++++++++++++++++++++++++++++++++++
 include/grub/lib/envblk.h |  1 +
 util/grub-editenv.c       | 25 +++++++++++++++-
 3 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/grub-core/lib/envblk.c b/grub-core/lib/envblk.c
index 230e0e9d9abe..8ddbe2e8267e 100644
--- a/grub-core/lib/envblk.c
+++ b/grub-core/lib/envblk.c
@@ -295,3 +295,64 @@ grub_envblk_iterate (grub_envblk_t envblk,
       p = find_next_line (p, pend);
     }
 }
+
+int
+grub_envblk_add (grub_envblk_t envblk, const char *name, const char *add)
+{
+  char *current, *new, *ostart, *pstart, *pend;
+  int newsize, ret = 1;
+
+  /* get a copy of the existing entry */
+  pstart = envblk->buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1;
+  pstart = grub_strstr (pstart, name);
+  if (!pstart)
+  {
+     ret = -1; /* existing entry not found */
+     goto out;
+  }
+  pend = grub_strchr (pstart, '\n');
+  if (!pend || pend > (envblk->buf + envblk->size))
+  {
+     ret = -1; /* existing entry not found */
+     goto out;
+  }
+
+  current = grub_zalloc (pend - pstart + 1);
+  if (!current)
+  {
+     ret = -2; /* out of memory */
+     goto out;
+  }
+  grub_strncpy (current, pstart, (int)(pend - pstart));
+
+  ostart = grub_strchr (current, '=');
+  ostart++;
+
+  /* create a buffer for the updated entry. */
+  newsize = grub_strlen (ostart) + grub_strlen (add) + 2;
+  new = grub_zalloc (newsize);
+  if (!new)
+    {
+      return -2; /* out of memory */
+      goto out;
+    }
+
+  grub_strcpy (new, ostart);
+  grub_memcpy (new + grub_strlen (new), " ", 1);
+  grub_strcpy (new + grub_strlen (new), add);
+
+  /* erase the current entry */
+  grub_envblk_delete (envblk, name);
+  /* add the updated entry */
+  if (!grub_envblk_set (envblk, name, new))
+    {
+      /* restore the original entry.  This should always work */
+      grub_envblk_set (envblk, name, ostart);
+      ret = 0;
+    }
+
+out:
+  grub_free(new);
+  grub_free(current);
+  return ret;
+}
diff --git a/include/grub/lib/envblk.h b/include/grub/lib/envblk.h
index c3e655921709..2a0f09e3435b 100644
--- a/include/grub/lib/envblk.h
+++ b/include/grub/lib/envblk.h
@@ -37,6 +37,7 @@ void grub_envblk_delete (grub_envblk_t envblk, const char 
*name);
 void grub_envblk_iterate (grub_envblk_t envblk,
                           void *hook_data,
                           int hook (const char *name, const char *value, void 
*hook_data));
+int grub_envblk_add(grub_envblk_t envblk, const char *name, const char *add);
 void grub_envblk_close (grub_envblk_t envblk);
 
 static inline char *
diff --git a/util/grub-editenv.c b/util/grub-editenv.c
index 118e89fe57fe..2df81a20b6bc 100644
--- a/util/grub-editenv.c
+++ b/util/grub-editenv.c
@@ -210,15 +210,38 @@ set_variables (const char *name, int argc, char *argv[])
   while (argc)
     {
       char *p;
+      int add = 0;
 
       p = strchr (argv[0], '=');
       if (! p)
         grub_util_error (_("invalid parameter %s"), argv[0]);
 
+      if ( *(p - 1) == '+')
+        {
+          add = 1;
+          *(p - 1) = 0;
+        }
       *(p++) = 0;
 
-      if (! grub_envblk_set (envblk, argv[0], p))
+      if (!add && ! grub_envblk_set (envblk, argv[0], p))
         grub_util_error ("%s", _("environment block too small"));
+      else if (add) {
+        int ret;
+        ret = grub_envblk_add (envblk, argv[0], p);
+        switch (ret) {
+        case (0):
+          grub_util_error ("%s", _("environment block too small"));
+          break;
+        case (-1):
+          grub_util_error("%s", _("existing entry not found"));
+          break;
+        case (-2):
+          grub_util_error("%s", _("out of memory error"));
+          break;
+        default:
+          break;
+        }
+      }
 
       argc--;
       argv++;
-- 
2.17.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]