:: commit f67649238b726a294cd8ac2960495c403ce5eda6

Mintsuki <mintsuki@protonmail.com> — 2026-01-31 13:46

parents: b90552adb3

drivers/disk: Refactor disk_volume_from_efi_handle() and disk_create_index() to not ever attempt disk writes

diff --git a/common/drivers/disk.s2.c b/common/drivers/disk.s2.c
index e27c67cb..e61fc3de 100644
--- a/common/drivers/disk.s2.c
+++ b/common/drivers/disk.s2.c
@@ -7,7 +7,6 @@
 #  include <lib/real.h>
 #elif defined (UEFI)
 #  include <efi.h>
-#  include <crypt/blake2b.h>
 #endif
 #include <lib/misc.h>
 #include <lib/print.h>
@@ -419,23 +418,6 @@ static struct volume *pxe_from_efi_handle(EFI_HANDLE efi_handle) {
     return vol;
 }
 
-#define UNIQUE_SECTOR_POOL_SIZE 65536
-static uint8_t *unique_sector_pool;
-
-static struct volume *volume_by_unique_sector(void *b2b) {
-    for (size_t i = 0; i < volume_index_i; i++) {
-        if (volume_index[i]->unique_sector_valid == false) {
-            continue;
-        }
-
-        if (memcmp(volume_index[i]->unique_sector_b2b, b2b, BLAKE2B_OUT_BYTES) == 0) {
-            return volume_index[i];
-        }
-    }
-
-    return NULL;
-}
-
 static bool is_efi_handle_to_skip(EFI_HANDLE efi_handle) {
     EFI_STATUS status;
 
@@ -484,7 +466,7 @@ static bool is_efi_handle_to_skip(EFI_HANDLE efi_handle) {
     return false;
 }
 
-static bool is_efi_handle_hdd(EFI_HANDLE efi_handle) {
+static bool is_efi_handle_optical(EFI_HANDLE efi_handle) {
     EFI_STATUS status;
 
     EFI_GUID dp_guid = EFI_DEVICE_PATH_PROTOCOL_GUID;
@@ -500,192 +482,199 @@ static bool is_efi_handle_hdd(EFI_HANDLE efi_handle) {
             break;
         }
 
-        if (dp->Type == MEDIA_DEVICE_PATH) {
-            switch (dp->SubType) {
-                case MEDIA_HARDDRIVE_DP:
-                    return true;
-            }
-        }
-
         uint16_t len = *(uint16_t *)dp->Length;
         if (len < sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
             break;  // Malformed device path node
         }
+
+        if (dp->Type == MEDIA_DEVICE_PATH && dp->SubType == MEDIA_CDROM_DP) {
+            return true;
+        }
+
         dp = (void *)dp + len;
     }
 
     return false;
 }
 
-struct volume *disk_volume_from_efi_handle(EFI_HANDLE efi_handle) {
-    struct volume *ret;
-
+static EFI_DEVICE_PATH_PROTOCOL *get_device_path(EFI_HANDLE efi_handle) {
     EFI_STATUS status;
+    EFI_GUID dp_guid = EFI_DEVICE_PATH_PROTOCOL_GUID;
+    EFI_DEVICE_PATH_PROTOCOL *dp = NULL;
 
-    EFI_GUID block_io_guid = BLOCK_IO_PROTOCOL;
-    EFI_BLOCK_IO *block_io = NULL;
-
-    if (is_efi_handle_to_skip(efi_handle)) {
+    status = gBS->HandleProtocol(efi_handle, &dp_guid, (void **)&dp);
+    if (status) {
         return NULL;
     }
+    return dp;
+}
 
-    status = gBS->HandleProtocol(efi_handle, &block_io_guid, (void **)&block_io);
-    if (status) {
-        return pxe_from_efi_handle(efi_handle);
+// Compare device paths up to (but not including) partition nodes
+static bool device_paths_match_disk(EFI_DEVICE_PATH_PROTOCOL *dp1,
+                                    EFI_DEVICE_PATH_PROTOCOL *dp2) {
+    if (dp1 == NULL || dp2 == NULL) {
+        return false;
     }
 
-    uint64_t bdev_size = ((uint64_t)block_io->Media->LastBlock + 1) * (uint64_t)block_io->Media->BlockSize;
-    if (bdev_size < UNIQUE_SECTOR_POOL_SIZE) {
-        goto fallback;
-    }
+    while (!IsDevicePathEnd(dp1) && !IsDevicePathEnd(dp2)) {
+        // Stop at partition nodes
+        if (dp1->Type == MEDIA_DEVICE_PATH &&
+            (dp1->SubType == MEDIA_HARDDRIVE_DP || dp1->SubType == MEDIA_CDROM_DP)) {
+            break;
+        }
+        if (dp2->Type == MEDIA_DEVICE_PATH &&
+            (dp2->SubType == MEDIA_HARDDRIVE_DP || dp2->SubType == MEDIA_CDROM_DP)) {
+            break;
+        }
 
-    status = block_io->ReadBlocks(block_io, block_io->Media->MediaId,
-                                  0,
-                                  UNIQUE_SECTOR_POOL_SIZE,
-                                  unique_sector_pool);
-    if (status != 0) {
-        goto fallback;
-    }
+        uint16_t len1 = DevicePathNodeLength(dp1);
+        uint16_t len2 = DevicePathNodeLength(dp2);
 
-    uint8_t b2b[BLAKE2B_OUT_BYTES];
-    blake2b(b2b, unique_sector_pool, UNIQUE_SECTOR_POOL_SIZE);
+        if (len1 != len2) {
+            return false;
+        }
 
-    ret = volume_by_unique_sector(b2b);
-    if (ret != NULL) {
-        return ret;
-    }
+        if (memcmp(dp1, dp2, len1) != 0) {
+            return false;
+        }
 
-    // Fallback to read-back method
-fallback:;
-    if (!is_efi_handle_hdd(efi_handle)) {
-        return NULL;
+        dp1 = NextDevicePathNode(dp1);
+        dp2 = NextDevicePathNode(dp2);
     }
 
-    uint64_t signature = rand64();
-    uint64_t new_signature;
-    do { new_signature = rand64(); } while (new_signature == signature);
-    uint64_t orig;
-
-    status = block_io->ReadBlocks(block_io, block_io->Media->MediaId, 0, 4096, unique_sector_pool);
-    orig = *(uint64_t *)unique_sector_pool;
-    if (status) {
-        return NULL;
-    }
+    return true;
+}
 
-    *(uint64_t *)unique_sector_pool = signature;
-    status = block_io->WriteBlocks(block_io, block_io->Media->MediaId, 0, 4096, unique_sector_pool);
-    if (status) {
-        // Attempt to restore anyways, just in case.
-        *(uint64_t *)unique_sector_pool = orig;
-        block_io->WriteBlocks(block_io, block_io->Media->MediaId, 0, 4096, unique_sector_pool);
+static struct volume *volume_by_device_path(EFI_HANDLE query_handle) {
+    EFI_DEVICE_PATH_PROTOCOL *query_dp = get_device_path(query_handle);
+    if (query_dp == NULL) {
         return NULL;
     }
 
-    ret = NULL;
     for (size_t i = 0; i < volume_index_i; i++) {
-        uint64_t compare;
-
-        status = volume_index[i]->block_io->ReadBlocks(volume_index[i]->block_io,
-                          volume_index[i]->block_io->Media->MediaId,
-                          (volume_index[i]->first_sect * 512) / volume_index[i]->sector_size,
-                          4096, unique_sector_pool);
-        compare = *(uint64_t *)unique_sector_pool;
-        if (status) {
+        EFI_DEVICE_PATH_PROTOCOL *vol_dp = get_device_path(volume_index[i]->efi_handle);
+        if (vol_dp == NULL) {
             continue;
         }
 
-        if (compare == signature) {
-            // Double check
-            status = block_io->ReadBlocks(block_io, block_io->Media->MediaId, 0, 4096, unique_sector_pool);
-            if (status) {
-                break;
-            }
-            *(uint64_t *)unique_sector_pool = new_signature;
-            status = block_io->WriteBlocks(block_io, block_io->Media->MediaId, 0, 4096, unique_sector_pool);
-            if (status) {
-                break;
+        if (device_paths_match_disk(query_dp, vol_dp)) {
+            EFI_DEVICE_PATH_PROTOCOL *qp = query_dp;
+            while (!IsDevicePathEnd(qp)) {
+                if (qp->Type == MEDIA_DEVICE_PATH && qp->SubType == MEDIA_HARDDRIVE_DP) {
+                    HARDDRIVE_DEVICE_PATH *query_hd = (HARDDRIVE_DEVICE_PATH *)qp;
+                    if (volume_index[i]->first_sect == query_hd->PartitionStart) {
+                        return volume_index[i];
+                    }
+                    break;
+                }
+                qp = NextDevicePathNode(qp);
             }
 
-            status = volume_index[i]->block_io->ReadBlocks(volume_index[i]->block_io,
-                          volume_index[i]->block_io->Media->MediaId,
-                          (volume_index[i]->first_sect * 512) / volume_index[i]->sector_size,
-                          4096, unique_sector_pool);
-            compare = *(uint64_t *)unique_sector_pool;
-            if (status) {
-                continue;
+            if (IsDevicePathEnd(qp) && volume_index[i]->partition == 0) {
+                return volume_index[i];
             }
+        }
+    }
+
+    return NULL;
+}
+
+static struct volume *volume_by_partition_signature(EFI_HANDLE query_handle) {
+    EFI_DEVICE_PATH_PROTOCOL *dp = get_device_path(query_handle);
+    if (dp == NULL) {
+        return NULL;
+    }
+
+    while (!IsDevicePathEnd(dp)) {
+        uint16_t len = DevicePathNodeLength(dp);
+        if (len < sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
+            break;
+        }
 
-            if (compare == new_signature) {
-                ret = volume_index[i];
+        if (dp->Type == MEDIA_DEVICE_PATH && dp->SubType == MEDIA_HARDDRIVE_DP) {
+            if (len < sizeof(HARDDRIVE_DEVICE_PATH)) {
                 break;
             }
 
-            status = block_io->ReadBlocks(block_io, block_io->Media->MediaId, 0, 4096, unique_sector_pool);
-            if (status) {
-                break;
+            HARDDRIVE_DEVICE_PATH *hd = (HARDDRIVE_DEVICE_PATH *)dp;
+
+            // GPT: match by partition GUID
+            if (hd->SignatureType == SIGNATURE_TYPE_GUID) {
+                for (size_t i = 0; i < volume_index_i; i++) {
+                    if (volume_index[i]->guid_valid &&
+                        memcmp(&volume_index[i]->guid, hd->Signature, sizeof(EFI_GUID)) == 0) {
+                        return volume_index[i];
+                    }
+                }
             }
-            *(uint64_t *)unique_sector_pool = signature;
-            status = block_io->WriteBlocks(block_io, block_io->Media->MediaId, 0, 4096, unique_sector_pool);
-            if (status) {
-                break;
+
+            // MBR: match by partition start LBA
+            if (hd->SignatureType == SIGNATURE_TYPE_MBR) {
+                for (size_t i = 0; i < volume_index_i; i++) {
+                    if (volume_index[i]->first_sect == hd->PartitionStart) {
+                        return volume_index[i];
+                    }
+                }
             }
+
+            break;
         }
-    }
 
-    status = block_io->ReadBlocks(block_io, block_io->Media->MediaId, 0, 4096, unique_sector_pool);
-    if (status) {
-        return NULL;
-    }
-    *(uint64_t *)unique_sector_pool = orig;
-    status = block_io->WriteBlocks(block_io, block_io->Media->MediaId, 0, 4096, unique_sector_pool);
-    if (status) {
-        return NULL;
+        dp = NextDevicePathNode(dp);
     }
 
-    if (ret != NULL) {
-        return ret;
+    return NULL;
+}
+
+static struct volume *volume_by_media_match(EFI_BLOCK_IO *query_bio) {
+    for (size_t i = 0; i < volume_index_i; i++) {
+        EFI_BLOCK_IO *vol_bio = volume_index[i]->block_io;
+
+        if (vol_bio->Media->BlockSize == query_bio->Media->BlockSize &&
+            vol_bio->Media->LastBlock == query_bio->Media->LastBlock &&
+            vol_bio->Media->ReadOnly == query_bio->Media->ReadOnly &&
+            vol_bio->Media->RemovableMedia == query_bio->Media->RemovableMedia &&
+            vol_bio->Media->LogicalPartition == query_bio->Media->LogicalPartition) {
+            return volume_index[i];
+        }
     }
 
     return NULL;
 }
 
-static void find_unique_sectors(void) {
-    EFI_STATUS status;
+struct volume *disk_volume_from_efi_handle(EFI_HANDLE efi_handle) {
+    struct volume *ret;
 
-    for (size_t i = 0; i < volume_index_i; i++) {
-        if ((volume_index[i]->first_sect * 512) % volume_index[i]->sector_size) {
-            continue;
-        }
+    EFI_STATUS status;
 
-        size_t first_sect = (volume_index[i]->first_sect * 512) / volume_index[i]->sector_size;
+    EFI_GUID block_io_guid = BLOCK_IO_PROTOCOL;
+    EFI_BLOCK_IO *block_io = NULL;
 
-        if (volume_index[i]->sect_count * volume_index[i]->sector_size < UNIQUE_SECTOR_POOL_SIZE) {
-            continue;
-        }
+    if (is_efi_handle_to_skip(efi_handle)) {
+        return NULL;
+    }
 
-        status = volume_index[i]->block_io->ReadBlocks(
-                            volume_index[i]->block_io,
-                            volume_index[i]->block_io->Media->MediaId,
-                            first_sect,
-                            UNIQUE_SECTOR_POOL_SIZE,
-                            unique_sector_pool);
-        if (status != 0) {
-            continue;
-        }
+    status = gBS->HandleProtocol(efi_handle, &block_io_guid, (void **)&block_io);
+    if (status) {
+        return pxe_from_efi_handle(efi_handle);
+    }
 
-        uint8_t b2b[BLAKE2B_OUT_BYTES];
-        blake2b(b2b, unique_sector_pool, UNIQUE_SECTOR_POOL_SIZE);
+    ret = volume_by_device_path(efi_handle);
+    if (ret != NULL) {
+        return ret;
+    }
 
-        struct volume *collision = volume_by_unique_sector(b2b);
-        if (collision == NULL) {
-            volume_index[i]->unique_sector_valid = true;
-            memcpy(volume_index[i]->unique_sector_b2b, b2b, BLAKE2B_OUT_BYTES);
-            continue;
-        }
+    ret = volume_by_partition_signature(efi_handle);
+    if (ret != NULL) {
+        return ret;
+    }
 
-        // Invalidate collision's unique sector
-        collision->unique_sector_valid = false;
+    ret = volume_by_media_match(block_io);
+    if (ret != NULL) {
+        return ret;
     }
+
+    return NULL;
 }
 
 static void find_part_handles(EFI_HANDLE *handles, size_t handle_count) {
@@ -701,8 +690,6 @@ static void find_part_handles(EFI_HANDLE *handles, size_t handle_count) {
 void disk_create_index(void) {
     EFI_STATUS status;
 
-    unique_sector_pool = ext_mem_alloc(UNIQUE_SECTOR_POOL_SIZE);
-
     EFI_HANDLE tmp_handles[1];
 
     EFI_GUID block_io_guid = BLOCK_IO_PROTOCOL;
@@ -751,20 +738,12 @@ fail:
         if (drive->Media->LogicalPartition)
             continue;
 
-        drive->Media->WriteCaching = false;
-
-        status = drive->ReadBlocks(drive, drive->Media->MediaId, 0, 4096, unique_sector_pool);
-        if (status) {
-            continue;
-        }
-
-        status = drive->WriteBlocks(drive, drive->Media->MediaId, 0, 4096, unique_sector_pool);
-
-        drive->Media->WriteCaching = true;
-
         struct volume *block = ext_mem_alloc(sizeof(struct volume));
 
-        if ((status || drive->Media->ReadOnly) && drive->Media->BlockSize == 2048) {
+        bool is_optical = is_efi_handle_optical(handles[i]) ||
+                          (drive->Media->ReadOnly && drive->Media->BlockSize == 2048);
+
+        if (is_optical) {
             block->index = optical_indices++;
             block->is_optical = true;
         } else {
@@ -824,7 +803,6 @@ fail:
         }
     }
 
-    find_unique_sectors();
     find_part_handles(handles, handle_count);
 
     pmm_free(handles, handles_size);
diff --git a/common/lib/part.h b/common/lib/part.h
index f09a2935..3ae86044 100644
--- a/common/lib/part.h
+++ b/common/lib/part.h
@@ -7,7 +7,6 @@
 #include <lib/guid.h>
 #if defined (UEFI)
 #  include <efi.h>
-#  include <crypt/blake2b.h>
 #endif
 
 #define NO_PARTITION  (-1)
@@ -24,9 +23,6 @@ struct volume {
 
     // PXE
     EFI_PXE_BASE_CODE_PROTOCOL *pxe_base_code;
-
-    bool unique_sector_valid;
-    uint8_t unique_sector_b2b[BLAKE2B_OUT_BYTES];
 #elif defined (BIOS)
     int drive;
 #endif
tab: 248 wrap: offon