:: commit 8631da1c925085767fde2c32c8ed39e60a02c09c

Mintsuki <mintsuki@protonmail.com> — 2026-02-01 13:26

parents: f67649238b

drivers/disk: Re-add unique sector volume detection method

diff --git a/common/drivers/disk.s2.c b/common/drivers/disk.s2.c
index e61fc3de..90e2e8be 100644
--- a/common/drivers/disk.s2.c
+++ b/common/drivers/disk.s2.c
@@ -7,6 +7,7 @@
 #  include <lib/real.h>
 #elif defined (UEFI)
 #  include <efi.h>
+#  include <crypt/blake2b.h>
 #endif
 #include <lib/misc.h>
 #include <lib/print.h>
@@ -418,6 +419,23 @@ 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;
 
@@ -659,6 +677,23 @@ struct volume *disk_volume_from_efi_handle(EFI_HANDLE efi_handle) {
         return pxe_from_efi_handle(efi_handle);
     }
 
+    uint64_t bdev_size = ((uint64_t)block_io->Media->LastBlock + 1) * (uint64_t)block_io->Media->BlockSize;
+    if (bdev_size >= UNIQUE_SECTOR_POOL_SIZE) {
+        status = block_io->ReadBlocks(block_io, block_io->Media->MediaId,
+                                      0,
+                                      UNIQUE_SECTOR_POOL_SIZE,
+                                      unique_sector_pool);
+        if (status == 0) {
+            uint8_t b2b[BLAKE2B_OUT_BYTES];
+            blake2b(b2b, unique_sector_pool, UNIQUE_SECTOR_POOL_SIZE);
+
+            ret = volume_by_unique_sector(b2b);
+            if (ret != NULL) {
+                return ret;
+            }
+        }
+    }
+
     ret = volume_by_device_path(efi_handle);
     if (ret != NULL) {
         return ret;
@@ -677,6 +712,44 @@ struct volume *disk_volume_from_efi_handle(EFI_HANDLE efi_handle) {
     return NULL;
 }
 
+static void find_unique_sectors(void) {
+    EFI_STATUS status;
+
+    for (size_t i = 0; i < volume_index_i; i++) {
+        if ((volume_index[i]->first_sect * 512) % volume_index[i]->sector_size) {
+            continue;
+        }
+
+        size_t first_sect = (volume_index[i]->first_sect * 512) / volume_index[i]->sector_size;
+
+        if (volume_index[i]->sect_count * volume_index[i]->sector_size < UNIQUE_SECTOR_POOL_SIZE) {
+            continue;
+        }
+
+        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;
+        }
+
+        uint8_t b2b[BLAKE2B_OUT_BYTES];
+        blake2b(b2b, unique_sector_pool, UNIQUE_SECTOR_POOL_SIZE);
+
+        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;
+        }
+
+        collision->unique_sector_valid = false;
+    }
+}
+
 static void find_part_handles(EFI_HANDLE *handles, size_t handle_count) {
     for (size_t i = 0; i < handle_count; i++) {
         struct volume *vol = disk_volume_from_efi_handle(handles[i]);
@@ -690,6 +763,8 @@ 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;
@@ -803,6 +878,7 @@ 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 3ae86044..f09a2935 100644
--- a/common/lib/part.h
+++ b/common/lib/part.h
@@ -7,6 +7,7 @@
 #include <lib/guid.h>
 #if defined (UEFI)
 #  include <efi.h>
+#  include <crypt/blake2b.h>
 #endif
 
 #define NO_PARTITION  (-1)
@@ -23,6 +24,9 @@ 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