The default ESP partition on some systems is limited in
space and storing a number of kernel and initrd images
can fill it up quickly.

It's not always practical to increase the size of the
existing ESP, so the Boot Loader Spec defines a new Extended
Boot Loader Partition (XBOOTLDR) with GPT type GUID of
bc13c2ff-59e6-4262-a352-b275fd6f7172 to be searched for BLS
enties and UKIs in addition to the ESP.

see https://uapi-group.org/specifications/specs/boot_loader_specification/

Signed-off-by: Radoslav Kolev <[email protected]>
---
 grub-core/commands/blsuki.c  | 86 +++++++++++++++++++++++++++++++++---
 include/grub/gpt_partition.h |  7 +++
 2 files changed, 86 insertions(+), 7 deletions(-)

diff --git a/grub-core/commands/blsuki.c b/grub-core/commands/blsuki.c
index a169e3f59..db5ab3a5c 100644
--- a/grub-core/commands/blsuki.c
+++ b/grub-core/commands/blsuki.c
@@ -31,6 +31,7 @@
 #include <grub/safemath.h>
 #include <grub/lib/envblk.h>
 #include <filevercmp.h>
+#include <grub/gpt_partition.h>
 
 #ifdef GRUB_MACHINE_EFI
 #include <grub/efi/efi.h>
@@ -1245,6 +1246,33 @@ blsuki_find_entry (struct find_entry_info *info, bool 
enable_fallback, enum blsu
   return GRUB_ERR_NONE;
 }
 
+static const grub_guid_t xbootldr_type = GRUB_GPT_PARTITION_TYPE_XBOOTLDR;
+static int find_xbootldr_iter (grub_disk_t disk, const grub_partition_t p, 
void *data) {
+  char **xbootldr_part = data;
+  struct grub_gpt_partentry gptdata;
+  grub_partition_t p2;
+
+  grub_dprintf("blsuki","Checking part number %d index %d \n", p->number, 
p->index);
+
+  p2 = disk->partition;
+  disk->partition = p->parent;
+  if (grub_disk_read (disk, p->offset, p->index, sizeof (gptdata), &gptdata))
+    {
+      disk->partition = p2;
+      return 0;
+    }
+  disk->partition = p2;
+  grub_dprintf("blsuki","Gptdata.type:  %x %x %x %x\n", gptdata.type.data1, 
gptdata.type.data2, gptdata.type.data3, gptdata.type.data4[0]);
+  grub_dprintf("blsuki","XBOOTLDR.type:  %x %x %x %x\n", xbootldr_type.data1, 
xbootldr_type.data2, xbootldr_type.data3, xbootldr_type.data4[0]);
+  if (! grub_memcmp (&gptdata.type, &xbootldr_type, 16))
+    {
+      *xbootldr_part = grub_xasprintf("%s,%s", disk->name, 
grub_partition_get_name(p));
+      grub_dprintf("blsuki","XBOOTLDR found! setting name to %s\n", 
*xbootldr_part);
+      return 1;
+    }
+  return 0;
+}
+
 static grub_err_t
 blsuki_load_entries (char *path, bool enable_fallback, enum blsuki_cmd_type 
cmd_type)
 {
@@ -1257,6 +1285,7 @@ blsuki_load_entries (char *path, bool enable_fallback, 
enum blsuki_cmd_type cmd_
   const char *cmd_dir = NULL;
   grub_size_t dir_size;
   const char *ext = NULL;
+  char *xbootldr_part = NULL;
   struct find_entry_info info = {
       .dev = NULL,
       .fs = NULL,
@@ -1329,16 +1358,59 @@ blsuki_load_entries (char *path, bool enable_fallback, 
enum blsuki_cmd_type cmd_
       tmp = grub_stpcpy (tmp, cmd_dir);
       dir = default_dir;
     }
+    //will search ESP ($root) if no device specified
+      r = blsuki_set_find_entry_info (&info, dir, devid, cmd_type);
+      if (r == GRUB_ERR_NONE)
+       r = blsuki_find_entry (&info, enable_fallback, cmd_type);
+      if (r != GRUB_ERR_NONE)
+       goto finish;
+     /*
+     * No device and partition specified - default behaviour as
+     * per the spec is to search both ESP and XBOOTLDR partitions
+     */
+  if (devid == NULL)
+    {
+      //find XBOOTLDR partition if it exists and scan it for entries
+      grub_disk_t esp_disk = grub_disk_open(grub_env_get ("root"));
+      grub_err_t err;
 
-  r = blsuki_set_find_entry_info (&info, dir, devid, cmd_type);
-  if (r == GRUB_ERR_NONE)
-    r = blsuki_find_entry (&info, enable_fallback, cmd_type);
+      if (esp_disk)
+       {
+         grub_free (esp_disk->partition);
+         //we want to access the disk device containing the ESP, so set 
partition to NULL
+         esp_disk->partition = NULL;
+         err = grub_gpt_partition_map_iterate (esp_disk, find_xbootldr_iter, 
&xbootldr_part);
+         if (err)
+           {
+             grub_dprintf("blsuki", "iterating partitions failed with err: 
%d\n",err);
+             goto finish;
+           }
+
+         if (xbootldr_part)
+           {
+             grub_dprintf("blsuki", "Found XBOOTLDR partition %s\n", 
xbootldr_part);
+             r = blsuki_set_find_entry_info (&info, dir, xbootldr_part, 
cmd_type);
+             if (r == GRUB_ERR_NONE)
+               r = blsuki_find_entry (&info, enable_fallback, cmd_type);
+             if (r != GRUB_ERR_NONE)
+               goto finish;
+           }
+         else
+           {
+             grub_dprintf("blsuki", "XBOOTLDR partition not found (%s)!\n", 
xbootldr_part);
+           }
+         grub_disk_close(esp_disk);
+       }
+      else grub_dprintf("blsuki", "Failed to open ESP disk looking for 
XBOOTLDR partition\n");
+    }
+  finish:
+    if (info.dev != NULL)
+      grub_device_close (info.dev);
 
-  if (info.dev != NULL)
-    grub_device_close (info.dev);
+    grub_free (default_dir);
+    grub_free (xbootldr_part);
 
-  grub_free (default_dir);
-  return r;
+    return r;
 }
 
 static bool
diff --git a/include/grub/gpt_partition.h b/include/grub/gpt_partition.h
index 292ea03f1..4833827ef 100644
--- a/include/grub/gpt_partition.h
+++ b/include/grub/gpt_partition.h
@@ -41,6 +41,13 @@
        { 0x85, 0xD2, 0xE1, 0xE9, 0x04, 0x34, 0xCF, 0xB3 }      \
   }
 
+#define GRUB_GPT_PARTITION_TYPE_XBOOTLDR \
+  { grub_cpu_to_le32_compile_time (0xbc13c2ffU),\
+      grub_cpu_to_le16_compile_time (0x59e6), \
+      grub_cpu_to_le16_compile_time (0x4262),         \
+       { 0xa3, 0x52, 0xb2, 0x75, 0xfd, 0x6f, 0x71, 0x72 }      \
+  }
+
 struct grub_gpt_header
 {
   grub_uint8_t magic[8];
-- 
2.51.1


_______________________________________________
Grub-devel mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to