Re: [PATCH] grub: add grub variable update functionality

2019-01-15 Thread Prarit Bhargava



On 1/14/19 10:49 AM, Daniel Kiper wrote:
> On Fri, Jan 04, 2019 at 07:53:42AM -0500, Prarit Bhargava wrote:
>> 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 root@intel-wildcatpass-07 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 root@intel-wildcatpass-07 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 root@intel-wildcatpass-07 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 root@intel-wildcatpass-07 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 root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv - set 
>> kernelopts+="newarg"
>> [10:59 AM root@intel-wildcatpass-07 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 
>> Cc: mleit...@redhat.com
>> Cc: pjo...@redhat.com
>> Cc: javi...@redhat.com
>> Cc: ar...@redhat.com
>> ---
>>  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)
> 
> s/grub_envblk_add/grub_envblk_extend/?

Hi Daniel, thanks for the valuable feedback.

After reading your comments I saw that using grub_envblk_iterate() to modify the
entry was easier than attempting to parse everything myself.  I've added that to
my v2.  Unfortunately this means I'm skipping over some of your comments which
are no longer applicable to v2.

> 
>> +{
>> +  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);
> 
> grub_strcmp() instead of grub_strstr()?
> 
> Even if not what will happen if e.g. env file contains this line among others:
> 
> xyx=kernelopts
> 
>> +  if (!pstart)
>> +  {
>> + ret = -1; /* existing entry not found */
>> + goto out;
> 
> s/out/err/

Applied to v2.

> 
>> +  }
>> +  pend = grub_strchr (pstart, '\n');
> 
> If grub_strcmp() then you do not need this...
> 
>> +  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));
> 
> Do we need (int) cast here?
> 
>> +  ostart = grub_strchr (current, '=');
>> +  ostart++;
>> +
>> +  /* create a buffer for the updated entry. */
> 
> Please start all comments with capital letter.

Applied to v2.

> 
>> +  newsize = grub_strlen (ostart) + grub_strlen (add) + 2;
>> +  new = grub_zalloc (newsize);
> 
> You do not need newsize here. Please drop it.

Applied to v2.

> 
>> +  if (!new)
>> +{
>> +  return -2; /* out of memory 

Re: [PATCH] grub: add grub variable update functionality

2019-01-14 Thread Daniel Kiper
On Fri, Jan 04, 2019 at 07:53:42AM -0500, Prarit Bhargava wrote:
> 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 root@intel-wildcatpass-07 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 root@intel-wildcatpass-07 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 root@intel-wildcatpass-07 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 root@intel-wildcatpass-07 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 root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv - set 
> kernelopts+="newarg"
> [10:59 AM root@intel-wildcatpass-07 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 
> Cc: mleit...@redhat.com
> Cc: pjo...@redhat.com
> Cc: javi...@redhat.com
> Cc: ar...@redhat.com
> ---
>  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)

s/grub_envblk_add/grub_envblk_extend/?

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

grub_strcmp() instead of grub_strstr()?

Even if not what will happen if e.g. env file contains this line among others:

xyx=kernelopts

> +  if (!pstart)
> +  {
> + ret = -1; /* existing entry not found */
> + goto out;

s/out/err/

> +  }
> +  pend = grub_strchr (pstart, '\n');

If grub_strcmp() then you do not need this...

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

Do we need (int) cast here?

> +  ostart = grub_strchr (current, '=');
> +  ostart++;
> +
> +  /* create a buffer for the updated entry. */

Please start all comments with capital letter.

> +  newsize = grub_strlen (ostart) + grub_strlen (add) + 2;
> +  new = grub_zalloc (newsize);

You do not need newsize here. Please drop it.

> +  if (!new)
> +{
> +  return -2; /* out of memory */

May I ask you to use proper GRUB errors, e.g. GRUB_ERR_OUT_OF_MEMORY here.
Please take a look at include/grub/err.h for more details.

> +  goto out;
> +}
> +
> +  grub_strcpy (new, ostart);
> +  grub_memcpy (new + grub_strlen (new), " ", 1);
> +  grub_strcpy (new + grub_strlen (new), add);

grub_snprintf() is your friend.

> +  /* 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 */
> +  

Re: [PATCH] grub: add grub variable update functionality

2019-01-11 Thread Prarit Bhargava


Just re-pinging on this ...

P.

On 1/4/19 7:53 AM, Prarit Bhargava wrote:
> 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 root@intel-wildcatpass-07 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 root@intel-wildcatpass-07 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 root@intel-wildcatpass-07 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 root@intel-wildcatpass-07 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 root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv - set 
> kernelopts+="newarg"
> [10:59 AM root@intel-wildcatpass-07 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 
> Cc: mleit...@redhat.com
> Cc: pjo...@redhat.com
> Cc: javi...@redhat.com
> Cc: ar...@redhat.com
> ---
>  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 

[PATCH] grub: add grub variable update functionality

2019-01-04 Thread Prarit Bhargava
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 root@intel-wildcatpass-07 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 root@intel-wildcatpass-07 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 root@intel-wildcatpass-07 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 root@intel-wildcatpass-07 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 root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv - set 
kernelopts+="newarg"
[10:59 AM root@intel-wildcatpass-07 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 
Cc: mleit...@redhat.com
Cc: pjo...@redhat.com
Cc: javi...@redhat.com
Cc: ar...@redhat.com
---
 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