aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/drivers/ide.c26
-rw-r--r--kernel/drivers/mbr.c67
-rw-r--r--kernel/features/fs.c70
-rw-r--r--kernel/features/proc.c2
-rw-r--r--kernel/inc/fs.h8
-rw-r--r--kernel/inc/mbr.h28
7 files changed, 148 insertions, 54 deletions
diff --git a/kernel/Makefile b/kernel/Makefile
index 8296e02..01fe3c1 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -10,6 +10,7 @@ COBJS = entry_asm.o \
drivers/serial.o \
drivers/pci.o \
drivers/rtc.o \
+ drivers/mbr.o \
drivers/ide.o \
drivers/fb.o \
drivers/timer.o \
diff --git a/kernel/drivers/ide.c b/kernel/drivers/ide.c
index 68e797f..bde72b7 100644
--- a/kernel/drivers/ide.c
+++ b/kernel/drivers/ide.c
@@ -5,6 +5,7 @@
#include <def.h>
#include <fs.h>
#include <ide.h>
+#include <mbr.h>
#include <mem.h>
#include <pci.h>
#include <print.h>
@@ -128,30 +129,17 @@ CLEAR static void ata_probe(void)
if (!ide_find(bus, drive))
continue;
- struct vfs_dev *dev = zalloc(sizeof(*dev));
- struct ata_data *data = malloc(sizeof(*data));
+ struct ata_data *data = zalloc(sizeof(*data));
data->drive = (bus << 1) | drive;
- char *str = zalloc(8);
- strlcpy(str, "hd", 8);
- str[2] = 'a' + i;
-
- dev->name = str;
+ struct vfs_dev *dev = zalloc(sizeof(*dev));
+ strlcpy(dev->name, "hd", 3);
+ dev->name[2] = 'a' + i;
dev->type = DEV_BLOCK;
dev->read = ata_read;
- vfs_add_dev(dev);
- if (vfs_mounted(dev, "/"))
- continue;
-
- // TODO: Check if ext2 first
- struct vfs *vfs = zalloc(sizeof(*vfs));
- vfs->type = VFS_EXT2;
- vfs->read = ext2_read;
- vfs->stat = ext2_stat;
- vfs->perm = ext2_perm;
- dev->vfs = vfs;
dev->data = data;
- vfs_mount(dev, "/");
+ vfs_add_dev(dev);
+ vfs_load(dev);
}
}
diff --git a/kernel/drivers/mbr.c b/kernel/drivers/mbr.c
new file mode 100644
index 0000000..c85061d
--- /dev/null
+++ b/kernel/drivers/mbr.c
@@ -0,0 +1,67 @@
+// MIT License, Copyright (c) 2021 Marvin Borner
+
+#include <def.h>
+#include <fs.h>
+#include <ide.h>
+#include <mbr.h>
+#include <mem.h>
+#include <print.h>
+#include <str.h>
+
+struct mbr_data {
+ struct mbr_entry mbr;
+ struct vfs_dev *dev;
+};
+
+static res mbr_read(void *buf, u32 lba, u32 sector_count, struct vfs_dev *part)
+{
+ struct mbr_data *data = part->data;
+ if (!data || !data->dev || !data->dev->read)
+ return -EINVAL;
+
+ return data->dev->read(buf, data->mbr.start + lba, sector_count, data->dev);
+}
+
+static res mbr_write(const void *buf, u32 lba, u32 sector_count, struct vfs_dev *part)
+{
+ struct mbr_data *data = part->data;
+ if (!data || !data->dev || !data->dev->write)
+ return -EINVAL;
+
+ return data->dev->write(buf, data->mbr.start + lba, sector_count, data->dev);
+}
+
+CLEAR u8 mbr_load(struct vfs_dev *dev)
+{
+ struct mbr mbr = { 0 };
+ dev->read(&mbr, 0, 1, dev); // Read first sector
+
+ if (mbr.magic != 0xaa55)
+ return 0;
+
+ for (u8 i = 0; i < 4; i++) {
+ struct mbr_entry *entry = &mbr.entries[i];
+ if (!entry->type || !entry->size)
+ continue;
+
+ struct mbr_data *data = zalloc(sizeof(*data));
+ memcpy(&data->mbr, entry, sizeof(*entry));
+ data->dev = dev;
+
+ struct vfs_dev *part = zalloc(sizeof(*part));
+ part->data = data;
+ strlcpy(part->name, dev->name, 4);
+ part->name[3] = '0' + i;
+ part->type = DEV_BLOCK;
+ part->read = mbr_read;
+ part->write = mbr_write;
+
+ /* printf("%s [start: %d; size: %dMiB; type: %d]\n", part->name, entry->start, */
+ /* (entry->size * SECTOR_SIZE) >> 20, entry->type); */
+
+ vfs_add_dev(part);
+ vfs_load(part);
+ }
+
+ return 1;
+}
diff --git a/kernel/features/fs.c b/kernel/features/fs.c
index 6cb10c8..fdd5154 100644
--- a/kernel/features/fs.c
+++ b/kernel/features/fs.c
@@ -7,6 +7,7 @@
#include <errno.h>
#include <fs.h>
#include <ide.h>
+#include <mbr.h>
#include <mem.h>
#include <mm.h>
#include <print.h>
@@ -94,33 +95,6 @@ struct vfs_dev *vfs_find_dev(const char *path)
return m && m->dev ? m->dev : NULL;
}
-/*static const char *vfs_resolve_type(enum vfs_type type)
-{
- switch (type) {
- case VFS_DEVFS:
- return "devfs";
- case VFS_TMPFS:
- return "tmpfs";
- case VFS_PROCFS:
- return "procfs";
- case VFS_EXT2:
- return "ext2";
- default:
- return "unknown";
- }
-}
-
-static void vfs_list_mounts()
-{
- struct node *iterator = mount_points->head;
- while (iterator) {
- struct mount_info *m = iterator->data;
- printf("%s on %s type %s\n", m->dev->name, m->path,
- vfs_resolve_type(m->dev->vfs->type));
- iterator = iterator->next;
- }
-}*/
-
res vfs_mount(struct vfs_dev *dev, const char *path)
{
if (!memory_readable(path))
@@ -223,6 +197,14 @@ res vfs_stat(const char *path, struct stat *buf)
return m->dev->vfs->stat(path, buf, m->dev);
}
+CLEAR void vfs_load(struct vfs_dev *dev)
+{
+ if (!mbr_load(dev)) {
+ assert(ext2_load(dev));
+ // TODO: Add GPT support
+ }
+}
+
CLEAR void vfs_install(void)
{
mount_points = list_new();
@@ -458,7 +440,7 @@ static struct ext2_inode *ext2_find_inode_by_path(const char *path, struct ext2_
return ext2_get_inode(inode, in_buf, dev);
}
-res ext2_read(const char *path, void *buf, u32 offset, u32 count, struct vfs_dev *dev)
+static res ext2_read(const char *path, void *buf, u32 offset, u32 count, struct vfs_dev *dev)
{
struct ext2_inode in = { 0 };
if (ext2_find_inode_by_path(path, &in, dev) == &in) {
@@ -467,7 +449,7 @@ res ext2_read(const char *path, void *buf, u32 offset, u32 count, struct vfs_dev
return -ENOENT;
}
-res ext2_stat(const char *path, struct stat *buf, struct vfs_dev *dev)
+static res ext2_stat(const char *path, struct stat *buf, struct vfs_dev *dev)
{
struct ext2_inode in = { 0 };
if (ext2_find_inode_by_path(path, &in, dev) != &in)
@@ -484,7 +466,7 @@ res ext2_stat(const char *path, struct stat *buf, struct vfs_dev *dev)
return EOK;
}
-res ext2_perm(const char *path, enum vfs_perm perm, struct vfs_dev *dev)
+static res ext2_perm(const char *path, enum vfs_perm perm, struct vfs_dev *dev)
{
struct ext2_inode in = { 0 };
if (ext2_find_inode_by_path(path, &in, dev) != &in)
@@ -501,3 +483,31 @@ res ext2_perm(const char *path, enum vfs_perm perm, struct vfs_dev *dev)
return -EINVAL;
}
}
+
+CLEAR u8 ext2_load(struct vfs_dev *dev)
+{
+ struct ext2_superblock *sb = ext2_buffer_read(EXT2_SUPER, dev);
+ if (sb->magic != EXT2_MAGIC) {
+ free(sb);
+ return 0;
+ }
+
+ struct vfs *vfs = zalloc(sizeof(*vfs));
+ vfs->type = VFS_EXT2;
+ vfs->read = ext2_read;
+ vfs->stat = ext2_stat;
+ vfs->perm = ext2_perm;
+ dev->vfs = vfs;
+
+ // Verify that '/' is unmounted
+ struct mount_info *m = vfs_find_mount_info("/");
+ if (m && m->dev)
+ panic("Found multiple ext2 disks!\n");
+
+ // TODO: Mount other ext2 disks somewhere else
+ printf("Mounting disk %s to '/'\n", dev->name);
+ vfs_mount(dev, "/");
+
+ free(sb);
+ return 1;
+}
diff --git a/kernel/features/proc.c b/kernel/features/proc.c
index ffa711b..36ee6b9 100644
--- a/kernel/features/proc.c
+++ b/kernel/features/proc.c
@@ -332,7 +332,7 @@ NORETURN void proc_init(void)
vfs->perm = procfs_perm;
vfs->data = NULL;
struct vfs_dev *dev = zalloc(sizeof(*dev));
- dev->name = "proc";
+ strlcpy(dev->name, "proc", sizeof(dev->name));
dev->type = DEV_CHAR;
dev->vfs = vfs;
vfs_add_dev(dev);
diff --git a/kernel/inc/fs.h b/kernel/inc/fs.h
index 329af21..a1cb696 100644
--- a/kernel/inc/fs.h
+++ b/kernel/inc/fs.h
@@ -15,7 +15,7 @@ enum dev_type { DEV_BLOCK, DEV_CHAR };
struct vfs_dev {
u32 id;
- const char *name;
+ char name[8];
enum dev_type type;
struct vfs *vfs;
void *data;
@@ -65,6 +65,8 @@ res vfs_read(const char *path, void *buf, u32 offset, u32 count);
res vfs_write(const char *path, const void *buf, u32 offset, u32 count);
res vfs_stat(const char *path, struct stat *buf);
+void vfs_load(struct vfs_dev *dev) NONNULL;
+
struct vfs_dev *device_get_by_name(const char *name) NONNULL;
struct vfs_dev *device_get_by_id(u32 id) NONNULL;
@@ -170,8 +172,6 @@ struct ext2_file {
u32 curr_block_pos;
};
-res ext2_read(const char *path, void *buf, u32 offset, u32 count, struct vfs_dev *dev) NONNULL;
-res ext2_stat(const char *path, struct stat *buf, struct vfs_dev *dev) NONNULL;
-res ext2_perm(const char *path, enum vfs_perm perm, struct vfs_dev *dev) NONNULL;
+u8 ext2_load(struct vfs_dev *dev) NONNULL;
#endif
diff --git a/kernel/inc/mbr.h b/kernel/inc/mbr.h
new file mode 100644
index 0000000..07f6da0
--- /dev/null
+++ b/kernel/inc/mbr.h
@@ -0,0 +1,28 @@
+// MIT License, Copyright (c) 2021 Marvin Borner
+
+#ifndef MBR_H
+#define MBR_H
+
+#include <def.h>
+#include <fs.h>
+
+struct mbr_entry {
+ u8 attributes;
+ u8 chs_start[3];
+ u8 type;
+ u8 chs_end[3];
+ u32 start;
+ u32 size;
+} PACKED;
+
+struct mbr {
+ u8 bootstrap[440];
+ u32 signature;
+ u16 reserved;
+ struct mbr_entry entries[4];
+ u16 magic;
+} PACKED;
+
+u8 mbr_load(struct vfs_dev *dev);
+
+#endif