:: commit 225a7c238d3cd9377c4a4d0618392b0cc0248002

mintsuki <mintsuki@protonmail.com> — 2020-03-14 23:12

parents: 1ce2a8d3ab

echfs: Add open and read functions

diff --git a/src/fs/echfs.c b/src/fs/echfs.c
index 20c1491f..95758a09 100644
--- a/src/fs/echfs.c
+++ b/src/fs/echfs.c
@@ -12,70 +12,86 @@ struct echfs_identity_table {
     uint64_t block_size;
 } __attribute__((packed));
 
-struct echfs_dir_entry {
-    uint64_t parent_id;
-    uint8_t type;
-    char name[201];
-    uint64_t atime;
-    uint64_t mtime;
-    uint16_t perms;
-    uint16_t owner;
-    uint16_t group;
-    uint64_t ctime;
-    uint64_t payload;
-    uint64_t size;
-} __attribute__((packed));
-
 #define ROOT_DIR_ID  (~((uint64_t)0))
 #define END_OF_CHAIN (~((uint64_t)0))
 #define FILE_TYPE    0
 
-int load_echfs_file(int disk, int partition, void *buffer, const char *filename) {
-    struct mbr_part mbr_part;
-    mbr_get_part(&mbr_part, disk, partition);
+#define CACHE_ADDR   ((uint8_t *)(0x1000000))
+
+static int cache_block(struct echfs_file_handle *file, uint64_t block) {
+    // Load the file.
+    uint64_t block_val = file->dir_entry.payload;
+    for (uint64_t i = 0; i < block; i++) {
+        if (block_val == END_OF_CHAIN)
+            return -1;
+
+        // Read the next block.
+        read_partition(file->disk, &file->mbr_part, &block_val, file->alloc_table_offset + block_val * sizeof(uint64_t),
+sizeof(uint64_t));
+    }
+
+    if (block_val == END_OF_CHAIN)
+        return -1;
+
+    return read_partition(file->disk, &file->mbr_part, CACHE_ADDR, block_val * file->block_size, file->block_size);
+}
+
+int echfs_read(struct echfs_file_handle *file, void *buf, uint64_t loc, uint64_t count) {
+    for (uint64_t progress = 0; progress < count;) {
+        /* cache the block */
+        uint64_t block = (loc + progress) / file->block_size;
+
+        int ret = cache_block(file, block);
+        if (ret)
+            return ret;
+
+        uint64_t chunk = count - progress;
+        uint64_t offset = (loc + progress) % file->block_size;
+        if (chunk > file->block_size - offset)
+            chunk = file->block_size - offset;
+
+        memcpy(buf + progress, &CACHE_ADDR[offset], chunk);
+        progress += chunk;
+    }
+
+    return 0;
+}
+
+int echfs_open(struct echfs_file_handle *ret, int disk, int partition, const char *filename) {
+    ret->disk = disk;
+
+    mbr_get_part(&ret->mbr_part, disk, partition);
 
     struct echfs_identity_table id_table;
-    read_partition(disk, &mbr_part, &id_table, 0, sizeof(struct echfs_identity_table));
+    read_partition(disk, &ret->mbr_part, &id_table, 0, sizeof(struct echfs_identity_table));
 
     if (strncmp(id_table.signature, "_ECH_FS_", 8)) {
         print("echfs: signature invalid\n", filename);
         return -1;
     }
 
-    const uint64_t block_size         = id_table.block_size;
-    const uint64_t block_count        = id_table.block_count;
-    const uint64_t dir_length         = id_table.dir_length * block_size;
-    const uint64_t alloc_table_size   = DIV_ROUNDUP(block_count * sizeof(uint64_t), block_size) * block_size;
-    const uint64_t alloc_table_offset = 16 * block_size;
-    const uint64_t dir_offset         = alloc_table_offset + alloc_table_size;
+    ret->block_size         = id_table.block_size;
+    ret->block_count        = id_table.block_count;
+    ret->dir_length         = id_table.dir_length * ret->block_size;
+    ret->alloc_table_size   = DIV_ROUNDUP(ret->block_count * sizeof(uint64_t), ret->block_size) * ret->block_size;
+    ret->alloc_table_offset = 16 * ret->block_size;
+    ret->dir_offset         = ret->alloc_table_offset + ret->alloc_table_size;
 
     // Find the file in the root dir.
-    struct echfs_dir_entry entry;
-    for (uint64_t i = 0; i < dir_length; i += sizeof(struct echfs_dir_entry)) {
-        read_partition(disk, &mbr_part, &entry, i + dir_offset, sizeof(struct echfs_dir_entry));
+    for (uint64_t i = 0; i < ret->dir_length; i += sizeof(struct echfs_dir_entry)) {
+        read_partition(disk, &ret->mbr_part, &ret->dir_entry, i + ret->dir_offset, sizeof(struct echfs_dir_entry));
 
-        if (!entry.parent_id) {
+        if (!ret->dir_entry.parent_id) {
             break;
         }
 
-        if (!strcmp(filename, entry.name) && entry.parent_id == ROOT_DIR_ID && entry.type == FILE_TYPE) {
-            goto found;
+        if (!strcmp(filename, ret->dir_entry.name) &&
+            ret->dir_entry.parent_id == ROOT_DIR_ID &&
+            ret->dir_entry.type == FILE_TYPE) {
+            return 0;
         }
     }
 
     print("echfs: file %s not found\n", filename);
     return -1;
-
-found:;
-    // Load the file.
-    for (uint64_t i = entry.payload; i != END_OF_CHAIN;) {
-        // Read block.
-        read_partition(disk, &mbr_part, buffer, i * block_size, block_size);
-        buffer += block_size;
-
-        // Read the next block.
-        read_partition(disk, &mbr_part, &i, alloc_table_offset + i * sizeof(uint64_t), sizeof(uint64_t));
-    }
-
-    return 0;
 }
diff --git a/src/fs/echfs.h b/src/fs/echfs.h
index 7323e470..369212de 100644
--- a/src/fs/echfs.h
+++ b/src/fs/echfs.h
@@ -1,6 +1,36 @@
 #ifndef __FS__ECHFS_H__
 #define __FS__ECHFS_H__
 
-int load_echfs_file(int disk, int partition, void *buffer, const char *filename);
+#include <stdint.h>
+#include <lib/mbr.h>
+
+struct echfs_dir_entry {
+    uint64_t parent_id;
+    uint8_t type;
+    char name[201];
+    uint64_t atime;
+    uint64_t mtime;
+    uint16_t perms;
+    uint16_t owner;
+    uint16_t group;
+    uint64_t ctime;
+    uint64_t payload;
+    uint64_t size;
+} __attribute__((packed));
+
+struct echfs_file_handle {
+    int disk;
+    struct mbr_part mbr_part;
+    uint64_t block_size;
+    uint64_t block_count;
+    uint64_t dir_length;
+    uint64_t alloc_table_size;
+    uint64_t alloc_table_offset;
+    uint64_t dir_offset;
+    struct echfs_dir_entry dir_entry;
+};
+
+int echfs_open(struct echfs_file_handle *ret, int disk, int partition, const char *filename);
+int echfs_read(struct echfs_file_handle *file, void *buf, uint64_t loc, uint64_t count);
 
 #endif
diff --git a/src/main.c b/src/main.c
index e83c90d0..bcb4eb4d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -21,6 +21,8 @@ extern symbol bss_end;
 static int config_loaded = 0;
 
 void main(int boot_drive) {
+    struct echfs_file_handle f;
+
     // Zero out .bss section
     for (uint8_t *p = bss_begin; p < bss_end; p++)
         *p = 0;
@@ -43,7 +45,8 @@ void main(int boot_drive) {
         } else {
             print("   Found!\n");
             if (!config_loaded) {
-                if (!load_echfs_file(boot_drive, i, (void *)0x100000, CONFIG_NAME)) {
+                if (!echfs_open(&f, boot_drive, i, CONFIG_NAME)) {
+                    echfs_read(&f, (void *)0x100000, 0, f.dir_entry.size);
                     config_loaded = 1;
                     print("   Config file found and loaded!\n");
                 }
@@ -77,7 +80,8 @@ void main(int boot_drive) {
         }
     }
 
-    load_echfs_file(drive, part, (void *)0x100000, path);
+    echfs_open(&f, drive, part, path);
+    echfs_read(&f, (void *)0x100000, 0, f.dir_entry.size);
 
     // Boot the kernel.
     asm volatile (
tab: 248 wrap: offon