:: commit 3e4b4a6b9b732ea0d8660a85bd126b7a7c7f6d2c

mintsuki <mintsuki@protonmail.com> — 2021-03-03 19:53

parents: 0ec053710c

disk: Move caching code to part.c from disk.c

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 <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
 #include <lib/part.h>
 
 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 <lib/print.h>
 #include <mm/pmm.h>
 
-#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;
+
+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 (!dap) {
+    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;
-
-    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;
-    }
+    memcpy(buf, xfer_buf, count * volume->sector_size);
 
-    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 <mm/pmm.h>
 #include <fs/file.h>
 
-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);
tab: 248 wrap: offon