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