disk: Misc bug fixes and improvements

This commit is contained in:
mintsuki 2021-06-12 13:13:19 +02:00
parent 662b5b7624
commit eb83d013ca
7 changed files with 100 additions and 85 deletions

View File

@ -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++;

View File

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

View File

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

View File

@ -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; \
\

View File

@ -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

View File

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

View File

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