diff --git a/README.md b/README.md index fa9230f..3affa44 100755 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ -# LittleOS# OS +# LittleOS + +This project consists of writing an Operating System in x86 architecture. This project requires work within a UNIX/Linux environment, systems programming, C language, and computer systems in general. diff --git a/c_to_nasm.sh b/c_to_nasm.sh new file mode 100644 index 0000000..37b9e7a --- /dev/null +++ b/c_to_nasm.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Translates a C header to a NASM header +# The C header can only make use of: +# - #define +# - #ifndef +# - #endif + +# INPUT: A list of the required NASM headers + +set -e + +for NASM_HEADER in $@ +do + C_HEADER="${NASM_HEADER%%.inc}.h" + if [ $C_HEADER -nt $NASM_HEADER ]; then + sed 's/\/\*/;/' $C_HEADER | # change start of comments + sed 's/\*\///' | # change end of comments + sed 's/^#/%/' > $NASM_HEADER + fi +done diff --git a/constants.inc b/constants.inc new file mode 100644 index 0000000..93728b3 --- /dev/null +++ b/constants.inc @@ -0,0 +1,29 @@ +%ifndef CONSTANTS_H +%define CONSTANTS_H + +; numeric contants +%define FOUR_KB 0x1000 +%define ONE_MB 0x100000 +%define FOUR_MB 0x400000 +%define EIGHT_MB 0x800000 + +; virtual memory +%define KERNEL_START_VADDR 0xC0000000 +%define KERNEL_PDT_IDX (KERNEL_START_VADDR >> 22) + +; kernel stack +%define KERNEL_STACK_SIZE FOUR_KB + +; interrupts +%define SYSCALL_INT_IDX 0xAE + +; segements +%define SEGSEL_KERNEL_CS 0x08 +%define SEGSEL_KERNEL_DS 0x10 +%define SEGSEL_USER_SPACE_CS 0x18 +%define SEGSEL_USER_SPACE_DS 0x20 + +; registers +%define REG_EFLAGS_DEFAULT 0x202 + +%endif diff --git a/devfs.c b/devfs.c new file mode 100644 index 0000000..9ea282b --- /dev/null +++ b/devfs.c @@ -0,0 +1,148 @@ +#include "devfs.h" +#include "common.h" +#include "kmalloc.h" +#include "log.h" +#include "string.h" + +struct devfs_inode { + struct devfs_inode *next; + char const *name; + vnode_t *node; +}; +typedef struct devfs_inode devfs_inode_t; + +static devfs_inode_t *devices = NULL; + +static vnode_t root; +static vnodeops_t vnodeops; +static vfsops_t vfsops; + +static int devfs_root(vfs_t *vfs, vnode_t *out) +{ + UNUSED_ARGUMENT(vfs); + + out->v_op = root.v_op; + out->v_data = root.v_data; + + return 0; +} + +static int devfs_open(vnode_t *n) +{ + UNUSED_ARGUMENT(n); + + return -1; +} +static int devfs_read(vnode_t *node, void *buf, uint32_t count) +{ + UNUSED_ARGUMENT(node); + UNUSED_ARGUMENT(buf); + UNUSED_ARGUMENT(count); + + return -1; +} + +static int devfs_write(vnode_t *n, char const *s, size_t l) +{ + UNUSED_ARGUMENT(n); + UNUSED_ARGUMENT(s); + UNUSED_ARGUMENT(l); + + return -1; +} + +static int devfs_getattr(vnode_t *n, vattr_t *attr) +{ + UNUSED_ARGUMENT(n); + + attr->file_size = 0; + + return 0; +} + +static int devfs_lookup(vnode_t *dir, char const *name, vnode_t *out) +{ + UNUSED_ARGUMENT(dir); + + if (name == NULL) { + log_error("devfs_lookup", + "Trying to lookup a null path\n"); + return -1; + } + + devfs_inode_t *i; + for (i = devices; i != NULL; i = i->next) { + if (strcmp(i->name, name) == 0) { + out->v_op = i->node->v_op; + out->v_data = i->node->v_data; + return 0; + } + } + + return -1; +} + +int devfs_add_device(char const *path, vnode_t *node) +{ + if (path == NULL || strlen(path) == 0) { + log_error("devfs_add_device", + "path is empty or NULL\n"); + return -1; + } + + devfs_inode_t *i; + for (i = devices; i != NULL; i = i->next) { + if (strcmp(i->name, path) == 0) { + log_error("devfs_add_device", + "Trying to add a device that is already added: %s\n", + path); + return -1; + } + } + + int len = strlen(path) + 1; + char *copy = kmalloc(len); + if (copy == NULL) { + log_error("devfs_add_device", + "Could not allocated memory for path name %s\n", + path); + return -1; + } + memcpy(copy, path, len); + + devfs_inode_t *inode = kmalloc(sizeof(devfs_inode_t)); + if (inode == NULL) { + log_error("devfs_add_device", + "Could not allocated memory for devfs_inode_t struct\n"); + kfree(copy); + return -1; + } + + inode->next = NULL; + inode->name = copy; + inode->node = node; + + if (devices == NULL) { + devices = inode; + } else { + devices->next = inode; + } + + return 0; +} + +int devfs_init(vfs_t *vfs) +{ + vnodeops.vn_open = &devfs_open; + vnodeops.vn_getattr = &devfs_getattr; + vnodeops.vn_read = &devfs_read; + vnodeops.vn_lookup = &devfs_lookup; + vnodeops.vn_write = &devfs_write; + root.v_op = &vnodeops; + + vfsops.vfs_root = &devfs_root; + vfs->vfs_op = &vfsops; + vfs->vfs_data = 0; + + return 0; +} diff --git a/devfs.h b/devfs.h new file mode 100644 index 0000000..e7894fa --- /dev/null +++ b/devfs.h @@ -0,0 +1,10 @@ +#ifndef DEVFS_H +#define DEVFS_H + +#include "vfs.h" +#include "vnode.h" + +int devfs_init(vfs_t *vfs); +int devfs_add_device(char const *path, vnode_t *node); + +#endif /* DEVFS_H */ diff --git a/devfs.o b/devfs.o new file mode 100644 index 0000000..4b15c04 Binary files /dev/null and b/devfs.o differ diff --git a/fb.o b/fb.o index 54b9af8..1ced180 100644 Binary files a/fb.o and b/fb.o differ diff --git a/gdt.h b/gdt.h index bf36d72..7641042 100644 --- a/gdt.h +++ b/gdt.h @@ -10,3 +10,4 @@ void gdt_init(uint32_t tss_vaddr); #endif /* GDT_H */ + diff --git a/gdt_asm.o b/gdt_asm.o new file mode 100644 index 0000000..98bb953 Binary files /dev/null and b/gdt_asm.o differ diff --git a/gdt_asm.s b/gdt_asm.s new file mode 100644 index 0000000..62283fc --- /dev/null +++ b/gdt_asm.s @@ -0,0 +1,27 @@ +; these are functions dealing with the gdt and idt +; see also descriptor_tables.[c,h] + +global gdt_load_and_set + +SEGSEL_KERNEL_CS equ 0x08 +SEGSEL_KERNEL_DS equ 0x10 + +section .text + +; load the gdt into the cpu, and enter the kernel segments +gdt_load_and_set: + mov eax, [esp+4] ; fetch gdt_ptr from parameter stack + lgdt [eax] ; load gdt table + + ; load cs segment by doing a far jump + jmp SEGSEL_KERNEL_CS:.reload_segments + +.reload_segments: + ; we only use one segment for data + mov ax, SEGSEL_KERNEL_DS + mov ds, ax + mov ss, ax + mov es, ax + mov gs, ax + mov fs, ax + ret diff --git a/idt.c b/idt.c index 41f464e..3808be1 100644 --- a/idt.c +++ b/idt.c @@ -10,8 +10,6 @@ #define IDT_TIMER_INTERRUPT_INDEX 0x20 #define IDT_KEYBOARD_INTERRUPT_INDEX 0x21 -//for part 6 of little os - #define CREATE_IDT_GATE(idx) \ create_idt_gate(idx, (uint32_t) &interrupt_handler_##idx,\ IDT_TRAP_GATE_TYPE, PL0); @@ -165,3 +163,4 @@ static void create_idt_gate(uint8_t n, uint32_t handler, uint8_t type, (0x01 << 1) | type; } + diff --git a/idt.o b/idt.o index abf1fad..e461511 100644 Binary files a/idt.o and b/idt.o differ diff --git a/interrupt.c b/interrupt.c index af517eb..c02215a 100644 --- a/interrupt.c +++ b/interrupt.c @@ -8,10 +8,8 @@ #include "log.h" #include "constants.h" -//interupt handler for part 6 - static interrupt_handler_t interrupt_handlers[IDT_NUM_ENTRIES]; -/* + uint32_t register_interrupt_handler(uint32_t interrupt, interrupt_handler_t handler) { @@ -28,7 +26,7 @@ uint32_t register_interrupt_handler(uint32_t interrupt, interrupt_handlers[interrupt] = handler; return 0; } -*/ + void interrupt_handler(cpu_state_t state, idt_info_t info, stack_state_t exec) { if (interrupt_handlers[info.idt_index] != NULL) { diff --git a/interrupt.o b/interrupt.o index 42b903a..4e6d6be 100644 Binary files a/interrupt.o and b/interrupt.o differ