I poked at this a bit more today. What I've got so far:
*
http://www.freedesktop.org/wiki/MatthewGarrett/BootLoaderSpec/ - a
modified version of the BLS, along with a description and justification
of the changes.
* An entirely untested patch to grub2 that implements all of the spec
other than the devicetree bit.
* No changes to os-prober
* No changes to anaconda
* No changes to grubby
But those shouldn't really be too difficult to fix (a-ha ha ha). Diff
follows.
commit cce95c9dbc123e9b65e683913c5a29befa826a89
Author: Matthew Garrett <matthew.garrett(a)nebula.com>
Date: Mon Jul 7 18:50:44 2014 -0400
Extend BLS support
diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
index 4274aca..6b762fb 100644
--- a/grub-core/commands/blscfg.c
+++ b/grub-core/commands/blscfg.c
@@ -36,14 +36,13 @@ GRUB_MOD_LICENSE ("GPLv3+");
#ifdef GRUB_MACHINE_EFI
#define GRUB_LINUX_CMD "linuxefi"
#define GRUB_INITRD_CMD "initrdefi"
-#define GRUB_BLS_CONFIG_PATH "/EFI/fedora/loader/entries/"
#define GRUB_BOOT_DEVICE "($boot)"
#else
#define GRUB_LINUX_CMD "linux"
#define GRUB_INITRD_CMD "initrd"
-#define GRUB_BLS_CONFIG_PATH "/loader/entries/"
#define GRUB_BOOT_DEVICE "($root)"
#endif
+#define GRUB_BLS_CONFIG_PATH "/org/freedesktop/bls/entries/"
static int parse_entry (
const char *filename,
@@ -54,7 +53,7 @@ static int parse_entry (
char *p;
grub_file_t f = NULL;
grub_off_t sz;
- char *title = NULL, *options = NULL, *clinux = NULL, *initrd = NULL, *src = NULL;
+ char *title = NULL, *options = NULL, *clinux = NULL, *initrd = NULL, *src = NULL, *root
= NULL, *chainload = NULL;
const char *args[2] = { NULL, NULL };
if (filename[0] == '.')
@@ -113,25 +112,103 @@ static int parse_entry (
if (!initrd)
goto finish;
}
+ else if (grub_strncmp (buf, "filesystem ", 10) == 0)
+ {
+ char *path = buf + 10;
+
+ if (grub_strncmp (p, "0x", 2)) /* BIOS-style disk name */
+ {
+ char c, *d = path;
+ int drive, partition, partoff = 0;
+
+ while ((c = *d++) != '\0')
+ {
+ if (c == ',')
+ partoff = d - path;
+ }
+ if (partoff)
+ {
+ drive = (int) grub_strtoul (p, 0, 16);
+ partition = (int) grub_strtoul (path + partoff, 0, 16);
+ }
+ else
+ {
+ drive = (int) grub_strtoul (path, 0, 16);
+ partition = 0;
+ }
+
+ drive -= 0x80;
+ if (partition)
+ {
+ root = grub_xasprintf ("set root=(hd(%d,%d))\n",
+ drive,
+ partition);
+ }
+ else
+ {
+ root = grub_xasprintf ("set root=hd(%d)\n",
+ drive);
+ }
+ if (!root)
+ goto finish;
+ }
+ else /* Assume UUID */
+ {
+ root = grub_xasprintf ("insmod search_fs_uuid\n"
+ "search --no-floppy -u %s\n",
+ path);
+ if (!root)
+ goto finish;
+ }
+ }
+ else if (grub_strncmp (buf, "chainload", 14) == 0)
+ {
+ chainload = grub_xasprintf ("chainloader %s+1", GRUB_BOOT_DEVICE);
+ if (!chainload)
+ goto finish;
+ }
+ else if (grub_strncmp (buf, "efi ", 4) == 0)
+ {
+ chainload = grub_xasprintf ("chainloader %s%s", GRUB_BOOT_DEVICE,
+ buf + 4);
+ if (!chainload)
+ goto finish;
+ }
grub_free(buf);
}
- if (!linux)
+ if (!linux && !chainload)
{
- grub_printf ("Skipping file %s with no 'linux' key.", p);
+ grub_printf ("Skipping file %s with no 'linux' or 'chainload'
key.",
+ p);
goto finish;
}
args[0] = title ? title : filename;
- src = grub_xasprintf ("load_video\n"
- "set gfx_payload=keep\n"
- "insmod gzio\n"
- GRUB_LINUX_CMD " %s%s%s%s\n"
- "%s%s%s%s",
- GRUB_BOOT_DEVICE, clinux, options ? " " : "", options ? options :
"",
- initrd ? GRUB_INITRD_CMD " " : "", initrd ? GRUB_BOOT_DEVICE :
"", initrd ? initrd : "", initrd ? "\n" : "");
+ if (chainload) {
+ src = grub_xasprintf ("insmod part_msdos\n"
+ "insmod part_gpt\n"
+ "insmod chain\n"
+ "%s"
+ "%s",
+ root ? root : "",
+ chainload);
+ } else {
+ src = grub_xasprintf ("load_video\n"
+ "set gfx_payload=keep\n"
+ "insmod gzio\n"
+ "insmod part_msdos\n"
+ "insmod part_gpt\n"
+ "insmod ext2\n"
+ "insmod xfs\n"
+ "%s"
+ GRUB_LINUX_CMD " %s%s%s%s\n"
+ "%s%s%s%s",
+ GRUB_BOOT_DEVICE, root ? root : "", clinux, options ? " " :
"", options ? options : "",
+ initrd ? GRUB_INITRD_CMD " " : "", initrd ? GRUB_BOOT_DEVICE :
"", initrd ? initrd : "", initrd ? "\n" : "");
+ }
grub_normal_add_menu_entry (1, args, NULL, NULL, "bls", NULL, NULL, src, 0);
@@ -142,6 +219,8 @@ finish:
grub_free (clinux);
grub_free (initrd);
grub_free (src);
+ grub_free (chainload);
+ grub_free (root);
if (f)
grub_file_close (f);
--
Matthew Garrett | mjg59(a)srcf.ucam.org