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 #endif #include -#include #include #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);