94 lines
2.6 KiB
C
94 lines
2.6 KiB
C
#include <stdint.h>
|
|
#include <stddef.h>
|
|
|
|
#include "memory/mm.h"
|
|
#include "process.h"
|
|
#include "scheduler.h"
|
|
|
|
#include <drivers/vga/vga.h>
|
|
|
|
typedef struct registers {
|
|
uint32_t gs, fs, es, ds; // Pushed manually
|
|
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha
|
|
uint32_t int_no, err_code; // Pushed manually
|
|
uint32_t eip, cs, eflags, useresp, ss; // Pushed automatically by CPU
|
|
} registers_t;
|
|
|
|
|
|
static int32_t sys_exit(int status) {
|
|
exit();
|
|
return 0;
|
|
}
|
|
|
|
static int32_t sys_write(int fd, const void* buf, size_t count) {
|
|
if (fd == 1 || fd == 2) { // stdout or stderr
|
|
const char* cbuf = (const char*)buf;
|
|
for (size_t i = 0; i < count; i++) {
|
|
vga_putchar(cbuf[i]);
|
|
}
|
|
return count;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static int32_t sys_read(int fd, void* buf, size_t count) {
|
|
if (fd == 0) { // stdin
|
|
char* cbuf = (char*)buf;
|
|
size_t bytes_read = 0;
|
|
while (bytes_read < count) {
|
|
char c = 'r';
|
|
cbuf[bytes_read++] = c;
|
|
if (c == '\n') break;
|
|
}
|
|
return bytes_read;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static int32_t sys_open(const char* filename, int flags) {
|
|
return -1;
|
|
}
|
|
|
|
static int32_t sys_close(int fd) {
|
|
return -1;
|
|
}
|
|
|
|
static int32_t sys_brk(uint32_t new_break) {
|
|
process_t* current = current_task();
|
|
|
|
if (new_break == 0) {
|
|
return current->heap_end;
|
|
}
|
|
|
|
if (new_break < current->heap_end) {
|
|
current->heap_end = new_break;
|
|
return current->heap_end;
|
|
}
|
|
|
|
uint32_t page_start = (current->heap_end + 4095) & ~4095;
|
|
uint32_t page_end = (new_break + 4095) & ~4095;
|
|
|
|
for (uint32_t addr = page_start; addr < page_end; addr += 4096) {
|
|
// 1. Allocate a physical frame using your PMM (Physical Memory Manager)
|
|
void* phys = p_alloc_frame();
|
|
|
|
// 2. Map it into the current page directory using your VMM (Virtual Memory Manager)
|
|
map_page(addr, (uint32_t)phys, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER);
|
|
}
|
|
|
|
current->heap_end = new_break;
|
|
return current->heap_end;
|
|
}
|
|
|
|
int32_t syscall(registers_t* regs) {
|
|
switch(regs->eax) {
|
|
case 1: return sys_exit(regs->ebx);
|
|
case 3: return sys_read(regs->ebx, (void*)regs->ecx, regs->edx);
|
|
case 4: return sys_write(regs->ebx, (const void*)regs->ecx, regs->edx);
|
|
case 5: return sys_open((const char*)regs->ebx, regs->ecx);
|
|
case 6: return sys_close(regs->ebx);
|
|
case 12: return sys_brk(regs->ebx);
|
|
default:
|
|
return -1;
|
|
}
|
|
} |