:: commit 956b7db3b02ffabef3bbdf1935fd89b91585918b

mintsuki <mintsuki@protonmail.com> — 2022-07-10 23:30

parents: 9ebd6e10de

chainload: Implement MBR_ID config option. Closes #190

diff --git a/CONFIG.md b/CONFIG.md
index 7e67af72..d348bf4d 100644
--- a/CONFIG.md
+++ b/CONFIG.md
@@ -127,6 +127,7 @@ Editor control options.
 * 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.
 
 * Chainload protocol on UEFI:
   * `IMAGE_PATH` - URI of the EFI application to chainload.
diff --git a/common/lib/part.h b/common/lib/part.h
index 9de453f5..e092a17b 100644
--- a/common/lib/part.h
+++ b/common/lib/part.h
@@ -55,6 +55,7 @@ struct volume {
 };
 
 void list_volumes(void);
+bool is_valid_mbr(struct volume *volume);
 
 extern struct volume **volume_index;
 extern size_t volume_index_i;
diff --git a/common/lib/part.s2.c b/common/lib/part.s2.c
index e8befe83..eadd53e9 100644
--- a/common/lib/part.s2.c
+++ b/common/lib/part.s2.c
@@ -244,7 +244,7 @@ struct mbr_entry {
 	uint32_t sect_count;
 } __attribute__((packed));
 
-static bool is_valid_mbr(struct volume *volume) {
+bool is_valid_mbr(struct volume *volume) {
     // Check if actually valid mbr
     uint16_t hint = 0;
     volume_read(volume, &hint, 218, sizeof(uint16_t));
diff --git a/common/protos/chainload.c b/common/protos/chainload.c
index 93a4610b..354d3376 100644
--- a/common/protos/chainload.c
+++ b/common/protos/chainload.c
@@ -99,6 +99,29 @@ void chainload(char *config) {
 
     struct volume *p = volume_get_by_coord(false, drive, part);
 
+    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);
+
+        for (size_t i = 0; i < volume_index_i; i++) {
+            p = volume_index[i];
+
+            if (!is_valid_mbr(p)) {
+                continue;
+            }
+
+            uint32_t mbr_id_1;
+            volume_read(p, &mbr_id_1, 0x1b8, sizeof(uint32_t));
+
+            if (mbr_id_1 == mbr_id) {
+                goto load;
+            }
+        }
+
+        panic(true, "chainload: No matching MBR ID found");
+    }
+
+load:
     bios_chainload_volume(p);
 
     panic(true, "chainload: Volume is not bootable");
tab: 248 wrap: offon