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);
