CeDOS - Commit 7a5d14d9

Implemented Program Loader
Celina Sophie Kalus
Fri, 26 Jan 2018 23:30:27 +0100
19 files changed, 201 insertions(+), 82 deletions(-)
A apps/cedos/makefile

@@ -0,0 +1,4 @@

+.RECIPEPREFIX = > +.PHONY: build +build: +>
A apps/crt0/makefile

@@ -0,0 +1,4 @@

+.RECIPEPREFIX = > +.PHONY: build +build: +>
A apps/include/makefile

@@ -0,0 +1,4 @@

+.RECIPEPREFIX = > +.PHONY: build +build: +>
M apps/link.txtapps/link.txt

@@ -0,0 +1,16 @@

+OUTPUT_ARCH(i386) +OUTPUT_FORMAT(elf32-i386) + +MEMORY +{ + HEADER : ORIGIN = 0x00000000, LENGTH = 0x10000000 + CODE : ORIGIN = 0x10000000, LENGTH = 0xB0000000 +} + +SECTIONS +{ + .text : AT(0x0000) + { + */start.c.o(.*) + } >CODE +}
A apps/makefile

@@ -0,0 +1,27 @@

+.RECIPEPREFIX = > + +S_OBJECTS = $(patsubst %.s,$(LOCAL_BUILD)/%.s.o,$(wildcard *.s)) +C_OBJECTS = $(patsubst %.c,$(LOCAL_BUILD)/%.c.o,$(wildcard *.c)) +OBJECTS = $(S_OBJECTS) $(C_OBJECTS) + +LOCAL_BUILD = $(GLOBAL_BUILD)/apps + +SUBDIRS = $(wildcard */.) + +.PHONY: build +build: folder $(SUBDIRS) $(OBJECTS) +> $(GCC_PREFIX)ld -T link.txt $(wildcard $(LOCAL_BUILD)/*.o) -o $(GLOBAL_BUILD)/apps.o --oformat elf32-i386 + +.PHONY: folder +folder: +> @mkdir $(LOCAL_BUILD) 2> /dev/null; true + +.PHONY: $(SUBDIRS) +$(SUBDIRS): +> make -C $@ GLOBAL_BUILD=$(LOCAL_BUILD) build + +$(LOCAL_BUILD)/%.s.o: %.s +> $(GCC_PREFIX)as -o $@ $< + +$(LOCAL_BUILD)/%.c.o: %.c $(wildcard *.h) +> $(GCC_PREFIX)gcc -c -I$(INCLUDE_DIR) --prefix=$(GCC_PREFIX) $(GCC_OPTIONS) -o $@ $<
A apps/start.c

@@ -0,0 +1,24 @@

+#include <stdint.h> + +/*! + * Performs a syscall. + */ +__attribute__((always_inline)) inline int syscall(int eax, int ebx, int ecx, int edx) { + int res; + __asm__ volatile ( "mov %1, %%eax;" + "mov %2, %%ebx;" + "mov %3, %%ecx;" + "mov %4, %%edx;" + "int $0x30;" + "mov %%eax, %0;" : "=m" (res) : "" (eax), "" (ebx), "" (ecx), "" (edx) : "eax", "ebx", "ecx", "edx"); + return res; +} + +int start(void) { + uint32_t eip, esp, ebp; + __asm__ volatile ("call jump; jump: pop %0; mov %%esp, %1; mov %%ebp, %2" : "=m" (eip), "=m" (esp), "=m" (ebp)); + + syscall(0, eip, esp, ebp); + + while(1); +}
M boot/stage1/boot.sboot/stage1/boot.s

@@ -42,7 +42,9 @@ # TODO:

# - activate A20 gate # reset bootdrive + mov $10, %cx reset: + push %cx movw $reset_msg, %si call print movw $bootdrive_msg, %si

@@ -50,7 +52,11 @@ call print

movb $0x00, %ah int $0x13 + pop %cx + jnc reset_end + loop reset jc error +reset_end: movw $done_msg, %si call print

@@ -60,7 +66,9 @@ # (NOTE: this code can only be jumped to after loading the global descriptor table

# because it uses absolute adresses larger than 16 bit) # (NOTE2: this routine only loads 0x48 sectors of the second stage into memory # and is in general pretty whacky. should be replaced with sth more serious) + mov $10, %cx load: + push %cx movw $load_msg, %si call print

@@ -74,7 +82,11 @@ movb $0x02, %cl # sector

movb $0x00, %dh # head # dl (drive) keep as is int $0x13 + pop %cx + jnc load_end + loop load jc error +load_end: movw $done_msg, %si call print
M boot/stage2/linker.hboot/stage2/linker.h

@@ -14,6 +14,10 @@ extern uint8_t __KERNEL_VMA;

extern uint8_t __KERNEL_LMA; extern uint8_t __KERNEL_SIZE; +extern uint8_t __APP_VMA; +extern uint8_t __APP_LMA; +extern uint8_t __APP_SIZE; + #define SS_VMA (&__SS_VMA) #define SS_LMA (&__SS_LMA) #define SS_SIZE (uint32_t)(&__SS_SIZE)

@@ -21,5 +25,9 @@

#define KERNEL_VMA (&__KERNEL_VMA) #define KERNEL_LMA (&__KERNEL_LMA) #define KERNEL_SIZE (uint32_t)(&__KERNEL_SIZE) + +#define APP_VMA (&__APP_VMA) +#define APP_LMA (&__APP_LMA) +#define APP_SIZE (uint32_t)(&__APP_SIZE) #endif
M boot/stage2/main.cboot/stage2/main.c

@@ -41,7 +41,7 @@ void copy_kernel(void) {

uint8_t *kernel_dest = (uint8_t*)0x00100000; uint8_t *kernel_src = (SS_VMA + (KERNEL_LMA - SS_LMA)); - for (uint32_t i = 0; i < KERNEL_SIZE; i++) { + for (uint32_t i = 0; i < KERNEL_SIZE + APP_SIZE; i++) { kernel_dest[i] = kernel_src[i]; } }
M include/cedos/sched/sched.hinclude/cedos/sched/sched.h

@@ -10,6 +10,8 @@ #include "cedos/sched/process.h"

#include "cedos/mm/paging.h" +#define SCHED_INTERVAL (0xFFFF) + /*! * Structure of the process stack when the scheduler is executed. */

@@ -30,7 +32,7 @@

/*! * Executes a task. */ -PROCESS_ID sched_exec(PHYS_ADDR page_dir, PROCESS_MAIN *entry, const char *name); +PROCESS_ID sched_exec(VIRT_ADDR code, uint32_t code_len, PROCESS_MAIN *entry, const char *name); /*! * Return the ID of the current process.
M include/linker.hinclude/linker.h

@@ -14,6 +14,10 @@ extern uint8_t __KERNEL_VMA;

extern uint8_t __KERNEL_LMA; extern uint8_t __KERNEL_SIZE; +extern uint8_t __APP_VMA; +extern uint8_t __APP_LMA; +extern uint8_t __APP_SIZE; + #define SS_VMA (&__SS_VMA) #define SS_LMA (&__SS_LMA) #define SS_SIZE (uint32_t)(&__SS_SIZE)

@@ -21,5 +25,9 @@

#define KERNEL_VMA (&__KERNEL_VMA) #define KERNEL_LMA (&__KERNEL_LMA) #define KERNEL_SIZE (uint32_t)(&__KERNEL_SIZE) + +#define APP_VMA (&__APP_VMA) +#define APP_LMA (&__APP_LMA) +#define APP_SIZE (uint32_t)(&__APP_SIZE) #endif
M kernel/core.ckernel/core.c

@@ -49,6 +49,7 @@ rek_print_uint((unsigned int)value);

} void memdump(void* start, uint32_t size) { + crit_enter(); uint8_t* _start = (uint8_t*)((uint32_t)start & 0xFFFFFFF0); uint8_t* _end = (uint8_t*)(((uint32_t)start + size + 0xF) & 0xFFFFFFF0);

@@ -74,6 +75,8 @@ }

} core_con->write_c('\n'); } + + crit_exit(); } void stackdump(void) {

@@ -103,8 +106,8 @@ "=m" (edi),

"=m" (esp), "=m" (ebp)); - printk(" EAX=%i EBX=%i ECX=%i EDX=%i\n", eax, ebx, ecx, edx); - printk(" ESI=%i EDI=%i ESP=%i EBP=%i\n", esi, edi, esp, ebp); + printk(" EAX=%X EBX=%X ECX=%X EDX=%X\n", eax, ebx, ecx, edx); + printk(" ESI=%X EDI=%X ESP=%X EBP=%X\n", esi, edi, esp, ebp); } void printk(const char* fmt, ...) {

@@ -127,6 +130,9 @@ print_int(va_arg(args, int));

state = STATE_DEFAULT; } else if (state == STATE_ARGUMENT && *fmt == 'u') { print_uint(va_arg(args, unsigned int)); + state = STATE_DEFAULT; + } else if (state == STATE_ARGUMENT && *fmt == 'p') { + print_uint32(va_arg(args, uint32_t)); state = STATE_DEFAULT; } else if (state == STATE_ARGUMENT && *fmt == 's') { const char* string = va_arg(args, const char*);
M kernel/main.ckernel/main.c

@@ -12,6 +12,7 @@ #include "cedos/pic.h"

#include "cedos/pit.h" #include "cedos/core.h" +#include "linker.h" #include "assert.h" int os_init(void) {

@@ -93,50 +94,33 @@ crit_exit();

} } -int fibonacci(void) { - int a = 0, b = 1; +int sysinit(void) { + uint8_t scancode = 0; - while (1) { - int tmp = a + b; - b = a; - a = tmp; - printk("%i\n", a); - sched_yield(); - } -} + memdump((VIRT_ADDR)0x10000000, 0x3000); -int leaf(void) { - while (1) { hlt(); } -} + //syscall(0, 0xCAFEBABE, 0xDEADBEEF, 0x42069420); -int node(void) { - for (int i = 0; i < 8; i++) { - sched_yield(); - } + printk("PRESS ENTER:"); - sched_exec(create_empty_page_dir(), leaf, "leaf"); + do { + scancode = ps2_kb.read(); + printk("%c", scancode); + } while (scancode != 0x1C); - while (1) { hlt(); } -} + printk("THANKS, NOW PRESS ESC TO EXIT:"); -int sysinit(void) { - uint8_t scancode = 0; - - syscall(1, 0xCAFEBABE, 0xDEADBEEF, 0x42069420); - - printk("PRESS ENTER\n"); - - while (scancode != 0x1C) { + do { scancode = ps2_kb.read(); printk("%c", scancode); - } + } while (scancode != 0x01); - printk("THANKS\n"); + syscall(1, 0, 0, 0); - while (1) { - printk("x"); - hlt(); - } + //while (1) { + // printk("x"); + // hlt(); + //} //sched_exec(create_empty_page_dir(), fibonacci, "fibonacci"); //sched_exec(create_empty_page_dir(), node, "node");

@@ -150,7 +134,7 @@ infodump();

// create test tasks printk("Creating tasks.\n"); - sched_exec(create_empty_page_dir(), sysinit, "sysinit"); + sched_exec(SS_VMA + (APP_LMA - SS_LMA), APP_SIZE, APP_VMA, "sysinit"); printk("Starting scheduler.\n"); sched_start();
M kernel/mm/paging.ckernel/mm/paging.c

@@ -57,7 +57,7 @@ /*!

* WARNING: This method assumes the target page directory has already been mounted * to the second to last page directory entry */ -int map_page_to(PHYS_ADDR page_addr, uint32_t dir_index, uint32_t table_index, uint32_t flags) { +int force_map_page_to(PHYS_ADDR page_addr, uint32_t dir_index, uint32_t table_index, uint32_t flags) { PAGE_DIR_ENTRY* page_dir = PAGE_DIR_ALT_MAPPED_ADDR; PAGE_TABLE_ENTRY* page_table = PAGE_TABLE_ALT_MAPPED_ADDR(dir_index);

@@ -69,32 +69,16 @@ PHYS_ADDR new_page_table = get_free_page();

page_dir[dir_index] = MAKE_PAGE_ENTRY(new_page_table, PAGE_TABLE_FLAGS); } - if (!is_present(page_table[table_index])) { - // map page - page_table[table_index] = MAKE_PAGE_ENTRY(page_addr, flags); - return 1; - } else { - // didn't works - return 0; - } + // map page + page_table[table_index] = MAKE_PAGE_ENTRY(page_addr, flags); + inv_all_pages(); + return 1; } -int map_page_to_this(PHYS_ADDR page_addr, uint32_t dir_index, uint32_t table_index, uint32_t flags) { - PAGE_DIR_ENTRY* page_dir = PAGE_DIR_MAPPED_ADDR; - PAGE_TABLE_ENTRY* page_table = PAGE_TABLE_MAPPED_ADDR(dir_index); - - if (!is_present(page_dir[dir_index])) { - // acquire new page table - void *new_page_table = get_free_page(); - page_dir[dir_index] = MAKE_PAGE_ENTRY(new_page_table, PAGE_TABLE_FLAGS); - } - - if (!is_present(page_table[table_index])) { - // map page - page_table[table_index] = MAKE_PAGE_ENTRY(page_addr, flags); - return 1; +int map_page_to(PHYS_ADDR page_addr, uint32_t dir_index, uint32_t table_index, uint32_t flags) { + if (is_addr_available(dir_index, table_index)) { + force_map_page_to(page_addr, dir_index, table_index, flags); } else { - // didn't works return 0; } }

@@ -111,21 +95,41 @@ }

// map page page_table[table_index] = MAKE_PAGE_ENTRY(page_addr, flags); + inv_all_pages(); return 1; } +int map_page_to_this(PHYS_ADDR page_addr, uint32_t dir_index, uint32_t table_index, uint32_t flags) { + if (is_addr_available(dir_index, table_index)) { + force_map_page_to_this(page_addr, dir_index, table_index, flags); + } else { + return 0; + } +} + size_t copy_to_pdir(VIRT_ADDR src, size_t length, PHYS_ADDR pdir, VIRT_ADDR dest) { - PHYS_ADDR page = get_free_page(); VIRT_ADDR mount_dest = 0xe0000000; - force_map_page_to_this(page, PAGE_DIR_INDEX(mount_dest), PAGE_TABLE_INDEX(mount_dest), PAGE_TABLE_FLAGS); - uint32_t offset = ((uint32_t)dest) & 0xFFF; + mount_page_dir(pdir); + PHYS_ADDR page; + + while (length != 0) { + page = get_free_page(); + force_map_page_to_this(page, PAGE_DIR_INDEX(mount_dest), PAGE_TABLE_INDEX(mount_dest), PAGE_TABLE_FLAGS); + force_map_page_to(page, PAGE_DIR_INDEX(dest), PAGE_TABLE_INDEX(dest), PAGE_TABLE_FLAGS); + + uint32_t offset = ((uint32_t)dest % PAGE_SIZE); + uint32_t part_length = (offset + length <= PAGE_SIZE) ? length : PAGE_SIZE - offset; + + printk("src=%p dest=%p length=%i offset=%i plen=%i\n", src, dest, length, offset, part_length); - for (uint32_t i = 0; i < length; i++) { - ((uint8_t*)mount_dest)[offset + i] = ((uint8_t*)src)[i]; + for (uint32_t i = 0; i < part_length; i++) { + ((uint8_t*)mount_dest)[offset + i] = ((uint8_t*)src)[i]; + } + + dest += part_length; + src += part_length; + length -= part_length; } - - mount_page_dir(pdir); - map_page_to(page, PAGE_DIR_INDEX(dest), PAGE_TABLE_INDEX(dest), PAGE_TABLE_FLAGS); } int map_range_to(PHYS_ADDR page_dir, VIRT_ADDR dest, PHYS_ADDR src, uint32_t page_count, uint32_t flags) {

@@ -178,7 +182,7 @@ // map to itself

page_dir[PAGE_ENTRY_COUNT - 1] = MAKE_PAGE_ENTRY(page_dir_phys, PAGE_TABLE_FLAGS); page_dir = PAGE_DIR_ALT_MAPPED_ADDR; - + // identity map first 4MB page_dir[0] = PAGE_DIR_MAPPED_ADDR[0];

@@ -191,9 +195,10 @@

EXCEPTION(page_fault_isr, frame, error_code) { volatile VIRT_ADDR faulty_addr; __asm__ volatile ("mov %%cr2, %0" : "=a" (faulty_addr)); + //if (PAGE_DIR_INDEX(faulty_addr) >= PAGE_ENTRY_COUNT - 2) { return; } printk("PAGE FAULT: %X\n", faulty_addr); PHYS_ADDR new_page = get_free_page(); - map_page_to_this(new_page, PAGE_DIR_INDEX(faulty_addr), PAGE_TABLE_INDEX(faulty_addr), PAGE_TABLE_FLAGS); + force_map_page_to_this(new_page, PAGE_DIR_INDEX(faulty_addr), PAGE_TABLE_INDEX(faulty_addr), PAGE_TABLE_FLAGS); // dump registers to stdout }
M kernel/sched/sched.ckernel/sched/sched.c

@@ -15,10 +15,9 @@

#include "assembly.h" #define KERNEL_PRIVATE_STACK (void*)(0xC0600000) +#define USER_STACK (void*)(0xC0000000) #define PROCESS_STD_EFLAGS (0x00000286) - -#define SCHED_INTERVAL (0xFFFF) PROCESS* get_slot(void) { static PROCESS free_slots[8];

@@ -28,21 +27,30 @@ }

PROCESS_ID current_pid; +PROCESS_ID get_current_process(void) { + return current_pid; +} + int sched_dispatcher(void); /*! * Executes a task. */ -PROCESS_ID sched_exec(PHYS_ADDR page_dir, PROCESS_MAIN *entry, const char *name) { +PROCESS_ID sched_exec(VIRT_ADDR code, uint32_t code_len, PROCESS_MAIN *entry, const char *name) { crit_enter(); + PHYS_ADDR page_dir = create_empty_page_dir(); + + // copy app code + copy_to_pdir(code, code_len, page_dir, (VIRT_ADDR)0x10000000); + // set process context PROCESS *p = get_slot(); p->name = name; p->page_dir = page_dir; p->eip = sched_dispatcher; - p->ebp = KERNEL_PRIVATE_STACK; - p->esp = KERNEL_PRIVATE_STACK - sizeof(SCHED_FRAME); + p->ebp = USER_STACK; + p->esp = USER_STACK - sizeof(SCHED_FRAME); p->eflags = PROCESS_STD_EFLAGS; p->entry = entry; p->state = PSTATE_READY;

@@ -134,7 +142,7 @@

current_pid = 0; // create idle process - sched_exec(create_empty_page_dir(), idle, "idle"); + sched_exec(0, 0, idle, "idle"); return 1; }
M kernel/syscall.ckernel/syscall.c

@@ -1,11 +1,17 @@

#include "cedos/interrupts.h" #include "cedos/core.h" +#include "cedos/sched/sched.h" void test(uint32_t ebx, uint32_t ecx, uint32_t edx) { printk("SYSCALL 0x01: EBX=%X ECX=%X EDX=%X\n", ebx, ecx, edx); } -void* SYSCALL_TABLE[] = { hard_reset, test }; +void* SYSCALL_TABLE[] = { + test, + hard_reset, + sched_yield, + get_current_process + }; extern void syscall_interrupt(void);
M kernel/syscall.skernel/syscall.s

@@ -11,7 +11,7 @@

mov $SYSCALL_TABLE, %ecx mov (%ecx, %eax, 4), %eax - call %eax + call *%eax // restore stack add $12, %esp
M link.txtlink.txt

@@ -34,7 +34,7 @@ } >KERNEL

APPLICATION : AT(LOADADDR(KERNEL) + SIZEOF(KERNEL)) { - + */apps.o(.*) } >APPLICATION .bss : AT(LOADADDR(APPLICATION) + SIZEOF(APPLICATION))
M makefilemakefile

@@ -23,6 +23,7 @@ build:

> @mkdir $(LOCAL_BUILD) 2> /dev/null; true > $(MAKE) GLOBAL_BUILD=$(LOCAL_BUILD) -C boot build > $(MAKE) GLOBAL_BUILD=$(LOCAL_BUILD) -C kernel build +> $(MAKE) GLOBAL_BUILD=$(LOCAL_BUILD) -C apps build > $(GCC_PREFIX)ld $(LOCAL_BUILD)/*.o -T link.txt -Map=$(DEBUG_DIR)/mapfile.txt -o $(GLOBAL_BUILD)/base.o > $(GCC_PREFIX)objcopy --only-keep-debug $(GLOBAL_BUILD)/base.o $(DEBUG_DIR)/base.sym > $(GCC_PREFIX)objcopy -O binary $(GLOBAL_BUILD)/base.o $(GLOBAL_BUILD)/base.img