aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarvin Borner2019-10-31 17:47:40 +0100
committerGitHub2019-10-31 17:47:40 +0100
commitc7e755cb843593db1eedb26c5c24932bbe743745 (patch)
treead14da17e6d0d883e68cc6eacc99ae522036dda8
parentfd4f0a11126a20e75d72f8f2e6d418598fd5f37d (diff)
parent40a214f3c69a3d7da8c2f9bed5038dfa0ab72d4b (diff)
Merged pull request usermode
Added usermode
-rw-r--r--Makefile9
-rw-r--r--src/bootloader/grub.cfg (renamed from src/kernel/grub.cfg)2
-rw-r--r--src/bootloader/make_initrd.c53
-rw-r--r--src/bootloader/test.txt1
-rw-r--r--src/kernel/acpi/acpi.c6
-rw-r--r--src/kernel/boot.asm25
-rw-r--r--src/kernel/commands/command.c2
-rw-r--r--src/kernel/fs/initrd.c131
-rw-r--r--src/kernel/fs/initrd.h22
-rw-r--r--src/kernel/fs/vfs.c43
-rw-r--r--src/kernel/fs/vfs.h65
-rw-r--r--src/kernel/gdt/gdt.asm8
-rw-r--r--src/kernel/gdt/gdt.c75
-rw-r--r--src/kernel/gdt/gdt.h2
-rw-r--r--src/kernel/graphics/vesa.c8
-rw-r--r--src/kernel/graphics/vesa.h8
-rw-r--r--src/kernel/interrupts/idt.c2
-rw-r--r--src/kernel/kernel.c25
-rw-r--r--src/kernel/lib/lib.h6
-rw-r--r--src/kernel/lib/memory.c6
-rw-r--r--src/kernel/mutliboot.h47
-rw-r--r--src/kernel/paging/paging.c2
-rw-r--r--src/kernel/syscall/syscall.c46
-rw-r--r--src/kernel/syscall/syscall.h44
-rw-r--r--src/kernel/system.h5
-rw-r--r--src/userspace/main.c5
26 files changed, 617 insertions, 31 deletions
diff --git a/Makefile b/Makefile
index 6773be9..374a85b 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@ build: clean
nasm -f elf ./src/kernel/boot.asm -o ./build/boot.o || exit; \
# Make all C files
- find ./src/kernel/ -name \*.c >./build/tmp; \
+ find ./src/kernel/ ./src/userspace/ -name \*.c >./build/tmp; \
while read -r line; do \
stripped=$$(echo "$${line}" | sed -r 's/\//_/g'); \
stripped=$${stripped#??????}; \
@@ -40,7 +40,10 @@ build: clean
# Create ISO
mkdir -p ./iso/boot/grub; \
cp ./build/melvix.bin ./iso/boot/; \
- cp ./src/kernel/grub.cfg ./iso/boot/grub/; \
+ cp ./src/bootloader/grub.cfg ./iso/boot/grub/; \
+ gcc -w ./src/bootloader/make_initrd.c -o ./build/make_initrd || exit; \
+ ./build/make_initrd ./src/bootloader/test.txt test.txt || exit; \
+ mv initrd.img ./iso/boot/melvix.initrd || exit; \
grub-mkrescue -o ./build/melvix.iso ./iso/;
cross:
@@ -75,7 +78,7 @@ debug:
@rm -f qemu.log
@echo "Starting simulation"
@echo "[SERIAL OUTPUT]"
- @qemu-system-x86_64 -no-reboot -soundhw pcspk -M accel=kvm:tcg -vga std -serial stdio -d cpu_reset -D qemu.log -m 512M -cdrom ./build/melvix.iso
+ @qemu-system-x86_64 -no-reboot -soundhw pcspk -M accel=kvm:tcg -vga std -serial stdio -rtc base=localtime -d cpu_reset -D qemu.log -m 512M -cdrom ./build/melvix.iso
@echo "[END OF CONNECTION]"
.PHONY: build clean cross test debug \ No newline at end of file
diff --git a/src/kernel/grub.cfg b/src/bootloader/grub.cfg
index 8a452ed..cb265b1 100644
--- a/src/kernel/grub.cfg
+++ b/src/bootloader/grub.cfg
@@ -2,6 +2,6 @@ set timeout=0
set default=0
menuentry "Melvix" {
multiboot /boot/melvix.bin
- set gfxpayload=640x480x32
+ module /boot/melvix.initrd
boot
} \ No newline at end of file
diff --git a/src/bootloader/make_initrd.c b/src/bootloader/make_initrd.c
new file mode 100644
index 0000000..d7e0487
--- /dev/null
+++ b/src/bootloader/make_initrd.c
@@ -0,0 +1,53 @@
+#include <stdio.h>
+
+struct initrd_header {
+ unsigned char magic;
+ char name[64];
+ unsigned int offset;
+ unsigned int length;
+};
+
+int main(char argc, char **argv) {
+ int nheaders = (argc - 1) / 2;
+ struct initrd_header headers[64];
+ printf("size of header: %d\n", sizeof(struct initrd_header));
+ unsigned int off = sizeof(struct initrd_header) * 64 + sizeof(int);
+
+ for (int i = 0; i < nheaders; i++) {
+ printf("writing file %s->%s at 0x%x\n", argv[i * 2 + 1], argv[i * 2 + 2], off);
+ strcpy(headers[i].name, argv[i * 2 + 2]);
+ headers[i].name[strlen(argv[i * 2 + 2])] = '\0';
+ headers[i].offset = off;
+ FILE *stream = fopen(argv[i * 2 + 1], "r");
+ if (stream == 0) {
+ printf("Error: file not found: %s\n", argv[i * 2 + 1]);
+ return 1;
+ }
+ fseek(stream, 0, SEEK_END);
+ headers[i].length = ftell(stream);
+ off += headers[i].length;
+ fclose(stream);
+ headers[i].magic = 0xBF;
+ }
+
+ printf(headers[1].name);
+
+ FILE *wstream = fopen("./initrd.img", "w");
+ unsigned char *data = (unsigned char *) malloc(off);
+ fwrite(&nheaders, sizeof(int), 1, wstream);
+ fwrite(headers, sizeof(struct initrd_header), 64, wstream);
+
+ for (int i = 0; i < nheaders; i++) {
+ FILE *stream = fopen(argv[i * 2 + 1], "r");
+ unsigned char *buf = (unsigned char *) malloc(headers[i].length);
+ fread(buf, 1, headers[i].length, stream);
+ fwrite(buf, 1, headers[i].length, wstream);
+ fclose(stream);
+ free(buf);
+ }
+
+ fclose(wstream);
+ free(data);
+
+ return 0;
+}
diff --git a/src/bootloader/test.txt b/src/bootloader/test.txt
new file mode 100644
index 0000000..9033296
--- /dev/null
+++ b/src/bootloader/test.txt
@@ -0,0 +1 @@
+hallo \ No newline at end of file
diff --git a/src/kernel/acpi/acpi.c b/src/kernel/acpi/acpi.c
index 24da496..e0d260b 100644
--- a/src/kernel/acpi/acpi.c
+++ b/src/kernel/acpi/acpi.c
@@ -24,7 +24,7 @@ unsigned int *acpi_check_rsd_ptr(unsigned int *ptr) {
char check = 0;
unsigned int i;
- if (memory_compare(sig, rsdp, 8) == 0) {
+ if (memcmp(sig, rsdp, 8) == 0) {
bptr = (char *) ptr;
for (i = 0; i < sizeof(struct RSDPtr); i++) {
check += *bptr;
@@ -62,7 +62,7 @@ unsigned int *acpi_get_rsd_ptr() {
}
int acpi_check_header(unsigned int *ptr, char *sig) {
- if (memory_compare(ptr, sig, 4) == 0) {
+ if (memcmp(ptr, sig, 4) == 0) {
char *checkPtr = (char *) ptr;
int len = *(ptr + 1);
char check = 0;
@@ -122,7 +122,7 @@ int acpi_install() {
char *S5Addr = (char *) facp->DSDT + 36;
int dsdt_length = *(facp->DSDT + 1) - 36;
while (0 < dsdt_length--) {
- if (memory_compare(S5Addr, "_S5_", 4) == 0)
+ if (memcmp(S5Addr, "_S5_", 4) == 0)
break;
S5Addr++;
}
diff --git a/src/kernel/boot.asm b/src/kernel/boot.asm
index d533307..2501ed9 100644
--- a/src/kernel/boot.asm
+++ b/src/kernel/boot.asm
@@ -30,8 +30,13 @@ mboot:
dd start
; Endless loop
+extern kernel_main
stublet:
- extern kernel_main
+ ; Load multiboot information
+ push esp
+ push ebx
+
+ cli
call kernel_main
jmp $
@@ -45,6 +50,24 @@ stublet:
%include "src/kernel/interact.asm"
+global switch_to_user
+extern test_user
+switch_to_user:
+ sti
+ mov ax, 0x23
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+
+ mov eax, esp
+ push 0x23
+ push eax
+ pushf
+ push 0x1B
+ push test_user
+ iret
+
; Store the stack
SECTION .bss
resb 0x2000 ; Reserve 8KiB
diff --git a/src/kernel/commands/command.c b/src/kernel/commands/command.c
index 2334219..1118b29 100644
--- a/src/kernel/commands/command.c
+++ b/src/kernel/commands/command.c
@@ -8,7 +8,7 @@
int32_t starts_with(const char *a, const char *b) {
size_t length_pre = strlen(b);
size_t length_main = strlen(a);
- return length_main < length_pre ? 0 : memory_compare(b, a, length_pre) == 0;
+ return length_main < length_pre ? 0 : memcmp(b, a, length_pre) == 0;
}
void exec_command(char *command) {
diff --git a/src/kernel/fs/initrd.c b/src/kernel/fs/initrd.c
new file mode 100644
index 0000000..acaceb8
--- /dev/null
+++ b/src/kernel/fs/initrd.c
@@ -0,0 +1,131 @@
+#include <stdint.h>
+#include <kernel/fs/initrd.h>
+#include <kernel/fs/vfs.h>
+#include <kernel/lib/lib.h>
+#include <kernel/lib/alloc.h>
+#include <kernel/io/io.h>
+#include <kernel/graphics/vesa.h>
+
+initrd_header_t *initrd_header;
+initrd_file_header_t *file_headers;
+fs_node_t *initrd_root;
+fs_node_t *initrd_dev;
+fs_node_t *root_nodes;
+int nroot_nodes;
+
+struct dirent dirent;
+
+static uint32_t initrd_read(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
+ initrd_file_header_t header = file_headers[node->inode];
+ if (offset > header.length)
+ return 0;
+ if (offset + size > header.length)
+ size = header.length - offset;
+ memcpy(buffer, (uint8_t *) (header.offset + offset), size);
+ return size;
+}
+
+static struct dirent *initrd_readdir(fs_node_t *node, uint32_t index) {
+ if (node == initrd_root && index == 0) {
+ strcpy(dirent.name, "dev");
+ dirent.name[3] = 0;
+ dirent.ino = 0;
+ return &dirent;
+ }
+
+ if (index - 1 >= (uint32_t) nroot_nodes)
+ return 0;
+ strcpy(dirent.name, root_nodes[index - 1].name);
+ dirent.name[strlen(root_nodes[index - 1].name)] = 0;
+ dirent.ino = root_nodes[index - 1].inode;
+ return &dirent;
+}
+
+static fs_node_t *initrd_finddir(fs_node_t *node, char *name) {
+ if (node == initrd_root &&
+ !strcmp(name, "dev"))
+ return initrd_dev;
+
+ int i;
+ for (i = 0; i < nroot_nodes; i++)
+ if (!strcmp(name, root_nodes[i].name))
+ return &root_nodes[i];
+ return 0;
+}
+
+fs_node_t *initialise_initrd(uint32_t location) {
+ initrd_header = (initrd_header_t *) location;
+ file_headers = (initrd_file_header_t *) (location + sizeof(initrd_header_t));
+
+ initrd_root = (fs_node_t *) kmalloc(sizeof(fs_node_t));
+ strcpy(initrd_root->name, "initrd");
+ initrd_root->mask = initrd_root->uid = initrd_root->gid = initrd_root->inode = initrd_root->length = 0;
+ initrd_root->flags = FS_DIRECTORY;
+ initrd_root->read = 0;
+ initrd_root->write = 0;
+ initrd_root->open = 0;
+ initrd_root->close = 0;
+ initrd_root->readdir = &initrd_readdir;
+ initrd_root->finddir = &initrd_finddir;
+ initrd_root->ptr = 0;
+ initrd_root->impl = 0;
+
+ initrd_dev = (fs_node_t *) kmalloc(sizeof(fs_node_t));
+ strcpy(initrd_dev->name, "dev");
+ initrd_dev->mask = initrd_dev->uid = initrd_dev->gid = initrd_dev->inode = initrd_dev->length = 0;
+ initrd_dev->flags = FS_DIRECTORY;
+ initrd_dev->read = 0;
+ initrd_dev->write = 0;
+ initrd_dev->open = 0;
+ initrd_dev->close = 0;
+ initrd_dev->readdir = &initrd_readdir;
+ initrd_dev->finddir = &initrd_finddir;
+ initrd_dev->ptr = 0;
+ initrd_dev->impl = 0;
+
+ root_nodes = (fs_node_t *) kmalloc(sizeof(fs_node_t) * initrd_header->nfiles);
+ nroot_nodes = initrd_header->nfiles;
+
+ for (uint32_t i = 0; i < initrd_header->nfiles; i++) {
+ file_headers[i].offset += location;
+
+ strcpy(root_nodes[i].name, (const char *) &file_headers[i].name);
+ root_nodes[i].mask = root_nodes[i].uid = root_nodes[i].gid = 0;
+ root_nodes[i].length = file_headers[i].length;
+ root_nodes[i].inode = i;
+ root_nodes[i].flags = FS_FILE;
+ root_nodes[i].read = &initrd_read;
+ root_nodes[i].write = 0;
+ root_nodes[i].readdir = 0;
+ root_nodes[i].finddir = 0;
+ root_nodes[i].open = 0;
+ root_nodes[i].close = 0;
+ root_nodes[i].impl = 0;
+ }
+ return initrd_root;
+}
+
+void initrd_test() {
+ int i = 0;
+ struct dirent *node = 0;
+ vesa_draw_string("\n");
+ while ((node = readdir_fs(fs_root, i)) != 0) {
+ vesa_draw_string("Found file: ");
+ vesa_draw_string(node->name);
+ vesa_draw_string("\n");
+ fs_node_t *fsnode = finddir_fs(fs_root, node->name);
+
+ if ((fsnode->flags & 0x7) == FS_DIRECTORY)
+ vesa_draw_string("\t (directory)\n");
+ else {
+ vesa_draw_string("\t contents: \"");
+ uint8_t buf[fsnode->length];
+ uint32_t sz = read_fs(fsnode, 0, fsnode->length, buf);
+ for (uint32_t j = 0; j < sz; j++)
+ vesa_draw_char(buf[j]);
+
+ vesa_draw_string("\"\n");
+ }
+ i++;
+ }
+} \ No newline at end of file
diff --git a/src/kernel/fs/initrd.h b/src/kernel/fs/initrd.h
new file mode 100644
index 0000000..bb5c376
--- /dev/null
+++ b/src/kernel/fs/initrd.h
@@ -0,0 +1,22 @@
+#ifndef MELVIX_INITRD_H
+#define MELVIX_INITRD_H
+
+#include <stdint.h>
+#include <kernel/fs/vfs.h>
+
+typedef struct {
+ uint32_t nfiles;
+} initrd_header_t;
+
+typedef struct {
+ uint8_t magic;
+ int8_t name[64];
+ uint32_t offset;
+ uint32_t length;
+} initrd_file_header_t;
+
+fs_node_t *initialise_initrd(uint32_t location);
+
+void initrd_test();
+
+#endif
diff --git a/src/kernel/fs/vfs.c b/src/kernel/fs/vfs.c
new file mode 100644
index 0000000..5591a60
--- /dev/null
+++ b/src/kernel/fs/vfs.c
@@ -0,0 +1,43 @@
+#include <kernel/fs/vfs.h>
+
+fs_node_t *fs_root = 0;
+
+uint32_t read_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
+ if (node->read != 0)
+ return node->read(node, offset, size, buffer);
+ else
+ return 0;
+}
+
+uint32_t write_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
+ if (node->write != 0)
+ return node->write(node, offset, size, buffer);
+ else
+ return 0;
+}
+
+void open_fs(fs_node_t *node, uint8_t read, uint8_t write) {
+ if (node->open != 0)
+ return node->open(node);
+}
+
+void close_fs(fs_node_t *node) {
+ if (node->close != 0)
+ return node->close(node);
+}
+
+struct dirent *readdir_fs(fs_node_t *node, uint32_t index) {
+ if ((node->flags & 0x7) == FS_DIRECTORY &&
+ node->readdir != 0)
+ return node->readdir(node, index);
+ else
+ return 0;
+}
+
+fs_node_t *finddir_fs(fs_node_t *node, char *name) {
+ if ((node->flags & 0x7) == FS_DIRECTORY &&
+ node->finddir != 0)
+ return node->finddir(node, name);
+ else
+ return 0;
+}
diff --git a/src/kernel/fs/vfs.h b/src/kernel/fs/vfs.h
new file mode 100644
index 0000000..5a72861
--- /dev/null
+++ b/src/kernel/fs/vfs.h
@@ -0,0 +1,65 @@
+#ifndef MELVIX_VFS_H
+#define MELVIX_VFS_H
+
+#include <stdint.h>
+
+#define FS_FILE 0x01
+#define FS_DIRECTORY 0x02
+#define FS_CHARDEVICE 0x03
+#define FS_BLOCKDEVICE 0x04
+#define FS_PIPE 0x05
+#define FS_SYMLINK 0x06
+#define FS_MOUNTPOINT 0x08
+
+struct fs_node;
+
+typedef uint32_t (*read_type_t)(struct fs_node *, uint32_t, uint32_t, uint8_t *);
+
+typedef uint32_t (*write_type_t)(struct fs_node *, uint32_t, uint32_t, uint8_t *);
+
+typedef void (*open_type_t)(struct fs_node *);
+
+typedef void (*close_type_t)(struct fs_node *);
+
+typedef struct dirent *(*readdir_type_t)(struct fs_node *, uint32_t);
+
+typedef struct fs_node *(*finddir_type_t)(struct fs_node *, char *name);
+
+typedef struct fs_node {
+ char name[128];
+ uint32_t mask;
+ uint32_t uid;
+ uint32_t gid;
+ uint32_t flags;
+ uint32_t inode;
+ uint32_t length;
+ uint32_t impl;
+ read_type_t read;
+ write_type_t write;
+ open_type_t open;
+ close_type_t close;
+ readdir_type_t readdir;
+ finddir_type_t finddir;
+ struct fs_node *ptr;
+} fs_node_t;
+
+struct dirent {
+ char name[128];
+ uint32_t ino;
+};
+
+extern fs_node_t *fs_root;
+
+uint32_t read_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
+
+uint32_t write_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
+
+void open_fs(fs_node_t *node, uint8_t read, uint8_t write);
+
+void close_fs(fs_node_t *node);
+
+struct dirent *readdir_fs(fs_node_t *node, uint32_t index);
+
+fs_node_t *finddir_fs(fs_node_t *node, char *name);
+
+#endif
diff --git a/src/kernel/gdt/gdt.asm b/src/kernel/gdt/gdt.asm
index c2128e4..6cb2b7d 100644
--- a/src/kernel/gdt/gdt.asm
+++ b/src/kernel/gdt/gdt.asm
@@ -11,4 +11,10 @@ gdt_flush:
mov ss, ax
jmp 0x08:flush2 ; Code segment offset
flush2:
- ret ; Returns to C code \ No newline at end of file
+ ret ; Returns to C code
+
+global tss_flush
+tss_flush:
+ mov ax, 0x2B
+ ltr ax
+ ret \ No newline at end of file
diff --git a/src/kernel/gdt/gdt.c b/src/kernel/gdt/gdt.c
index a4d6a57..1c69602 100644
--- a/src/kernel/gdt/gdt.c
+++ b/src/kernel/gdt/gdt.c
@@ -1,4 +1,8 @@
+#include <stdint.h>
+#include <kernel/gdt/gdt.h>
#include <kernel/system.h>
+#include <kernel/lib/lib.h>
+#include <kernel/io/io.h>
struct gdt_entry {
unsigned short limit_low;
@@ -14,12 +18,46 @@ struct gdt_ptr {
void *base;
} __attribute__((packed));
-struct gdt_entry gdt[3];
+struct gdt_entry gdt[6];
struct gdt_ptr gp;
+struct tss_entry_struct {
+ uint32_t prev_tss;
+ uint32_t esp0;
+ uint32_t ss0;
+ uint32_t esp1;
+ uint32_t ss1;
+ uint32_t esp2;
+ uint32_t ss2;
+ uint32_t cr3;
+ uint32_t eip;
+ uint32_t eflags;
+ uint32_t eax;
+ uint32_t ecx;
+ uint32_t edx;
+ uint32_t ebx;
+ uint32_t esp;
+ uint32_t ebp;
+ uint32_t esi;
+ uint32_t edi;
+ uint32_t es;
+ uint32_t cs;
+ uint32_t ss;
+ uint32_t ds;
+ uint32_t fs;
+ uint32_t gs;
+ uint32_t ldt;
+ uint16_t trap;
+ uint16_t iomap_base;
+} __attribute__((packed));
+
+struct tss_entry_struct tss_entry;
+
extern void gdt_flush();
-void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran) {
+extern void tss_flush();
+
+void gdt_set_gate(int32_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) {
// Set descriptor base address
gdt[num].base_low = (base & 0xFFFF);
gdt[num].base_middle = (base >> 16) & 0xFF;
@@ -36,7 +74,7 @@ void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned cha
void gdt_install() {
// Set GDT pointer and limit
- gp.limit = (sizeof(struct gdt_entry) * 3) - 1;
+ gp.limit = (sizeof(struct gdt_entry) * 6) - 1;
gp.base = &gdt;
// NULL descriptor
@@ -48,8 +86,37 @@ void gdt_install() {
// Data segment
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
+ // User mode code segment
+ gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF);
+
+ // User mode data segment
+ gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF);
+
+ // Write TSS
+ tss_write(5, 0x10, 0x0);
+
// Remove old GDT and install the new changes!
gdt_flush();
+ tss_flush();
vga_log("Installed Global Descriptor Table", 2);
-} \ No newline at end of file
+}
+
+void tss_write(int32_t num, uint16_t ss0, uint32_t esp0) {
+ uint32_t base = (uint32_t) &tss_entry;
+ uint32_t limit = base + sizeof(tss_entry);
+
+ gdt_set_gate(num, base, limit, 0xE9, 0x00);
+
+ memset(&tss_entry, 0, sizeof(tss_entry));
+
+ tss_entry.ss0 = ss0;
+ tss_entry.esp0 = esp0;
+
+ tss_entry.cs = 0x0b;
+ tss_entry.ss = tss_entry.ds = tss_entry.es = tss_entry.fs = tss_entry.gs = 0x13;
+}
+
+void set_kernel_stack(uint32_t stack) {
+ tss_entry.esp0 = stack;
+}
diff --git a/src/kernel/gdt/gdt.h b/src/kernel/gdt/gdt.h
index de8a6ff..0fffc20 100644
--- a/src/kernel/gdt/gdt.h
+++ b/src/kernel/gdt/gdt.h
@@ -6,4 +6,6 @@
*/
void gdt_install();
+void tss_write(int32_t num, uint16_t ss0, uint32_t esp0);
+
#endif
diff --git a/src/kernel/graphics/vesa.c b/src/kernel/graphics/vesa.c
index 8347c56..858ed95 100644
--- a/src/kernel/graphics/vesa.c
+++ b/src/kernel/graphics/vesa.c
@@ -167,7 +167,7 @@ void set_optimal_resolution() {
switch_to_vga();
} else vga_log("Mode detection succeeded", 11);
- timer_wait(500);
+ // timer_wait(500);
vbe_set_mode(highest);
@@ -287,6 +287,8 @@ void vesa_draw_char(char ch) {
} else if (ch == '\n') {
terminal_x = 0;
terminal_y += font_height + 2;
+ } else if (ch == '\t') {
+ terminal_x += 4 * (font_width + 2);
}
if (terminal_x >= vbe_width) {
@@ -309,7 +311,7 @@ void vesa_keyboard_char(char ch) {
} else if (ch == '\n') {
vesa_draw_char(ch);
exec_command(text);
- memory_set(text, 0, sizeof(text));
+ memset(text, 0, sizeof(text));
// terminal_scroll();
} else if (ch >= ' ') {
vesa_draw_char(ch);
@@ -322,7 +324,7 @@ void vesa_keyboard_char(char ch) {
terminal_color);
}
-void vesa_draw_string(char *data) {
+void vesa_draw_string(const char *data) {
int i = 0;
while (data[i] != '\0') {
vesa_draw_char(data[i]);
diff --git a/src/kernel/graphics/vesa.h b/src/kernel/graphics/vesa.h
index 649c6ee..3fcef24 100644
--- a/src/kernel/graphics/vesa.h
+++ b/src/kernel/graphics/vesa.h
@@ -129,6 +129,12 @@ void vesa_clear();
void vesa_set_font(int height);
/**
+ * Draws a single char
+ * @param ch The char
+ */
+void vesa_draw_char(char ch);
+
+/**
* Draw a char from keyboard
* @param ch The character
*/
@@ -138,7 +144,7 @@ void vesa_keyboard_char(char ch);
* Draw a string in VESA mode
* @param data The string
*/
-void vesa_draw_string(char *data);
+void vesa_draw_string(const char *data);
/**
* Draw a number in VESA mode
diff --git a/src/kernel/interrupts/idt.c b/src/kernel/interrupts/idt.c
index 26489c4..5f92294 100644
--- a/src/kernel/interrupts/idt.c
+++ b/src/kernel/interrupts/idt.c
@@ -39,7 +39,7 @@ void idt_install() {
idtp.base = &idt;
// Clear IDT by setting memory cells to 0
- memory_set(&idt, 0, sizeof(struct idt_entry) * 256);
+ memset(&idt, 0, sizeof(struct idt_entry) * 256);
idt_load();
vga_log("Installed Interrupt Descriptor Table", 6);
diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c
index 75867a8..b133a0c 100644
--- a/src/kernel/kernel.c
+++ b/src/kernel/kernel.c
@@ -6,8 +6,13 @@
#include <kernel/paging/paging.h>
#include <kernel/input/input.h>
#include <kernel/acpi/acpi.h>
+#include <kernel/mutliboot.h>
+#include <kernel/fs/initrd.h>
+#include <kernel/syscall/syscall.h>
-void init() {
+extern void switch_to_user();
+
+void kernel_main(struct multiboot *mboot_ptr) {
vga_log("Installing basic features of Melvix...", 0);
// Install features
timer_install();
@@ -19,14 +24,26 @@ void init() {
isrs_install();
irq_install();
set_optimal_resolution();
+
// Install drivers
asm volatile ("cli");
keyboard_install();
asm volatile ("sti");
-}
-void kernel_main(void) {
- init();
+ // Setup initial ramdisk
+ assert(mboot_ptr->mods_count > 0);
+ uint32_t initrd_location = *((uint32_t *) mboot_ptr->mods_addr);
+ uint32_t initrd_end = *(uint32_t *) (mboot_ptr->mods_addr + 4);
+ paging_set_used(0, (initrd_end >> 12) + 1);
+ fs_root = initialise_initrd(initrd_location);
+ initrd_test();
+
+ // User mode!
+ info("Switching to user mode...");
+ syscalls_install();
+ switch_to_user();
+
+ panic("This should NOT happen!");
// asm volatile ("div %0" :: "r"(0)); // Exception testing x/0
loop:
diff --git a/src/kernel/lib/lib.h b/src/kernel/lib/lib.h
index de09e0f..420dd5b 100644
--- a/src/kernel/lib/lib.h
+++ b/src/kernel/lib/lib.h
@@ -39,7 +39,7 @@ void strcpy(char *dest, const char *src);
* @param count The number of bytes to be copied (src)
* @return The modified dest pointer
*/
-void *memory_copy(void *dest, const void *src, size_t count);
+void *memcpy(void *dest, const void *src, size_t count);
/**
* Replace n bytes of dest by val
@@ -48,7 +48,7 @@ void *memory_copy(void *dest, const void *src, size_t count);
* @param count The number of times val should replace dest entry
* @return The modified dest pointer
*/
-void *memory_set(void *dest, char val, size_t count);
+void *memset(void *dest, char val, size_t count);
/**
* Compare the first n bytes of a and b
@@ -57,6 +57,6 @@ void *memory_set(void *dest, char val, size_t count);
* @param size The number of bytes to be compared
* @return -1 if a < b, 0 if a = b and 1 if a > b
*/
-int memory_compare(const void *a_ptr, const void *b_ptr, size_t size);
+int memcmp(const void *a_ptr, const void *b_ptr, size_t size);
#endif
diff --git a/src/kernel/lib/memory.c b/src/kernel/lib/memory.c
index 6ec4ed9..a030c9a 100644
--- a/src/kernel/lib/memory.c
+++ b/src/kernel/lib/memory.c
@@ -1,19 +1,19 @@
#include <stddef.h>
-void *memory_copy(void *dest, const void *src, size_t count) {
+void *memcpy(void *dest, const void *src, size_t count) {
const char *sp = (const char *) src;
char *dp = (char *) dest;
for (; count != 0; count--) *dp++ = *sp++;
return dest;
}
-void *memory_set(void *dest, char val, size_t count) {
+void *memset(void *dest, char val, size_t count) {
char *temp = (char *) dest;
for (; count != 0; count--) *temp++ = val;
return dest;
}
-int memory_compare(const void *a_ptr, const void *b_ptr, size_t size) {
+int memcmp(const void *a_ptr, const void *b_ptr, size_t size) {
const unsigned char *a = (const unsigned char *) a_ptr;
const unsigned char *b = (const unsigned char *) b_ptr;
for (size_t i = 0; i < size; i++) {
diff --git a/src/kernel/mutliboot.h b/src/kernel/mutliboot.h
new file mode 100644
index 0000000..683f95f
--- /dev/null
+++ b/src/kernel/mutliboot.h
@@ -0,0 +1,47 @@
+#ifndef MELVIX_MUTLIBOOT_H
+#define MELVIX_MUTLIBOOT_H
+
+#include <stdint.h>
+
+#define MULTIBOOT_FLAG_MEM 0x001
+#define MULTIBOOT_FLAG_DEVICE 0x002
+#define MULTIBOOT_FLAG_CMDLINE 0x004
+#define MULTIBOOT_FLAG_MODS 0x008
+#define MULTIBOOT_FLAG_AOUT 0x010
+#define MULTIBOOT_FLAG_ELF 0x020
+#define MULTIBOOT_FLAG_MMAP 0x040
+#define MULTIBOOT_FLAG_CONFIG 0x080
+#define MULTIBOOT_FLAG_LOADER 0x100
+#define MULTIBOOT_FLAG_APM 0x200
+#define MULTIBOOT_FLAG_VBE 0x400
+
+struct multiboot {
+ uint32_t flags;
+ uint32_t mem_lower;
+ uint32_t mem_upper;
+ uint32_t boot_device;
+ uint32_t cmdline;
+ uint32_t mods_count;
+ uint32_t mods_addr;
+ uint32_t num;
+ uint32_t size;
+ uint32_t addr;
+ uint32_t shndx;
+ uint32_t mmap_length;
+ uint32_t mmap_addr;
+ uint32_t drives_length;
+ uint32_t drives_addr;
+ uint32_t config_table;
+ uint32_t boot_loader_name;
+ uint32_t apm_table;
+ uint32_t vbe_control_info;
+ uint32_t vbe_mode_info;
+ uint32_t vbe_mode;
+ uint32_t vbe_interface_seg;
+ uint32_t vbe_interface_off;
+ uint32_t vbe_interface_len;
+} __attribute__((packed));
+
+typedef struct multiboot_header multiboot_header_t;
+
+#endif
diff --git a/src/kernel/paging/paging.c b/src/kernel/paging/paging.c
index 02fc253..bb3b1df 100644
--- a/src/kernel/paging/paging.c
+++ b/src/kernel/paging/paging.c
@@ -2,8 +2,6 @@
#include <kernel/paging/paging.h>
#include <kernel/system.h>
-extern void *end;
-
uint32_t page_directory[1024] __attribute__((aligned(4096)));
uint32_t page_tables[1024][1024] __attribute__((aligned(4096)));
diff --git a/src/kernel/syscall/syscall.c b/src/kernel/syscall/syscall.c
new file mode 100644
index 0000000..dec3e8e
--- /dev/null
+++ b/src/kernel/syscall/syscall.c
@@ -0,0 +1,46 @@
+#include <stdint.h>
+#include <kernel/syscall/syscall.h>
+#include <kernel/interrupts/interrupts.h>
+#include <kernel/graphics/vesa.h>
+#include <kernel/io/io.h>
+
+DEFN_SYSCALL1(vesa_draw_string, 0, const char *);
+
+DEFN_SYSCALL1(vesa_draw_number, 1, int);
+
+DEFN_SYSCALL1(serial_write, 2, const char *);
+
+static void *syscalls[3] = {
+ &vesa_draw_string,
+ &vesa_draw_number,
+ &serial_write,
+};
+uint32_t num_syscalls = 3;
+
+void syscall_handler(struct regs *r) {
+ serial_write("SYSCALL");
+ if (r->eax >= num_syscalls)
+ return;
+
+ void *location = syscalls[r->eax];
+
+ int ret;
+ asm volatile (" \
+ push %1; \
+ push %2; \
+ push %3; \
+ push %4; \
+ push %5; \
+ call *%6; \
+ pop %%ebx; \
+ pop %%ebx; \
+ pop %%ebx; \
+ pop %%ebx; \
+ pop %%ebx; \
+ " : "=a" (ret) : "r" (r->edi), "r" (r->esi), "r" (r->edx), "r" (r->ecx), "r" (r->ebx), "r" (location));
+ r->eax = ret;
+}
+
+void syscalls_install() {
+ irq_install_handler(0x80, syscall_handler);
+}
diff --git a/src/kernel/syscall/syscall.h b/src/kernel/syscall/syscall.h
new file mode 100644
index 0000000..d35c4e6
--- /dev/null
+++ b/src/kernel/syscall/syscall.h
@@ -0,0 +1,44 @@
+#ifndef MELVIX_SYSCALL_H
+#define MELVIX_SYSCALL_H
+
+#include <kernel/interrupts/interrupts.h>
+
+void syscalls_install();
+
+void syscall_handler(struct regs *r);
+
+#define DECL_SYSCALL0(fn) int syscall_##fn();
+#define DECL_SYSCALL1(fn, p1) int syscall_##fn(p1);
+#define DECL_SYSCALL2(fn, p1, p2) int syscall_##fn(p1,p2);
+#define DECL_SYSCALL3(fn, p1, p2, p3) int syscall_##fn(p1,p2,p3);
+#define DECL_SYSCALL4(fn, p1, p2, p3, p4) int syscall_##fn(p1,p2,p3,p4);
+#define DECL_SYSCALL5(fn, p1, p2, p3, p4, p5) int syscall_##fn(p1,p2,p3,p4,p5);
+
+#define DEFN_SYSCALL0(fn, num) \
+int syscall_##fn() { \
+ int a; \
+ asm volatile("int $0x80" : "=a" (a) : "0" (num)); \
+ return a; \
+}
+
+#define DEFN_SYSCALL1(fn, num, P1) \
+int syscall_##fn(P1 p1) { \
+ int a; \
+ asm volatile("int $0x80" : "=a" (a) : "0" (num), "b" ((int)p1)); \
+ return a; \
+}
+
+#define DEFN_SYSCALL2(fn, num, P1, P2) \
+int syscall_##fn(P1 p1, P2 p2) { \
+ int a; \
+ asm volatile("int $0x80" : "=a" (a) : "0" (num), "b" ((int)p1), "c" ((int)p2)); \
+ return a; \
+}
+
+DECL_SYSCALL1(vesa_draw_string, const char *)
+
+DECL_SYSCALL1(vesa_draw_number, int)
+
+DECL_SYSCALL1(serial_write, const char *)
+
+#endif
diff --git a/src/kernel/system.h b/src/kernel/system.h
index e6888fc..d431a9e 100644
--- a/src/kernel/system.h
+++ b/src/kernel/system.h
@@ -2,6 +2,11 @@
#define MELVIX_SYSTEM_H
/**
+ * The kernel end
+ */
+extern void *end;
+
+/**
* Initialize the basic features of the OS
*/
void init();
diff --git a/src/userspace/main.c b/src/userspace/main.c
new file mode 100644
index 0000000..526144e
--- /dev/null
+++ b/src/userspace/main.c
@@ -0,0 +1,5 @@
+#include <kernel/syscall/syscall.h>
+
+void test_user() {
+ syscall_serial_write("Hello, user world!\n");
+} \ No newline at end of file