MAJOR RESTRUCTURE

This commit is contained in:
2024-12-28 21:23:58 +01:00
parent 12b07a9f70
commit 2e0b030324
81 changed files with 1168 additions and 579 deletions
+25
View File
@@ -0,0 +1,25 @@
#include <cpu/idt.h>
#include <stdint.h>
__attribute__ ((aligned(0x10))) // For performance
idtEntry_t idt[IDT_ENTRIES] = { 0 };
idtp_t idtp;
void idtSetGate(uint8_t i, void* handler, uint8_t flags) {
uint32_t offset = (uint32_t)handler;
idtEntry_t* entry = &idt[i];
entry->offsetLow = (uint16_t)offset;
entry->selector = 0x08;
entry->zero = 0;
entry->typeAttr = flags;
entry->offsetHigh = (uint16_t)(offset >> 16);
}
void setupIdt() {
idtp.limit = sizeof(idtEntry_t) * 256;
idtp.base = (uint32_t)&idt;
__asm__ volatile ("lidt %0" : : "m"(idtp));
}
+102
View File
@@ -0,0 +1,102 @@
#include <syscalls/syscalls.h>
#include <drivers/serial.h>
#include <cpu/system.h>
#include <cpu/idt.h>
#include <cpu/isr.h>
const char* format = "\x1b[31m[kernel] %s!\n\x1b[0m";
const char* exceptions[] = {
"Division By Zero",
"Debug",
"Non Maskable Interrupt",
"Breakpoint",
"Into Detected Overflow",
"Out of Bounds",
"Invalid Opcode",
"No Coprocessor",
"Double Fault",
"Coprocessor Segment Overrun",
"Bad TSS",
"Segment Not Present",
"Stack Fault",
"General Protection Fault",
"Page Fault",
"Unknown Interrupt",
"Coprocessor Fault",
"Alignment Check",
"Machine Check",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved"
};
void remapPic() {
outb(0x20, 0x11);
outb(0xa0, 0x11);
outb(0x21, 0x20);
outb(0xa1, 0x28);
outb(0x21, 0x04);
outb(0xa1, 0x02);
outb(0x21, 0x01);
outb(0xa1, 0x01);
outb(0x21, 0x00);
outb(0xa1, 0x00);
}
HandlerPtr irqHandlers[16] = { 0 }; // IRQ 0-15
void setupIsrs() {
setupIdt();
remapPic(); // Remap IRQs 0-15 -> 32-48
for (int i = 0; i < 48; i++) {
idtSetGate(i, asm_isrRedirectTable[i], TRAP_GATE_FLAGS);
}
// System call
idtSetGate(0x80, isr128, USR_INT_GATE_FLAGS);
__asm__ volatile ("sti");
}
void registerIrq(uint8_t id, HandlerPtr handler) {
irqHandlers[id] = handler;
}
void sendPicEOI(uint8_t irq) {
if (irq >= 8) {
outb(0xA0, 0x20); // PIC2 Command
}
outb(0x20, 0x20); // PIC1 Command
}
int handleInterrupt(intFrame_t iframe) {
if (iframe.interrupt < 32) {
// ISRs 0-31 - Exceptions
debugf(format, exceptions[iframe.interrupt]);
panic();
} else if (iframe.interrupt >= 32 && iframe.interrupt < 48) {
// ISRs 32-47 - Hardware interrupts
uint8_t irq = iframe.interrupt - 32;
if (irqHandlers[irq]) {
irqHandlers[irq](&iframe);
sendPicEOI(irq);
}
} else if (iframe.interrupt == 128) {
// ISR 128 - System call
return syscallHandler(&iframe);
}
return 0;
}
+116
View File
@@ -0,0 +1,116 @@
; ISR Assembly
[bits 32]
isrCommon:
;; Push registers to the intFrame_t struct
push eax
push gs
push fs
push es
push ds
push ebp
push edi
push esi
push edx
push ecx
push ebx
push esp
[extern handleInterrupt]
call handleInterrupt
isrReturn:
add esp, 4 ; Keep ESP
pop ebx
pop ecx
pop edx
pop esi
pop edi
pop ebp
pop ds
pop es
pop fs
pop gs
add esp, 4 ; Keep EAX
add esp, 8 ; Pop interupt number and error code
iretd ; Pop CS, EIP & EFLAGS (Also SS & ESP if it's from userspace)
%macro ISR_WITH_ERRNO 1
isr%1:
push dword %1
jmp isrCommon
%endmacro
%macro ISR_WITHOUT_ERRNO 1
isr%1:
push dword 0 ; Instead of error code
push dword %1
jmp isrCommon
%endmacro
;; Exceptions
ISR_WITHOUT_ERRNO 0
ISR_WITHOUT_ERRNO 1
ISR_WITHOUT_ERRNO 2
ISR_WITHOUT_ERRNO 3
ISR_WITHOUT_ERRNO 4
ISR_WITHOUT_ERRNO 5
ISR_WITHOUT_ERRNO 6
ISR_WITHOUT_ERRNO 7
ISR_WITH_ERRNO 8
ISR_WITHOUT_ERRNO 9
ISR_WITH_ERRNO 10
ISR_WITH_ERRNO 11
ISR_WITH_ERRNO 12
ISR_WITH_ERRNO 13
ISR_WITH_ERRNO 14
ISR_WITHOUT_ERRNO 15
ISR_WITHOUT_ERRNO 16
ISR_WITHOUT_ERRNO 17
ISR_WITHOUT_ERRNO 18
ISR_WITHOUT_ERRNO 19
ISR_WITHOUT_ERRNO 20
ISR_WITHOUT_ERRNO 21
ISR_WITHOUT_ERRNO 22
ISR_WITHOUT_ERRNO 23
ISR_WITHOUT_ERRNO 24
ISR_WITHOUT_ERRNO 25
ISR_WITHOUT_ERRNO 26
ISR_WITHOUT_ERRNO 27
ISR_WITHOUT_ERRNO 28
ISR_WITHOUT_ERRNO 29
ISR_WITHOUT_ERRNO 30
ISR_WITHOUT_ERRNO 31
;; IRQs 0-15 (mapped 32-47)
ISR_WITHOUT_ERRNO 32
ISR_WITHOUT_ERRNO 33
ISR_WITHOUT_ERRNO 34
ISR_WITHOUT_ERRNO 35
ISR_WITHOUT_ERRNO 36
ISR_WITHOUT_ERRNO 37
ISR_WITHOUT_ERRNO 38
ISR_WITHOUT_ERRNO 39
ISR_WITHOUT_ERRNO 40
ISR_WITHOUT_ERRNO 41
ISR_WITHOUT_ERRNO 42
ISR_WITHOUT_ERRNO 43
ISR_WITHOUT_ERRNO 44
ISR_WITHOUT_ERRNO 45
ISR_WITHOUT_ERRNO 46
ISR_WITHOUT_ERRNO 47
;; Syscall ISR128
[global isr128]
ISR_WITHOUT_ERRNO 128
;; Create table of ISRs
[global asm_isrRedirectTable]
asm_isrRedirectTable:
%assign i 0
%rep 48
dd isr%+i
%assign i i+1
%endrep
+49
View File
@@ -0,0 +1,49 @@
#include <cpu/system.h>
#include <drivers/serial.h>
#include <stdint.h>
void cpuid(uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) {
__asm__ volatile (
"cpuid"
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
: "a"(*eax)
);
}
uint8_t inb(uint16_t port) {
uint8_t result;
__asm__ volatile("inb %1, %0" : "=a"(result) : "Nd"(port));
return result;
}
void outb(uint16_t port, uint8_t data) {
__asm__ volatile("outb %0, %1" :: "a"(data), "Nd"(port));
}
uint16_t inw(uint16_t port) {
uint16_t result;
__asm__ volatile("inw %1, %0" : "=a"(result) : "Nd"(port));
return result;
}
void outw(uint16_t port, uint16_t data) {
__asm__ volatile("outw %0, %1" :: "a"(data), "Nd"(port));
}
uint32_t inl(uint16_t port) {
uint32_t result;
__asm__ volatile("inl %1, %0" : "=a"(result) : "Nd"(port));
return result;
}
void outl(uint16_t port, uint32_t data) {
__asm__ volatile("outl %0, %1" :: "a"(data), "Nd"(port));
}
void ioWait() {
// Waits ~1 I/O Cycle (Linux uses this so it should be good)
__asm__ volatile("outb %%al, $0x80" : : "a"(0));
}
void panic() {
debugf("\x1b[31m[kernel] Kern panic!\x1b[0m\n");
while (1) { __asm__ volatile ("cli; hlt"); }
}
+53
View File
@@ -0,0 +1,53 @@
#include <drivers/disk.h>
#include <cpu/system.h>
#include <stdint.h>
void diskRead(uint32_t lbaAddress, uint8_t sectorCount, char* dst) {
outb(PIO_PORT + 6, ((lbaAddress >> 24) & 0x0f) | 0xe0); // 6 - Use LBA; 4 - Drive number; 3-0 - Highest lba address nibble
outb(PIO_PORT + 2, sectorCount); // Sector count register
outb(PIO_PORT + 3, (uint8_t)(lbaAddress)); // Lowest lba address byte
outb(PIO_PORT + 4, (uint8_t)(lbaAddress >> 8)); // Middle lba address byte
outb(PIO_PORT + 5, (uint8_t)(lbaAddress >> 16)); // High lba address byte
outb(PIO_PORT + 7, READ_COMMAND); // Command register
uint16_t* address = (uint16_t*)dst;
for (uint8_t i = sectorCount; i > 0; i--) {
while (inb(PIO_PORT + 7) & (1 << 7)); // Poll status register untill BSY bit is clear
for (size_t j = 0; j < 256; j++) {
*address++ = inw(PIO_PORT); // Read 256 words (512 Bytes = 1 Sector)
}
for (uint8_t delay = 0; delay < 4; delay++) { // 400ns delay
inb(0x3f6); // Alternate status register
}
}
}
void diskWrite(uint32_t lbaAddress, uint8_t sectorCount, char* src) {
outb(PIO_PORT + 6, ((lbaAddress >> 24) & 0x0f) | 0xe0); // 6 - Use LBA; 4 - Drive number; 3-0 - Highest lba address nibble
outb(PIO_PORT + 2, sectorCount); // Sector count register
outb(PIO_PORT + 3, (uint8_t)(lbaAddress)); // Lowest lba address byte
outb(PIO_PORT + 4, (uint8_t)(lbaAddress >> 8)); // Middle lba address byte
outb(PIO_PORT + 5, (uint8_t)(lbaAddress >> 16)); // High lba address byte
outb(PIO_PORT + 7, WRITE_COMMAND); // Command register
uint16_t* address = (uint16_t*)src;
for (uint8_t i = sectorCount; i > 0; i--) {
while (inb(PIO_PORT + 7) & (1 << 7)); // Poll status register untill BSY bit is clear
for (size_t j = 0; j < 256; j++) {
outw(PIO_PORT, *address++); // Write 256 words (512 Bytes = 1 Sector)
}
for (uint8_t delay = 0; delay < 4; delay++) { // 400ns delay
inb(0x3f6); // Alternate status register
}
}
outb(PIO_PORT + 7, CACHE_FLUSH); // Cache flush
while (inb(PIO_PORT + 7) & (1 << 7)); // Poll status register untill BSY bit is clear
}
+23
View File
@@ -0,0 +1,23 @@
#include <drivers/keyboard.h>
#include <memory/addresses.h>
#include <cpu/system.h>
#include <cpu/isr.h>
static const uint8_t US_Keyboard[2][128] = US_KEYBOARD;
keyboardState_t* keyboard = (keyboardState_t*)KEYBOARD_STATE_LOC;
// TODO: Make this better and be able to read multi-byte scancode
void keyboardHandler(intFrame_t*) {
uint8_t scancode = inb(0x60);
char c = US_Keyboard[keyboard->shift][scancode];
if (scancode == LEFT_SHIFT_PRESS || scancode == RIGHT_SHIFT_PRESS) {
keyboard->shift = 1;
} else if (scancode == LEFT_SHIFT_RELEASE || scancode == RIGHT_SHIFT_RELEASE) {
keyboard->shift = 0;
}
if (scancode & 0x80) { // Keyup
} else if (c != '\0') { keyboard->character = c; }
}
+27
View File
@@ -0,0 +1,27 @@
#include <drivers/pcspk.h>
#include <drivers/timer.h>
#include <cpu/system.h>
#include <sys/notes.h>
#include <stdint.h>
#include <time.h>
void enableSpeaker() {
uint8_t temp = inb(PC_SPEAKER);
outb(PC_SPEAKER, temp | 0x03); // Set first 2 bits
}
void disableSpeaker() {
uint8_t temp = inb(PC_SPEAKER);
outb(PC_SPEAKER, temp & 0xfc); // Set first 2 bits
}
void playNote(note_t note, uint32_t ms) {
setPitPhase(2, 3, note);
sleep(ms);
}
void rest(uint32_t ms) {
setPitPhase(2, 3, 30000); // Unhearable noise
sleep(ms);
}
+131
View File
@@ -0,0 +1,131 @@
#include <drivers/rtc.h>
#include <screen/gfxmode.h>
#include <screen/text.h>
#include <screen/tty.h>
#include <cpu/system.h>
#include <cpu/isr.h>
#include <string.h>
static datetime_t* datetime = (datetime_t*)DATETIME_LOC;
int cmosUpdateProgress() {
outb(CMOS_ADDRESS, 0x8a); // Read status reg A, disable NMI
return inb(CMOS_DATA) & 0x80;
}
uint8_t getRtcRegister(uint8_t reg) {
outb(CMOS_ADDRESS, reg | 0x80); // Disable NMI when sending
return inb(CMOS_DATA);
}
void enableRtc() {
uint8_t regB = getRtcRegister(0x0b);
outb(CMOS_ADDRESS, 0x8b);
outb(CMOS_DATA, regB | 0x40); // Set bit 6 - periodic int at 1024Hz
getRtcRegister(0x0c); // Clear pending interrupts
}
void disableRtc() {
__asm__ volatile ("cli");
uint8_t regB = getRtcRegister(0x0b);
outb(CMOS_ADDRESS, 0x8b);
outb(CMOS_DATA, regB & 0xbf); // Clear bit 6
__asm__ volatile ("sti");
}
void rtcHandler(intFrame_t* iframe) {
datetime_t newDatetime, oldDatetime;
static uint16_t rtcTicks = 0;
__asm__ volatile ("cli");
rtcTicks++;
if (rtcTicks % 1024 == 0) { // 1 Second has passed
while (cmosUpdateProgress()); // Wait
newDatetime.second = getRtcRegister(0);
newDatetime.minute = getRtcRegister(2);
newDatetime.hour = getRtcRegister(4);
newDatetime.day = getRtcRegister(7);
newDatetime.month = getRtcRegister(8);
newDatetime.year = getRtcRegister(9);
do {
oldDatetime = newDatetime;
while (cmosUpdateProgress()); // Wait
newDatetime.second = getRtcRegister(0);
newDatetime.minute = getRtcRegister(2);
newDatetime.hour = getRtcRegister(4);
newDatetime.day = getRtcRegister(7);
newDatetime.month = getRtcRegister(8);
newDatetime.year = getRtcRegister(9);
} while (
newDatetime.second != oldDatetime.second ||
newDatetime.minute != oldDatetime.minute ||
newDatetime.hour != oldDatetime.hour ||
newDatetime.day != oldDatetime.day ||
newDatetime.month != oldDatetime.month ||
newDatetime.year != oldDatetime.year
);
uint8_t regB = getRtcRegister(0x0b);
if (!(regB & 0x04)) {
newDatetime.second = (newDatetime.second & 0x0f) + ((newDatetime.second >> 4) * 10);
newDatetime.minute = (newDatetime.minute & 0x0f) + ((newDatetime.minute >> 4) * 10);
newDatetime.hour = ((newDatetime.hour & 0x0F) + (((newDatetime.hour & 0x70) / 16) * 10)) | (newDatetime.hour & 0x80); // 12/24 Hour format bs
newDatetime.day = (newDatetime.day & 0x0f) + ((newDatetime.day >> 4) * 10);
newDatetime.month = (newDatetime.month & 0x0f) + ((newDatetime.month >> 4) * 10);
newDatetime.year = (newDatetime.year & 0x0f) + ((newDatetime.year >> 4) * 10);
}
// Convert 12 to 14 hour format
if (!(regB & 0x02) && (newDatetime.hour & 0x80)) {
newDatetime.hour = ((newDatetime.hour & 0x7f) + 12) % 24;
}
newDatetime.year += 2000; // Add current century
//*datetime = newDatetime;
datetime->second = newDatetime.second;
datetime->minute = newDatetime.minute;
datetime->hour = newDatetime.hour;
datetime->day = newDatetime.day;
datetime->month = newDatetime.month;
datetime->year = newDatetime.year;
if (1) { // TODO: Probably get rid of this idk
char buf[20] = { 0 }; // "12/12 2012 12:12:12" - Max string 20 chars with null byte
strcat(buf, itoa(datetime->day, 10));
strcat(buf, "/");
strcat(buf, itoa(datetime->month, 10));
strcat(buf, " ");
strcat(buf, itoa(datetime->year, 10));
strcat(buf, " ");
if (datetime->hour < 10) strcat(buf, "0");
strcat(buf, itoa(datetime->hour, 10));
strcat(buf, ":");
if (datetime->minute < 10) strcat(buf, "0");
strcat(buf, itoa(datetime->minute, 10));
strcat(buf, ":");
if (datetime->second < 10) strcat(buf, "0");
strcat(buf, itoa(datetime->second, 10));
// The clock is a little offset down (about 0.4 of a character) It does look nice though!
uint8_t len = strlen(buf);
uint32_t x = gfxMode->xRes - len - 1;
char* str = &buf[0];
for (uint8_t i = 0; i != len; i++, x++) {
drawChar(str[i], x, 0, console->fg, console->bg);
}
}
}
getRtcRegister(0x0c);
__asm__ volatile ("sti");
}
+50
View File
@@ -0,0 +1,50 @@
#include <drivers/serial.h>
#include <cpu/system.h>
#include <stdio.h>
#include <stdarg.h>
int serialEnable(int port) {
outb(port + 1, 0x00); // Disable all interrupts
outb(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
outb(port + 0, 0x03); // Set divisor to 3 (low byte) 38400 baud
outb(port + 1, 0x00); // (high byte)
outb(port + 3, 0x03); // 8 bits, no parity, one stop bit
outb(port + 2, 0xC7); // Enable FIFO, clear them, with 14 byte threshold
outb(port + 4, 0x0B); // IRQs enabled, RTS/DSR set
outb(port + 4, 0x1E); // Set in loopback mode, test the serial chip
outb(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if it returns)
if (inb(port + 0) != 0xAE) return 1;
outb(port + 4, 0x0F); // non-loopback, IRQs enabled, OUT#1 and OUT#2 bits enabled
return 0;
}
int setupSerial() {
if (serialEnable(PORT_COM1) != 0) { return 1; }
outb(PORT_COM1 + 1, 0x01);
return 0;
}
static int serialTransimitEmpty(int port) { return inb(port + 5) & 0x20; }
static int serialRecieved(int port) { return inb(port + 5) & 0x01; }
void serialWrite(int port, char c) { while (!serialTransimitEmpty(port)); outb(port, c); }
char serialRead(int port) { while (!serialRecieved(port)); return inb(port); }
char serialReadAsync(int port) { return inb(port); }
void _dbgPutc(char c, void* arg) {
(void)arg;
serialWrite(PORT_COM1, c);
if (c == '\n') serialWrite(PORT_COM1, '\r');
}
int vdebugf(const char* fmt, va_list va) { return vpprintf(_dbgPutc, NULL, fmt, va); }
int debugf(const char* fmt, ...) {
va_list va;
va_start(va, fmt);
int ret = vdebugf(fmt, va);
va_end(va);
return ret;
}
+33
View File
@@ -0,0 +1,33 @@
#include <drivers/timer.h>
#include <memory/addresses.h>
#include <screen/tty.h>
#include <cpu/system.h>
#include <cpu/isr.h>
#include <stdint.h>
void timerHandler(intFrame_t*) {
static uint32_t cursorTicks = 0;
cursorTicks++;
if (!console->hideCursor) { // TODO: Make a better cursor drawing thing
if (cursorTicks % 500 == 0) toggleCursor();
}
if (*(uint32_t*)SLEEP_TIMER > 0) { --(*(uint32_t*)SLEEP_TIMER); }
}
void setPitPhase(uint8_t channel, uint8_t opMode, uint16_t hz) {
if (channel > 2 || opMode > 7) { return; }
__asm__ volatile ("cli");
// Send command - bits 7-6 channel, 5-4 Access mode, 3-1 operating mode, 0 - Should be zero in x86
outb(COMMAND, ((channel << 6) | (3 << 4) | (opMode << 1)));
// Send frequency
uint16_t freq = INPUT_CLK / hz; // I solved an equation to figure this out
outb(CHANNEL_0 + channel, (uint8_t)freq);
outb(CHANNEL_0 + channel, (uint8_t)(freq >> 8));
__asm__ volatile ("sti");
}
+63
View File
@@ -0,0 +1,63 @@
#include <fs/kernfs.h>
#include <memory/addresses.h>
#include <drivers/disk.h>
#include <fs/fs.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
superblock_t* impl_superblock = (superblock_t*)SUPERBLOCK_LOC;
fsInfo_t* fsInfo = (fsInfo_t*)FS_INFO_LOC;
inode_t* getInode(char* path, dirEntry_t* dentries) {
while (dentries->name[0] != '\0') {
if (strcmp(dentries->name, path) == 0) break;
dentries++;
}
if (dentries->name[0] == '\0') { return NULL; }
inode_t* inode = (inode_t*)BOOT_FIRST_INODE_LOC + dentries->id;
return inode;
}
uint8_t loadFile(inode_t* inode, void* dest) {
uint32_t totalBlocks = BYTES2BLOCKS(inode->sizeBytes);
uint32_t offset = 0;
for (uint8_t i = 0; i < 4 && totalBlocks > 0; i++) {
diskRead(inode->extent[i].block * 8, inode->extent[i].length * 8, dest + offset);
offset += inode->extent[i].length * FS_BLOCK_SIZE;
totalBlocks -= inode->extent[i].length;
}
if (totalBlocks > 0) {
// TODO: Indirect extents
return 1;
}
return 0;
}
void initOpenFileTable() {
fsInfo->openFileTable = malloc(sizeof(FILE) * MAX_OPEN_FILES);
if (fsInfo->openFileTable == NULL) { printf("\e[1MFailed to init file table! Malloc() error.\e[8M"); }
memset(fsInfo->openFileTable, 0, sizeof(FILE) * MAX_OPEN_FILES);
// offset and ptr are unused in these
stdin = fsInfo->openFileTable + 0;
stdin->_file = STDIN_FILENO;
stdin->_flag = O_RDONLY;
stdout = fsInfo->openFileTable + 1;
stdout->_file = STDOUT_FILENO;
stdout->_flag = O_WRONLY | O_APPEND;
stderr = fsInfo->openFileTable + 2;
stderr->_file = STDERR_FILENO;
stderr->_flag = O_WRONLY | O_APPEND;
fsInfo->openFiles = 3;
}
+28
View File
@@ -0,0 +1,28 @@
#ifndef _CPU_IDT_H
#define _CPU_IDT_H
#include <stdint.h>
#define IDT_ENTRIES 256
#define TRAP_GATE_FLAGS 0x8f // P = 1, DPL = 00, S = 0, Type = 1111 (32-bit Trap gate)
#define INT_GATE_FLAGS 0x8e // P = 1, DPL = 00, S = 0, Type = 1110 (32-bit Int gate)
#define USR_INT_GATE_FLAGS 0xee // P = 1, DPL = 11, S = 0, Type = 1110 (32-bit Int gate)
typedef struct {
uint16_t offsetLow;
uint16_t selector;
uint8_t zero;
uint8_t typeAttr;
uint16_t offsetHigh;
} __attribute__ ((packed)) idtEntry_t;
typedef struct {
uint16_t limit;
uint32_t base;
} __attribute__ ((packed)) idtp_t;
void idtSetGate(uint8_t i, void* handler, uint8_t flags);
void setupIdt();
#endif
+27
View File
@@ -0,0 +1,27 @@
#ifndef _CPU_ISR_H
#define _CPU_ISR_H
#include <stdint.h>
typedef struct {
// Pushed by OS
uint32_t esp, ebx, ecx, edx, esi, edi, ebp;
uint32_t ds, es, fs, gs, eax;
uint32_t interrupt, error;
// Pushed by CPU
uint32_t eip, cs, eflags, user_esp, user_ss;
} intFrame_t;
typedef void (*HandlerPtr)(intFrame_t* iframe);
void setupIsrs();
void registerIrq(uint8_t id, HandlerPtr handler);
int handleInterrupt(intFrame_t iframe);
// ISR Table
extern void* asm_isrRedirectTable[48];
// Int 0x80 - Syscall
extern void isr128();
#endif
+19
View File
@@ -0,0 +1,19 @@
#ifndef _CPU_SYSTEM_H
#define _CPU_SYSTEM_H
#include <stdint.h>
void cpuid(uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx);
void outb(uint16_t port, uint8_t data);
void outw(uint16_t port, uint16_t data);
void outl(uint16_t port, uint32_t data);
uint8_t inb(uint16_t port);
uint16_t inw(uint16_t port);
uint32_t inl(uint16_t port);
void ioWait();
void panic();
#endif
+14
View File
@@ -0,0 +1,14 @@
#ifndef _DRIVERS_DISK_H
#define _DRIVERS_DISK_H
#include <stdint.h>
#define PIO_PORT 0x1f0
#define READ_COMMAND 0x20
#define WRITE_COMMAND 0x30
#define CACHE_FLUSH 0xE7
void diskRead(uint32_t lbaAddress, uint8_t sectorCount, char* dst);
void diskWrite(uint32_t lbaAddress, uint8_t sectorCount, char* src);
#endif
+48
View File
@@ -0,0 +1,48 @@
#ifndef _DRIVERS_KEYBOARD_H
#define _DRIVERS_KEYBOARD_H
#include <cpu/isr.h>
// Special keys
#define LEFT_SHIFT_PRESS 0x2a
#define LEFT_SHIFT_RELEASE (LEFT_SHIFT_PRESS | 0x80)
#define RIGHT_SHIFT_PRESS 0x36
#define RIGHT_SHIFT_RELEASE (RIGHT_SHIFT_PRESS | 0x80)
#define LEFT_CTRL_PRESS 0x1D
#define LEFT_CTRL_RELEASE (LEFT_CTRL_PRESS | 0x80)
#define RIGHT_CTRL_PRESS 0x1D
#define RIGHT_CTRL_RELEASE (RIGHT_CTRL_PRESS | 0x80)
#define LEFT_ALT_PRESS 0x38
#define LEFT_ALT_RELEASE (LEFT_ALT_PRESS | 0x80)
#define RIGHT_ALT_PRESS 0x38
#define RIGHT_ALT_RELEASE (RIGHT_ALT_PRESS | 0x80)
// Basic US Keyboard layout
#define US_KEYBOARD {\
{\
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',\
'\t','q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',\
0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'','`',\
0, '\\','z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0,\
'*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\
'7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.',\
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\
},\
{\
0, 27, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b', '\t',\
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', 0, 'A', 'S',\
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', 0, '|', 'Z', 'X', 'C', 'V',\
'B', 'N', 'M', '<', '>', '?', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\
0, 0, 0, 0, 0, 0, 0, '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.',\
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\
}\
}
typedef struct {
char character;
int shift;
} keyboardState_t;
void keyboardHandler(intFrame_t*);
#endif
+14
View File
@@ -0,0 +1,14 @@
#ifndef _DRIVERS_PCSPK_H
#define _DRIVERS_PCSPK_H
#include <sys/notes.h>
#include <stdint.h>
#define PC_SPEAKER 0x61
void enableSpeaker();
void disableSpeaker();
void playNote(note_t note, uint32_t ms);
void rest(uint32_t ms);
#endif
+25
View File
@@ -0,0 +1,25 @@
#ifndef _DRIVERS_RTC_H
#define _DRIVERS_RTC_H
#include <cpu/isr.h>
#include <stdint.h>
#define CMOS_ADDRESS 0x70
#define CMOS_DATA 0x71
typedef struct {
uint8_t second;
uint8_t minute;
uint8_t hour;
uint8_t day;
uint8_t month;
uint16_t year;
} __attribute__ ((packed)) datetime_t;
void rtcHandler(intFrame_t*);
int cmosUpdateProgress();
uint8_t getRtcRegister(uint8_t reg);
void enableRtc();
void disableRtc();
#endif
+23
View File
@@ -0,0 +1,23 @@
#ifndef _DRIVERS_SERIAL_H
#define _DRIVERS_SERIAL_H
#include <stdarg.h>
#define PORT_COM1 0x3f8
#define PORT_COM2 0x2f8
#define PORT_COM3 0x3e8
#define PORT_COM4 0x2e8
// IRQ4 -> COM1, IRQ3 -> COM2
#define SERIAL_IRQ 4
int serialEnable(int port);
int setupSerial();
void serialWrite(int port, char c);
char serialRead(int port);
char serialReadAsync(int port);
int debugf(const char* fmt, ...);
int vdebugf(const char* fmt, va_list va);
#endif
+14
View File
@@ -0,0 +1,14 @@
#ifndef _DRIVERS_TIMER_H
#define _DRIVERS_TIMER_H
#include <cpu/isr.h>
#include <stdint.h>
#define CHANNEL_0 0x40 // Offset it by 1 or 2 for ch1 and ch2
#define COMMAND 0x43
#define INPUT_CLK 1193182
void timerHandler(intFrame_t*);
void setPitPhase(uint8_t channel, uint8_t opMode, uint16_t hz);
#endif
+83
View File
@@ -0,0 +1,83 @@
#ifndef _FS_FS_H
#define _FS_FS_H
/*
* For info, read the fs-spec.txt document inside of docs/
*/
#include <stdint.h>
// FS Definitions
#define FS_SECTOR_SIZE 512
#define FS_BLOCK_SIZE 4096
// Conversion Macros (beatiful)
#define BYTES2BLOCKS(_n) ( (_n) == 0 ? 0 : \
(_n) <= (FS_BLOCK_SIZE) ? 1 : \
((_n) / FS_BLOCK_SIZE) + (((_n) % FS_BLOCK_SIZE) > 0 ? 1 : 0) )
#define BYTES2SECTORS(_n) ( (_n) == 0 ? 0 : \
(_n) <= (FS_SECTOR_SIZE) ? 1 : \
((_n) / FS_SECTOR_SIZE) + (((_n) % FS_SECTOR_SIZE) > 0 ? 1 : 0) )
// Filetypes
#define FT_FILE 0
#define FT_DIR 1
// FS Structures
// TODO: datetime_t?
typedef struct {
uint8_t sectors[FS_BLOCK_SIZE / FS_SECTOR_SIZE][FS_SECTOR_SIZE];
} __attribute__ ((packed)) bootblock_t;
// Superblock - Padded to 4096 Bytes
typedef struct {
// Constant data
uint16_t deviceId;
uint16_t extentsPerIndirect;
uint32_t maxFileSize;
uint16_t inodesPerSector;
// INode data
uint32_t inodeCount;
uint32_t inodeBitmapBlock;
uint32_t inodesStart;
uint32_t inodeBlockCount;
// Data data :)
uint32_t dataBitmapBlock;
uint32_t dataStart;
uint32_t dataBlockCount;
// Other
uint32_t rootInodePtr;
uint32_t firstUnreservedInode;
} __attribute__ ((packed)) superblock_t;
// Extent - 8 Bytes
typedef struct {
uint32_t block;
uint32_t length;
} __attribute__ ((packed)) extent_t;
// INode - 64 Bytes
typedef struct {
uint32_t id;
uint8_t type;
uint32_t sizeBytes; // Size in bytes
uint32_t sizeSectors; // Size in sectors
uint8_t mode; // Access permisions
extent_t extent[4];
uint32_t singleIndirect;
uint32_t doubleIndirect;
uint8_t reserved[10];
} __attribute__ ((packed)) inode_t;
typedef struct {
char name[60];
uint32_t id;
} __attribute__ ((packed)) dirEntry_t;
#endif
+22
View File
@@ -0,0 +1,22 @@
#ifndef _FS_KERNFS_H
#define _FS_KERNFS_H
#include <fs/fs.h>
#include <stdint.h>
#include <stdio.h>
#define MAX_OPEN_FILES 256
typedef struct {
FILE* openFileTable;
uint32_t openFiles;
} fsInfo_t;
extern superblock_t* impl_superblock;
extern fsInfo_t* fsInfo;
inode_t* getInode(char* path, dirEntry_t* dentries);
uint8_t loadFile(inode_t* inode, void* dest);
void initOpenFileTable();
#endif
+61
View File
@@ -0,0 +1,61 @@
#ifndef _MEMORY_ADDRESSES_H
#define _MEMORY_ADDRESSES_H
/*
* Memory layout of addresses 0x0000 - 0x12000
* 0x0000-0x0fff - Probably shouldn't mess with this? idk it feels wrong
* 0x1000-0x17ff - Free
* 0x1800-0x1fff - Global Variables
* 0x2000-0x2fff - Larger structs
* 0x3000-0x3fff - Filesystem Info
* 0x4000-0x4fff - Font area
* 0x6000-0x6fff - VBE info area
* 0x7000-0x7bff - SMAP Area
* 0x7c00-0x8bff - Bootblock
* 0x8c00-0x9bff - Superblock
* 0x9c00-0xafff - Free
* 0xb000-0xbfff - Bootloader first INode
* 0xc000-0xcfff - Scratch INode block
*/
// Global Variables 0x1800-0x1fff
#define SLEEP_TIMER 0x1800
#define CURRENT_PAGE_DIR_ADDR 0x1804
#define PHYS_MEM_MAX_BLOCKS 0x1808
#define PHYS_MEM_USED_BLOCKS 0x180C
// Some structs 0x2000-0x2fff
#define CONSOLE_INFO_LOC 0x2000
#define KEYBOARD_STATE_LOC 0x2100
#define DATETIME_LOC 0x2200
// Filesystem Area 0x3000 - 0x3fff
#define FS_INFO_LOC 0x3000
// Font area 0x4000 - 0x4fff
#define FONT_LOC 0x4000
// VBE Info Area 0x6000 - 0x6fff
#define MODE_INFO_BLOCK_LOC 0x6000 // 512 Bytes
// Smap Area 0x7000 - 0x7bff
#define SMAP_ENTRY_COUNT 0x7000
#define SMAP_ENTRIES 0x7004
// Bootblock 0x7c00-0x9bff
#define BOOTBLOCK_LOC 0x7c00
// Superblock 0x9c00-0xabff
#define SUPERBLOCK_LOC 0x8c00
// First INode from bootloader
#define BOOT_FIRST_INODE_LOC 0xb000
#define SCRATCH_BLOCK_LOC 0xc000
// Other addresses
#define KERNEL_LOC 0x100000
#define KERNEL_MALLOC_AREA 0x300000
#define MEMMAP_AREA 0x30000
#define OPEN_FILE_LOC 0xd000
#endif
+27
View File
@@ -0,0 +1,27 @@
#ifndef _MEMORY_MALLOC_H
#define _MEMORY_MALLOC_H
#include <memory/virtual.h>
#include <memory/physical.h>
#include <stdbool.h>
#include <stdint.h>
// Singly linked list!
typedef struct mallocNode_s {
uint32_t size;
bool free;
struct mallocNode_s* next;
} mallocNode_t;
extern mallocNode_t* mallocListHead;
extern uint32_t mallocVirtualAddr;
extern uint32_t mallocPhysicalAddr;
extern uint32_t mallocPages;
void mallocInit(uint32_t size);
void mallocSplit(mallocNode_t* node, uint32_t size);
void* mallocNextNode(uint32_t size);
void mallocMergeFree();
void mallocFree(void* ptr);
#endif
+33
View File
@@ -0,0 +1,33 @@
#ifndef _MEMORY_PHYSICAL_H
#define _MEMORY_PHYSICAL_H
#include <memory/addresses.h>
#include <string.h>
#include <stdint.h>
#define BLOCK_SIZE 4096 // 4kB
#define BLOCKS_PER_BYTE 8
typedef struct smapEntry_s {
uint64_t baseAddress;
uint64_t length;
uint32_t type;
uint32_t acpiAttr;
} __attribute__ ((packed)) smapEntry_t;
extern uint32_t* memoryMap;
extern uint32_t maxBlocks;
extern uint32_t usedBlocks;
void setBlock(uint32_t block);
void unsetBlock(uint32_t block);
uint8_t testBlock(uint32_t block);
int32_t findFreeBlocks(uint32_t blockCount);
void setupPhysicalMemoryManager(uint32_t startAddress, uint32_t size);
void initMemoryRegion(uint32_t baseAddress, uint32_t size);
void deinitMemoryRegion(uint32_t baseAddress, uint32_t size);
void* allocBlocks(uint32_t blockCount);
void freeBlocks(void* address, uint32_t blockCount);
#endif
+70
View File
@@ -0,0 +1,70 @@
#ifndef _MEMORY_VIRTUAL_H
#define _MEMORY_VIRTUAL_H
#include <memory/physical.h>
#include <stdint.h>
#define PAGES_PER_TABLE 1024
#define TABLES_PER_DIRECTORY 1024
#define PAGE_SIZE 4096
#define PD_INDEX(_vAddress) ((_vAddress) >> 22)
#define PT_INDEX(_vAddress) (((_vAddress) >> 12) & 0x3ff)
#define PAGE_PHYS_ADDRESS(_dirEntry) (*(_dirEntry) & ~ 0xfff)
#define SET_ATTR(_entry, _attr) (*(_entry) |= (_attr))
#define CLEAR_ATTR(_entry, _attr) (*(_entry) &= ~(_attr))
#define TEST_ATTR(_entry, _attr) (*(_entry) & (_attr))
#define SET_FRAME(_entry, _address) (*(_entry) = (*(_entry) & ~0xfffff000) | (_address))
typedef uint32_t ptEntry_t;
typedef uint32_t pdEntry_t;
typedef enum {
PTE_PRESENT = 0x01,
PTE_READ_WRITE = 0x02,
PTE_USER = 0x04,
PTE_WRITE_THROUGH = 0x08,
PTE_CACHE_DISABLE = 0x10,
PTE_ACCESSED = 0x20,
PTE_DIRTY = 0x40,
PTE_PAT = 0x80,
PTE_GLOBAL = 0x100,
PTE_FRAME = 0x7ffff000,
} PAGE_TABLE_FLAGS;
typedef enum {
PDE_PRESENT = 0x01,
PDE_READ_WRITE = 0x02,
PDE_USER = 0x04,
PDE_WRITE_THROUGH = 0x08,
PDE_CACHE_DISABLE = 0x10,
PDE_ACCESSED = 0x20,
PDE_DIRTY = 0x40, // Only with 4MB pages
PDE_PAGE_SIZE = 0x80, // Is page 4MB
PDE_GLOBAL = 0x100,
PDE_PAT = 0x2000,
PDE_FRAME = 0x7ffff000,
} PAGE_DIR_FLAGS;
typedef struct {
ptEntry_t entries[PAGES_PER_TABLE];
} pageTable_t;
typedef struct {
pdEntry_t entries[TABLES_PER_DIRECTORY];
} pageDirectory_t;
extern pageDirectory_t* currentPd;
ptEntry_t* getPtEntry(pageTable_t* pt, uint32_t virtualAddress);
pdEntry_t* getPdEntry(pageDirectory_t* pd, uint32_t virtualAddress);
ptEntry_t* getPage(uint32_t virtualAddress);
void* allocPage(ptEntry_t* page);
void freePage(ptEntry_t* page);
uint8_t setPageDirectory(pageDirectory_t* pd);
void flushTlbEntry(uint32_t virtualAddress);
uint8_t mapPage(void* physicalAddr, void* virtualAddr);
void unmapPage(void* virtualAddress);
uint8_t setupVirtualMemoryManager();
#endif
+72
View File
@@ -0,0 +1,72 @@
#ifndef _SCREEN_GFXMODE_H
#define _SCREEN_GFXMODE_H
#include <memory/addresses.h>
#include <stdint.h>
#define BG_COLOR 0x00010b17
#define FG_COLOR 0x00ebddf4
typedef struct modeInfoBlock_s {
// Required by all VBE revisions
uint16_t modeAttr;
uint8_t windowAAtrr;
uint8_t windowBAttr;
uint16_t windowGranularity;
uint16_t windowSize;
uint16_t windowASegment;
uint16_t windowBSegment;
uint32_t windowFunctionPtr;
uint16_t bytesPerScanline;
// Required by VBE 1.2+
uint16_t xRes;
uint16_t yRes;
uint8_t xCharSize;
uint8_t yCharSize;
uint8_t planeCount;
uint8_t bpp;
uint8_t bankCount;
uint8_t memoryModel;
uint8_t bankSize;
uint8_t imagePageCount;
uint8_t reserved1;
// Direct color fields
uint8_t redMaskSize;
uint8_t redFieldPos;
uint8_t greenMaskSize;
uint8_t greenFieldPos;
uint8_t blueMaskSize;
uint8_t blueFieldPos;
uint8_t reservedMaskSize;
uint8_t reservedFieldPos;
uint8_t directColorModeInfo;
// Required by VBE 2.0+
uint32_t physicalBasePtr;
uint32_t reserved2;
uint16_t reserved3;
// Required by VBE 3.0+
uint16_t linearBytesPerScanline;
uint8_t bankImagePageCount;
uint8_t linearImagePageCount;
uint8_t linearRedMaskSize;
uint8_t linearRedFieldPos;
uint8_t linearGreenMaskSize;
uint8_t linearGreenFieldPos;
uint8_t linearBlueMaskSize;
uint8_t linearBlueFieldPos;
uint8_t linearReservedMaskSize;
uint8_t linearReservedFieldPos;
uint32_t maxPixelClock;
uint8_t reserved4[190];
} __attribute__ ((packed)) modeInfoBlock_t;
extern modeInfoBlock_t* gfxMode;
uint32_t convertColor(uint32_t color);
#endif
+18
View File
@@ -0,0 +1,18 @@
#ifndef _SCREEN_GRAPHICS_H
#define _SCREEN_GRAPHICS_H
#include <stdint.h>
#define rgb(_r,_g,_b) ( ((_r) << 16 | (_g) << 8 | (_b)) & 0x00ffffff )
void drawPixel(int32_t x, int32_t y, uint32_t color);
void drawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color);
void drawRect(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color);
void drawTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, uint32_t color);
void drawCircle(int32_t x, int32_t y, uint16_t radius, uint32_t color);
void boundaryFill(int32_t x, int32_t y, uint32_t fillColor, uint32_t boundaryColor);
void fillRect(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color);
void fillTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, uint32_t color);
void fillCircle(int32_t x, int32_t y, uint16_t radius, uint32_t color);
#endif
+18
View File
@@ -0,0 +1,18 @@
#ifndef _SCREEN_TEXT_H
#define _SCREEN_TEXT_H
#include <stdint.h>
typedef union {
struct {
uint8_t width;
uint8_t height;
};
uint8_t data[4096];
} __attribute__ ((packed)) font_t;
void drawChar(char c, uint32_t x, uint32_t y, uint32_t fgColor, uint32_t bgColor);
void scroll();
void clearScreen(uint32_t bgColor);
#endif
+23
View File
@@ -0,0 +1,23 @@
#ifndef _SCREEN_TTY_H
#define _SCREEN_TTY_H
#include <stdint.h>
#include <stdbool.h>
struct console {
uint32_t x; // X Position of cursor in characters
uint32_t y; // Y Position of cursor in characters
uint32_t bg; // Printed character background
uint32_t fg; // Printed character foreground
uint32_t width; // Width in characters
uint32_t height; // Height in characters
char cursorChar; // Character to use as a cursor
bool hideCursor; // Should we display the cursor
}
extern struct console* console;
int32_t consoleWrite(const void* buf, uint32_t len);
void toggleCursor();
#endif
+19
View File
@@ -0,0 +1,19 @@
#ifndef _SYSCALLS_SYSCALLS_H
#define _SYSCALLS_SYSCALLS_H
#include <cpu/isr.h>
int sys_exit (intFrame_t* iframe);
int sys_read (intFrame_t* iframe);
int sys_write (intFrame_t* iframe);
int sys_open (intFrame_t* iframe);
int sys_close (intFrame_t* iframe);
int sys_seek (intFrame_t* iframe);
int sys_malloc (intFrame_t* iframe);
int sys_free (intFrame_t* iframe);
int sys_sleep (intFrame_t* iframe);
// Main syscall handler/dispatcher
int syscallHandler(intFrame_t* iframe);
#endif
+17
View File
@@ -0,0 +1,17 @@
#
# Kernel library
#
include make.defaults
LIBK_ASM=$(LIBK_DIR)/cpu/isr.s
$(LIBK): $(LIBK_SRC) $(LIBK_ASM) $(LIBC)
@echo "Building $(LIBK)..."
nasm -felf32 -o $(BIN)/libk/isr_asm.o $(LIBK_ASM)
for f in $(LIBK_SRC); do\
filename=$$(basename $$f .c);\
$(CC) $(CFLAGS) -I$(LIBC_INC) -I$(LIBK_INC) -o $(BIN)/libk/$$filename.o -c $$f;\
done
$(LD) $(LDFLAGS) -r -o $(LIBK) $(LIBC) $(BIN)/libk/**.o
+114
View File
@@ -0,0 +1,114 @@
#include <memory/virtual.h>
#include <memory/physical.h>
#include <memory/malloc.h>
#include <stdbool.h>
#include <stdint.h>
mallocNode_t* mallocListHead = NULL;
uint32_t mallocVirtualAddr = 0;
uint32_t mallocPhysicalAddr = 0;
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;
}
}
+122
View File
@@ -0,0 +1,122 @@
#include <memory/physical.h>
#include <memory/addresses.h>
#include <string.h>
#include <stdint.h>
uint32_t* memoryMap = 0;
uint32_t maxBlocks;
uint32_t usedBlocks = 0;
void setBlock(uint32_t block) {
// Set the right bit to 1
memoryMap[block/32] |= (1 << (block % 32));
}
void unsetBlock(uint32_t block) {
// Set the right bit to 0
memoryMap[block/32] &= ~(1 << (block % 32));
}
uint8_t testBlock(uint32_t block) {
// Check the bit
return memoryMap[block/32] & (1 << (block % 32)) ? 1 : 0;
}
// TODO: Refactor whatever the fuck this is
int32_t findFreeBlocks(uint32_t blockCount) {
if (blockCount == 0) { // Error
return -1;
}
uint32_t maxBlockEntries = maxBlocks / 32;
for (uint32_t i = 0; i < maxBlockEntries; i++) {
if (memoryMap[i] != 0xffffffff) {
for (uint8_t j = 0; j < 32; j++) {
uint32_t block = 1 << j;
if (!(memoryMap[i] & block)) {
// uint32_t startBlock = i * 32 + block;
// uint32_t freeBlocks = 0;
for (uint32_t count = i, freeBlocks = 0; count < blockCount; count++) {
if (j + count > 31 && i + 1 <= maxBlocks / 32) {
if (!(memoryMap[i+1] & (1 << (j + count)))) {
freeBlocks++;
}
} else {
if (!(memoryMap[i] & (1 << (j + count)))) {
freeBlocks++;
}
}
if (freeBlocks == blockCount) {
return i * 32 + j;
}
}
}
}
}
}
return -1; // No free memory found :/
}
void setupPhysicalMemoryManager(uint32_t startAddress, uint32_t size) {
memoryMap = (uint32_t*)startAddress;
maxBlocks = size / BLOCK_SIZE;
usedBlocks = maxBlocks;
memset((char*)memoryMap, 0xff, maxBlocks / BLOCKS_PER_BYTE);
}
void initMemoryRegion(uint32_t baseAddress, uint32_t size) {
uint32_t align = baseAddress / BLOCK_SIZE;
uint32_t blockCount = size / BLOCK_SIZE;
while (blockCount-- > 0) {
unsetBlock(align++);
usedBlocks--;
}
setBlock(0); // Make sure we don't override the first block that contains IDT, BIOS stuff etc.
}
void deinitMemoryRegion(uint32_t baseAddress, uint32_t size) {
uint32_t align = baseAddress / BLOCK_SIZE;
uint32_t blockCount = size / BLOCK_SIZE;
while (blockCount-- > 0) {
setBlock(align++);
usedBlocks++;
}
}
void* allocBlocks(uint32_t blockCount) {
if ((maxBlocks - usedBlocks) < blockCount) {
return NULL;
}
int32_t startBlock = findFreeBlocks(blockCount);
if (startBlock == -1) {
return NULL;
}
for (uint32_t i = 0; i < blockCount; i++) {
setBlock(startBlock + i);
usedBlocks++;
}
return (void*)(startBlock * BLOCK_SIZE);
}
void freeBlocks(void* address, uint32_t blockCount) {
uint32_t startBlock = (uint32_t)(address) / BLOCK_SIZE;
for (uint32_t i = 0; i < blockCount; i++) {
unsetBlock(startBlock + i);
usedBlocks--;
}
setBlock(0); // Make sure that block 0 is always set
}
+153
View File
@@ -0,0 +1,153 @@
#include <memory/virtual.h>
#include <memory/physical.h>
#include <memory/addresses.h>
#include <string.h>
#include <stdint.h>
pageDirectory_t* currentPd = NULL;
ptEntry_t* getPtEntry(pageTable_t* pt, uint32_t virtualAddress) {
if (pt) return &pt->entries[PT_INDEX(virtualAddress)];
return NULL;
}
pdEntry_t* getPdEntry(pageDirectory_t* pd, uint32_t virtualAddress) {
if (pd) return &pd->entries[PT_INDEX(virtualAddress)]; // It it supposed to be PT_INDEX, don't worry
return NULL;
}
ptEntry_t* getPage(uint32_t virtualAddress) {
pageDirectory_t* pd = currentPd;
pdEntry_t* entry = &pd->entries[PD_INDEX(virtualAddress)];
pageTable_t* table = (pageTable_t*)PAGE_PHYS_ADDRESS(entry);
ptEntry_t* page = &table->entries[PT_INDEX(virtualAddress)];
return page;
}
void* allocPage(ptEntry_t* page) {
void* block = allocBlocks(1);
if (block) {
SET_FRAME(page, (uint32_t)block);
SET_ATTR(page, PTE_PRESENT);
}
return block;
}
void freePage(ptEntry_t* page) {
void* address = (void*)PAGE_PHYS_ADDRESS(page);
if (address) {
freeBlocks(address, 1);
}
CLEAR_ATTR(page, PTE_PRESENT);
}
uint8_t setPageDirectory(pageDirectory_t* pd) {
if (!pd) { return 1; } // Nuh uh
currentPd = pd;
// cr3 (Control register 3) - current page dir address
__asm__ volatile("movl %%eax, %%cr3" : : "a"(currentPd));
return 0; // Success
}
void flushTlbEntry(uint32_t virtualAddress) {
__asm__ volatile("cli; invlpg (%0); sti" : : "r"(virtualAddress));
}
uint8_t mapPage(void* physicalAddr, void* virtualAddr) {
pageDirectory_t* pd = currentPd;
pdEntry_t* entry = &pd->entries[PD_INDEX((uint32_t)virtualAddr)];
if (!TEST_ATTR(entry, PTE_PRESENT)) {
// Assuming that the page is not allocated since it's not present
pageTable_t* table = (pageTable_t*)allocBlocks(1);
if (!table) return 1; // Out of memory!!
// Clear page table (may be slow?)
memset(table, 0, sizeof(pageTable_t));
pdEntry_t* entry = &pd->entries[PD_INDEX((uint32_t)virtualAddr)];
// Enable attributes and map in table
SET_ATTR(entry, PDE_PRESENT);
SET_ATTR(entry, PDE_READ_WRITE);
SET_FRAME(entry, (uint32_t)table);
}
pageTable_t* table = (pageTable_t*)PAGE_PHYS_ADDRESS(entry);
ptEntry_t* page = &table->entries[PT_INDEX((uint32_t)virtualAddr)];
SET_ATTR(page, PTE_PRESENT);
SET_FRAME(page, (uint32_t)physicalAddr);
return 0; // Success
}
void unmapPage(void* virtualAddress) {
ptEntry_t* page = getPage((uint32_t)virtualAddress);
SET_FRAME(page, 0);
CLEAR_ATTR(page, PDE_PRESENT);
}
uint8_t setupVirtualMemoryManager() {
// Create a default page dir
pageDirectory_t* dir = (pageDirectory_t*)allocBlocks(3);
if (!dir) { return 1; } // Out of memory
memset(dir, 0, sizeof(pageDirectory_t));
for (uint32_t i = 0; i < 1024; i++) {
dir->entries[i] = 0x02; // Supervisor, r/w, not present
}
// Alloc default page table
pageTable_t* table = (pageTable_t*)allocBlocks(1);
if (!table) { return 1; } // Out of memory
// Alloc a 3GB page
pageTable_t* table3gb = (pageTable_t*)allocBlocks(1);
if (!table) { return 1; } // Out of memory
memset(table, 0, sizeof(pageTable_t));
memset(table3gb, 0, sizeof(pageTable_t));
// Identity map first 4MB
for (uint32_t i = 0, frame = 0, virt = 0; i < 1024; i++, frame += PAGE_SIZE, virt += PAGE_SIZE) {
ptEntry_t page = 0;
SET_ATTR(&page, PTE_PRESENT);
SET_ATTR(&page, PTE_READ_WRITE);
SET_FRAME(&page, frame);
table3gb->entries[PT_INDEX(virt)] = page;
}
// Map kernel to 3GB+
for (uint32_t i = 0, frame = KERNEL_LOC, virt = 0xc0000000; i < 1024; i++, frame += PAGE_SIZE, virt += PAGE_SIZE) {
ptEntry_t page = 0;
SET_ATTR(&page, PTE_PRESENT);
SET_ATTR(&page, PTE_READ_WRITE);
SET_FRAME(&page, frame);
table->entries[PT_INDEX(virt)] = page;
}
pdEntry_t* entry = &dir->entries[PD_INDEX(0xc0000000)];
SET_ATTR(entry, PDE_PRESENT);
SET_ATTR(entry, PDE_READ_WRITE);
SET_FRAME(entry, (uint32_t)table);
pdEntry_t* entry2 = &dir->entries[PD_INDEX(0x00000000)];
SET_ATTR(entry2, PDE_PRESENT);
SET_ATTR(entry2, PDE_READ_WRITE);
SET_FRAME(entry2, (uint32_t)table3gb);
setPageDirectory(dir);
// ENABLE PAGING!!! Set PG bit 31 and PE bit 0 in cr0
__asm__ volatile("movl %cr0, %eax; orl $0x80000001, %eax; movl %eax, %cr0");
return 0; // Success
}
+20
View File
@@ -0,0 +1,20 @@
#include <screen/gfxmode.h>
#include <memory/addresses.h>
#include <stdint.h>
modeInfoBlock_t* gfxMode = (modeInfoBlock_t*)MODE_INFO_BLOCK_LOC;
uint32_t convertColor(uint32_t color) {
if (gfxMode->bpp == 8) { // Uses VGA Color pallete, idk how to support that
return color & 0xff;
}
// TODO: !! Important !! - Is should be divided by 255.0 (for floats), but using '-mgeneral-regs-only' removes fp-registers and
// wants to use some dumb functions for converting fp numbers in the stdlib (that we don't have)
uint8_t red = ((color >> 16) & 0xff) * (((1 << gfxMode->linearRedMaskSize) - 1) / 255);
uint8_t green = ((color >> 8 ) & 0xff) * (((1 << gfxMode->linearGreenMaskSize) - 1) / 255);
uint8_t blue = ((color ) & 0xff) * (((1 << gfxMode->linearBlueMaskSize) - 1) / 255);
return (red << gfxMode->redFieldPos) | (green << gfxMode->greenFieldPos) | (blue << gfxMode->blueFieldPos);
}
+143
View File
@@ -0,0 +1,143 @@
#include <screen/graphics.h>
#include <screen/text.h>
#include <screen/gfxmode.h>
#include <stdint.h>
#include <math.h>
void drawPixel(int32_t x, int32_t y, uint32_t color) {
uint8_t* vidmem = (uint8_t*)gfxMode->physicalBasePtr;
uint8_t bytesPerPx = gfxMode->bpp / 8;
uint32_t convColor = convertColor(color); // Idk if i should convert this for every px or just put in a preconverted color
uint32_t offset = ((y * gfxMode->xRes) + x) * bytesPerPx;
for (uint8_t i = 0; i < bytesPerPx; i++) {
vidmem[offset + i] = (uint8_t)(convColor >> (i*8));
}
}
// Source: https://en.wikipedia.org/wiki/Bresenham's_line_algorithm
void drawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color) {
int32_t dx = abs(x2 - x1);
int32_t dy = -abs(y2 - y1);
int8_t sx = (x1 < x2) ? 1 : -1;
int8_t sy = (y1 < y2) ? 1 : -1;
int16_t err = dx + dy;
// TODO: Sometimes the condition isn't met for some reason and it breaks everything
while (!(x1 == x2 && y1 == y2)) {
drawPixel(x1, y1, color);
if (err * 2 >= dy) {
err += dy;
x1 += sx;
}
if (err * 2 <= dx) {
err += dx;
y1 += sy;
}
}
}
void drawRect(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color) {
drawLine(x1, y1, x2, y1, color);
drawLine(x2, y1, x2, y2, color);
drawLine(x2, y2, x1, y2, color);
drawLine(x1, y2, x1, y1, color);
}
void drawTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, uint32_t color) {
drawLine(x1, y1, x2, y2, color);
drawLine(x2, y2, x3, y3, color);
drawLine(x3, y3, x1, y1, color);
}
void drawCircle(int32_t x, int32_t y, uint16_t radius, uint32_t color) {
int16_t offX = 0;
int16_t offY = radius;
int16_t p = 1 - radius;
// Draw 8 octant points
drawPixel(x + offX, y + offY, color);
drawPixel(x - offX, y + offY, color);
drawPixel(x + offX, y - offY, color);
drawPixel(x - offX, y - offY, color);
drawPixel(x + offY, y + offX, color);
drawPixel(x - offY, y + offX, color);
drawPixel(x + offY, y - offX, color);
drawPixel(x - offY, y - offX, color);
while (offX < offY) {
offX++;
if (p < 0) p += 2 * offX + 1;
else {
offY--;
p += 2 * (offX - offY) + 1;
}
drawPixel(x + offX, y + offY, color);
drawPixel(x - offX, y + offY, color);
drawPixel(x + offX, y - offY, color);
drawPixel(x - offX, y - offY, color);
drawPixel(x + offY, y + offX, color);
drawPixel(x - offY, y + offX, color);
drawPixel(x + offY, y - offX, color);
drawPixel(x - offY, y - offX, color);
}
}
// Recursive (may need large stack)
// TODO: Fix this for all bpp values
void boundaryFill(int32_t x, int32_t y, uint32_t fillColor, uint32_t boundaryColor) {
uint8_t* vidmem = (uint8_t*)gfxMode->physicalBasePtr;
uint8_t bytesPerPx = (gfxMode->bpp+1) / 8;
uint32_t convColorF = convertColor(fillColor);
uint32_t convColorB = convertColor(boundaryColor);
uint32_t offset = (y * gfxMode->xRes + x) * bytesPerPx;
uint8_t draw = 0;
for (uint8_t i = 0; i < bytesPerPx; i++) {
if (vidmem[offset + i] != (uint8_t)(convColorF >> (i*8)) && vidmem[offset + i] != (uint8_t)(convColorB >> (i*8))) {
draw = 1;
break;
}
}
if (draw) {
for (uint8_t i = 0; i < bytesPerPx; i++) {
vidmem[offset + i] = (uint8_t)(convColorF >> (i*8));
}
boundaryFill(x + 1, y, fillColor, boundaryColor);
boundaryFill(x, y + 1, fillColor, boundaryColor);
boundaryFill(x - 1, y, fillColor, boundaryColor);
boundaryFill(x, y - 1, fillColor, boundaryColor);
}
}
// TODO: After i fix boundary fill, uncomment it from these functions
void fillRect(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color) {
int32_t cx = (x1 + x2) / 2;
int32_t cy = (y1 + y2) / 2;
drawRect(x1, y1, x2, y2, color - 1);
boundaryFill(cx, cy, color, color - 1);
drawRect(x1, y1, x2, y2, color);
}
void fillTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, uint32_t color) {
int32_t cx = (x1 + x2 + x3) / 3;
int32_t cy = (y1 + y2 + y3) / 3;
drawTriangle(x1, y1, x2, y2, x3, y3, color - 1);
boundaryFill(cx, cy, color, color - 1);
drawTriangle(x1, y1, x2, y2, x3, y3, color);
}
void fillCircle(int32_t x, int32_t y, uint16_t radius, uint32_t color) {
drawCircle(x, y, radius, color - 1);
// boundaryFill(x, y, color, color - 1); TODO: It just doesn't feel like working here and hangs
drawCircle(x, y, radius, color);
}
+91
View File
@@ -0,0 +1,91 @@
#include <screen/text.h>
#include <screen/gfxmode.h>
#include <screen/tty.h>
#include <memory/addresses.h>
#include <stdint.h>
#include <string.h>
// TODO: Reimplement larger text
void drawChar(char c, uint32_t x, uint32_t y, uint32_t fgColor, uint32_t bgColor) {
// Font info
font_t* font = (font_t*)FONT_LOC;
uint8_t charWidth = font->width;
uint8_t charHeight = font->height;
// uint8_t bitmapRowLen = (charWidth - 1) / 8 + 1; // TODO: Larger font support
// Video stuff
uint8_t bytesPerPx = (gfxMode->bpp+7) / 8;
uint8_t* vidmem = (uint8_t*)gfxMode->physicalBasePtr;
uint32_t offset = (gfxMode->xRes * y * charHeight + x * charWidth) * bytesPerPx;
uint8_t* bitmap = &font->data[(c - 1) * charHeight];
for (uint8_t i = 0; i < charHeight; i++) { // Rows
uint8_t bitmapRow = bitmap[i];
uint32_t color = convertColor((bitmapRow & 0x80) ? fgColor : bgColor);
for (uint8_t j = 0; j < charWidth * bytesPerPx; ++j) { // Cols
uint8_t byte = j % bytesPerPx;
vidmem[offset + j] = (uint8_t)(color >> (8 * byte));
if (byte == bytesPerPx - 1) {
bitmapRow = bitmapRow << 1;
color = convertColor((bitmapRow & 0x80) ? fgColor : bgColor);
}
}
offset += gfxMode->linearBytesPerScanline; // gfxMode->xRes * bytesPerPx
}
}
void scroll() { // TODO: Make this faster (still kinda slow, but memcpy32() helped alot)
uint8_t charHeight = ((font_t*)FONT_LOC)->height;
if (console->y+1 < console->height) { return; } // Check if we should scroll
uint32_t bytesPerLine = charHeight * gfxMode->bytesPerScanline;
uint32_t lines = console->height;
uint32_t vidmem = gfxMode->physicalBasePtr;
for (uint32_t i = 1; i < lines; i++) {
uint32_t address = vidmem + i * bytesPerLine;
memcpy32((char*)address, (char*)(address - bytesPerLine), bytesPerLine);
}
uint32_t color = convertColor(console->bg);
uint8_t* lastLine = (uint8_t*)(vidmem + (lines-1) * bytesPerLine);
uint8_t bytesPerPx = (gfxMode->bpp+1) / 8;
for (uint32_t i = 0; i < bytesPerLine; i++) {
for (uint8_t j = 0; j < bytesPerPx; j++) {
lastLine[j] = (uint8_t)(color >> (j * 8));
}
lastLine += bytesPerPx;
}
console->y--;
}
// TODO: Make this comply with the new console.h thing!
void clearScreen(uint32_t bgColor) {
uint8_t* vidmem = (uint8_t*)gfxMode->physicalBasePtr;
uint8_t bytesPerPx = (gfxMode->bpp+1) / 8;
console->x = 0;
console->y = 0;
uint32_t color = convertColor(bgColor);
for (uint32_t i = 0; i < gfxMode->xRes; i++) { // Clear one line of pixels
for (uint8_t j = 0; j < bytesPerPx; j++) {
vidmem[j] = (uint8_t)(color >> (j * 8));
}
vidmem += bytesPerPx;
}
vidmem -= gfxMode->bytesPerScanline;
for (uint32_t i = 0; i < gfxMode->yRes; i++) { // Copy that line to clear the entire screen (using memcpy32 is fast!)
memcpy32(vidmem, vidmem + gfxMode->bytesPerScanline, gfxMode->bytesPerScanline);
vidmem += gfxMode->bytesPerScanline;
}
}
+129
View File
@@ -0,0 +1,129 @@
#include <screen/tty.h>
#include <screen/gfxmode.h>
#include <screen/text.h>
#include <memory/addresses.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <sys/gfx.h>
console_t* console = (console_t*)CONSOLE_INFO_LOC;
int32_t consoleWrite(const void* buf, uint32_t len) { // TODO fix font size
console->width = gfxMode->xRes / 8;//*(uint8_t*)(FONT_LOC);
console->height = gfxMode->yRes / 16;//*(uint8_t*)(FONT_LOC+1);
char* str = (char*)buf;
uint32_t i;
// Do we need to check for NULL? Can we just skip it/ignore it?
for (i = 0; i < len && str[i] != '\0'; i++) {
if (str[i] == '\n') {
drawChar(' ', console->x, console->y, console->fg, console->bg);
console->y++;
console->x = 0;
} else if (str[i] == '\b') {
drawChar(' ', console->x, console->y, console->fg, console->bg);
if (console->x == 0) {
console->x = console->width - 1;
console->y--; // Y could be 0?
} else {
console->x--;
}
drawChar(' ', console->x, console->y, console->fg, console->bg);
} else if (str[i] == '\x1b') { // Escape sequence
if (str[++i] != '[') { // TODO: Support more types of escape sequences
i--;
continue;
}
i++;
uint32_t args[8] = { 0 };
uint8_t argc = 0;
while (1) { // I'm not 100% sure this works, but i'd like to imagine it does
if (argc > 8) break; // Max arg count? idk
uint32_t value = atoi(&str[i]);
args[argc++] = value;
while (value != 0) { // Skip by the number string
value /= 10;
i++;
}
if (str[i] != ';') break;
i++;
}
switch (str[i]) { // TODO: Add default values (see docs/escape.txt)
case 'A': // Cursor up
console->y -= args[0];
break;
case 'B': // Cursor down
console->y += args[0];
break;
case 'C': // Cursor left
console->x -= args[0];
break;
case 'D': // Cursor right
console->x += args[0];
break;
case 'E': // nth row
console->x = args[0];
break;
case 'F': // nth col
console->y = args[0];
break;
case 'G': // show/hide cursor
console->hideCursor = args[0] ? false : true;
break;
case 'H': // move cursor to (x,y)
console->x = args[0];
console->y = args[1];
break;
case 'I': // RESERVED
case 'J': // Erase screen
clearScreen(console->bg);
break;
case 'K': // Erase line
break; // TODO
case 'L': // Erase collumn
break; // TODO
case 'M': // Set FG
if (args[0] < 8) {
console->fg = codeToColor(args[0]);
} else if (args[0] == 8) {
console->fg = FG_COLOR;
}
break;
case 'N': // Set BG
if (args[0] < 8) {
console->bg = codeToColor(args[0]);
} else if (args[0] == 8) {
console->bg = BG_COLOR;
}
break;
default: break;
}
} else {
drawChar(str[i], console->x, console->y, console->fg, console->bg);
console->x++;
if (console->x >= console->width) { // Go to next line
console->y++;
console->x = 0;
}
}
}
scroll();
return i; // Number of characters that were printed
}
void toggleCursor() {
static bool visible = false;
visible = !visible;
drawChar(visible ? 127 : ' ', console->x, console->y, console->fg, console->bg);
}
+9
View File
@@ -0,0 +1,9 @@
#include <syscalls/syscalls.h>
#include <cpu/isr.h>
#include <stdio.h>
int sys_close(intFrame_t* iframe) {
// TODO
return -1;
}
+9
View File
@@ -0,0 +1,9 @@
#include <syscalls/syscalls.h>
#include <drivers/serial.h>
#include <cpu/isr.h>
int sys_exit(intFrame_t* iframe) {
debugf("Tried to exit with %d", iframe->eax);
return iframe->eax;
}
+10
View File
@@ -0,0 +1,10 @@
#include <syscalls/syscalls.h>
#include <memory/malloc.h>
#include <cpu/isr.h>
int sys_free(intFrame_t* iframe) {
void* ptr = (void*)iframe->ebx;
mallocFree(ptr);
return 0;
}
+18
View File
@@ -0,0 +1,18 @@
#include <syscalls/syscalls.h>
#include <memory/malloc.h>
#include <cpu/isr.h>
#include <stddef.h>
int sys_malloc(intFrame_t* iframe) {
size_t count = iframe->ebx;
// First Malloc()
if (!mallocListHead) {
mallocInit(count); // Setup malloc linked list
}
void* ptr = mallocNextNode(count);
mallocMergeFree();
return (size_t)ptr;
}
+9
View File
@@ -0,0 +1,9 @@
#include <syscalls/syscalls.h>
#include <cpu/isr.h>
#include <stdio.h>
int sys_open(intFrame_t* iframe) {
// TODO
return -1;
}
+11
View File
@@ -0,0 +1,11 @@
#include <syscalls/syscalls.h>
#include <cpu/isr.h>
#include <stdio.h>
int sys_read(intFrame_t* iframe) {
char* s = (char*)iframe->ebx;
gets(s, 0xffffffff);
return 0;
}
+8
View File
@@ -0,0 +1,8 @@
#include <syscalls/syscalls.h>
#include <cpu/isr.h>
int sys_seek(intFrame_t* iframe) {
// TODO
return -1;
}
+14
View File
@@ -0,0 +1,14 @@
#include <syscalls/syscalls.h>
#include <memory/addresses.h>
#include <cpu/isr.h>
#include <stdint.h>
int sys_sleep(intFrame_t* iframe) {
uint32_t* sleepTimerTicks = (uint32_t*)SLEEP_TIMER;
*sleepTimerTicks = iframe->ebx;
while (*sleepTimerTicks > 0) { __asm__ volatile ("sti; hlt"); }
return 0;
}
+15
View File
@@ -0,0 +1,15 @@
#include <syscalls/syscalls.h>
#include <screen/tty.h>
#include <cpu/isr.h>
#include <stddef.h>
int sys_write(intFrame_t* iframe) {
int fd = iframe->ebx;
void* buf = (void*)iframe->ecx;
size_t len = iframe->edx;
if (fd == 1) {
return consoleWrite(buf, len);
} else { return -1; }
}
+28
View File
@@ -0,0 +1,28 @@
#include <syscalls/syscalls.h>
#include <drivers/serial.h>
#include <cpu/isr.h>
#include <syscall.h>
// System call table
int (*syscalls[SYSCALL_COUNT])(intFrame_t*) = {
[SYS_EXIT] = sys_exit,
[SYS_READ] = sys_read,
[SYS_WRITE] = sys_write,
[SYS_OPEN] = sys_open,
[SYS_CLOSE] = sys_close,
[SYS_SEEK] = sys_seek,
[SYS_MALLOC] = sys_malloc,
[SYS_FREE] = sys_free,
[SYS_SLEEP] = sys_sleep,
};
// Syscall handler
int syscallHandler(intFrame_t* iframe) {
if (iframe->eax > SYSCALL_COUNT-1) { // Syscall doesn't exist
debugf("Error: Syscall(%d) does not exist!\n", iframe->eax);
return -1;
}
return syscalls[iframe->eax](iframe);
}