Project restructure (no new code added)

Moved all header files into include/ and removed their C counterparts -> code inside .h files
Also added a kernel.ld linker file
since we don't have many code files in src/ now, i removed src/kernel/
only real code change is that i moved memcopy() and memset() into string.h from system.h
This commit is contained in:
2024-04-14 18:27:53 +02:00
parent 60cca470b4
commit 90ac82eebc
25 changed files with 204 additions and 273 deletions
+63
View File
@@ -0,0 +1,63 @@
#ifndef DRIVE_H
#define DRIVE_H
#include "stdint.h"
#include "system.h"
#define PIO_PORT 0x1f0
#define READ_COMMAND 0x20
#define WRITE_COMMAND 0x30
#define CACHE_FLUSH 0xE7
extern uint8_t driveNum;
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
}
#endif
+49
View File
@@ -0,0 +1,49 @@
#ifndef IDT_H
#define IDT_H
#include "stdint.h"
#include "system.h"
struct idtEntry {
uint16_t offsetLow;
uint16_t selector;
uint8_t zero;
uint8_t typeAttr;
uint16_t offsetHigh;
} __attribute__((packed));
struct idtPointer {
uint16_t limit;
uint32_t base;
} __attribute__((packed));
struct idtEntry idt[256] = { 0 };
struct idtPointer idtp;
extern void idtLoad();
void idtSetGate(uint8_t i, uint32_t offset, uint16_t selector, uint8_t typeAttr) {
idt[i].offsetLow = (uint16_t)offset;
idt[i].selector = selector;
idt[i].zero = 0;
idt[i].typeAttr = typeAttr;
idt[i].offsetHigh = (uint16_t)(offset >> 16);
}
void setupIdt() {
idtp.limit = sizeof(struct idtEntry) * 256;
idtp.base = (uint32_t)&idt;
idtLoad();
}
// Contains values of registers and exception info from isrs
struct regs {
unsigned int gs, fs, es, ds;
unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;
unsigned int intNo, errCode;
unsigned int eip, cs, eflags, useresp, ss;
};
#endif
+80
View File
@@ -0,0 +1,80 @@
#ifndef IRQ_H
#define IRQ_H
#include "stdint.h"
#include "idt.h"
void* irqRoutines[16] = { 0 };
extern void irq0();
extern void irq1();
extern void irq2();
extern void irq3();
extern void irq4();
extern void irq5();
extern void irq6();
extern void irq7();
extern void irq8();
extern void irq9();
extern void irq10();
extern void irq11();
extern void irq12();
extern void irq13();
extern void irq14();
extern void irq15();
void installIrqHandler(uint32_t irq, void (*handler)(struct regs* r)) {
irqRoutines[irq] = handler;
}
void uninstallIrqHandler(uint32_t irq) {
irqRoutines[irq] = 0;
}
void irqHandler(struct regs* r) {
void (*handler)(struct regs* r);
handler = irqRoutines[r->intNo - 32]; // Offset by 32 because of isrs
if (handler) handler(r);
// Something about master and slave handlers
if (r->intNo >= 40) outb(0xa0, 0x20);
outb(0x20, 0x20);
}
void irqRemap(void) {
outb(0xa0, 0x11);
outb(0x20, 0x11);
outb(0x21, 0x20);
outb(0xa1, 0x28);
outb(0x21, 0x04);
outb(0xa1, 0x02);
outb(0x21, 0x01);
outb(0xa1, 0x01);
outb(0x21, 0x0);
outb(0xa1, 0x0);
}
void setupIrqs() {
irqRemap();
// Same as isrs, but differnet handlers :o
idtSetGate(32, (unsigned)irq0, 0x08, 0x8e);
idtSetGate(33, (unsigned)irq1, 0x08, 0x8e);
idtSetGate(34, (unsigned)irq2, 0x08, 0x8e);
idtSetGate(35, (unsigned)irq3, 0x08, 0x8e);
idtSetGate(36, (unsigned)irq4, 0x08, 0x8e);
idtSetGate(37, (unsigned)irq5, 0x08, 0x8e);
idtSetGate(38, (unsigned)irq6, 0x08, 0x8e);
idtSetGate(39, (unsigned)irq7, 0x08, 0x8e);
idtSetGate(40, (unsigned)irq8, 0x08, 0x8e);
idtSetGate(41, (unsigned)irq9, 0x08, 0x8e);
idtSetGate(42, (unsigned)irq10, 0x08, 0x8e);
idtSetGate(43, (unsigned)irq11, 0x08, 0x8e);
idtSetGate(44, (unsigned)irq12, 0x08, 0x8e);
idtSetGate(45, (unsigned)irq13, 0x08, 0x8e);
idtSetGate(46, (unsigned)irq14, 0x08, 0x8e);
idtSetGate(47, (unsigned)irq15, 0x08, 0x8e);
}
#endif
+128
View File
@@ -0,0 +1,128 @@
#ifndef ISRS_H
#define ISRS_H
#include "idt.h"
#include "screen.h"
#include "system.h"
#include "string.h"
char* exceptionMessages[] = {
"Divide By Zero Error",
"Debug Exception",
"NMI Interrupt",
"Breakpoint",
"Overflow",
"BOUND Range Exceeded",
"Invalid Opcode",
"Device Not Available",
"Double Fault",
"Coprocessor Segment Overrun",
"Invalid TSS",
"Segment Not Present",
"Stack-Segment Fault",
"General Protection Fault",
"Page Fault",
"Reserved",
"x87 FPU Floating-Point Error",
"Alignment Check",
"Machine Check",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
};
// Repetative isr definitions
extern void isr0();
extern void isr1();
extern void isr2();
extern void isr3();
extern void isr4();
extern void isr5();
extern void isr6();
extern void isr7();
extern void isr8();
extern void isr9();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();
void setupIsrs() {
idtSetGate(0, (unsigned)isr0, 0x08, 0x8e);
idtSetGate(1, (unsigned)isr1, 0x08, 0x8e);
idtSetGate(2, (unsigned)isr2, 0x08, 0x8e);
idtSetGate(3, (unsigned)isr3, 0x08, 0x8e);
idtSetGate(4, (unsigned)isr4, 0x08, 0x8e);
idtSetGate(5, (unsigned)isr5, 0x08, 0x8e);
idtSetGate(6, (unsigned)isr6, 0x08, 0x8e);
idtSetGate(7, (unsigned)isr7, 0x08, 0x8e);
idtSetGate(8, (unsigned)isr8, 0x08, 0x8e);
idtSetGate(9, (unsigned)isr9, 0x08, 0x8e);
idtSetGate(10, (unsigned)isr10, 0x08, 0x8e);
idtSetGate(11, (unsigned)isr11, 0x08, 0x8e);
idtSetGate(12, (unsigned)isr12, 0x08, 0x8e);
idtSetGate(13, (unsigned)isr13, 0x08, 0x8e);
idtSetGate(14, (unsigned)isr14, 0x08, 0x8e);
idtSetGate(15, (unsigned)isr15, 0x08, 0x8e);
idtSetGate(16, (unsigned)isr16, 0x08, 0x8e);
idtSetGate(17, (unsigned)isr17, 0x08, 0x8e);
idtSetGate(18, (unsigned)isr18, 0x08, 0x8e);
idtSetGate(19, (unsigned)isr19, 0x08, 0x8e);
idtSetGate(20, (unsigned)isr20, 0x08, 0x8e);
idtSetGate(21, (unsigned)isr21, 0x08, 0x8e);
idtSetGate(22, (unsigned)isr22, 0x08, 0x8e);
idtSetGate(23, (unsigned)isr23, 0x08, 0x8e);
idtSetGate(24, (unsigned)isr24, 0x08, 0x8e);
idtSetGate(25, (unsigned)isr25, 0x08, 0x8e);
idtSetGate(26, (unsigned)isr26, 0x08, 0x8e);
idtSetGate(27, (unsigned)isr27, 0x08, 0x8e);
idtSetGate(28, (unsigned)isr28, 0x08, 0x8e);
idtSetGate(29, (unsigned)isr29, 0x08, 0x8e);
idtSetGate(30, (unsigned)isr30, 0x08, 0x8e);
idtSetGate(31, (unsigned)isr31, 0x08, 0x8e);
}
void faultHandler(struct regs* r) {
if (r->intNo < 32) {
print(exceptionMessages[r->intNo], 0x04);
if (r->errCode) {
print(": 0x", 0x04);
print(itoa(r->errCode, 16), 0x04);
}
cli();
hlt();
}
}
#endif
+97
View File
@@ -0,0 +1,97 @@
#ifndef KEYBOARD_H
#define KEYBOARD_H
#include "irq.h"
#include "idt.h"
#include "system.h"
#include "screen.h"
#include "stdint.h"
#include "stdbool.h"
// Keycodes
#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)
#define MAX_BUFFER_SIZE 256
const char US_Keyboard[2][128] = {
{
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', '.', // Numpad
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
}
};
uint8_t shift = 0;
uint16_t bufferLen = 0;
char buffer[MAX_BUFFER_SIZE + 1] = { 0 };
bool echo = false;
uint8_t echoAttr = 0x0f;
bool canBackspace = false;
void keyboardHandler() {
uint8_t scancode;
scancode = inb(0x60);
if (scancode == LEFT_SHIFT_PRESS || scancode == RIGHT_SHIFT_PRESS) shift = 1;
else if (scancode == LEFT_SHIFT_RELEASE || scancode == RIGHT_SHIFT_RELEASE) shift = 0;
char c = US_Keyboard[shift][scancode];
if (scancode & 0x80) { // Keyup
} else if (c != 0) {
if (!canBackspace && c == '\b') return;
if (echo) putc(c, echoAttr);
buffer[bufferLen] = c;
if (c == '\b') bufferLen--;
else bufferLen++;
if (bufferLen > 0) canBackspace = true;
else canBackspace = false;
}
}
char* read(char terminator, uint8_t attr) {
bufferLen = 0;
echo = attr ? true : false;
echoAttr = attr;
while (buffer[bufferLen-1] != terminator && bufferLen < MAX_BUFFER_SIZE);
echo = false;
canBackspace = false;
buffer[bufferLen] = '\0';
return buffer;
}
void setupKeyboard() {
installIrqHandler(1, keyboardHandler);
}
#endif
+138
View File
@@ -0,0 +1,138 @@
#ifndef SCREEN_H
#define SCREEN_H
#include "screen.h"
#include "stdint.h"
#include "system.h"
#include "string.h"
#define VIDMEM 0xb8000
#define CURSOR_HIGH 14
#define CURSOR_LOW 15
#define CTRLREG 0x3d4
#define DATAREG 0x3d5
// 80x25 VGA Text mode
#define ROWS 25
#define COLS 80
#define CHARS (ROWS*COLS)
uint32_t cursor = 0;
void updateCursor() {
// Move visual cursor position
outb(0x3d4, 0x0f); // Low byte
outb(0x3d5, cursor & 0xff);
outb(0x3d4, 0x0e); // High byte
outb(0x3d5, cursor >> 8);
}
void setCursorPos(uint32_t offset) {
cursor = offset;
updateCursor();
}
uint32_t getCursorPos() {
return cursor;
}
uint32_t calcOffset(uint8_t col, uint8_t row) {
return row * COLS + col;
}
void scroll() {
if (cursor < COLS * ROWS) return;
for (int i = 1; i < ROWS; i++) {
memcopy((char*)(calcOffset(0, i)*2)+VIDMEM, (char*)(calcOffset(0, i-1)*2)+VIDMEM, COLS*2);
}
char* lastRow = (char*)(calcOffset(0, ROWS-1)*2)+VIDMEM;
for (int i = 0; i < COLS*2; i += 2) {
lastRow[i] = '\0';
lastRow[i+1] = 0x0f;
}
cursor = calcOffset(0, ROWS-1);
}
void putc(char c, uint8_t attr) {
if (c == '\n') {
uint16_t line = cursor - (cursor % COLS);
setCursorPos(line + COLS);
scroll();
updateCursor();
return;
} else if (c == '\b') {
cursor--;
int mem = VIDMEM + cursor * 2;
*(char*)(mem) = ' ';
*(char*)(mem+1) = attr;
updateCursor();
return;
}
int mem = VIDMEM + cursor * 2;
*(char*)(mem) = c;
*(char*)(mem+1) = attr;
cursor++;
scroll();
updateCursor();
}
void print(char* s, uint8_t attr) {
char c = *s;
while (c != '\0') {
putc(c, attr);
c = *(++s);
}
scroll();
updateCursor();
}
void putcAt(char c, uint8_t attr, uint8_t col, uint8_t row) {
uint16_t offset = calcOffset(col, row);
*(char*)(VIDMEM + offset * 2) = c;
*(char*)(VIDMEM + offset * 2 + 1) = attr;
}
void printAt(char* s, uint8_t attr, uint8_t col, uint8_t row) {
uint16_t offset = calcOffset(col, row);
char c = *s;
while (c != '\0') {
*(char*)(VIDMEM + offset * 2) = c;
*(char*)(VIDMEM + offset * 2 + 1) = attr;
c = *(++s);
offset++;
}
}
void clear(uint8_t attr) {
for (int i = 0; i < CHARS*2; i += 2) {
*(char*)(VIDMEM + i) = ' ';
*(char*)(VIDMEM + i + 1) = attr;
}
cursor = 0;
updateCursor();
}
void enableCursor(uint8_t start, uint8_t end) {
outb(0x3d4, 0x0a); // Sending cursor start
outb(0x3d5, (inb(0x3d5) & 0xc0) | start);
outb(0x3d4, 0x0b); // Sending cursor end
outb(0x3d5, (inb(0x3d5) & 0xe0) | end);
}
void disableCursor() {
outb(0x3d4, 0x0a);
outb(0x3d4, 0x0b);
}
#endif
+8
View File
@@ -0,0 +1,8 @@
#ifndef BOOL_H
#define BOOL_H
#define bool _Bool
#define true 1
#define false 0
#endif
+21
View File
@@ -0,0 +1,21 @@
#ifndef STDINT_H
#define STDINT_H
#define NULL ((void*)0)
// Signed ints
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef signed long long int64_t;
// Unsigned ints
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
// Other
typedef unsigned int size_t;
#endif
+94
View File
@@ -0,0 +1,94 @@
#ifndef STRING_H
#define STRING_H
#include "stdint.h"
// Source: http://www.strudel.org.uk/itoa/
char* itoa(uint32_t val, uint8_t base) {
static char buf[32] = { 0 };
if (base == 0 || base > 16) {
// TODO: Add errors!!
return buf;
}
int i = 30;
for (; val && i; i--, val /= base) {
buf[i] = "0123456789abcdef"[val % base];
}
return &buf[i + 1];
}
uint32_t atoi(const char* str) {
uint32_t res = 0;
// TODO: Add error checking
while (*str >= '0' && *str <= '9') {
res = res * 10 + (*str++ - '0');
}
return res;
}
int isSpace(char c) {
if (c == ' ' || c == '\t' || c == '\n') return 1;
else return 0;
}
// Some implementations taken from https://en.wikibooks.org/wiki/C_Programming/String_manipulation
char* strcpy(char* str1, const char* str2) {
char* dst = str1;
const char* src = str2;
while ((*dst++ = *src++) != '\0');
return str1;
}
char* strcat(char* str1, const char* str2) {
char* s = str1;
while (*s != '\0') { s++; }
strcpy(s, str2);
return str1;
}
char* strchr(const char* str, char c) {
const char* s = str;
while (*s != '\0' && *s != c) { s++; }
return (*s == c) ? (char*)s : NULL;
}
int strcmp(const char* str1, const char* str2) {
while (*str1 != '\0' && *str1 == *str2) {
str1++;
str2++;
}
uint8_t c1 = (*(uint8_t*)str1);
uint8_t c2 = (*(uint8_t*)str2);
return ((c1 < c2) ? -1 : (c1 > c2));
}
uint32_t strlen(const char* str) {
const char* p = str;
while (*++p != '\0');
return (uint32_t)(p - str);
}
// Memory functions
char* memcopy(char* src, char* dst, uint16_t length) {
for (int i = 0; i < length; i++) {
*(dst + i) = *(src + i);
}
return dst;
}
char* memset(char* dst, char value, uint16_t length) {
for (int i = 0; i < length; i++) {
*(dst + i) = value;
}
return dst;
}
#endif
+41
View File
@@ -0,0 +1,41 @@
#ifndef SYSTEM_H
#define SYSTEM_H
#include "stdint.h"
// Port functions
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));
}
// Assembly stuff
void cli() {
asm volatile("cli");
}
void sti() {
asm volatile("sti");
}
void hlt() {
asm volatile("hlt");
}
#endif
+37
View File
@@ -0,0 +1,37 @@
#ifndef TIMER_H
#define TIMER_H
#include "stdint.h"
#include "idt.h"
#include "irq.h"
#include "system.h"
#define INPUT_CLK 1193180
uint32_t timerTicks = 0;
void timerHandler() {
timerTicks++;
}
void setupTimer() {
installIrqHandler(0, timerHandler);
}
// Source: https://en.wikibooks.org/wiki/X86_Assembly/Programmable_Interval_Timer
void timerPhase(uint32_t hz) {
uint16_t div = INPUT_CLK / hz;
outb(0x43, 0x36); // Tell PIT that we're setting channel 0
outb(0x40, div & 0xff); // Low byte
outb(0x40, div >> 8); // High byte
}
void sleep(uint32_t ticks) {
uint32_t eticks = ticks + timerTicks;
while (timerTicks != eticks); // Should avoid overflows unlike '<'
}
#endif