Getting the (approximate) Bootloader Spec into Fedora

Matthew Garrett mjg59 at srcf.ucam.org
Mon Jul 7 23:03:17 UTC 2014


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 at 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 at srcf.ucam.org


More information about the desktop mailing list