From 350748137b62e2aa15c62c53ebf4d30816e441f4 Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Fri, 30 Apr 2021 15:03:27 +0200 Subject: Added MBR driver and better disk creation --- kernel/Makefile | 1 + kernel/drivers/ide.c | 26 +++++-------------- kernel/drivers/mbr.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++ kernel/features/fs.c | 70 ++++++++++++++++++++++++++++---------------------- kernel/features/proc.c | 2 +- kernel/inc/fs.h | 8 +++--- kernel/inc/mbr.h | 28 ++++++++++++++++++++ 7 files changed, 148 insertions(+), 54 deletions(-) create mode 100644 kernel/drivers/mbr.c create mode 100644 kernel/inc/mbr.h (limited to 'kernel') 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 #include #include +#include #include #include #include @@ -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 +#include +#include +#include +#include +#include +#include + +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 #include #include +#include #include #include #include @@ -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 +#include + +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 -- cgit v1.2.3