Re: [PATCH] uboot: Add the missing disk write operation support

2019-01-16 Thread Daniel Kiper
On Tue, Jan 15, 2019 at 04:59:56PM +0200, Cristian Ciocaltea wrote:
> uboot_disk_write() is currently lacking the write support
> to storage devices because, historically, those devices did not
> implement block_write() in U-Boot.
>
> The solution has been tested using a patched U-Boot loading
> and booting GRUB in a QEMU vexpress-a9 environment.
> The disk write operations were triggered with GRUB's save_env
> command.
>
> Signed-off-by: Cristian Ciocaltea 

Reviewed-by: Daniel Kiper 

If there are no objections I will apply this patch in a week or so.

Daniel

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH v2 2/3] grub: Make grub_envblk_iterate() return an int

2019-01-16 Thread Daniel Kiper
On Wed, Jan 16, 2019 at 01:34:42PM -0500, Prarit Bhargava wrote:
> grub_envblk_iterate() is a void.  Future functions will require the
> ability to interpret return codes from the iteration, so
> grub_envblk_iterate() should be an int.
>
> The value of 0 returned from the hook functions is overloaded and cannot
> be parsed by callers to grub_envblk_iterate() for error handling.  To fix
> this add GRUB_ERR_ITERATE_STOP and GRUB_ERR_ITERATE_CONTINUE to the error
> returns so the iteration can be stopped and continued respectively.
>
> Make grub_envblk_iterate() return an int.
>
> Signed-off-by: Prarit Bhargava 

I do not like this patch. First of all GRUB errors are defined as an enum
not as an int. The second: do not add error codes if they are not really
needed. And yours are not needed at all.

Daniel

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH v2 3/3] grub: add extend variable functionality

2019-01-16 Thread Daniel Kiper
On Wed, Jan 16, 2019 at 01:34:43PM -0500, Prarit Bhargava wrote:
> 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 

I prefer v1 patch +/- my suggestions. IMO current solution is an overkill.

Daniel

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH v2 1/3] grub-editenv: Verify the variable size

2019-01-16 Thread Daniel Kiper
On Wed, Jan 16, 2019 at 01:34:41PM -0500, Prarit Bhargava wrote:
> It is possible to execute 'grub-editenv - set ="some data"',
> which results in an unremoveable entry
>
> ="some data"

Please explain why it happens.

> Verify the variable has a size before setting a value.

s/variable/argument/
s/size/size greater than zero/

> Signed-off-by: Prarit Bhargava 
> Cc: mleit...@redhat.com
> Cc: pjo...@redhat.com
> Cc: javi...@redhat.com
> Cc: ar...@redhat.com
> Cc: Daniel Kiper 
> ---
>  util/grub-editenv.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/util/grub-editenv.c b/util/grub-editenv.c
> index 118e89fe57fe..0b6c69b9688c 100644
> --- a/util/grub-editenv.c
> +++ b/util/grub-editenv.c
> @@ -217,6 +217,9 @@ set_variables (const char *name, int argc, char *argv[])
>
>*(p++) = 0;
>
> +  if (! grub_strlen(argv[0]))
> +grub_util_error (_("No parameter specified"));

s/parameter/argument/

Daniel

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: MKPasswd idempotency patch

2019-01-16 Thread Daniel Kiper
On Tue, Dec 25, 2018 at 12:01:12PM +0100, grub-de...@agowa338.de wrote:
> Hello,
>
> I want to use grub-mkpasswd inside of a ansible playbook, therefore a
> idempotency or check feature is required. Without it, there is no
> posibility to verify, that the configuration is already inplace.
> Therefore I want to suggest implementing the attached changes. The
> simplest one I was thinking of, is grub-mkpasswd allowing to specify a
> salt and comparing the results.

I am not sure I understand. Could you elaborate on this?

> My patch also introduces a quiet mode, that basically suppresses all
> prompts and only expects the password to be entered/piped in once. It
> also changes the output slightly to not inlcude the `PBKDF2 hash of
> your password is `-part.

It seems to me that it should be split into 3 parts...

> The patch is attached to this mail.
>
> Best,
> Klaus Frank

> >From d289bbb5f5dffbbed2c871989f55e48b756e9ae2 Mon Sep 17 00:00:00 2001
> From: Klaus Frank 
> Date: Tue, 25 Dec 2018 06:17:38 +0100
> Subject: [PATCH] Implement salt-value and quiet parameter for
>  grub-mkpasswd-pbkdf2
>
> ---
>  util/grub-mkpasswd-pbkdf2.c | 103 ++--
>  1 file changed, 88 insertions(+), 15 deletions(-)
>
> diff --git a/util/grub-mkpasswd-pbkdf2.c b/util/grub-mkpasswd-pbkdf2.c
> index 5805f3c10..018715bf3 100644
> --- a/util/grub-mkpasswd-pbkdf2.c
> +++ b/util/grub-mkpasswd-pbkdf2.c
> @@ -42,10 +42,15 @@
>
>  #include "progname.h"
>
> +static int dec_from_hex(const int); // Converts the charcode into an integer 
> representation of the representing hex value.
> +int unhexify(grub_uint8_t*, const char*);
> +
>  static struct argp_option options[] = {
>{"iteration-count",  'c', N_("NUM"), 0, N_("Number of PBKDF2 iterations"), 
> 0},
>{"buflen",  'l', N_("NUM"), 0, N_("Length of generated hash"), 0},
>{"salt",  's', N_("NUM"), 0, N_("Length of salt"), 0},
> +  {"salt-value", 'v', N_("STR"), 0, N_("Salt"), 0},

For this patch number one...

> +  {"quiet", 'q', 0, 0, N_("Only output hash, suppress other output, indended 
> for pipes"), 0},

...and for this patch number two.

The rest goes into patch three. The basic idea is that one logical
change is one patch.

>{ 0, 0, 0, 0, 0, 0 }
>  };
>
> @@ -54,6 +59,8 @@ struct arguments
>unsigned int count;
>unsigned int buflen;
>unsigned int saltlen;
> +  char *value;
> +  unsigned char quiet;
>  };
>
>  static error_t
> @@ -76,6 +83,15 @@ argp_parser (int key, char *arg, struct argp_state *state)
>  case 's':
>arguments->saltlen = strtoul (arg, NULL, 0);
>break;
> +
> +case 'v':
> +  arguments->value = arg;
> +  break;
> +
> +case 'q':
> +  arguments->quiet = 1;
> +  break;
> +
>  default:
>return ARGP_ERR_UNKNOWN;
>  }
> @@ -94,29 +110,70 @@ hexify (char *hex, grub_uint8_t *bin, grub_size_t n)
>  {
>while (n--)
>  {
> -  if (((*bin & 0xf0) >> 4) < 10)
> - *hex = ((*bin & 0xf0) >> 4) + '0';
> -  else
> - *hex = ((*bin & 0xf0) >> 4) + 'A' - 10;
> +  if (((*bin & 0xf0) >> 4) < 10) {
> +*hex = ((*bin & 0xf0) >> 4) + '0';
> +  } else {

Curly braces are not needed here and below.

> +*hex = ((*bin & 0xf0) >> 4) + 'A' - 10;
> +  }

Please do not introduce clutter like this. If you wish to do some
cleanups do it in separate patch.

>hex++;
>
>if ((*bin & 0xf) < 10)
> - *hex = (*bin & 0xf) + '0';
> +*hex = (*bin & 0xf) + '0';

Ditto.

>else
> - *hex = (*bin & 0xf) + 'A' - 10;
> +*hex = (*bin & 0xf) + 'A' - 10;

Ditto.

>hex++;
>bin++;
>  }
>*hex = 0;
>  }
>
> +static int
> +dec_from_hex(const int hex) {
> +  if (48 <= hex && hex <= 57) {
> +return hex - 48;
> +  } else if (65 <= hex && hex <= 90) {
> +return hex - 65 + 10;
> +  } else if (97 <= hex && hex <= 122) {
> +return hex - 97 + 10;
> +  } else {
> +exit(1);
> +  }
> +}

grub_strtoul() please.

> +int
> +unhexify(grub_uint8_t* output, const char* hexstring) {
> +  // sizeof(output) == (sizeof(hexstring) - 1) / 2 + 1
> +  if (sizeof(output) < (sizeof(hexstring) - 1) / 2 + 1) {
> +return -1;
> +  }
> +  char *output_ptr = NULL;
> +  output_ptr = (char*)output;
> +  int CharCodeInDecimal = 0;
> +  void *HexDigits = xmalloc(sizeof("FF"));
> +  char *HexDigitOne = HexDigits;
> +  char *HexDigitTwo = (char*)HexDigits + 1;
> +  char *HexString_ptr = NULL;
> +  HexString_ptr = (char*)hexstring;
> +  while(*HexString_ptr) {
> +memcpy (HexDigitOne, HexString_ptr++, sizeof (char));
> +memcpy (HexDigitTwo, HexString_ptr++, sizeof (char));
> +
> +CharCodeInDecimal = dec_from_hex((int)*HexDigitOne) * 16 + 
> dec_from_hex((int)*HexDigitTwo);
> +*output_ptr++ = (char)CharCodeInDecimal;
> +  }
> +  output_ptr = '\0';
> +  return 0;
> +}

This is a mess. There is a pretty good chance that similar function
exists in the wild. So, please do not reinvent the wheel.

Daniel

_

Re: GRUB Xen PVH chainloading

2019-01-16 Thread Daniel Kiper
On Mon, Jan 07, 2019 at 01:43:11PM +0100, Juergen Gross wrote:
> On 07/01/2019 12:41, Colin Watson wrote:
> > Hi,
> >
> > I'm working on integrating the recently-merged PVH support for GRUB into
> > the Debian packages.  As a result I find myself thinking about how to
> > handle the two-stage boot loader scheme that our packages currently
> > implement for PV.  I think that it would not be very hard to do this for
> > PVH in the manner outlined below, but my x86 asm skills aren't quite up
> > to some of the work needed in GRUB.  Assuming that nobody sees any
> > obvious holes in this, does anyone fancy giving it a go?
>
> Seems to be a very good idea.
>
> > Background
> > --
> >
> > Around the time PV support was implemented in GRUB 2, we put together a
> > scheme to minimise the coupling between the guest configuration file on
> > the host and the boot loader configuration in the guest.  The scheme and
> > its rationale are described here:
> >
> >   
> > https://wiki.xen.org/wiki/PvGrub2#Chainloading_guest_pvgrub2_from_domain_0_pvgrub2
> >
> > Essentially the same rationale applies to the PVH case: it should be
> > possible for the guest to declare its own booting arrangements (though
> > of course some hosts may wish to just provide a grub.cfg and handle all
> > that on the host side), and this should be decoupled from the GRUB image
> > provided by the host as far as possible in order to minimise
> > compatibility issues.
> >
> > There seems to be no obstacle to this in principle: just as a PV boot
> > loader can chainload another one from the guest's disk, so too could a
> > PVH boot loader chainload another one from the guest's disk.
> >
> > What needs to be done
> > -
> >
> > GRUB needs to support chainloading another PVH boot loader.  I think
> > this involves observing the existence of the XEN_ELFNOTE_PHYS32_ENTRY
> > note and following the machine state rules for the domain builder here:
> >
> >   https://xenbits.xen.org/docs/unstable-staging/misc/pvh.html
> >
> > (I had a brief go at implementing this, but foundered on my fairly
> > minimal understanding of GRUB's relocator/boot code.)
>
> The needed effort should indeed be rather small.
>
> In the moment I have no idea when I'll be able to do it, as I have
> plenty of other things to do. In case you want to try it and need some
> hints, please feel free to ask (maybe I'm able to give an answer
> without having to try to implement it myself ;-) ).
>
> > We need to define a modification to
> > https://xenbits.xen.org/docs/unstable-staging/misc/x86-xenpv-bootloader.html
> > for PVH boot loaders.  I suggest the obvious: a second-stage PVH boot
> > loader should be installed into the guest filesystem as
> > /boot/xen/pvhboot-.elf, and otherwise things generally behave the
> > same way.  I'd be happy to draft a patch to the protocol specification
> > once a proof-of-concept exists.
> >
> > The as-yet-unmerged GRUB patch to support the existing PV boot protocol
> > (https://salsa.debian.org/grub-team/grub/blob/master/debian/patches/grub-install-pvxen-paths.patch)
> > needs to be extended to support the amended protocol.  This is trivial
> > given the above.
>
> Would you mind trying to upstream this patch? I have CC-ed Daniel Kiper
> one of the grub2 maintainers), as I guess with his Xen skills he will be
> the one looking at the patch.

Yes, I am happy to help in development, e.g. give some hints if needed,
and review the patches. Sadly I am not able to do development myself
because I am busy with other stuff right now.

Daniel

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH 1/1] Upgrade Gnulib; switch to bootstrap tool

2019-01-16 Thread Daniel Kiper
On Wed, Jan 09, 2019 at 12:29:30PM +, Colin Watson wrote:
> Upgrade Gnulib files to 20190105.
>
> It's much easier to maintain GRUB's use of portability support files
> from Gnulib when the process is automatic and driven by a single
> configuration file, rather than by maintainers occasionally running
> gnulib-tool and committing the result.  Removing these
> automatically-copied files from revision control also removes the
> temptation to hack the output in ways that are difficult for future
> maintainers to follow.  Gnulib includes a "bootstrap" program which is
> designed for this.
>
> The canonical way to bootstrap GRUB from revision control is now
> "./bootstrap", but "./autogen.sh" is still useful if you just want to
> generate the GRUB-specific parts of the build system.
>
> GRUB now requires Autoconf >= 2.63 and Automake >= 1.11, in line with
> Gnulib.

Could you update INSTALL file too?

Additionally, if you do such huge change could you move Gnulib from
grub-core/gnulib to grub-core/lib/gnulib? Including all diffs which are
currently outside of grub-core/gnulib directory.  Well, maybe *.diff
files should be renamed to *.patch...

Could you add to the commit message how to exactly update Gnulib?
Just list of steps like in the commit 461f1d8af (Import upstream
zstd-1.3.6).

Daniel

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v2 2/3] grub: Make grub_envblk_iterate() return an int

2019-01-16 Thread Prarit Bhargava
grub_envblk_iterate() is a void.  Future functions will require the
ability to interpret return codes from the iteration, so
grub_envblk_iterate() should be an int.

The value of 0 returned from the hook functions is overloaded and cannot
be parsed by callers to grub_envblk_iterate() for error handling.  To fix
this add GRUB_ERR_ITERATE_STOP and GRUB_ERR_ITERATE_CONTINUE to the error
returns so the iteration can be stopped and continued respectively.

Make grub_envblk_iterate() return an int.

Signed-off-by: Prarit Bhargava 
Cc: mleit...@redhat.com
Cc: pjo...@redhat.com
Cc: javi...@redhat.com
Cc: ar...@redhat.com
Cc: Daniel Kiper 
---
 grub-core/commands/loadenv.c |  6 +++---
 grub-core/lib/envblk.c   | 17 -
 include/grub/err.h   |  4 +++-
 include/grub/lib/envblk.h|  6 +++---
 util/grub-editenv.c  |  2 +-
 5 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c
index 3fd664aac331..1bbae5f7f332 100644
--- a/grub-core/commands/loadenv.c
+++ b/grub-core/commands/loadenv.c
@@ -144,14 +144,14 @@ set_var (const char *name, const char *value, void 
*whitelist)
   if (! whitelist)
 {
   grub_env_set (name, value);
-  return 0;
+  return GRUB_ERR_ITERATE_CONTINUE;
 }
 
   if (test_whitelist_membership (name,
 (const grub_env_whitelist_t *) whitelist))
 grub_env_set (name, value);
 
-  return 0;
+  return GRUB_ERR_ITERATE_CONTINUE;
 }
 
 static grub_err_t
@@ -192,7 +192,7 @@ print_var (const char *name, const char *value,
void *hook_data __attribute__ ((unused)))
 {
   grub_printf ("%s=%s\n", name, value);
-  return 0;
+  return GRUB_ERR_ITERATE_CONTINUE;
 }
 
 static grub_err_t
diff --git a/grub-core/lib/envblk.c b/grub-core/lib/envblk.c
index 230e0e9d9abe..3e43843c4535 100644
--- a/grub-core/lib/envblk.c
+++ b/grub-core/lib/envblk.c
@@ -223,7 +223,7 @@ grub_envblk_delete (grub_envblk_t envblk, const char *name)
 }
 }
 
-void
+int
 grub_envblk_iterate (grub_envblk_t envblk,
  void *hook_data,
  int hook (const char *name, const char *value, void 
*hook_data))
@@ -247,8 +247,7 @@ grub_envblk_iterate (grub_envblk_t envblk,
   while (p < pend && *p != '=')
 p++;
   if (p == pend)
-/* Broken.  */
-return;
+return GRUB_ERR_OUT_OF_RANGE;
   name_end = p;
 
   p++;
@@ -264,13 +263,11 @@ grub_envblk_iterate (grub_envblk_t envblk,
 }
 
   if (p >= pend)
-/* Broken.  */
-return;
+return GRUB_ERR_OUT_OF_RANGE;
 
   name = grub_malloc (p - name_start + 1);
   if (! name)
-/* out of memory.  */
-return;
+return GRUB_ERR_OUT_OF_MEMORY;
 
   value = name + (value_start - name_start);
 
@@ -288,10 +285,12 @@ grub_envblk_iterate (grub_envblk_t envblk,
 
   ret = hook (name, value, hook_data);
   grub_free (name);
-  if (ret)
-return;
+  if (ret != GRUB_ERR_ITERATE_CONTINUE)
+return ret;
 }
 
   p = find_next_line (p, pend);
 }
+
+return GRUB_ERR_NONE;
 }
diff --git a/include/grub/err.h b/include/grub/err.h
index 1590c688e1d3..75ebb54201e8 100644
--- a/include/grub/err.h
+++ b/include/grub/err.h
@@ -71,7 +71,9 @@ typedef enum
 GRUB_ERR_NET_PACKET_TOO_BIG,
 GRUB_ERR_NET_NO_DOMAIN,
 GRUB_ERR_EOF,
-GRUB_ERR_BAD_SIGNATURE
+GRUB_ERR_BAD_SIGNATURE,
+GRUB_ERR_ITERATE_STOP,
+GRUB_ERR_ITERATE_CONTINUE
   }
 grub_err_t;
 
diff --git a/include/grub/lib/envblk.h b/include/grub/lib/envblk.h
index c3e655921709..7637791f4228 100644
--- a/include/grub/lib/envblk.h
+++ b/include/grub/lib/envblk.h
@@ -34,9 +34,9 @@ typedef struct grub_envblk *grub_envblk_t;
 grub_envblk_t grub_envblk_open (char *buf, grub_size_t size);
 int grub_envblk_set (grub_envblk_t envblk, const char *name, const char 
*value);
 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_iterate (grub_envblk_t envblk,
+ void *hook_data,
+ int hook (const char *name, const char *value, void 
*hook_data));
 void grub_envblk_close (grub_envblk_t envblk);
 
 static inline char *
diff --git a/util/grub-editenv.c b/util/grub-editenv.c
index 0b6c69b9688c..5f87b09d924a 100644
--- a/util/grub-editenv.c
+++ b/util/grub-editenv.c
@@ -169,7 +169,7 @@ print_var (const char *varname, const char *value,
void *hook_data __attribute__ ((unused)))
 {
   printf ("%s=%s\n", varname, value);
-  return 0;
+  return GRUB_ERR_ITERATE_CONTINUE;
 }
 
 static void
-- 
2.17.2


___
Gru

[PATCH v2 0/3] grub: add grub variable extend functionality

2019-01-16 Thread Prarit Bhargava
This patchset allows a user to update an existing grub variable on the
commandline.

v2:  
- Split into 3 patches.
- fix "=value" bug.  An additional consequence of this is that the
  value pointer p in set_variable() cannot underflow.
- make grub_envblk_iterate return an int and fix return values.
- add "+=" functionality
- Changes suggested by David Kiper: Change name to grub_envblk_extend(),
capitalize comments, use standard GRUB error enum, change goto from
"out" to "err", drop cast in grub_strlen() call, use grub_snprintf()
instead of strcpy & memcpy.
- Instead of parsing envblk separately, use grub_envblk_iterate()
- use a case statement in set_variable() error handling, and add a comment
about deleting the "=" sign.

Signed-off-by: Prarit Bhargava 
Cc: mleit...@redhat.com
Cc: pjo...@redhat.com
Cc: javi...@redhat.com
Cc: ar...@redhat.com
Cc: Daniel Kiper 

Prarit Bhargava (3):
  grub-editenv: Verify the variable size
  grub: Make grub_envblk_iterate() return an int
  grub: add extend variable functionality

 grub-core/commands/loadenv.c |  6 +--
 grub-core/lib/envblk.c   | 17 ---
 include/grub/err.h   |  4 +-
 include/grub/lib/envblk.h|  6 +--
 util/grub-editenv.c  | 86 ++--
 5 files changed, 100 insertions(+), 19 deletions(-)

-- 
2.17.2


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v2 3/3] grub: add extend variable functionality

2019-01-16 Thread Prarit Bhargava
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
---
 util/grub-editenv.c | 81 +++--
 1 file changed, 79 insertions(+), 2 deletions(-)

diff --git a/util/grub-editenv.c b/util/grub-editenv.c
index 5f87b09d924a..bc997c5312d0 100644
--- a/util/grub-editenv.c
+++ b/util/grub-editenv.c
@@ -201,6 +201,49 @@ write_envblk (const char *name, grub_envblk_t envblk)
   fclose (fp);
 }
 
+struct extend_variable_data {
+  grub_envblk_t envblk;
+  const char *name;
+  const char *add;
+};
+
+static int
+extend_variable_hook (const char *varname, const char *value, void *hook_data)
+{
+  char *new = NULL;
+  int ret = GRUB_ERR_NONE;
+  struct extend_variable_data *data = hook_data;
+
+  if (grub_strcmp (data->name, varname))
+return GRUB_ERR_ITERATE_CONTINUE;
+
+  /* Create the new entry.*/
+  new = grub_zalloc (grub_strlen (value) + grub_strlen (data->add) + 2);
+  if (!new)
+{
+  return GRUB_ERR_OUT_OF_MEMORY;
+  goto err;
+}
+  grub_snprintf(new, grub_strlen (value) + grub_strlen (data->add) + 2,
+   "%s %s", value, data->add);
+
+  /* Erase the current entry. */
+  grub_envblk_delete (data->envblk, varname);
+  /* Add the updated entry. */
+  if (! grub_envblk_set (data->envblk, varname, new))
+{
+  /* Restore the original entry.  This should always work. */
+  grub_envblk_set (data->envblk, varname, value);
+  ret = GRUB_ERR_EOF;
+  goto err;
+}
+
+ err:
+grub_free(new);
+return GRUB_ERR_ITERATE_STOP;
+
+}
+
 static void
 set_variables (const char *name, int argc, char *argv[])
 {
@@ -210,18 +253,52 @@ set_variables (const char *name, int argc, char *argv[])
   while (argc)
 {
   char *p;
+  struct extend_variable_data data;
+  int err;
 
   p = strchr (argv[0], '=');
   if (! p)
 grub_util_error (_("invalid parameter %s"), argv[0]);
 
+  /* Delete "=" to separate variable name and value */
   *(p++) = 0;
 
   if (! grub_strlen(argv[0]))
 grub_util_error (_("No parameter specified"));
 
-  if (! grub_envblk_set (envblk, argv[0], p))
-grub_util_error ("%s", _("environment block too small"));
+  switch (*(p - 2))
+{
+  case '+': /* Extend a parameter */
+*(p - 2) = 0; /* Delete "+" from variable name */
+
+data.envblk = envblk;
+data.name = argv[0];
+data.add = p;
+err = grub_envblk_iterate (envblk, &data, extend_variable_hook);
+switch (err)
+  {
+   case GRUB_ERR_ITERATE_STOP: /* Success */
+  break;
+
+case GRUB_ERR_OUT_OF_RANGE:
+case GRUB_ERR_EOF:
+  grub_util_error ("%s", _("environment block too small"));
+  break;
+
+ 

[PATCH v2 1/3] grub-editenv: Verify the variable size

2019-01-16 Thread Prarit Bhargava
It is possible to execute 'grub-editenv - set ="some data"',
which results in an unremoveable entry

="some data"

Verify the variable has a size before setting a value.

Signed-off-by: Prarit Bhargava 
Cc: mleit...@redhat.com
Cc: pjo...@redhat.com
Cc: javi...@redhat.com
Cc: ar...@redhat.com
Cc: Daniel Kiper 
---
 util/grub-editenv.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/util/grub-editenv.c b/util/grub-editenv.c
index 118e89fe57fe..0b6c69b9688c 100644
--- a/util/grub-editenv.c
+++ b/util/grub-editenv.c
@@ -217,6 +217,9 @@ set_variables (const char *name, int argc, char *argv[])
 
   *(p++) = 0;
 
+  if (! grub_strlen(argv[0]))
+grub_util_error (_("No parameter specified"));
+
   if (! grub_envblk_set (envblk, argv[0], p))
 grub_util_error ("%s", _("environment block too small"));
 
-- 
2.17.2


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel