From 3e4b4a6b9b732ea0d8660a85bd126b7a7c7f6d2c Mon Sep 17 00:00:00 2001 From: mintsuki Date: Wed, 3 Mar 2021 20:53:26 +0100 Subject: [PATCH] disk: Move caching code to part.c from disk.c --- stage23/drivers/disk.h | 5 +- stage23/drivers/disk.s2.c | 84 ++++++++------------------------- stage23/entry.s2.c | 2 +- stage23/entry.s3.c | 2 +- stage23/fs/echfs.s2.c | 2 +- stage23/fs/fat32.s2.c | 11 +---- stage23/lib/part.h | 5 +- stage23/lib/part.s2.c | 95 +++++++++++++++++++++++--------------- stage23/lib/uri.c | 6 +-- stage23/protos/chainload.c | 2 +- 10 files changed, 92 insertions(+), 122 deletions(-) diff --git a/stage23/drivers/disk.h b/stage23/drivers/disk.h index c5a6b1fd..3a883d31 100644 --- a/stage23/drivers/disk.h +++ b/stage23/drivers/disk.h @@ -2,6 +2,8 @@ #define __DRIVERS__DISK_H__ #include +#include +#include #include struct bios_drive_params { @@ -15,8 +17,7 @@ struct bios_drive_params { uint32_t edd; } __attribute__((packed)); -int disk_get_sector_size(int drive); -int disk_read(int drive, void *buffer, uint64_t loc, uint64_t count); size_t disk_create_index(struct volume **ret); +bool disk_read_sectors(struct volume *volume, void *buf, uint64_t block, size_t count); #endif diff --git a/stage23/drivers/disk.s2.c b/stage23/drivers/disk.s2.c index 08806c71..54d8a580 100644 --- a/stage23/drivers/disk.s2.c +++ b/stage23/drivers/disk.s2.c @@ -9,14 +9,6 @@ #include #include -#define BLOCK_SIZE_IN_SECTORS 16 -#define BLOCK_SIZE (sector_size * BLOCK_SIZE_IN_SECTORS) - -#define CACHE_INVALID (~((uint64_t)0)) - -static uint8_t *cache = NULL; -static uint64_t cached_block = CACHE_INVALID; - struct dap { uint16_t size; uint16_t count; @@ -27,26 +19,30 @@ struct dap { static struct dap *dap = NULL; -static int cache_block(int drive, uint64_t block, int sector_size) { - if (block == cached_block) - return 0; +#define XFER_BUF_SIZE 16384 +static void *xfer_buf = NULL; - if (!dap) { +bool disk_read_sectors(struct volume *volume, void *buf, uint64_t block, size_t count) { + if (count * volume->sector_size > XFER_BUF_SIZE) + panic("XFER"); + + if (xfer_buf == NULL) + xfer_buf = conv_mem_alloc_aligned(XFER_BUF_SIZE, 16); + + if (dap == NULL) { dap = conv_mem_alloc(sizeof(struct dap)); dap->size = 16; - dap->count = BLOCK_SIZE_IN_SECTORS; } - if (!cache) - cache = conv_mem_alloc_aligned(BLOCK_SIZE, 16); + dap->count = count; - dap->segment = rm_seg(cache); - dap->offset = rm_off(cache); - dap->lba = block * BLOCK_SIZE_IN_SECTORS; + dap->segment = rm_seg(xfer_buf); + dap->offset = rm_off(xfer_buf); + dap->lba = block; struct rm_regs r = {0}; r.eax = 0x4200; - r.edx = drive; + r.edx = volume->drive; r.esi = (uint32_t)rm_off(dap); r.ds = rm_seg(dap); @@ -54,56 +50,12 @@ static int cache_block(int drive, uint64_t block, int sector_size) { if (r.eflags & EFLAGS_CF) { int ah = (r.eax >> 8) & 0xff; - panic("Disk error %x. Drive %x, LBA %x.", ah, drive, dap->lba); + panic("Disk error %x. Drive %x, LBA %x.", ah, volume->drive, dap->lba); } - cached_block = block; + memcpy(buf, xfer_buf, count * volume->sector_size); - return 0; -} - -int disk_get_sector_size(int drive) { - struct rm_regs r = {0}; - struct bios_drive_params drive_params; - - r.eax = 0x4800; - r.edx = drive; - r.ds = rm_seg(&drive_params); - r.esi = rm_off(&drive_params); - - drive_params.buf_size = sizeof(struct bios_drive_params); - - rm_int(0x13, &r, &r); - - if (r.eflags & EFLAGS_CF) { - int ah = (r.eax >> 8) & 0xff; - panic("Disk error %x. Drive %x.", ah, drive); - } - - return drive_params.bytes_per_sect; -} - -int disk_read(int drive, void *buffer, uint64_t loc, uint64_t count) { - int sector_size = disk_get_sector_size(drive); - - uint64_t progress = 0; - while (progress < count) { - uint64_t block = (loc + progress) / BLOCK_SIZE; - - int ret; - if ((ret = cache_block(drive, block, sector_size))) - return ret; - - uint64_t chunk = count - progress; - uint64_t offset = (loc + progress) % BLOCK_SIZE; - if (chunk > BLOCK_SIZE - offset) - chunk = BLOCK_SIZE - offset; - - memcpy(buffer + progress, &cache[offset], chunk); - progress += chunk; - } - - return 0; + return true; } size_t disk_create_index(struct volume **ret) { diff --git a/stage23/entry.s2.c b/stage23/entry.s2.c index a78ce59e..6fba5037 100644 --- a/stage23/entry.s2.c +++ b/stage23/entry.s2.c @@ -84,7 +84,7 @@ void entry(uint8_t _boot_drive, int boot_from) { switch (boot_from) { case BOOT_FROM_HDD: case BOOT_FROM_CD: { - struct volume boot_volume; + struct volume boot_volume = {0}; volume_get_by_coord(&boot_volume, boot_drive, -1); struct volume part = boot_volume; for (int i = 0; ; i++) { diff --git a/stage23/entry.s3.c b/stage23/entry.s3.c index 04816df8..8de693ff 100644 --- a/stage23/entry.s3.c +++ b/stage23/entry.s3.c @@ -46,7 +46,7 @@ void stage3_entry(int boot_from) { switch (boot_from) { case BOOT_FROM_HDD: case BOOT_FROM_CD: { - struct volume boot_volume; + struct volume boot_volume = {0}; volume_get_by_coord(&boot_volume, boot_drive, -1); struct volume part = boot_volume; for (int i = 0; ; i++) { diff --git a/stage23/fs/echfs.s2.c b/stage23/fs/echfs.s2.c index 89a838de..4e1428b6 100644 --- a/stage23/fs/echfs.s2.c +++ b/stage23/fs/echfs.s2.c @@ -22,7 +22,7 @@ struct echfs_identity_table { #define FILE_TYPE 0 #define DIR_TYPE 1 -static int read_block(struct echfs_file_handle *file, void *buf, uint64_t block, uint64_t offset, uint64_t count) { +static bool read_block(struct echfs_file_handle *file, void *buf, uint64_t block, uint64_t offset, uint64_t count) { return volume_read(&file->part, buf, (file->alloc_map[block] * file->block_size) + offset, count); } diff --git a/stage23/fs/fat32.s2.c b/stage23/fs/fat32.s2.c index a9edf310..0433486a 100644 --- a/stage23/fs/fat32.s2.c +++ b/stage23/fs/fat32.s2.c @@ -98,11 +98,7 @@ static int fat32_read_cluster_from_map(struct fat32_context* context, uint32_t c const uint32_t offset = cluster % (FAT32_SECTOR_SIZE / 4); uint32_t clusters[FAT32_SECTOR_SIZE / sizeof(uint32_t)]; - int r = volume_read(&context->part, &clusters[0], (context->fat_start_lba + sector) * FAT32_SECTOR_SIZE, sizeof(clusters)); - - if (r) { - return r; - } + volume_read(&context->part, &clusters[0], (context->fat_start_lba + sector) * FAT32_SECTOR_SIZE, sizeof(clusters)); *out = clusters[offset] & 0x0FFFFFFF; return 0; @@ -143,10 +139,7 @@ static bool read_cluster_chain(struct fat32_context *context, chunk = block_size - offset; uint64_t base = (context->data_start_lba + (cluster_chain[block] - 2)) * block_size; - int r = volume_read(&context->part, buf + progress, base + offset, chunk); - - if (r) - return false; + volume_read(&context->part, buf + progress, base + offset, chunk); progress += chunk; } diff --git a/stage23/lib/part.h b/stage23/lib/part.h index 9243f51b..ddab7085 100644 --- a/stage23/lib/part.h +++ b/stage23/lib/part.h @@ -22,6 +22,9 @@ struct volume { drive_t drive; int partition; int sector_size; + int cache_status; + uint8_t *cache; + uint64_t cached_block; uint64_t first_sect; uint64_t sect_count; bool guid_valid; @@ -38,6 +41,6 @@ int part_get(struct volume *part, struct volume *volume, int partition); bool volume_get_by_guid(struct volume *part, struct guid *guid); bool volume_get_by_coord(struct volume *part, drive_t drive, int partition); -int volume_read(struct volume *part, void *buffer, uint64_t loc, uint64_t count); +bool volume_read(struct volume *part, void *buffer, uint64_t loc, uint64_t count); #endif diff --git a/stage23/lib/part.s2.c b/stage23/lib/part.s2.c index 17af8d3e..97f35db8 100644 --- a/stage23/lib/part.s2.c +++ b/stage23/lib/part.s2.c @@ -11,14 +11,55 @@ #include #include -size_t volume_get_sector_size(struct volume *volume) { -#if defined (bios) - return disk_get_sector_size(volume->drive); -#elif defined (uefi) - (void)volume; - return -1; -#endif +#define BLOCK_SIZE_IN_SECTORS 8 +enum { + CACHE_NOT_READY = 0, + CACHE_READY +}; + +static bool cache_block(struct volume *volume, uint64_t block) { + if (volume->cache_status == CACHE_READY && block == volume->cached_block) + return true; + + volume->cache_status = CACHE_NOT_READY; + + if (volume->cache == NULL) + volume->cache = + ext_mem_alloc_aligned(BLOCK_SIZE_IN_SECTORS * volume->sector_size, + 4096); + + if (!disk_read_sectors(volume, volume->cache, + volume->first_sect + block * BLOCK_SIZE_IN_SECTORS, + BLOCK_SIZE_IN_SECTORS)) + return false; + + volume->cache_status = CACHE_READY; + volume->cached_block = block; + + return true; +} + +bool volume_read(struct volume *volume, void *buffer, uint64_t loc, uint64_t count) { + uint64_t block_size = BLOCK_SIZE_IN_SECTORS * volume->sector_size; + + uint64_t progress = 0; + while (progress < count) { + uint64_t block = (loc + progress) / block_size; + + if (!cache_block(volume, block)) + return false; + + uint64_t chunk = count - progress; + uint64_t offset = (loc + progress) % block_size; + if (chunk > block_size - offset) + chunk = block_size - offset; + + memcpy(buffer + progress, &volume->cache[offset], chunk); + progress += chunk; + } + + return true; } struct gpt_table_header { @@ -61,7 +102,7 @@ struct gpt_entry { bool gpt_get_guid(struct guid *guid, struct volume *volume) { struct gpt_table_header header = {0}; - int sector_size = volume_get_sector_size(volume); + int sector_size = volume->sector_size; // read header, located after the first block volume_read(volume, &header, sector_size * 1, sizeof(header)); @@ -81,7 +122,7 @@ bool gpt_get_guid(struct guid *guid, struct volume *volume) { static int gpt_get_part(struct volume *ret, struct volume *volume, int partition) { struct gpt_table_header header = {0}; - int sector_size = volume_get_sector_size(volume); + int sector_size = volume->sector_size; // read header, located after the first block volume_read(volume, &header, sector_size * 1, sizeof(header)); @@ -144,10 +185,7 @@ static int mbr_get_logical_part(struct volume *ret, struct volume *extended_part for (int i = 0; i < partition; i++) { size_t entry_offset = ebr_sector * extended_part->sector_size + 0x1ce; - int r; - r = volume_read(extended_part, &entry, entry_offset, sizeof(struct mbr_entry)); - if (r) - return r; + volume_read(extended_part, &entry, entry_offset, sizeof(struct mbr_entry)); if (entry.type != 0x0f && entry.type != 0x05) return END_OF_TABLE; @@ -157,17 +195,14 @@ static int mbr_get_logical_part(struct volume *ret, struct volume *extended_part size_t entry_offset = ebr_sector * extended_part->sector_size + 0x1be; - int r; - r = volume_read(extended_part, &entry, entry_offset, sizeof(struct mbr_entry)); - if (r) - return r; + volume_read(extended_part, &entry, entry_offset, sizeof(struct mbr_entry)); if (entry.type == 0) return NO_PARTITION; ret->drive = extended_part->drive; ret->partition = partition + 4; - ret->sector_size = volume_get_sector_size(extended_part); + 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; @@ -197,18 +232,16 @@ static int mbr_get_part(struct volume *ret, struct volume *volume, int partition for (int i = 0; i < 4; i++) { size_t entry_offset = 0x1be + sizeof(struct mbr_entry) * i; - int r = volume_read(volume, &entry, entry_offset, sizeof(struct mbr_entry)); - if (r) - return r; + volume_read(volume, &entry, entry_offset, sizeof(struct mbr_entry)); if (entry.type != 0x0f) continue; - struct volume extended_part; + struct volume extended_part = {0}; extended_part.drive = volume->drive; extended_part.partition = i; - extended_part.sector_size = volume_get_sector_size(volume); + extended_part.sector_size = volume->sector_size; extended_part.first_sect = entry.first_sect; extended_part.sect_count = entry.sect_count; @@ -220,16 +253,14 @@ static int mbr_get_part(struct volume *ret, struct volume *volume, int partition size_t entry_offset = 0x1be + sizeof(struct mbr_entry) * partition; - int r = volume_read(volume, &entry, entry_offset, sizeof(struct mbr_entry)); - if (r) - return r; + volume_read(volume, &entry, entry_offset, sizeof(struct mbr_entry)); if (entry.type == 0) return NO_PARTITION; ret->drive = volume->drive; ret->partition = partition; - ret->sector_size = volume_get_sector_size(volume); + ret->sector_size = volume->sector_size; ret->first_sect = entry.first_sect; ret->sect_count = entry.sect_count; @@ -302,13 +333,3 @@ found: *part = volume_index[i]; return true; } - -int volume_read(struct volume *part, void *buffer, uint64_t loc, uint64_t count) { -#if defined (bios) - return disk_read(part->drive, buffer, - loc + (part->first_sect * part->sector_size), count); -#elif defined (uefi) - (void)part; (void)buffer; (void)loc; (void)count; - return -1; -#endif -} diff --git a/stage23/lib/uri.c b/stage23/lib/uri.c index d355556b..705de6dd 100644 --- a/stage23/lib/uri.c +++ b/stage23/lib/uri.c @@ -95,7 +95,7 @@ static bool parse_bios_partition(char *loc, uint8_t *drive, uint8_t *partition) static bool uri_bios_dispatch(struct file_handle *fd, char *loc, char *path) { uint8_t drive, partition; - struct volume volume; + struct volume volume = {0}; if (!parse_bios_partition(loc, &drive, &partition)) return false; @@ -114,7 +114,7 @@ static bool uri_guid_dispatch(struct file_handle *fd, char *guid_str, char *path if (!string_to_guid_be(&guid, guid_str)) return false; - struct volume part; + struct volume part = {0}; if (!volume_get_by_guid(&part, &guid)) { if (!string_to_guid_mixed(&guid, guid_str)) return false; @@ -174,7 +174,7 @@ static bool uri_boot_dispatch(struct file_handle *fd, char *s_part, char *path) panic("Boot partition information is unavailable."); } - struct volume part; + struct volume part = {0}; if (!volume_get_by_coord(&part, boot_drive, partition)) return false; diff --git a/stage23/protos/chainload.c b/stage23/protos/chainload.c index 73092258..e6e2f172 100644 --- a/stage23/protos/chainload.c +++ b/stage23/protos/chainload.c @@ -77,7 +77,7 @@ void chainload(char *config) { term_deinit(); - struct volume p; + struct volume p = {0}; volume_get_by_coord(&p, drive, part); volume_read(&p, (void *)0x7c00, 0, 512);