# HG changeset patch # User windel # Date 1328288478 -3600 # Node ID 980b2f14c9be42f25fc8339e635b9dc3c32cc967 # Parent 35cc54e078dde5fff3dd32afb29476e4271c8f8f# Parent 600f48b7479935665b8e1897add75384e3b88c7c Merge diff -r 600f48b74799 -r 980b2f14c9be README --- a/README Fri Feb 03 18:40:43 2012 +0100 +++ b/README Fri Feb 03 18:01:18 2012 +0100 @@ -22,3 +22,22 @@ $ cd ide $ python runide.py += About the C version of the OS = + +To build the C kernel, enter: +$ cd cos +$ make + +Running the OS with bochs: +$ bochs -q + +required tools: +- bochs: for simulating the OS +- mtools: for copying files to the bootdisk +- nasm: for assembler instructions +- gcc: for compiling the C sources +- make: for building the system +- python 3: for building the initial ramdisk + +Enjoy! + diff -r 600f48b74799 -r 980b2f14c9be cos/Makefile --- a/cos/Makefile Fri Feb 03 18:40:43 2012 +0100 +++ b/cos/Makefile Fri Feb 03 18:01:18 2012 +0100 @@ -2,7 +2,7 @@ all: make -C kernel - python makeinitrd.py lcfosinitrd.img hello/hello.bin + python utils/makeinitrd.py lcfosinitrd.img hello/hello.bin cp grub/emptybootdisk.img bootdisk.img mcopy -D o -i bootdisk.img kernel/lcfos.bin :: mcopy -D o -i bootdisk.img lcfosinitrd.img :: diff -r 600f48b74799 -r 980b2f14c9be cos/README --- a/cos/README Fri Feb 03 18:40:43 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -This directory contains the C version of the OS. - -To build the kernel, enter: -$ make - -To make the bootdisk, hit: -$ make bootdisk - -Running the OS with bochs: -$ bochs -q - -required tools: -- bochs: for simulating the OS -- mtools: for copying files to the bootdisk -- nasm: for assembler instructions -- gcc: for compiling the C sources -- make: for building the system -- python: for building the initial ramdisk - -Enjoy! - diff -r 600f48b74799 -r 980b2f14c9be cos/kernel/handlers.c --- a/cos/kernel/handlers.c Fri Feb 03 18:40:43 2012 +0100 +++ b/cos/kernel/handlers.c Fri Feb 03 18:01:18 2012 +0100 @@ -1,43 +1,43 @@ #include "kernel.h" // Assembler wrapper prototypes: -void INT255(void); -void INT0(void); -void INT1(void); -void INT2(void); -void INT3(void); -void INT4(void); -void INT5(void); -void INT6(void); -void INT7(void); -void INT8(void); -void INT9(void); -void INT10(void); -void INT11(void); -void INT12(void); -void INT13(void); -void INT14(void); -void INT16(void); -void INT17(void); -void INT18(void); -void INT19(void); +extern void INT255(void); +extern void INT0(void); +extern void INT1(void); +extern void INT2(void); +extern void INT3(void); +extern void INT4(void); +extern void INT5(void); +extern void INT6(void); +extern void INT7(void); +extern void INT8(void); +extern void INT9(void); +extern void INT10(void); +extern void INT11(void); +extern void INT12(void); +extern void INT13(void); +extern void INT14(void); +extern void INT16(void); +extern void INT17(void); +extern void INT18(void); +extern void INT19(void); // Remapped irq assembler wrappers: -void INT32(void); -void INT33(void); -void INT34(void); -void INT35(void); -void INT36(void); -void INT37(void); -void INT38(void); -void INT39(void); -void INT40(void); -void INT41(void); -void INT42(void); -void INT43(void); -void INT44(void); -void INT45(void); -void INT46(void); -void INT47(void); +extern void INT32(void); +extern void INT33(void); +extern void INT34(void); +extern void INT35(void); +extern void INT36(void); +extern void INT37(void); +extern void INT38(void); +extern void INT39(void); +extern void INT40(void); +extern void INT41(void); +extern void INT42(void); +extern void INT43(void); +extern void INT44(void); +extern void INT45(void); +extern void INT46(void); +extern void INT47(void); // THE interrupt descriptor table: IDT_entry *idt = (IDT_entry*)0x5000; @@ -184,8 +184,8 @@ panic("No resolution to page fault!"); } + // Global isr handler: - // Hopefully, this function get called with the correct registers. void isr_handler(uint64_t* registers) { @@ -223,30 +223,3 @@ outb(0x20, 0x20); // EOI to master } -// Interrupt service routines: - -void INT14handler() -{ - uint64_t faulting_address; - - printf("Segfault!\n"); - - // Retrieve failed page from CR2: - asm volatile("mov %%cr2, %0" : "=r" (faulting_address)); - - printf("INT14 called! Page fault for address 0x%X!\n", faulting_address); - - panic("Unhandled exception!"); -} - -void INT15handler() -{ - printf("INT15 called!\n"); - panic("Unhandled exception!"); -} - -void INTDEF_handler() -{ - panic("Default int handler called\n"); -} - diff -r 600f48b74799 -r 980b2f14c9be cos/kernel/initrd.c --- a/cos/kernel/initrd.c Fri Feb 03 18:40:43 2012 +0100 +++ b/cos/kernel/initrd.c Fri Feb 03 18:01:18 2012 +0100 @@ -4,22 +4,81 @@ #include "kernel.h" -fs_node_t *initrd_root = 0; - -typedef struct -{ - uint32_t magic; - uint32_t numfiles; -} initrd_header_t; +// Global data struct: +initrd_file_header_t *files; fs_node_t* initialize_initrd(uint64_t location) { - // We need a valid malloc here! - initrd_root = (fs_node_t*)kmalloc(sizeof(fs_node_t)); + uint32_t *u32ptr; + + u32ptr = (uint32_t*)location; + if (*u32ptr != 0x1337babe) + { + printf("Invalid ramdisk magic\n"); + return 0; + } - initrd_header_t *header = (initrd_header_t*)location; - initrd_root->length = header->numfiles; + // Allocate root dir: + fs_node_t *root = (fs_node_t*)kmalloc(sizeof(fs_node_t)); + memset(root, 0, sizeof(fs_node_t)); + root->flags = FS_DIRECTORY; + root->readdir = initrd_readdir; + + u32ptr++; + root->length = *u32ptr; + + // Allocate an node for each file. + void *x = kmalloc(sizeof(fs_node_t) * root->length); + memset(x, 0, sizeof(fs_node_t) * root->length); - return initrd_root; + for (i = 0; i < root->length; i++) + { + + } + + return root; } +void load_ramdisk() +{ + printf("Ramdisk location: %p\n", ramdisk_location); + + fs_node_t *root = initialize_initrd(ramdisk_location); + + if (root != 0) + { + fs_node_t *node = 0; + int i = 0; + while ( (node = readdir_fs(root, i)) != 0) + { + printf("File %s\n", node->name); + } + } +} + +static uint64_t initrd_read(fs_node_t *node, uint64_t offset, uint64_t size, void *buffer) +{ + // TODO: check errors + + if (size > node->length) + { + return 0; + } + + if (size + offset > node->length) + { + size = node->length - offset; + } + + memcpy(buffer, node.data + offset, size); + return size; +} + +fs_node_t *readdir(fs_node_t *dir, int index) +{ + if (index >= dir->length) + { + return 0; + } +} + diff -r 600f48b74799 -r 980b2f14c9be cos/kernel/kernel.c --- a/cos/kernel/kernel.c Fri Feb 03 18:40:43 2012 +0100 +++ b/cos/kernel/kernel.c Fri Feb 03 18:01:18 2012 +0100 @@ -13,23 +13,7 @@ // From here kmalloc can be used. keyboard_init(); timer_init(); - printf("Ramdisk location: %p\n", ramdisk_location); - - /* - fs_node_t *fs_root = 0; - - fs_root = initialize_initrd(ramdisk_location); - - if (fs_root != 0) - { - fs_dirent_t *node = 0; - int i = 0; - while ( (node = readdir_fs(fs_root, i)) != 0) - { - - } - } - */ + load_ramdisk(); // TODO: make shell a user space program! shell(); // Start user shell diff -r 600f48b74799 -r 980b2f14c9be cos/kernel/kernel.h --- a/cos/kernel/kernel.h Fri Feb 03 18:40:43 2012 +0100 +++ b/cos/kernel/kernel.h Fri Feb 03 18:01:18 2012 +0100 @@ -147,7 +147,6 @@ uint64_t physicalAddress; } PD_t; - typedef struct { unsigned present : 1; @@ -181,6 +180,20 @@ // Make memmap a PML4 type: typedef PML4_t memmap_t; +// Malloc related functions +typedef struct { + uint64_t magic; + uint64_t state; + uint64_t size; +} heap_header_t; + +typedef struct +{ + heap_header_t *first_block; + uint64_t start_address; + uint64_t end_address; +} heap_t; + // Task related types: typedef struct { @@ -254,6 +267,8 @@ // Initial ramdisk functions: fs_node_t* initialize_initrd(uint64_t location); +void load_ramdisk(void); + // Variable argument list things: #define va_start(v,l) __builtin_va_start(v,l) #define va_end(v) __builtin_va_end(v) @@ -263,23 +278,25 @@ /* Global variables */ extern uint64_t kernel_end; extern uint64_t placement_address; +extern memmap_t* kernel_map; /* Procedures */ // memory functions: // TODO: remove some redundant API functions: -void init_heap(); void init_memory(uint64_t total_mem_size); page_t* get_page(uint64_t address, memmap_t*); -void* kmalloc(uint64_t size); -void kfree(void* ptr); -void* kmalloc_int(uint64_t size); -void* kmalloc_aligned_int(uint64_t size); -void mappage(uint64_t address); +void alloc_frame(page_t *page); void loadPageTable(void* tableAddress); void switch_mapping(memmap_t* mapping); void enablePaging(); +// Malloc related: +void* kmalloc(uint64_t size); +void* kmalloc_a(uint64_t size); // Aligned on a 4 KiB page. +void kfree(void* ptr); +heap_t* create_heap(uint64_t location, uint64_t size); + // task related functions: void initialize_tasking(); void new_task(); diff -r 600f48b74799 -r 980b2f14c9be cos/kernel/malloc.c --- a/cos/kernel/malloc.c Fri Feb 03 18:40:43 2012 +0100 +++ b/cos/kernel/malloc.c Fri Feb 03 18:01:18 2012 +0100 @@ -5,104 +5,153 @@ uint64_t placement_address = (uint64_t)&kernel_end; -void* kmalloc_int(uint64_t size) -{ - uint64_t tmp = placement_address; - placement_address += size; - return (void*)tmp; -} - -void* kmalloc_aligned_int(uint64_t size) -{ - if ( (placement_address | 0xFFF) != 0 ) - { - placement_address &= ~(0xFFF); - placement_address += 0x1000; - } - uint64_t tmp = placement_address; - placement_address += size; - return (void*)tmp; -} - - // ================= Other malloc // TODO: move this to user space? #define HEAP_MAGIC 0xc0ffee -#define HEAP_START 0x400000 -#define HEAP_SIZE 0x200000 #define HEAP_INUSE 1 #define HEAP_FREE 0 -typedef struct { - uint64_t magic; - uint64_t state; - uint64_t size; -} heap_t; - /* malloc and free divide the chunks of memory present at the heap of the kernel into smaller parts. The heap is located at: 0x */ -static heap_t* kernel_heap = (heap_t*) 0x400000; // 4 MB - 6 MB is heap +static heap_t* kernel_heap = 0; + +void expand_heap(heap_t *heap, uint64_t newsize); + /* Allocates 'size' bytes and returns the pointer if succesfull. + Before the kernel is initialized, placement malloc is used. Kernelpanic in case of failure.. */ - -void* kmalloc(uint64_t size) +static void* kmalloc_int(uint64_t size, uint64_t aligned) { - return kmalloc_int(size); - - // Start at the beginning of our heap and search a free block: - heap_t *current = kernel_heap; - while (current->magic == HEAP_MAGIC) + // Check if there exists a kernel heap. If not, use placement malloc for now. + if (kernel_heap == 0) { - if ((current->state == HEAP_FREE) && (current->size >= size)) + // Before that the heap is initialized, use placement malloc + if (aligned == 1) { - // Mark block as used: - current->state = HEAP_INUSE; + // Align placement address + if ( (placement_address | 0xFFF) != 0 ) + { + placement_address &= ~(0xFFF); + placement_address += 0x1000; + } + } + uint64_t tmp = placement_address; + placement_address += size; + return (void*)tmp; + } + else + { + // We have a kernel heap, search the heap for a block of suitable size. - // Insert a heap header if required: - if (current->size > size + sizeof(heap_t) + 1) + // Start at the beginning of our heap and search a free block: + heap_header_t *current = kernel_heap->first_block; + while (current->magic == HEAP_MAGIC) + { + if ((current->state == HEAP_FREE) && (current->size >= size)) { - // Calculate location of the inserted header: - heap_t *newheader = (heap_t*) (((char*)current)+size+sizeof(heap_t)); + // We found a hole with suitable size. Determine if split is of any use. + + // Insert a heap header if required: + if (current->size > size + sizeof(heap_t) + 1) + { + // Calculate location of the inserted header: + heap_header_t *newheader = (heap_header_t*) (((uint64_t)current)+size+sizeof(heap_header_t)); - // Set the new header fields: - newheader->size = current->size - size - sizeof(heap_t); - newheader->state = HEAP_FREE; - newheader->magic = HEAP_MAGIC; + // Set the new header fields: + newheader->size = current->size - size - sizeof(heap_header_t); + newheader->state = HEAP_FREE; + newheader->magic = HEAP_MAGIC; - // Set the size of this block - current->size = size; + // Set the size of this block + current->size = size; + } + else + { + // We allocate this whole block + // Mark block as used: + current->state = HEAP_INUSE; + } + // Calculate the size of the block: + char *address = ((char*)current)+sizeof(heap_header_t); + return address; + } - else - { - // We allocate this whole block - } - // Calculate the size of the block: - char *address = ((char*)current)+sizeof(heap_t); - return address; - + // Goto next heap block: + current = (heap_header_t*)(((uint64_t) current) + current->size + sizeof(heap_header_t)); } - // Goto next heap block: - current = (heap_t*)(((char*) current) + current->size + sizeof(heap_t)); + + // We did not find a block large enough. Expand the heap and try again. + expand_heap(kernel_heap, 0x10000000); + return kmalloc_int(size, aligned); } - return 0x0; +} + +// Convenient wrappers: +void* kmalloc(uint64_t size) +{ + return kmalloc_int(size, 0); +} + +void* kmalloc_a(uint64_t size) +{ + return kmalloc_int(size, 1); } void kfree(void* ptr) { - printf("Free address %x\n", ptr); + printf("Free address %x\n", ptr); + if (kernel_heap == 0) + { + return; + } + else + { + // TODO + } + // TODO: free blocks: } -void init_heap(void) +heap_t* create_heap(uint64_t location, uint64_t size) { - // Initialize the kernel heap: - kernel_heap->magic = HEAP_MAGIC; - kernel_heap->state = HEAP_FREE; - kernel_heap->size = HEAP_SIZE - sizeof(heap_t); + // Make sure that the new heap location is mapped into the address space: + uint64_t i = 0; + while (i < size) + { + alloc_frame( get_page(location + i, kernel_map)); + i += 0x1000; + } + + // create new heap structure: + heap_t* h = (heap_t*)kmalloc(sizeof(heap_t)); + + // Create one big hole: + h->first_block = (heap_header_t*)location; // Place header at beginning of heap + h->first_block->magic = HEAP_MAGIC; + h->first_block->state = HEAP_FREE; + h->first_block->size = size - sizeof(heap_header_t); + return h; } +// Make the total heap bigger: +void expand_heap(heap_t *heap, uint64_t newsize) +{ + uint64_t oldsize = heap->end_address - heap->start_address; + if (newsize < oldsize) + { + panic("Cannot expand heap to a smaller size\n"); + } + + uint64_t i = oldsize; + while (i < newsize) + { + alloc_frame( get_page(heap->start_address + i, kernel_map)); + i += 0x1000; + } +} + diff -r 600f48b74799 -r 980b2f14c9be cos/kernel/mm.c --- a/cos/kernel/mm.c Fri Feb 03 18:40:43 2012 +0100 +++ b/cos/kernel/mm.c Fri Feb 03 18:01:18 2012 +0100 @@ -6,13 +6,19 @@ #include "kernel.h" +#define HEAP_START 0xC000000000000000 +#define HEAP_INITIAL_SIZE 0x100000 + // Bitmap that keeps track of all the 4 kB memory pages in the system: static uint64_t *frames = 0; static uint64_t nframes = 0; memmap_t* kernel_map = 0; // kernel memory mapping +// TODO: determine if this is required. memmap_t* current_map = 0; // The currently active memory mapping +heap_t* kernel_heap = 0; + static void set_frame(uint64_t frame) { uint64_t idx = frame / 64; @@ -56,6 +62,24 @@ return (uint64_t) -1; } +void memory_status(void) +{ + // Determine amount of used memory. + uint64_t i, j; + uint64_t inuse = 0; + for (i = 0; i < nframes / 64; i++) + { + for (j = 0; j < 64; j++) + { + if ((frames[i] & (1UL<table)); // Enable paging (and flush cache): @@ -152,7 +183,9 @@ else { // Create new table: - pdpt = (PDPT_t*)kmalloc_aligned_int(sizeof(PDPT_t)); + printf("Get page for address %x\n", address); + // TODO: make sure that this function calls kmalloc instead of placement malloc. + pdpt = (PDPT_t*)kmalloc_a(sizeof(PDPT_t)); memset(pdpt, 0, sizeof(PDPT_t)); // TODO: get function like virt2phys or something here @@ -173,7 +206,7 @@ else { // Create a new table: - pd = (PD_t*)kmalloc_aligned_int(sizeof(PD_t)); + pd = (PD_t*)kmalloc_a(sizeof(PD_t)); memset(pd, 0, sizeof(PD_t)); // Enter table into PDPT: @@ -195,7 +228,7 @@ else { // Create table: - pt = (PT_t*)kmalloc_aligned_int(sizeof(PD_t)); + pt = (PT_t*)kmalloc_a(sizeof(PD_t)); memset(pt, 0, sizeof(PT_t)); // Enter PT into PD: diff -r 600f48b74799 -r 980b2f14c9be cos/kernel/shell.c --- a/cos/kernel/shell.c Fri Feb 03 18:40:43 2012 +0100 +++ b/cos/kernel/shell.c Fri Feb 03 18:01:18 2012 +0100 @@ -17,6 +17,8 @@ kfree(a); } +void memory_status(void); + void shell() { printf("Welcome!\n"); @@ -30,6 +32,7 @@ if (buffer[0] == 'x') { printf("System time in ms: %d\n", getTimeMS()); + memory_status(); } if (buffer[0] == 't') { diff -r 600f48b74799 -r 980b2f14c9be cos/makeinitrd.py --- a/cos/makeinitrd.py Fri Feb 03 18:40:43 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -#!/usr/bin/python - -# Script for generation of an initial ramdisk that contains -# the first programs to run. - -import struct -import sys - -if len(sys.argv) < 3: - print('Usage: {0} output file1 [file2] ...'.format(sys.argv[0])) - sys.exit(1) - -outputfilename = sys.argv[1] -inputFileNames = sys.argv[2:] - -with open(outputfilename, 'wb') as outputFile: - # Amount of files: - outputFile.write(struct.pack('