forked from PoliEcho-holding-org/kern
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:
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef BOOL_H
|
||||
#define BOOL_H
|
||||
|
||||
#define bool _Bool
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user