:: commit 85d615202527fc596a52f0564327cf6b223fa602

streaksu <assemblyislaw@gmail.com> — 2020-01-22 00:55

parents: 9339c093fe

Further work in echfs and partition management

diff --git a/src/drivers/disk.c b/src/drivers/disk.c
index 8558d5e6..bc53728d 100644
--- a/src/drivers/disk.c
+++ b/src/drivers/disk.c
@@ -4,6 +4,7 @@
 #include <drivers/disk.h>
 #include <lib/real.h>
 #include <lib/print.h>
+#include <lib/mbr.h>
 
 #define SECTOR_SIZE 512
 
@@ -77,3 +78,13 @@ int read(int drive, void *buffer, uint64_t loc, uint64_t count) {
 
     return 0;
 }
+
+int read_partition(int drive, int partition, void *buffer, uint64_t loc, uint64_t count) {
+    struct mbr_part part;
+    int ret = mbr_get_part(&part, drive, partition);
+    if (ret) {
+        return ret;
+    }
+
+    return read(drive, buffer, loc + (part.first_sect * 512), count);
+}
diff --git a/src/drivers/disk.h b/src/drivers/disk.h
index 635c2714..4bce1fb1 100644
--- a/src/drivers/disk.h
+++ b/src/drivers/disk.h
@@ -6,5 +6,6 @@
 
 int read_sector(int drive, void *buffer, uint64_t lba, uint64_t count);
 int read(int drive, void *buffer, uint64_t loc, uint64_t count);
+int read_partition(int drive, int partition, void *buffer, uint64_t loc, uint64_t count);
 
 #endif
diff --git a/src/fs/echfs.c b/src/fs/echfs.c
new file mode 100644
index 00000000..d685f90d
--- /dev/null
+++ b/src/fs/echfs.c
@@ -0,0 +1,74 @@
+#include <fs/echfs.h>
+#include <stdint.h>
+#include <lib/libc.h>
+#include <lib/print.h>
+
+struct echfs_identity_table {
+    uint8_t jmp[4];
+    uint8_t signature[8];
+    uint64_t block_count;
+    uint64_t dir_length;
+    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) {
+    // Read the S U P E R B L O C K.
+    struct echfs_identity_table id_table;
+    read_partition(disk, partition, &id_table, 0, sizeof(struct echfs_identity_table));
+
+    // Check the signature.
+    if (strncmp(id_table.signature, "_ECH_FS_", 8)) {
+        return -1;
+    }
+
+    // Variables from the table.
+    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;
+
+    // Calculate the offset, jumping the Allocation table and reserved blocks.
+    int offset = (16 * block_size) + (block_count * sizeof(uint64_t) / block_size);
+
+    // Find the file in the root dir.
+    struct echfs_dir_entry entry;
+    for (int i = offset; i < dir_length * block_size; i += sizeof(struct echfs_dir_entry)) {
+        read_partition(disk, partition, &entry, i, sizeof(struct echfs_dir_entry));
+
+        if (!strcmp(filename, entry.name) && entry.parent_id == ROOT_DIR_ID && entry.type == FILE_TYPE) {
+            goto FOUND;
+        }
+    }
+
+    return -1;
+
+    FOUND:;
+    // Load the file.
+    for (uint64_t i = entry.payload; i != END_OF_CHAIN;) {
+        // Read block.
+        read_partition(disk, partition, buffer, i * block_size, block_size);
+        buffer += block_size;
+
+        // Read the next block.
+        read_partition(disk, partition, &i, (16 * block_size) + i * sizeof(uint64_t), sizeof(uint64_t));
+    }
+
+    return 0;
+}
diff --git a/src/fs/echfs.h b/src/fs/echfs.h
new file mode 100644
index 00000000..1132ecd5
--- /dev/null
+++ b/src/fs/echfs.h
@@ -0,0 +1,6 @@
+#ifndef __ECHFS_H__
+#define __ECHFS_H__
+
+int load_echfs_file(int disk, int partition, void *buffer, const char *filename);
+
+#endif
diff --git a/src/lib/mbr.c b/src/lib/mbr.c
index 4249ebef..13cd429d 100644
--- a/src/lib/mbr.c
+++ b/src/lib/mbr.c
@@ -22,6 +22,11 @@ int mbr_get_part(struct mbr_part *part, int drive, int partition) {
         return ret;
     }
 
+    // Check if the partition exists, fail if it doesnt.
+    if (entry.type == 0) {
+        return -1;
+    }
+
     // Assign the final fields and return.
     part->first_sect = entry.first_sect;
     part->sect_count = entry.sect_count;
diff --git a/src/main.c b/src/main.c
index 35568d52..54351234 100644
--- a/src/main.c
+++ b/src/main.c
@@ -9,24 +9,53 @@ asm (
 #include <lib/real.h>
 #include <lib/print.h>
 #include <lib/types.h>
+#include <lib/mbr.h>
+#include <fs/echfs.h>
 
 extern symbol bss_begin;
 extern symbol bss_end;
 
+#define QWORD_KERNEL "qword.bin"
+
 void main(int boot_drive) {
     // Zero out .bss section
     for (uint8_t *p = bss_begin; p < bss_end; p++)
         *p = 0;
 
+    // Initial prompt.
     init_vga_textmode();
     print("qLoader 2\n\n");
-
     print("=> Boot drive: %x\n\n", boot_drive);
 
-    for (;;) {
+    // Enumerate partitions.
+    struct mbr_part parts[4];
+    for (int i = 0; i < 4; i++) {
+        print("=> Checking for partition %d...", i);
+        int ret = mbr_get_part(&parts[i], boot_drive, i);
+        if (ret) {
+            print("Not found!\n");
+        } else {
+            print("Found!\n");
+        }
+    }
+
+    // Load the file from the chooen partition at 1 MiB.
+    int part = 1; // TODO: The boot partition is hardcoded for now.
+    print("=> Booting %s in partition %d\n", QWORD_KERNEL, part);
+    load_echfs_file(boot_drive, part, (void *)0x100000, QWORD_KERNEL);
+
+    // Boot the kernel.
+    asm volatile (
+        "jmp 0x100000"
+        :
+        : "b" ("")
+        : "memory"
+    );
+
+    /*for (;;) {
         struct rm_regs r = {0};
         rm_int(0x16, &r, &r);    // Real mode interrupt 16h
         char c = (char)(r.eax & 0xff);
         text_write(&c, 1);
-    }
+    }*/
 }
tab: 248 wrap: offon