diff options
author | Marvin Borner | 2021-07-05 18:00:17 +0200 |
---|---|---|
committer | Marvin Borner | 2021-07-05 18:00:17 +0200 |
commit | 4e5b18fb3284705904a2f15f790b8c15b5767fd0 (patch) | |
tree | 0034c491e0e95f0f7472ce86a0a0ff7725e816ef | |
parent | 46ce42e9b13ce209c8c971084cfc849a83848270 (diff) |
Ext2 and fixes
-rw-r--r-- | makefile | 4 | ||||
-rw-r--r-- | src/loader/dev.c | 12 | ||||
-rw-r--r-- | src/loader/dsk.c | 17 | ||||
-rw-r--r-- | src/loader/fs.c | 10 | ||||
-rw-r--r-- | src/loader/fs/ext2.c | 201 | ||||
-rw-r--r-- | src/loader/inc/dev.h | 3 | ||||
-rw-r--r-- | src/loader/inc/dsk.h | 21 | ||||
-rw-r--r-- | src/loader/inc/fs.h | 15 | ||||
-rw-r--r-- | src/loader/inc/fs/ext2.h | 98 | ||||
-rw-r--r-- | src/loader/inc/ide.h | 5 | ||||
-rw-r--r-- | src/loader/inc/lib.h | 1 | ||||
-rw-r--r-- | src/loader/lib.c | 16 | ||||
-rw-r--r-- | src/loader/log.c | 2 | ||||
-rw-r--r-- | src/loader/main.c | 2 | ||||
-rw-r--r-- | src/loader/mbr.c | 3 |
15 files changed, 366 insertions, 44 deletions
@@ -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; |