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
