:: commit 4c6fba824c2568f426b7040b7c494447b26f28ee

mintsuki <mintsuki@protonmail.com> — 2022-07-26 17:21

parents: 7bfa2cd775

chainload: Add GPT_GUID support and improve documentation. Closes #201

diff --git a/CONFIG.md b/CONFIG.md
index cce17965..44bed234 100644
--- a/CONFIG.md
+++ b/CONFIG.md
@@ -119,9 +119,10 @@ Editor control options.
   * `KASLR` - For relocatable kernels, if set to `no`, disable kernel address space layout randomisation. KASLR is enabled by default.
 
 * Chainload protocol on BIOS:
-  * `DRIVE` - The 1-based BIOS drive to chainload, if omitted, assume boot drive.
-  * `PARTITION` - The 1-based BIOS partition to chainload, if omitted, chainload drive (MBR).
-  * `MBR_ID` - Optional. If passed, use an MBR ID (32-bit hex value) to identify the volume to chainload.
+  * `DRIVE` - The 1-based drive to chainload, if omitted, assume boot drive.
+  * `PARTITION` - The 1-based partition to chainload, if omitted, or set to 0, chainload drive (MBR).
+  * `MBR_ID` - Optional. If passed, use an MBR ID (32-bit hex value) to identify the drive containing the volume to chainload. Overrides `DRIVE`, if present, but does *not* override `PARTITION`.
+  * `GPT_UUID` or `GPT_GUID` - Optional. If passed, use the GPT GUID to identify the drive containing the volume to chainload. Overrides `DRIVE` and `MBR_ID`, if present, but does *not* override `PARTITION`.
 
 * Chainload protocol on UEFI:
   * `IMAGE_PATH` - URI of the EFI application to chainload.
diff --git a/common/protos/chainload.c b/common/protos/chainload.c
index cf6d4cd0..eee0f681 100644
--- a/common/protos/chainload.c
+++ b/common/protos/chainload.c
@@ -102,6 +102,42 @@ noreturn void chainload(char *config) {
 
     struct volume *p = volume_get_by_coord(false, drive, part);
 
+    char *gpt_guid_s = config_get_value(config, 0, "GPT_GUID");
+    if (gpt_guid_s == NULL) {
+        gpt_guid_s = config_get_value(config, 0, "GPT_UUID");
+    }
+    if (gpt_guid_s != NULL) {
+        struct guid guid;
+        if (!string_to_guid_be(&guid, gpt_guid_s)) {
+            panic(true, "chainload: Malformed GUID");
+        }
+
+        p = volume_get_by_guid(&guid);
+        if (p == NULL) {
+            if (!string_to_guid_mixed(&guid, gpt_guid_s)) {
+                panic(true, "chainload: Malformed GUID");
+            }
+
+            p = volume_get_by_guid(&guid);
+        }
+
+        if (p == NULL) {
+            panic(true, "chainload: No matching GPT drive for GPT_GUID found");
+        }
+
+        if (p->partition != 0) {
+            panic(true, "chainload: GPT_GUID is that of a partition, not a drive");
+        }
+
+        p = volume_get_by_coord(false, p->index, part);
+
+        if (p == NULL) {
+            panic(true, "chainload: Partition specified is not valid");
+        }
+
+        goto load;
+    }
+
     char *mbr_id_s = config_get_value(config, 0, "MBR_ID");
     if (mbr_id_s != NULL) {
         uint32_t mbr_id = strtoui(mbr_id_s, NULL, 16);
@@ -118,6 +154,11 @@ noreturn void chainload(char *config) {
 
             if (mbr_id_1 == mbr_id) {
                 p = volume_get_by_coord(false, p->index, part);
+
+                if (p == NULL) {
+                    panic(true, "chainload: Partition specified is not valid");
+                }
+
                 goto load;
             }
         }
tab: 248 wrap: offon