aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rwxr-xr-xrun4
-rw-r--r--src/drivers/cpu.c8
-rw-r--r--src/drivers/ide.c41
-rw-r--r--src/features/fs.c150
-rw-r--r--src/inc/cpu.h1
-rw-r--r--src/inc/fs.h97
-rw-r--r--src/inc/ide.h40
-rw-r--r--src/lib/inc/str.h1
-rw-r--r--src/lib/str.c16
-rw-r--r--src/main.c5
11 files changed, 364 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index 5954371..31666a7 100644
--- a/Makefile
+++ b/Makefile
@@ -7,6 +7,8 @@ COBJS = src/main.o \
src/drivers/interrupts.o \
src/drivers/interrupts_asm.o \
src/drivers/keyboard.o \
+ src/drivers/ide.o \
+ src/features/fs.o \
src/lib/str.o \
src/lib/mem.o \
src/lib/math.o \
@@ -17,7 +19,7 @@ LD = cross/opt/bin/i686-elf-ld
AS = nasm
# TODO: Use lib as external library
-CFLAGS = -Wall -Wextra -nostdlib -nostdinc -ffreestanding -mgeneral-regs-only -mno-80387 -std=c99 -pedantic-errors -Isrc/lib/inc/ -Isrc/inc/ -c
+CFLAGS = -Wall -Wextra -nostdlib -nostdinc -ffreestanding -mgeneral-regs-only -std=c99 -pedantic-errors -Isrc/lib/inc/ -Isrc/inc/ -c
ASFLAGS = -f elf32
diff --git a/run b/run
index 87ff8bf..0a41b63 100755
--- a/run
+++ b/run
@@ -73,7 +73,9 @@ make_build() {
dd if=/dev/zero of=build/disk.img bs=1k count=16k
sudo mke2fs build/disk.img >/dev/null
dd if=build/boot.bin of=build/disk.img conv=notrunc
- ./ext2util/ext2util -x build/disk.img -wf build/kernel.bin -i 5 >/dev/null
+ cp build/kernel.bin . # For nicer disk img
+ ./ext2util/ext2util -x build/disk.img -wf kernel.bin -i 5 >/dev/null
+ rm kernel.bin
printf "Build finshed successfully!\n\n"
}
diff --git a/src/drivers/cpu.c b/src/drivers/cpu.c
index 22691fb..d6a1760 100644
--- a/src/drivers/cpu.c
+++ b/src/drivers/cpu.c
@@ -24,6 +24,14 @@ u32 inl(u16 port)
return value;
}
+void insl(u16 port, void *addr, int n)
+{
+ __asm__("cld; rep insl"
+ : "=D"(addr), "=c"(n)
+ : "d"(port), "0"(addr), "1"(n)
+ : "memory", "cc");
+}
+
void outb(u16 port, u8 data)
{
__asm__("outb %0, %1" ::"a"(data), "Nd"(port));
diff --git a/src/drivers/ide.c b/src/drivers/ide.c
new file mode 100644
index 0000000..fe3955c
--- /dev/null
+++ b/src/drivers/ide.c
@@ -0,0 +1,41 @@
+// MIT License, Copyright (c) 2020 Marvin Borner
+
+#include <cpu.h>
+#include <def.h>
+#include <ide.h>
+
+int ide_wait(int check)
+{
+ char r;
+
+ // Wait while drive is busy. Once just ready is set, exit the loop
+ while (((r = (char)inb(IDE_IO | IDE_CMD)) & (IDE_BUSY | IDE_READY)) != IDE_READY)
+ ;
+
+ // Check for errors
+ if (check && (r & (IDE_DRIVE_FAULT | IDE_ERROR)) != 0)
+ return 0xF;
+ return 0;
+}
+
+void *ide_read(void *b, u32 block)
+{
+ int sector_per_block = BLOCK_SIZE / SECTOR_SIZE; // 2
+ int sector = block * sector_per_block;
+
+ ide_wait(0);
+ outb(IDE_IO | IDE_SECTOR_COUNT, sector_per_block); // Number of sectors
+ outb(IDE_IO | IDE_LOW, LBA_LOW(sector));
+ outb(IDE_IO | IDE_MID, LBA_MID(sector));
+ outb(IDE_IO | IDE_HIGH, LBA_HIGH(sector));
+
+ // Slave/Master << 4 and last 4 bits
+ outb(IDE_IO | IDE_HEAD, 0xE0 | (1 << 4) | LBA_LAST(sector));
+ outb(IDE_IO | IDE_CMD, IDE_CMD_READ);
+ ide_wait(0);
+
+ // Read-only
+ insl(IDE_IO, b, BLOCK_SIZE / 4);
+
+ return b;
+}
diff --git a/src/features/fs.c b/src/features/fs.c
new file mode 100644
index 0000000..ba66033
--- /dev/null
+++ b/src/features/fs.c
@@ -0,0 +1,150 @@
+// MIT License, Copyright (c) 2020 Marvin Borner
+// EXT2 based filesystem
+
+#include <def.h>
+#include <fs.h>
+#include <ide.h>
+#include <mem.h>
+#include <print.h>
+#include <str.h>
+
+void *buffer_read(int block)
+{
+ return ide_read(malloc(BLOCK_SIZE), block);
+}
+
+struct superblock *get_superblock()
+{
+ struct superblock *sb = buffer_read(EXT2_SUPER);
+ if (sb->magic != EXT2_MAGIC)
+ return NULL;
+ return sb;
+}
+
+struct bgd *get_bgd()
+{
+ return buffer_read(EXT2_SUPER + 1);
+}
+
+struct inode *get_inode(int i)
+{
+ struct superblock *s = get_superblock();
+ struct bgd *b = get_bgd();
+
+ int block_group = (i - 1) / s->inodes_per_group;
+ int index = (i - 1) % s->inodes_per_group;
+ int block = (index * INODE_SIZE) / BLOCK_SIZE;
+ b += block_group;
+
+ u32 *data = buffer_read(b->inode_table + block);
+ struct inode *in =
+ (struct inode *)((u32)data + (index % (BLOCK_SIZE / INODE_SIZE)) * INODE_SIZE);
+ return in;
+}
+
+u32 read_indirect(u32 indirect, u32 block_num)
+{
+ char *data = buffer_read(indirect);
+ return *(u32 *)((u32)data + block_num * 4);
+}
+
+void *read_file(struct inode *in)
+{
+ //assert(in);
+ if (!in)
+ return NULL;
+
+ int num_blocks = in->blocks / (BLOCK_SIZE / SECTOR_SIZE);
+
+ // assert(num_blocks != 0);
+ if (!num_blocks)
+ return NULL;
+
+ u32 sz = BLOCK_SIZE * num_blocks;
+ void *buf = malloc(sz);
+ //assert(buf != NULL);
+
+ int indirect = 0;
+
+ // Single indirect pointer
+ if (num_blocks > 12) {
+ indirect = in->block[13];
+ }
+
+ int blocknum = 0;
+ char *data;
+ for (int i = 0; i < num_blocks; i++) {
+ if (i < 12) {
+ blocknum = in->block[i];
+ data = buffer_read(blocknum);
+ memcpy((void *)((u32)buf + (i * BLOCK_SIZE)), data, BLOCK_SIZE);
+ }
+ if (i > 12) {
+ blocknum = read_indirect(indirect, i - 13);
+ data = buffer_read(blocknum);
+ memcpy((void *)((u32)buf + ((i - 1) * BLOCK_SIZE)), data, BLOCK_SIZE);
+ }
+ }
+ return buf;
+}
+
+int find_inode(const char *name, int dir_inode)
+{
+ if (!dir_inode)
+ return -1;
+
+ struct inode *i = get_inode(dir_inode);
+
+ char *buf = malloc(BLOCK_SIZE * i->blocks / 2);
+ memset(buf, 0, BLOCK_SIZE * i->blocks / 2);
+
+ for (u32 q = 0; q < i->blocks / 2; q++) {
+ char *data = buffer_read(i->block[q]);
+ memcpy((void *)((u32)buf + (q * BLOCK_SIZE)), data, BLOCK_SIZE);
+ }
+
+ struct dirent *d = (struct dirent *)buf;
+
+ u32 sum = 0;
+ do {
+ // Calculate the 4byte aligned size of each entry
+ sum += d->total_len;
+ //printf("%2d %10s\t%2d %3d\n", (int)d->inode, d->name, d->name_len, d->rec_len);
+ if (strncmp((void *)d->name, name, d->name_len) == 0) {
+ free(buf);
+ return d->inode_num;
+ }
+ d = (struct dirent *)((u32)d + d->total_len);
+
+ } while (sum < (1024 * i->blocks / 2));
+ free(buf);
+ return -1;
+}
+
+void ls_root()
+{
+ struct inode *i = get_inode(2);
+
+ char *buf = malloc(BLOCK_SIZE * i->blocks / 2);
+
+ for (u32 q = 0; q < i->blocks / 2; q++) {
+ char *data = buffer_read(i->block[q]);
+ memcpy((void *)((u32)buf + (q * BLOCK_SIZE)), data, BLOCK_SIZE);
+ }
+
+ struct dirent *d = (struct dirent *)buf;
+
+ int sum = 0;
+ int calc = 0;
+ printf("Root directory:\n");
+ do {
+ calc = (sizeof(struct dirent) + d->name_len + 4) & ~0x3;
+ sum += d->total_len;
+ printf("/%s\n", d->name);
+ if (d->total_len != calc && sum == 1024)
+ d->total_len = calc;
+
+ d = (struct dirent *)((u32)d + d->total_len);
+
+ } while (sum < 1024);
+}
diff --git a/src/inc/cpu.h b/src/inc/cpu.h
index ad83896..b8897de 100644
--- a/src/inc/cpu.h
+++ b/src/inc/cpu.h
@@ -8,6 +8,7 @@
u8 inb(u16 port);
u16 inw(u16 port);
u32 inl(u16 port);
+void insl(u16 port, void *addr, int n);
void outb(u16 port, u8 data);
void outw(u16 port, u16 data);
diff --git a/src/inc/fs.h b/src/inc/fs.h
new file mode 100644
index 0000000..e5e1ca7
--- /dev/null
+++ b/src/inc/fs.h
@@ -0,0 +1,97 @@
+// MIT License, Copyright (c) 2020 Marvin Borner
+// EXT2 based filesystem
+
+#ifndef FS_H
+#define FS_H
+
+#include <def.h>
+
+#define EXT2_BOOT 0
+#define EXT2_SUPER 1
+#define EXT2_MAGIC 0x0000EF53
+
+struct 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 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 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];
+};
+#define INODE_SIZE (sizeof(struct inode))
+
+struct dirent {
+ u32 inode_num;
+ u16 total_len;
+ u8 name_len;
+ u8 type_indicator;
+ u8 name[];
+};
+
+struct file {
+ struct inode inode;
+ u32 pos;
+ u8 block_index;
+ u8 *buf;
+ u32 curr_block_pos;
+};
+
+// DEMO ;)
+void ls_root();
+
+#endif
diff --git a/src/inc/ide.h b/src/inc/ide.h
new file mode 100644
index 0000000..9d753ae
--- /dev/null
+++ b/src/inc/ide.h
@@ -0,0 +1,40 @@
+// MIT License, Copyright (c) 2020 Marvin Borner
+
+#ifndef IDE_H
+#define IDE_H
+
+#include <def.h>
+
+#define BLOCK_SIZE 1024
+#define SECTOR_SIZE 512
+
+#define IDE_BUSY (1 << 7)
+#define IDE_READY (1 << 6)
+#define IDE_DRIVE_FAULT (1 << 5)
+#define IDE_ERROR (1 << 0)
+
+#define IDE_IO 0x1F0
+#define IDE_DATA 0x0
+#define IDE_FEATURES 0x1
+#define IDE_SECTOR_COUNT 0x2
+#define IDE_LOW 0x3
+#define IDE_MID 0x4
+#define IDE_HIGH 0x5
+#define IDE_HEAD 0x6
+#define IDE_CMD 0x7
+#define IDE_ALTERNATE 0x3F6
+
+#define LBA_LOW(c) ((u8)(c & 0xFF))
+#define LBA_MID(c) ((u8)(c >> 8) & 0xFF)
+#define LBA_HIGH(c) ((u8)(c >> 16) & 0xFF)
+#define LBA_LAST(c) ((u8)(c >> 24) & 0xF)
+
+#define IDE_CMD_READ (BLOCK_SIZE / SECTOR_SIZE == 1) ? 0x20 : 0xC4
+#define IDE_CMD_WRITE (BLOCK_SIZE / SECTOR_SIZE == 1) ? 0x30 : 0xC5
+#define IDE_CMD_READ_MUL 0xC4
+#define IDE_CMD_WRITE_MUL 0xC5
+
+int ide_wait(int check);
+void *ide_read(void *b, u32 block);
+
+#endif
diff --git a/src/lib/inc/str.h b/src/lib/inc/str.h
index 0e00e75..f4c63b1 100644
--- a/src/lib/inc/str.h
+++ b/src/lib/inc/str.h
@@ -10,6 +10,7 @@ char *strcpy(char *dst, const char *src);
char *strchr(const char *s, int c);
char *strcat(char *dst, const char *src);
int strcmp(const char *s1, const char *s2);
+int strncmp(const char *s1, const char *s2, u32 n);
char *strinv(char *s);
char *strdup(const char *s);
diff --git a/src/lib/str.c b/src/lib/str.c
index 24f95e5..d1ee325 100644
--- a/src/lib/str.c
+++ b/src/lib/str.c
@@ -40,6 +40,22 @@ int strcmp(const char *s1, const char *s2)
return d;
}
+int 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;
+}
+
char *strchr(const char *s, int c)
{
while (*s != (char)c) {
diff --git a/src/main.c b/src/main.c
index a4b290c..7e4c083 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2,6 +2,7 @@
#include <boot.h>
#include <def.h>
+#include <fs.h>
#include <interrupts.h>
#include <keyboard.h>
#include <print.h>
@@ -24,7 +25,9 @@ void main(struct mem_info *mem_info, struct vid_info *vid_info)
vesa_fill(terminal_background);
serial_install();
- printf("hello");
+ printf("hello\n");
+
+ ls_root();
while (1) {
};