grub-devel
[Top][All Lists]
Advanced

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

Syntax options for dynamic menu generation in grub-script


From: Jordan Uggla
Subject: Syntax options for dynamic menu generation in grub-script
Date: Mon, 23 Aug 2010 23:03:11 -0700

There has been some discussion recently on IRC about how to implement
dynamic menu generation in grub-script, and I think the discussion is
worth moving to the mailing list as whatever option we choose we will
be stuck supporting for a long time to come.

Dynamic menu generation basically means that "menuentry" will become a
true command that can be executed from loops / conditional statements
and that the resulting menu entry can be different depending on
different circumstances. For instance, you could detect all GNU/Linux
installations on a computer at boot and generate menu entries for
every kernel image found, passing the detected UUID for the root=
statement in the kernel parameters (see osdetect.cfg from bvk's
osdetect bzr branch which does this as well as detecting other OSs).

Two main options for the syntax of the menuentry command have been
fleshed out so far:

1. In the first, menu entries act very similar to functions, passing
variables like the kernel image path via positional parameters ( $1
being the title of the menu entry ). As an example, here is how you
could generate a menu for choosing among detected grub2 installations
with this syntax:

for core in (*)/boot/grub/core.img; do
  # Extract just the device portion from the path to the core.img
  regexp -s device '^(\(.-\))' $core

  menuentry "Load $core" $device $core {
    device=$2
    core=$3

    root=$device
    multiboot $core
  }
done

An example menu entry created by this code would be titled "Load
(hd0,1)/boot/grub/core.img" and if you pressed 'e' to view the source
you would see:

 +--------------------------------------------------------------------------+
 | setparams "Load (hd0,1)/boot/grub/core.img" (hd0,1) (hd0,1)/boot/grub c\ |
 | ore.img                                                                  |
 |                                                                          |
 | device=$2                                                                |
 | core=$3                                                                  |
 |                                                                          |
 | root=$device                                                             |
 | multiboot $core                                                          |
 |                                                                          |
 |                                                                          |
 |                                                                          |
 +--------------------------------------------------------------------------+


This is basically implemented right now.

2. The other option would be to pass the source of the menu entry as a
regular string, using normal shell syntax to construct this string. An
implementation of the same example would be:

for core in (*)/boot/grub/core.img; do
  # Extract just the device portion from the path to the core.img
  regexp -s device '^(\(.-\))' $core

  menuentry "Load $core" --source "
    root=$device
    multiboot $core
  "
done

And the resulting menu entry would show up in grub's menu entry editor as:

 +--------------------------------------------------------------------------+
 | root=(hd0,1)                                                             |
 | multiboot (hd0,1)/boot/grub/core.img                                     |
 |                                                                          |
 |                                                                          |
 |                                                                          |
 |                                                                          |
 |                                                                          |
 |                                                                          |
 |                                                                          |
 |                                                                          |
 |                                                                          |
 +--------------------------------------------------------------------------+


Points in favor of option one:

 * With option one syntax can be checked ahead of time. If
grub-script-check finds no syntax errors in the grub.cfg then there
will be no syntax errors in the generated menu entries. As any string
can be generated at runtime and passed via option two, this type of
checking is not possible.

 * Option one follows common pattern of passing variables via
positional parameters, familiar to anyone who has used functions in
*NIX shells.

 * Option one requires no additional escaping. With option two we open
ourselves to the escaping problems seen with grub-mkconfig, for
instance http://lists.gnu.org/archive/html/grub-devel/2010-04/msg00090.html

 * Option one doesn't treat dynamic menu entry generation as a special
case (with no extra parameters after the title, you are back to
exactly the same syntax currently used for static entries).

Points in favor of option two:

 * This is subjective, but I find the syntax of option one hard to
read, both in the grub.cfg and in the menu entries that it creates
when viewed in grub's menu entry editor.

 * Option one only allows for "templates" of menu entries, where the
source is basically always the same, but acts differently depending on
positional parameters. I have created a script with grub's lua support
which parses a grub legacy menu.lst file by building the source of
each menu entry line by line, replacing grub legacy commands with
their grub2 equivalents. I don't think that such a script would be
possible to create with this grub-script syntax (but would with option
two).


While I only mentioned the two options that were discussed on IRC, I
am sure there are other solutions to be brought to this discussion.

-- 
Jordan Uggla (Jordan_U on irc.freenode.net)



reply via email to

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