summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarvin Borner2021-07-05 18:00:17 +0200
committerMarvin Borner2021-07-05 18:00:17 +0200
commit4e5b18fb3284705904a2f15f790b8c15b5767fd0 (patch)
tree0034c491e0e95f0f7472ce86a0a0ff7725e816ef
parent46ce42e9b13ce209c8c971084cfc849a83848270 (diff)
Ext2 and fixes
-rw-r--r--makefile4
-rw-r--r--src/loader/dev.c12
-rw-r--r--src/loader/dsk.c17
-rw-r--r--src/loader/fs.c10
-rw-r--r--src/loader/fs/ext2.c201
-rw-r--r--src/loader/inc/dev.h3
-rw-r--r--src/loader/inc/dsk.h21
-rw-r--r--src/loader/inc/fs.h15
-rw-r--r--src/loader/inc/fs/ext2.h98
-rw-r--r--src/loader/inc/ide.h5
-rw-r--r--src/loader/inc/lib.h1
-rw-r--r--src/loader/lib.c16
-rw-r--r--src/loader/log.c2
-rw-r--r--src/loader/main.c2
-rw-r--r--src/loader/mbr.c3
15 files changed, 366 insertions, 44 deletions
diff --git a/makefile b/makefile
index ae77b9e..7677ff0 100644
--- a/makefile
+++ b/makefile
@@ -10,7 +10,7 @@ AS = nasm
BLD = $(PWD)/build
SRC = $(PWD)/src
-SRCS = $(wildcard $(SRC)/loader/*.c)
+SRCS = $(shell find $(SRC)/loader/ -type f -name "*.c")
OBJS = $(patsubst $(SRC)/%.c,$(BLD)/%.o,$(SRCS))
# Enable many warnings for less bugs :)
@@ -25,7 +25,7 @@ all: dir $(BLD)/boot.bin
dir:
@mkdir -p $(BLD)/entry/
- @mkdir -p $(BLD)/loader/
+ @mkdir -p $(BLD)/loader/fs/
$(BLD)/boot.bin: $(BLD)/loader.bin
@$(AS) -f bin $(SRC)/entry/bootsector.asm -o $@
diff --git a/src/loader/dev.c b/src/loader/dev.c
index be15083..e529dfa 100644
--- a/src/loader/dev.c
+++ b/src/loader/dev.c
@@ -2,7 +2,6 @@
// Device manager
#include <dev.h>
-#include <fs.h>
#include <lib.h>
#include <pnc.h>
@@ -31,7 +30,7 @@ u8 dev_register(enum dev_type type, char *name, u32 data,
s32 (*write)(const void *, u32, u32, struct dev *))
{
static u8 id = 0;
- assert(id + 1 < 0xff);
+ assert(++id < 0xff);
struct dev *dev = &devices[id];
dev->id = id;
@@ -39,23 +38,22 @@ u8 dev_register(enum dev_type type, char *name, u32 data,
dev->read = read;
dev->write = write;
dev->data = data;
- dev->exists = 1;
assert(strlen(name) < sizeof(dev->name));
memcpy(dev->name, name, sizeof(dev->name));
if (type == DEV_DISK)
- fs_detect(dev);
+ dsk_detect(dev);
- return id++;
+ return id;
}
void dev_print(void)
{
for (u8 i = 0; i < COUNT(devices); i++) {
struct dev *dev = &devices[i];
- if (!dev->exists)
+ if (!dev->id)
continue;
- log("%d: %s device: %s\n", dev->id, dev_resolve_type(dev->type), dev->name);
+ log("[DEV] %d: %s device: %s\n", dev->id, dev_resolve_type(dev->type), dev->name);
}
}
diff --git a/src/loader/dsk.c b/src/loader/dsk.c
new file mode 100644
index 0000000..338c985
--- /dev/null
+++ b/src/loader/dsk.c
@@ -0,0 +1,17 @@
+// MIT License, Copyright (c) 2021 Marvin Borner
+
+#include <dsk.h>
+#include <fs/ext2.h>
+#include <log.h>
+#include <mbr.h>
+
+void dsk_detect(struct dev *dev)
+{
+ if (mbr_detect(dev))
+ return;
+
+ if (ext2_detect(dev))
+ return;
+
+ log("[DSK] Couldn't detect type of disk %s\n", dev->name);
+}
diff --git a/src/loader/fs.c b/src/loader/fs.c
deleted file mode 100644
index 8e0dc01..0000000
--- a/src/loader/fs.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// MIT License, Copyright (c) 2021 Marvin Borner
-
-#include <fs.h>
-#include <mbr.h>
-
-void fs_detect(struct dev *dev)
-{
- if (mbr_detect(dev))
- return;
-}
diff --git a/src/loader/fs/ext2.c b/src/loader/fs/ext2.c
new file mode 100644
index 0000000..fd46ca6
--- /dev/null
+++ b/src/loader/fs/ext2.c
@@ -0,0 +1,201 @@
+// MIT License, Copyright (c) 2021 Marvin Borner
+
+#include <dev.h>
+#include <fs/ext2.h>
+#include <lib.h>
+#include <pnc.h>
+
+static void ext2_buffer_read(u32 block, void *buf, struct dev *dev)
+{
+ dev->read(buf, block * SECTOR_COUNT, SECTOR_COUNT, dev);
+}
+
+static void ext2_get_superblock(struct ext2_superblock *buf, struct dev *dev)
+{
+ u8 data[BLOCK_SIZE] = { 0 };
+ ext2_buffer_read(EXT2_SUPER, data, dev);
+ memcpy(buf, data, sizeof(*buf));
+
+ assert(buf->magic == EXT2_MAGIC);
+}
+
+static struct ext2_inode *ext2_get_inode(u32 i, struct ext2_inode *in_buf, struct dev *dev)
+{
+ struct ext2_superblock sb = { 0 };
+ ext2_get_superblock(&sb, dev);
+
+ u8 data[BLOCK_SIZE] = { 0 };
+ ext2_buffer_read(EXT2_SUPER + 1, data, dev);
+ struct ext2_bgd *bgd = (struct ext2_bgd *)data;
+
+ u32 block_group = (i - 1) / sb.inodes_per_group;
+ u32 index = (i - 1) % sb.inodes_per_group;
+ u32 block = (index * EXT2_INODE_SIZE) / BLOCK_SIZE;
+ bgd += block_group;
+
+ u8 buf[BLOCK_SIZE] = { 0 };
+ ext2_buffer_read(bgd->inode_table + block, buf, dev);
+ struct ext2_inode *in =
+ (struct ext2_inode *)((u32)buf +
+ (index % (BLOCK_SIZE / EXT2_INODE_SIZE)) * EXT2_INODE_SIZE);
+
+ memcpy(in_buf, in, sizeof(*in_buf));
+
+ return in_buf;
+}
+
+static u32 ext2_read_indirect(u32 indirect, u32 block_num, struct dev *dev)
+{
+ u8 buf[BLOCK_SIZE] = { 0 };
+ ext2_buffer_read(indirect, buf, dev);
+ u32 ind = *(u32 *)((u32)buf + block_num * sizeof(u32));
+ return ind;
+}
+
+static s32 ext2_read_inode(struct ext2_inode *in, void *buf, u32 offset, u32 count, struct dev *dev)
+{
+ if (!in || !buf)
+ return -1;
+
+ if (in->size == 0)
+ return 0;
+
+ u32 num_blocks = in->blocks / (BLOCK_SIZE / SECTOR_SIZE) + 1;
+
+ if (!num_blocks)
+ return -1;
+
+ u32 first_block = offset / BLOCK_SIZE;
+ u32 last_block = (offset + count) / BLOCK_SIZE;
+ if (last_block >= num_blocks)
+ last_block = num_blocks - 1;
+ u32 first_block_offset = offset % BLOCK_SIZE;
+
+ u32 remaining = MIN(count, in->size - offset);
+ u32 copied = 0;
+
+ u32 indirect, blocknum;
+
+ // TODO: Support triply indirect pointers
+ for (u32 i = first_block; i <= last_block; i++) {
+ if (i < 12) {
+ blocknum = in->block[i];
+ } else if (i < BLOCK_COUNT + 12) {
+ indirect = in->block[12];
+ blocknum = ext2_read_indirect(indirect, i - 12, dev);
+ } else {
+ indirect = in->block[13];
+ blocknum = ext2_read_indirect(indirect,
+ (i - (BLOCK_COUNT + 12)) / BLOCK_COUNT, dev);
+ blocknum = ext2_read_indirect(blocknum,
+ (i - (BLOCK_COUNT + 12)) % BLOCK_COUNT, dev);
+ }
+
+ u8 data[BLOCK_SIZE] = { 0 };
+ ext2_buffer_read(blocknum, data, dev);
+ u32 block_offset = (i == first_block) ? first_block_offset : 0;
+ u32 byte_count = MIN(BLOCK_SIZE - block_offset, remaining);
+
+ memcpy((u8 *)buf + copied, data + block_offset, byte_count);
+
+ copied += byte_count;
+ remaining -= byte_count;
+ }
+
+ return copied;
+}
+
+static u32 ext2_find_inode(const char *name, u32 dir_inode, struct dev *dev)
+{
+ if ((signed)dir_inode <= 0)
+ return (unsigned)-1;
+
+ struct ext2_inode i = { 0 };
+ ext2_get_inode(dir_inode, &i, dev);
+
+ char buf[BLOCK_SIZE] = { 0 };
+ assert(BLOCK_SIZE * i.blocks / 2 <= sizeof(buf)); // Shouldn't fail
+
+ u8 data[BLOCK_SIZE] = { 0 };
+ for (u32 q = 0; q < i.blocks / 2; q++) {
+ ext2_buffer_read(i.block[q], data, dev);
+ memcpy((u32 *)((u32)buf + q * BLOCK_SIZE), data, BLOCK_SIZE);
+ }
+
+ struct ext2_dirent *d = (struct ext2_dirent *)buf;
+
+ u32 sum = 0;
+ do {
+ // Calculate the 4byte aligned size of each entry
+ sum += d->total_len;
+ if (strlen(name) == d->name_len &&
+ strncmp((void *)d->name, name, d->name_len) == 0) {
+ return d->inode_num;
+ }
+ d = (struct ext2_dirent *)((u32)d + d->total_len);
+
+ } while (sum < (1024 * i.blocks / 2));
+
+ return (unsigned)-1;
+}
+
+static struct ext2_inode *ext2_find_inode_by_path(const char *path, struct ext2_inode *in_buf,
+ struct dev *dev)
+{
+ char path_arr[1024] = { 0 };
+ strlcpy(path_arr, path, sizeof(path_arr));
+ char *path_cp = path_arr;
+
+ if (path_cp[0] != '/')
+ return NULL;
+
+ path_cp++;
+ u32 current_inode = EXT2_ROOT;
+
+ while (1) {
+ u32 i;
+ for (i = 0; path_cp[i] != '/' && path_cp[i] != '\0'; i++)
+ ;
+
+ if (path_cp[i] == '\0')
+ break;
+
+ path_cp[i] = '\0';
+ current_inode = ext2_find_inode(path_cp, current_inode, dev);
+ path_cp[i] = '/';
+
+ if ((signed)current_inode <= 0) {
+ return NULL;
+ }
+
+ path_cp += i + 1;
+ }
+
+ u32 inode = ext2_find_inode(path_cp, current_inode, dev);
+ if ((signed)inode <= 0)
+ return NULL;
+
+ return ext2_get_inode(inode, in_buf, dev);
+}
+
+static s32 ext2_read(const char *path, void *buf, u32 offset, u32 count, struct dev *dev)
+{
+ struct ext2_inode in = { 0 };
+ if (ext2_find_inode_by_path(path, &in, dev) == &in) {
+ return ext2_read_inode(&in, buf, offset, count, dev);
+ } else {
+ return -1;
+ }
+}
+
+u8 ext2_detect(struct dev *dev)
+{
+ struct ext2_superblock sb = { 0 };
+ ext2_get_superblock(&sb, dev);
+ if (sb.magic != EXT2_MAGIC)
+ return 0;
+
+ dev->fs.read = ext2_read;
+
+ return 1;
+}
diff --git a/src/loader/inc/dev.h b/src/loader/inc/dev.h
index 7ea3147..6fcbf25 100644
--- a/src/loader/inc/dev.h
+++ b/src/loader/inc/dev.h
@@ -4,7 +4,7 @@
#define DEV_H
#include <def.h>
-#include <fs.h>
+#include <dsk.h>
enum dev_type {
DEV_DISK,
@@ -22,7 +22,6 @@ struct dev {
struct fs fs;
u32 data; // Optional (device-specific) data/information
- u8 exists : 1;
};
struct dev *dev_get(u8 id);
diff --git a/src/loader/inc/dsk.h b/src/loader/inc/dsk.h
new file mode 100644
index 0000000..5b2dec9
--- /dev/null
+++ b/src/loader/inc/dsk.h
@@ -0,0 +1,21 @@
+// MIT License, Copyright (c) 2021 Marvin Borner
+
+#ifndef DSK_H
+#define DSK_H
+
+#include <def.h>
+
+// General disk assumptions
+#define BLOCK_SIZE 1024
+#define BLOCK_COUNT 256 // BLOCK_SIZE / sizeof(u32)
+#define SECTOR_SIZE 512
+#define SECTOR_COUNT (BLOCK_SIZE / SECTOR_SIZE) // 2
+
+struct dev;
+struct fs {
+ s32 (*read)(const char *, void *, u32, u32, struct dev *);
+};
+
+void dsk_detect(struct dev *dev);
+
+#endif
diff --git a/src/loader/inc/fs.h b/src/loader/inc/fs.h
deleted file mode 100644
index 84cd2d7..0000000
--- a/src/loader/inc/fs.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// MIT License, Copyright (c) 2021 Marvin Borner
-
-#ifndef FS_H
-#define FS_H
-
-#include <def.h>
-struct dev;
-
-struct fs {
- s32 (*read)(void *, u32, u32, struct dev *);
-};
-
-void fs_detect(struct dev *dev);
-
-#endif
diff --git a/src/loader/inc/fs/ext2.h b/src/loader/inc/fs/ext2.h
new file mode 100644
index 0000000..10650cd
--- /dev/null
+++ b/src/loader/inc/fs/ext2.h
@@ -0,0 +1,98 @@
+// MIT License, Copyright (c) 2021 Marvin Borner
+
+#ifndef EXT2_H
+#define EXT2_H
+
+#include <def.h>
+#include <dev.h>
+
+#define EXT2_BOOT 0
+#define EXT2_SUPER 1
+#define EXT2_ROOT 2
+#define EXT2_MAGIC 0xef53
+
+#define EXT2_INODE_SIZE (sizeof(struct ext2_inode))
+
+struct ext2_superblock {
+ u32 total_inodes;
+ u32 total_blocks;
+ u32 su_res_blocks; // Superuser reserved
+ u32 free_blocks;
+ u32 free_inodes;
+ u32 superblock_block_num;
+ u32 log2_block_size;
+ u32 log2_frag_size;
+ u32 blocks_per_group;
+ u32 frags_per_group;
+ u32 inodes_per_group;
+ u32 last_mount_time;
+ u32 last_write_time;
+ u16 mounts_since_fsck;
+ u16 max_mounts_since_fsck;
+ u16 magic;
+ u16 state; // 1 clean; 2 errors
+ u16 error_action;
+ u16 minor_version;
+ u32 last_fsck_time;
+ u32 max_time_since_fsck;
+ u32 creator_os_id;
+ u32 major_version;
+ u16 res_block_uid;
+ u16 res_block_gid;
+};
+
+struct ext2_bgd {
+ u32 block_bitmap;
+ u32 inode_bitmap;
+ u32 inode_table;
+ u16 free_blocks;
+ u16 free_inodes;
+ u16 used_dirs;
+ u16 pad;
+ u8 bg_reserved[12];
+};
+
+struct ext2_inode {
+ u16 mode;
+ u16 uid;
+ u32 size;
+
+ u32 last_access_time;
+ u32 creation_time;
+ u32 last_modification_time;
+ u32 deletion_time;
+
+ u16 gid;
+ u16 link_count;
+ u32 blocks;
+ u32 flags;
+ u32 os_specific_val1;
+ u32 block[15];
+ u32 generation;
+
+ u32 reserved1;
+ u32 reserved2;
+
+ u32 fragment_addr;
+ u8 os_specific_val2[12];
+};
+
+struct ext2_dirent {
+ u32 inode_num;
+ u16 total_len;
+ u8 name_len;
+ u8 type_indicator;
+ u8 name[];
+};
+
+struct ext2_file {
+ struct ext2_inode inode;
+ u32 pos;
+ u8 block_index;
+ u8 *buf;
+ u32 curr_block_pos;
+};
+
+u8 ext2_detect(struct dev *dev);
+
+#endif
diff --git a/src/loader/inc/ide.h b/src/loader/inc/ide.h
index 24b4eb1..7faee03 100644
--- a/src/loader/inc/ide.h
+++ b/src/loader/inc/ide.h
@@ -3,11 +3,6 @@
#ifndef IDE_H
#define IDE_H
-#define BLOCK_SIZE 1024
-#define BLOCK_COUNT 256 // BLOCK_SIZE / sizeof(u32)
-#define SECTOR_SIZE 512
-#define SECTOR_COUNT (BLOCK_SIZE / SECTOR_SIZE)
-
#define ATA_PRIMARY_IO 0x1f0
#define ATA_SECONDARY_IO 0x170
diff --git a/src/loader/inc/lib.h b/src/loader/inc/lib.h
index d5984dd..e811670 100644
--- a/src/loader/inc/lib.h
+++ b/src/loader/inc/lib.h
@@ -8,6 +8,7 @@
u32 strlen(const char *str);
u32 strnlen(const char *s, u32 max);
u32 strlcpy(char *dst, const char *src, u32 size);
+s32 strncmp(const char *s1, const char *s2, u32 n);
void *memcpy(void *dest, const void *src, u32 n);
void *memset(void *dest, u32 val, u32 n);
diff --git a/src/loader/lib.c b/src/loader/lib.c
index a9fec01..83b1e25 100644
--- a/src/loader/lib.c
+++ b/src/loader/lib.c
@@ -44,6 +44,22 @@ u32 strlcpy(char *dst, const char *src, u32 size)
return src - orig - 1;
}
+s32 strncmp(const char *s1, const char *s2, u32 n)
+{
+ const u8 *c1 = (const u8 *)s1;
+ const u8 *c2 = (const u8 *)s2;
+ u8 ch;
+ int d = 0;
+
+ while (n--) {
+ d = (int)(ch = *c1++) - (int)*c2++;
+ if (d || !ch)
+ break;
+ }
+
+ return d;
+}
+
/**
* Common memory functions
*/
diff --git a/src/loader/log.c b/src/loader/log.c
index 4312fcc..b0f03b9 100644
--- a/src/loader/log.c
+++ b/src/loader/log.c
@@ -81,6 +81,8 @@ void serial_install(void)
// Activate
outb(PORT + 4, 0x0f);
+
+ log("[LOG] Initiated\n");
}
static int serial_empty(void)
diff --git a/src/loader/main.c b/src/loader/main.c
index 517e120..bf2604e 100644
--- a/src/loader/main.c
+++ b/src/loader/main.c
@@ -17,8 +17,6 @@ int start(void)
vga_clear();
serial_install();
- log("Log initiated\n");
-
pci_probe();
dev_print();
diff --git a/src/loader/mbr.c b/src/loader/mbr.c
index 1ee298b..599952c 100644
--- a/src/loader/mbr.c
+++ b/src/loader/mbr.c
@@ -47,11 +47,12 @@ u8 mbr_detect(struct dev *dev)
strlcpy(name, dev->name, sizeof(name));
name[3] = '0' + i;
+ log("[MBR] Found part %s\n", name);
+
// Saving space and everything
u16 data = mbr_add_entry(entry) | (dev->id << 8);
dev_register(DEV_DISK, name, data, mbr_read, NULL);
- log("Found part %s%c\n", dev->name, '0' + i);
}
return 1;