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);
- }
+ }*/
}
