:: commit eb83d013ca7b3570129d86a4a6e31b9b7c1d33ae

mintsuki <mintsuki@protonmail.com> — 2021-06-12 11:13

parents: 662b5b7624

disk: Misc bug fixes and improvements

diff --git a/stage23/drivers/disk.s2.c b/stage23/drivers/disk.s2.c
index 20598f32..da285f41 100644
--- a/stage23/drivers/disk.s2.c
+++ b/stage23/drivers/disk.s2.c
@@ -8,7 +8,6 @@
 #  include <efi.h>
 #endif
 #include <lib/blib.h>
-#include <lib/print.h>
 #include <mm/pmm.h>
 
 #if defined(bios)
@@ -78,14 +77,7 @@ bool disk_read_sectors(struct volume *volume, void *buf, uint64_t block, size_t
 void disk_create_index(void) {
     size_t volume_count = 0;
 
-    printv("Detected volumes:\n");
-
-    for (uint8_t drive = 0x80; ; drive++) {
-        if (drive == 0x90)
-            drive = 0xe0;
-        else if (drive == 0xf0)
-            break;
-
+    for (uint8_t drive = 0x80; drive < 0xf0; drive++) {
         struct rm_regs r = {0};
         struct bios_drive_params drive_params;
 
@@ -111,10 +103,12 @@ void disk_create_index(void) {
         block.first_sect = 0;
         block.sect_count = drive_params.lba_count;
 
-        // The medium could not be present (e.g.: CD-ROMs)
-        // Do a test run to see if we can actually read it
-        if (!disk_read_sectors(&block, NULL, 0, 1)) {
-            continue;
+        if (drive_params.info_flags & (1 << 2)) {
+            // The medium could not be present (e.g.: CD-ROMs)
+            // Do a test run to see if we can actually read it
+            if (!disk_read_sectors(&block, NULL, 0, 1)) {
+                continue;
+            }
         }
 
         volume_count++;
@@ -134,12 +128,9 @@ void disk_create_index(void) {
 
     volume_index = ext_mem_alloc(sizeof(struct volume) * volume_count);
 
-    for (uint8_t drive = 0x80; ; drive++) {
-        if (drive == 0x90)
-            drive = 0xe0;
-        else if (drive == 0xf0)
-            break;
+    int optical_indices = 1, hdd_indices = 1;
 
+    for (uint8_t drive = 0x80; drive < 0xf0; drive++) {
         struct rm_regs r = {0};
         struct bios_drive_params drive_params;
 
@@ -161,24 +152,28 @@ void disk_create_index(void) {
         struct volume *block = ext_mem_alloc(sizeof(struct volume));
 
         block->drive = drive;
-        block->partition = -1;
+        block->partition = 0;
         block->sector_size = drive_params.bytes_per_sect;
         block->first_sect = 0;
         block->sect_count = drive_params.lba_count;
         block->max_partition = -1;
 
-        // The medium could not be present (e.g.: CD-ROMs)
-        // Do a test run to see if we can actually read it
-        if (!disk_read_sectors(block, NULL, 0, 1)) {
-            continue;
+        if (drive_params.info_flags & (1 << 2)) {
+            // The medium could not be present (e.g.: CD-ROMs)
+            // Do a test run to see if we can actually read it
+            if (!disk_read_sectors(block, NULL, 0, 1)) {
+                continue;
+            }
+            block->index = optical_indices++;
+            block->is_optical = true;
+        } else {
+            block->index = hdd_indices++;
         }
 
         if (gpt_get_guid(&block->guid, block)) {
             block->guid_valid = true;
         }
 
-        printv("    %x\n", block->drive);
-
         volume_index[volume_index_i++] = block;
 
         for (int part = 0; ; part++) {
@@ -190,8 +185,6 @@ void disk_create_index(void) {
             if (ret == NO_PARTITION)
                 continue;
 
-            printv("    %x:%u\n", block->drive, part);
-
             volume_index[volume_index_i++] = p;
 
             block->max_partition++;
@@ -234,7 +227,7 @@ struct volume *disk_volume_from_efi_handle(EFI_HANDLE *efi_handle) {
     if (status) {
         // Really hacky support for CDs because they are read-only
         for (size_t i = 0; i < volume_index_i; i++) {
-            if (volume_index[i]->drive == 0xe0)
+            if (volume_index[i]->is_optical)
                 return volume_index[i];
         }
 
@@ -343,9 +336,7 @@ void disk_create_index(void) {
 
     volume_index = ext_mem_alloc(sizeof(struct volume) * volume_count);
 
-    printv("Detected volumes:\n");
-
-    size_t drives_counter = 0x80, optical_counter = 0xe0;
+    int optical_indices = 1, hdd_indices = 1;
 
     for (size_t i = 0; i < handles_size / sizeof(EFI_HANDLE); i++) {
         EFI_GUID disk_io_guid = DISK_IO_PROTOCOL;
@@ -373,12 +364,15 @@ void disk_create_index(void) {
 
         struct volume *block = ext_mem_alloc(sizeof(struct volume));
 
-        if (status)
-            block->drive = optical_counter++;
-        else
-            block->drive = drives_counter++;
+        if (status) {
+            block->index = optical_indices++;
+            block->is_optical = true;
+        } else {
+            block->index = hdd_indices++;
+        }
+
         block->efi_handle = handles[i];
-        block->partition = -1;
+        block->partition = 0;
         block->sector_size = drive->Media->BlockSize;
         block->first_sect = 0;
         block->sect_count = drive->Media->LastBlock + 1;
@@ -388,8 +382,6 @@ void disk_create_index(void) {
             block->guid_valid = true;
         }
 
-        printv("    %x\n", block->drive);
-
         volume_index[volume_index_i++] = block;
 
         for (int part = 0; ; part++) {
@@ -401,8 +393,6 @@ void disk_create_index(void) {
             if (ret == NO_PARTITION)
                 continue;
 
-            printv("    %x:%u\n", block->drive, part);
-
             volume_index[volume_index_i++] = p;
 
             block->max_partition++;
diff --git a/stage23/entry.s2.c b/stage23/entry.s2.c
index 5efa5760..86e34a6c 100644
--- a/stage23/entry.s2.c
+++ b/stage23/entry.s2.c
@@ -85,7 +85,7 @@ void entry(uint8_t boot_drive, int boot_from) {
     disk_create_index();
 
     if (boot_from == BOOTED_FROM_HDD || boot_from == BOOTED_FROM_CD) {
-        boot_volume = volume_get_by_coord(boot_drive, -1);
+        boot_volume = volume_get_by_bios_drive(boot_drive);
     } else if (boot_from == BOOTED_FROM_PXE) {
         pxe_init();
         boot_volume = pxe_bind_volume();
diff --git a/stage23/entry.s3.c b/stage23/entry.s3.c
index 5b25ce06..e79fbbc9 100644
--- a/stage23/entry.s3.c
+++ b/stage23/entry.s3.c
@@ -96,7 +96,7 @@ void stage3_common(void) {
     verbose = verbose_str != NULL && strcmp(verbose_str, "yes") == 0;
 
     if (verbose) {
-        print("Boot drive: %x\n", boot_volume->drive);
+        print("Boot drive: %x\n", boot_volume->index);
         print("Boot partition: %d\n", boot_volume->partition);
     }
 
diff --git a/stage23/lib/part.h b/stage23/lib/part.h
index 28f8fd46..e34ff5d4 100644
--- a/stage23/lib/part.h
+++ b/stage23/lib/part.h
@@ -16,11 +16,15 @@
 struct volume {
 #if defined (uefi)
     EFI_HANDLE efi_handle;
+#elif defined (bios)
+    int drive;
 #endif
 
+    int index;
+
+    bool is_optical;
     bool pxe;
 
-    int drive;
     int partition;
     int sector_size;
     struct volume *backing_dev;
@@ -48,7 +52,10 @@ bool gpt_get_guid(struct guid *guid, struct volume *volume);
 int part_get(struct volume *part, struct volume *volume, int partition);
 
 struct volume *volume_get_by_guid(struct guid *guid);
-struct volume *volume_get_by_coord(int drive, int partition);
+struct volume *volume_get_by_coord(bool optical, int drive, int partition);
+#if defined (bios)
+struct volume *volume_get_by_bios_drive(int drive);
+#endif
 
 bool volume_read(struct volume *part, void *buffer, uint64_t loc, uint64_t count);
 
@@ -65,11 +72,12 @@ bool volume_read(struct volume *part, void *buffer, uint64_t loc, uint64_t count
         } \
  \
         int _PART_CNT = -1; \
-        for (size_t _PARTNO = -1; ; _PARTNO++) { \
+        for (size_t _PARTNO = 0; ; _PARTNO++) { \
             if (_PART_CNT > _VOLUME->max_partition) \
                 break; \
  \
-            struct volume *_PART = volume_get_by_coord(_VOLUME->drive, _PARTNO); \
+            struct volume *_PART = volume_get_by_coord(_VOLUME->is_optical, \
+                                                       _VOLUME->index, _PARTNO); \
             if (_PART == NULL) \
                 continue; \
  \
diff --git a/stage23/lib/part.s2.c b/stage23/lib/part.s2.c
index d2850b24..1e555bf9 100644
--- a/stage23/lib/part.s2.c
+++ b/stage23/lib/part.s2.c
@@ -152,9 +152,12 @@ static int gpt_get_part(struct volume *ret, struct volume *volume, int partition
 
 #if defined (uefi)
     ret->efi_handle  = volume->efi_handle;
-#endif
+#elif defined (bios)
     ret->drive       = volume->drive;
-    ret->partition   = partition;
+#endif
+    ret->index       = volume->index;
+    ret->is_optical  = volume->is_optical;
+    ret->partition   = partition + 1;
     ret->sector_size = sector_size;
     ret->first_sect  = entry.starting_lba;
     ret->sect_count  = (entry.ending_lba - entry.starting_lba) + 1;
@@ -209,9 +212,12 @@ static int mbr_get_logical_part(struct volume *ret, struct volume *extended_part
 
 #if defined (uefi)
     ret->efi_handle  = extended_part->efi_handle;
-#endif
+#elif defined (bios)
     ret->drive       = extended_part->drive;
-    ret->partition   = partition + 4;
+#endif
+    ret->index       = extended_part->index;
+    ret->is_optical  = extended_part->is_optical;
+    ret->partition   = partition + 4 + 1;
     ret->sector_size = extended_part->sector_size;
     ret->first_sect  = extended_part->first_sect + ebr_sector + entry.first_sect;
     ret->sect_count  = entry.sect_count;
@@ -284,9 +290,12 @@ static int mbr_get_part(struct volume *ret, struct volume *volume, int partition
 
 #if defined (uefi)
             extended_part.efi_handle  = volume->efi_handle;
-#endif
+#elif defined (bios)
             extended_part.drive       = volume->drive;
-            extended_part.partition   = i;
+#endif
+            extended_part.index       = volume->index;
+            extended_part.is_optical  = volume->is_optical;
+            extended_part.partition   = i + 1;
             extended_part.sector_size = volume->sector_size;
             extended_part.first_sect  = entry.first_sect;
             extended_part.sect_count  = entry.sect_count;
@@ -307,9 +316,12 @@ static int mbr_get_part(struct volume *ret, struct volume *volume, int partition
 
 #if defined (uefi)
     ret->efi_handle  = volume->efi_handle;
-#endif
+#elif defined (bios)
     ret->drive       = volume->drive;
-    ret->partition   = partition;
+#endif
+    ret->index       = volume->index;
+    ret->is_optical  = volume->is_optical;
+    ret->partition   = partition + 1;
     ret->sector_size = volume->sector_size;
     ret->first_sect  = entry.first_sect;
     ret->sect_count  = entry.sect_count;
@@ -360,9 +372,10 @@ struct volume *volume_get_by_guid(struct guid *guid) {
     return NULL;
 }
 
-struct volume *volume_get_by_coord(int drive, int partition) {
+struct volume *volume_get_by_coord(bool optical, int drive, int partition) {
     for (size_t i = 0; i < volume_index_i; i++) {
-        if (volume_index[i]->drive == drive
+        if (volume_index[i]->index == drive
+         && volume_index[i]->is_optical == optical
          && volume_index[i]->partition == partition) {
             return volume_index[i];
         }
@@ -370,3 +383,15 @@ struct volume *volume_get_by_coord(int drive, int partition) {
 
     return NULL;
 }
+
+#if defined (bios)
+struct volume *volume_get_by_bios_drive(int drive) {
+    for (size_t i = 0; i < volume_index_i; i++) {
+        if (volume_index[i]->drive == drive) {
+            return volume_index[i];
+        }
+    }
+
+    return NULL;
+}
+#endif
diff --git a/stage23/lib/uri.c b/stage23/lib/uri.c
index c8f7c423..822b3180 100644
--- a/stage23/lib/uri.c
+++ b/stage23/lib/uri.c
@@ -55,7 +55,7 @@ bool uri_resolve(char *uri, char **resource, char **root, char **path) {
 }
 
 static bool parse_bios_partition(char *loc, int *drive, int *partition) {
-    int64_t val;
+    uint64_t val;
 
     for (size_t i = 0; ; i++) {
         if (loc[i] == 0)
@@ -67,8 +67,8 @@ static bool parse_bios_partition(char *loc, int *drive, int *partition) {
                 panic("Drive number cannot be omitted for hdd:// and odd://");
             } else {
                 val = strtoui(loc, NULL, 10);
-                if (val < 1 || val > 16) {
-                    panic("Drive number outside range 1-16");
+                if (val < 1 || val > 256) {
+                    panic("Drive number outside range 1-256");
                 }
                 *drive = val;
             }
@@ -77,16 +77,11 @@ static bool parse_bios_partition(char *loc, int *drive, int *partition) {
         }
     }
 
-    if (*loc == 0) {
-        *partition = -1;
-        return true;
-    }
-
     val = strtoui(loc, NULL, 10);
-    if (val < 1 || val > 256) {
-        panic("Partition number outside range 1-256");
+    if (val > 256) {
+        panic("Partition number outside range 0-256");
     }
-    *partition = val - 1;
+    *partition = val;
 
     return true;
 }
@@ -97,9 +92,7 @@ static bool uri_hdd_dispatch(struct file_handle *fd, char *loc, char *path) {
     if (!parse_bios_partition(loc, &drive, &partition))
         return false;
 
-    drive = (drive - 1) + 0x80;
-
-    struct volume *volume = volume_get_by_coord(drive, partition);
+    struct volume *volume = volume_get_by_coord(false, drive, partition);
 
     if (volume == NULL)
         return false;
@@ -116,9 +109,7 @@ static bool uri_odd_dispatch(struct file_handle *fd, char *loc, char *path) {
     if (!parse_bios_partition(loc, &drive, &partition))
         return false;
 
-    drive = (drive - 1) + 0xe0;
-
-    struct volume *volume = volume_get_by_coord(drive, partition);
+    struct volume *volume = volume_get_by_coord(true, drive, partition);
 
     if (volume == NULL)
         return false;
@@ -184,15 +175,16 @@ static bool uri_boot_dispatch(struct file_handle *fd, char *s_part, char *path)
 
     if (s_part[0] != '\0') {
         uint64_t val = strtoui(s_part, NULL, 10);
-        if (val < 1 || val > 256) {
-            panic("Partition number outside range 1-256");
+        if (val > 256) {
+            panic("Partition number outside range 0-256");
         }
-        partition = val - 1;
+        partition = val;
     } else {
         partition = boot_volume->partition;
     }
 
-    struct volume *volume = volume_get_by_coord(boot_volume->drive, partition);
+    struct volume *volume = volume_get_by_coord(boot_volume->is_optical,
+                                                boot_volume->index, partition);
     if (volume == NULL)
         return false;
 
diff --git a/stage23/protos/chainload.c b/stage23/protos/chainload.c
index 036eea95..33ece904 100644
--- a/stage23/protos/chainload.c
+++ b/stage23/protos/chainload.c
@@ -75,13 +75,13 @@ void chainload(char *config) {
     int part; {
         char *part_config = config_get_value(config, 0, "PARTITION");
         if (part_config == NULL) {
-            part = -1;
+            part = 0;
         } else {
             val = strtoui(part_config, NULL, 10);
-            if (val < 1 || val > 256) {
-                panic("BIOS partition number outside range 1-256");
+            if (val > 256) {
+                panic("BIOS partition number outside range 0-256");
             }
-            part = val - 1;
+            part = val;
         }
     }
     int drive; {
@@ -90,16 +90,16 @@ void chainload(char *config) {
             panic("DRIVE not specified");
         }
         val = strtoui(drive_config, NULL, 10);
-        if (val < 1 || val > 16) {
-            panic("BIOS drive number outside range 1-16");
+        if (val < 1 || val > 256) {
+            panic("BIOS drive number outside range 1-256");
         }
-        drive = (val - 1) + 0x80;
+        drive = val;
     }
 
     int rows, cols;
     init_vga_textmode(&rows, &cols, false);
 
-    struct volume *p = volume_get_by_coord(drive, part);
+    struct volume *p = volume_get_by_coord(false, drive, part);
 
     volume_read(p, (void *)0x7c00, 0, 512);
 
tab: 248 wrap: offon