diff --git a/include/c/stdlib.h b/include/c/stdlib.h new file mode 100644 index 0000000..624cffc --- /dev/null +++ b/include/c/stdlib.h @@ -0,0 +1,18 @@ +#ifndef STDLIB_H +#define STDLIB_H + +#include + +void* malloc(const uint32_t size) { // Use Syscall(3) - Malloc() + void* ptr = 0; + __asm__ volatile ("int $0x80" : : "a"(3), "b"(size)); + __asm__ volatile ("movl %%eax, %0" : "=r"(ptr)); + + return ptr; +} + +void free(const void* ptr) { // Use Syscall(4) - Free() + __asm__ volatile ("int $0x80" : : "a"(4), "b"(ptr)); +} + +#endif diff --git a/include/interrupt/syscall.h b/include/interrupt/syscall.h index 183d705..8f98ac8 100644 --- a/include/interrupt/syscall.h +++ b/include/interrupt/syscall.h @@ -1,12 +1,14 @@ #ifndef SYSCALL_H #define SYSCALL_H +#include #include #include #include +#include // System call count -#define MAX_SYSCALLS 3 +#define MAX_SYSCALLS 5 // Args: ebx - number of miliseconds void sys_sleep() { @@ -35,22 +37,48 @@ void sys_gets() { read(s); } +// Args: ebx - amount of bytes to malloc +void sys_malloc() { + uint32_t size = 0; + __asm__ volatile ("movl %%ebx, %0" : "=b"(size)); + + // First Malloc() + if (!mallocListHead) { + mallocInit(size); // Setup malloc linked list + } + + void* ptr = mallocNextNode(size); + mallocMergeFree(); + + // Return allocated address in eax + __asm__ volatile ("movl %0, %%eax" : : "r"(ptr)); +} + +// Args: ebx - allocated pointer +void sys_free() { + void* ptr = NULL; + __asm__ volatile ("movl %%ebx, %0" : "=b"(ptr)); + mallocFree(ptr); +} + // System call table void* syscalls[MAX_SYSCALLS] = { - sys_sleep, // Syscall(0) - sys_puts, // Syscall(1) - sys_gets, // Syscall(2) + sys_sleep, // Syscall(0) + sys_puts, // Syscall(1) + sys_gets, // Syscall(2) + sys_malloc, // Syscall(3) + sys_free, // Syscall(4) }; // int 0x80 - Syscall interrupt, handled by this function // eax : Syscall number __attribute__ ((naked)) // No prologue or epilogue, just assembly -void syscallHandler(void) { +void syscallHandler(intFrame_t* iframe) { // Interrupt - Stack should contain: ss, esp, eflags, cs, eip // We should also push these regs: ax, gs, fs, es, ds, bp, di, si, dx, cx, bx __asm__ volatile ( ".intel_syntax noprefix\n" // We use intel syntax - ".equ MAX_SYSCALLS, 3\n" // Define MAX_SYSCALLS again TODO: I don't want to have to do this + ".equ MAX_SYSCALLS, 5\n" // Define MAX_SYSCALLS again TODO: I don't want to have to do this // Check if syscall exists "cmp eax, MAX_SYSCALLS - 1\n" @@ -86,6 +114,7 @@ void syscallHandler(void) { // TODO: Send an error or something here "invalidSyscall:\n" + "mov eax, -1\n" // Current error thing "iretd\n" ".att_syntax" // Switch back to Att Syntax (Just in case) diff --git a/include/memory/malloc.h b/include/memory/malloc.h new file mode 100644 index 0000000..d4312f8 --- /dev/null +++ b/include/memory/malloc.h @@ -0,0 +1,124 @@ +#ifndef MALLOC_H +#define MALLOC_H + +#include +#include +#include +#include + +// Singly linked list! +typedef struct mallocNode_s { + uint32_t size; + bool free; + struct mallocNode_s* next; +} mallocNode_t; + +mallocNode_t* mallocListHead = NULL; +static uint32_t mallocVirtualAddr = 0; +static uint32_t mallocPhysicalAddr = 0; +static uint32_t mallocPages = 0; + +void mallocInit(uint32_t size) { + mallocPages = size / PAGE_SIZE; + if (size % PAGE_SIZE > 0) { mallocPages++; } + + mallocPhysicalAddr = (uint32_t)allocBlocks(mallocPages); + mallocListHead = (mallocNode_t*)mallocVirtualAddr; + + // Map pages + for (uint32_t i = 0, virtualAddr = mallocVirtualAddr; i < mallocPages; i++, virtualAddr += PAGE_SIZE) { + mapPage((void*)(mallocPhysicalAddr + i * PAGE_SIZE), (void*)virtualAddr); + + ptEntry_t* page = getPage(virtualAddr); + SET_ATTR(page, PTE_READ_WRITE); + } + + if (mallocListHead) { + mallocListHead->size = (mallocPages * PAGE_SIZE) - sizeof(mallocNode_t); + mallocListHead->free = true; + mallocListHead->next = NULL; + } +} + +void mallocSplit(mallocNode_t* node, uint32_t size) { + if (node->size < size + sizeof(mallocNode_t)) { return; } // Can't split - node too small + + // Remainder node + mallocNode_t* newNode = (mallocNode_t*)((void*)node + size + sizeof(mallocNode_t)); + newNode->size = node->size - size - sizeof(mallocNode_t); + newNode->free = true; + newNode->next = node->next; + + // Split node + node->size = size; + node->free = false; + node->next = newNode; +} + +void* mallocNextNode(uint32_t size) { + if (size == 0) { return NULL; } // Why would you try that? (undefined behaviour i guess) + + mallocNode_t* current = mallocListHead; + + if (mallocListHead->size == 0) { mallocInit(size); } + + while (((current->size < size) || !current->free) && current->next != NULL) { + current = current->next; + } + + if (current->size == size) { + current->free = false; + } else if (current->size > size + sizeof(mallocNode_t)) { + mallocSplit(current, size); // Modifies current into the right size and makes it point to the remainder + } else { // There's no large enough node -> try to allocate more pages + uint8_t pageCount = 1; + while (current->size + pageCount * PAGE_SIZE < size + sizeof(mallocNode_t)) { + pageCount++; + } + + // Allocate and map new pages + uint32_t virtualAddr = mallocVirtualAddr + mallocPages * PAGE_SIZE; + for (uint32_t i = 0; i < pageCount; i++) { + ptEntry_t page = 0; + uint32_t* temp = allocPage(&page); + + mapPage((void*)temp, (void*)virtualAddr); + SET_ATTR(&page, PTE_READ_WRITE); + virtualAddr += PAGE_SIZE; + current->size += PAGE_SIZE; + mallocPages++; + } + + mallocSplit(current, size); + } + + return (void*)current + sizeof(mallocNode_t); +} + +void mallocMergeFree() { + mallocNode_t* current = mallocListHead; + + while (current && current->next != NULL) { + if (current->free && current->next->free) { + current->size += (current->next->size) + sizeof(mallocNode_t); + current->next = current->next->next; + } + current = current->next; + } +} + +void mallocFree(void* ptr) { + mallocNode_t* current = mallocListHead; + + while (current->next) { + if ((void*)current + sizeof(mallocNode_t) == ptr) { + current->free = true; + mallocMergeFree(); + break; + } + + current = current->next; + } +} + +#endif diff --git a/src/calc.c b/src/calc.c index 2913ecd..a0137f5 100644 --- a/src/calc.c +++ b/src/calc.c @@ -1,6 +1,5 @@ #include -__attribute__ ((section ("entry"))) void main() { char msg[8] = { 'H','e','l','l','o','!','\n',0 }; print(msg); diff --git a/src/calc.ld b/src/calc.ld index fd8721d..70eec33 100644 --- a/src/calc.ld +++ b/src/calc.ld @@ -1,6 +1,6 @@ +ENTRY("main"); SECTIONS { .text : { - *(entry); *(.text*); } .data : { @@ -13,3 +13,4 @@ SECTIONS { *(.bss*); } } + diff --git a/src/kernel.c b/src/kernel.c index 065bf00..2b31f03 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -16,6 +16,7 @@ #include #include #include +#include #define PROMPT "#> " @@ -303,8 +304,29 @@ void main() { diskRead(sector, size, entryPoint); - if (strcmp(fileType, "bin") == 0) { // TODO: Improve this + if (strcmp(fileType, "bin") == 0) { + // Reset malloc + mallocListHead = NULL; + mallocVirtualAddr = (uint32_t)entryPoint + neededPages * PAGE_SIZE; + mallocPhysicalAddr = 0; + mallocPages = 0; + ((void(*)(void))entryPoint)(); // Call program + + for (uint32_t i = 0, virtualAddr = mallocVirtualAddr; i < mallocPages; i++, virtualAddr += PAGE_SIZE) { + ptEntry_t* page = getPage(virtualAddr); + + if (PAGE_PHYS_ADDRESS(page) && TEST_ATTR(page, PTE_PRESENT)) { + freePage(page); + unmapPage((void*)virtualAddr); + flushTlbEntry(virtualAddr); + } + } + + mallocListHead = NULL; + mallocVirtualAddr = 0; + mallocPhysicalAddr = 0; + mallocPages = 0; } else if (strcmp(fileType, "tab") == 0) { printFiletable(entryPoint); } else if (strcmp(fileType, "fnt") == 0) { diff --git a/todo.txt b/todo.txt index 1d4597c..16dd0ed 100644 --- a/todo.txt +++ b/todo.txt @@ -89,13 +89,12 @@ Legend: - [ ] Hard - [ ] System Calls - [x] Sleep() - - [x] Print() - Temporary for printing before we get Write(stdout) :) - - [ ] Write() - - [ ] Read() + - [ ] Write() (temporarly puts()) + - [ ] Read() (temporarly gets()) - [ ] Open() - [ ] Close() - - [ ] Malloc() - - [ ] Free() + - [x] Malloc() + - [x] Free() - [ ] Seek() - [ ] Shell - [ ] Separate file/program @@ -126,10 +125,13 @@ Legend: - [x] Loading them - [x] Running them - [x] Exit back to kernel/shell - - [ ] Let them use libs + - [x] Let them use libs - [ ] Proper include files (LibC?) - [ ] argc, argv[] - [ ] Standalone shell program +- [ ] Userspace programs + - [ ] Calculator + - [ ] Caledar - [ ] Code Editor - [ ] Text editor - [ ] Syntax highlighting @@ -145,4 +147,5 @@ Legend: - [ ] Games - [ ] Minesweeper - [ ] Solitaire + - [ ] Tetris