From bca17fe5b99cd7f2b3913027e75e0105b691dbad Mon Sep 17 00:00:00 2001 From: TriMill Date: Fri, 21 Apr 2023 09:39:35 -0400 Subject: [PATCH] keyboard drivers --- Makefile | 6 +- grub.cfg | 2 +- kernel/bootinfo.c | 46 +++++++++ kernel/bootinfo.h | 7 ++ kernel/drivers/keycodes.h | 134 ++++++++++++++++++++++++ kernel/drivers/ps2ctrl.c | 73 +++++++++++++ kernel/drivers/ps2ctrl.h | 13 +++ kernel/drivers/ps2kb.c | 127 +++++++++++++++++++++++ kernel/drivers/ps2kb.h | 11 ++ kernel/drivers/serial.c | 39 +++++++ kernel/drivers/serial.h | 7 ++ kernel/interrupt/idt.asm | 10 +- kernel/interrupt/idt.c | 88 +++++++++------- kernel/interrupt/idt.h | 22 ++-- kernel/interrupt/pic.c | 116 ++++++++++----------- kernel/interrupt/pic.h | 2 +- kernel/main.c | 52 +++++++--- kernel/panic.c | 23 +++++ kernel/panic.h | 6 ++ kernel/start.asm | 59 ++++++----- kernel/term.c | 183 +++++++++++++++++++++++++++++---- kernel/term.h | 7 +- libk/include/stdlib.h | 1 - libk/include/string.h | 3 + libk/include/string_volatile.h | 5 + libk/stdlib.c | 27 ----- libk/string.c | 20 +++- libk/string_volatile.c | 36 +++++++ libk/sys.c | 8 +- linker.ld | 18 ++-- 30 files changed, 931 insertions(+), 220 deletions(-) create mode 100644 kernel/bootinfo.c create mode 100644 kernel/bootinfo.h create mode 100644 kernel/drivers/keycodes.h create mode 100644 kernel/drivers/ps2ctrl.c create mode 100644 kernel/drivers/ps2ctrl.h create mode 100644 kernel/drivers/ps2kb.c create mode 100644 kernel/drivers/ps2kb.h create mode 100644 kernel/drivers/serial.c create mode 100644 kernel/drivers/serial.h create mode 100644 kernel/panic.c create mode 100644 kernel/panic.h create mode 100644 libk/include/string_volatile.h create mode 100644 libk/string_volatile.c diff --git a/Makefile b/Makefile index 1393f90..98f2190 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CC=i386-elf-gcc LD=i386-elf-ld -CFLAGS=-ffreestanding -g -m32 -std=c2x -O2 -Wall -Wextra -pedantic -lgcc -isystem ./libk/include +CFLAGS=-ffreestanding -ggdb -m32 -std=gnu17 -O3 -Wall -Wextra -pedantic -lgcc -isystem ./libk/include C_SOURCE=$(shell find kernel -type f -name "*.c") C_OBJ=$(patsubst %.c,bin/%.o,$(C_SOURCE)) @@ -31,11 +31,11 @@ bin/libk.a: $(LIBK_OBJ) @mkdir -p $(@D) $(AR) rcs bin/libk.a $(LIBK_OBJ) -bin/kernel.bin: bin/libk.a $(A_OBJ) $(C_OBJ) +bin/kernel.bin: bin/libk.a linker.ld $(A_OBJ) $(C_OBJ) @mkdir -p $(@D) $(LD) -nmagic -o bin/kernel.bin -T linker.ld $(A_OBJ) $(C_OBJ) bin/libk.a -bin/os.iso: bin/kernel.bin +bin/os.iso: bin/kernel.bin grub.cfg @mkdir -p $(@D) @mkdir -p bin/iso/boot/grub cp grub.cfg bin/iso/boot/grub diff --git a/grub.cfg b/grub.cfg index 6c9df17..0cb8ace 100644 --- a/grub.cfg +++ b/grub.cfg @@ -1,4 +1,4 @@ -set timeout=0 +set timeout=1 set default=0 menuentry "trios" { diff --git a/kernel/bootinfo.c b/kernel/bootinfo.c new file mode 100644 index 0000000..7b8fb04 --- /dev/null +++ b/kernel/bootinfo.c @@ -0,0 +1,46 @@ +#include +#include +#include + +#include "panic.h" +#include "term.h" +#include "bootinfo.h" + +#define CMDLINE_MAX 128 + +static char boot_cmdline[CMDLINE_MAX]; + +static uint32_t *read_tag(uint32_t *tag) { + uint32_t type = tag[0]; + size_t size = tag[1]; + + switch(type) { + case 0: return NULL; + case 1: { + size_t cmdline_len = size - 2 * sizeof(uint32_t); + if(cmdline_len > CMDLINE_MAX) { + panic("Command line argument length %d exceeds maximum length %d", cmdline_len, CMDLINE_MAX); + } + char* cmdline = (char*)(tag + 2); + memcpy(boot_cmdline, cmdline, cmdline_len); + break; + } + default: break; + } + if(size % 8 != 0) { + size += 8 - (size % 8); + } + return tag + size / sizeof(uint32_t); +} + +void bootinfo_load(void *ptr) { + uint32_t *p = ptr; + p += 2; + while(p != NULL) { + p = read_tag(p); + } +} + +char* bootinfo_get_cmdline(void) { + return boot_cmdline; +} diff --git a/kernel/bootinfo.h b/kernel/bootinfo.h new file mode 100644 index 0000000..b4aa9ad --- /dev/null +++ b/kernel/bootinfo.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +void bootinfo_load(void* ptr); + +char* bootinfo_get_cmdline(void); diff --git a/kernel/drivers/keycodes.h b/kernel/drivers/keycodes.h new file mode 100644 index 0000000..4855007 --- /dev/null +++ b/kernel/drivers/keycodes.h @@ -0,0 +1,134 @@ +#pragma once + +#include + +struct Keycode { + uint8_t key; + uint8_t flags; +}; + +#define KC_FLAG_KEY_DOWN 0x01 +#define KC_FLAG_KEY_UP 0x02 +#define KC_FLAG_ERROR 0x04 + +#define KEY_NONE 0x00 +#define KEY_UNKNOWN 0x01 + +#define KEY_ESCAPE 0x10 +#define KEY_1 0x11 +#define KEY_2 0x12 +#define KEY_3 0x13 +#define KEY_4 0x14 +#define KEY_5 0x15 +#define KEY_6 0x16 +#define KEY_7 0x17 +#define KEY_8 0x18 +#define KEY_9 0x19 +#define KEY_0 0x1A +#define KEY_MINUS 0x1B +#define KEY_EQUAL 0x1C +#define KEY_BACKSPACE 0x1D +#define KEY_L_SHIFT 0x1E +#define KEY_R_SHIFT 0x1F + +#define KEY_TAB 0x20 +#define KEY_Q 0x21 +#define KEY_W 0x22 +#define KEY_E 0x23 +#define KEY_R 0x24 +#define KEY_T 0x25 +#define KEY_Y 0x26 +#define KEY_U 0x27 +#define KEY_I 0x28 +#define KEY_O 0x29 +#define KEY_P 0x2A +#define KEY_L_BRACE 0x2B +#define KEY_R_BRACE 0x2C +#define KEY_BACKSLASH 0x2D +#define KEY_L_CTRL 0x2E +#define KEY_R_CTRL 0x2F + +#define KEY_CAPS_LOCK 0x30 +#define KEY_A 0x31 +#define KEY_S 0x32 +#define KEY_D 0x33 +#define KEY_F 0x34 +#define KEY_G 0x35 +#define KEY_H 0x36 +#define KEY_J 0x37 +#define KEY_K 0x38 +#define KEY_L 0x39 +#define KEY_SEMICOLON 0x3A +#define KEY_QUOTE 0x3B +#define KEY_ENTER 0x3C +#define KEY_MENU 0x3D +#define KEY_L_ALT 0x3E +#define KEY_R_ALT 0x3F + +#define KEY_SPACE 0x40 +#define KEY_Z 0x41 +#define KEY_X 0x42 +#define KEY_C 0x43 +#define KEY_V 0x44 +#define KEY_B 0x45 +#define KEY_N 0x46 +#define KEY_M 0x47 +#define KEY_COMMA 0x48 +#define KEY_PERIOD 0x49 +#define KEY_SLASH 0x4A +#define KEY_BACKTICK 0x4B +#define KEY_NUM_LOCK 0x4C +#define KEY_SCROLL_LOCK 0x4D +#define KEY_L_META 0x4E +#define KEY_R_META 0x4F + +#define KEY_NP_SLASH 0x50 +#define KEY_NP_7 0x51 +#define KEY_NP_8 0x52 +#define KEY_NP_9 0x53 +#define KEY_NP_ASTERISK 0x54 +#define KEY_NP_4 0x55 +#define KEY_NP_5 0x56 +#define KEY_NP_6 0x57 +#define KEY_NP_MINUS 0x58 +#define KEY_NP_1 0x59 +#define KEY_NP_2 0x5A +#define KEY_NP_3 0x5B +#define KEY_NP_PLUS 0x5C +#define KEY_NP_0 0x5D +#define KEY_NP_PERIOD 0x5E +#define KEY_NP_ENTER 0x5F + +#define KEY_PRINT_SCREEN 0x60 +#define KEY_PAUSE 0x61 +#define KEY_INSERT 0x62 +#define KEY_HOME 0x63 +#define KEY_PAGE_UP 0x64 +#define KEY_DELETE 0x65 +#define KEY_END 0x66 +#define KEY_PAGE_DOWN 0x67 +#define KEY_UP 0x68 +#define KEY_DOWN 0x69 +#define KEY_LEFT 0x6A +#define KEY_RIGHT 0x6B +// #define _ 0x6C +// #define _ 0x6D +// #define _ 0x6E +// #define _ 0x6F + +#define KEY_F1 0x70 +#define KEY_F2 0x71 +#define KEY_F3 0x72 +#define KEY_F4 0x73 +#define KEY_F5 0x74 +#define KEY_F6 0x75 +#define KEY_F7 0x76 +#define KEY_F8 0x77 +#define KEY_F9 0x78 +#define KEY_F10 0x79 +#define KEY_F11 0x7A +#define KEY_F12 0x7B +// #define _ 0x7C +// #define _ 0x7D +// #define _ 0x7E +// #define _ 0x7F diff --git a/kernel/drivers/ps2ctrl.c b/kernel/drivers/ps2ctrl.c new file mode 100644 index 0000000..97705d6 --- /dev/null +++ b/kernel/drivers/ps2ctrl.c @@ -0,0 +1,73 @@ +#include +#include +#include "ps2ctrl.h" +#include "../panic.h" +#include "../interrupt/pic.h" + +#define STATUS_OUT_BUF ((uint8_t)0x01) +#define STATUS_IN_BUF ((uint8_t)0x02) + +#define CONFIG_INT_0 ((uint8_t)0x01) +#define CONFIG_INT_1 ((uint8_t)0x02) +#define CONFIG_SYS ((uint8_t)0x04) +#define CONFIG_CLOCK_0 ((uint8_t)0x10) +#define CONFIG_CLOCK_1 ((uint8_t)0x20) +#define CONFIG_TRANS ((uint8_t)0x40) + +uint8_t ps2ctrl_in_status(void) { + return inb(0x64); +} + +uint8_t ps2ctrl_in(void) { + while((ps2ctrl_in_status() & STATUS_OUT_BUF) == 0) { + io_wait(); + } + return inb(0x60); +} + +void ps2ctrl_out_cmd(uint8_t cmd) { + while((ps2ctrl_in_status() & STATUS_IN_BUF) != 0) { + io_wait(); + } + outb(0x64, cmd); +} + +void ps2ctrl_out_data(uint8_t data) { + while((ps2ctrl_in_status() & STATUS_IN_BUF) != 0) { + io_wait(); + } + outb(0x60, data); +} + +static bool is_init = false; + +void ps2ctrl_init(void) { + is_init = false; + pic_mask(1); + // clear buffer + inb(0x60); + + // self-test + ps2ctrl_out_cmd(0xAA); + uint8_t response = ps2ctrl_in(); + if(response != 0x55) { + panic("PS/2 controller failed to initialize"); + } + + // set config + ps2ctrl_out_cmd(0x20); + uint8_t config = ps2ctrl_in(); + config = (config | CONFIG_INT_0) & ~CONFIG_TRANS & ~CONFIG_INT_1; + ps2ctrl_out_cmd(0x60); + ps2ctrl_out_data(config); + + // enable port 0 + ps2ctrl_out_cmd(0xAE); + + pic_unmask(1); + is_init = true; +} + +bool ps2ctrl_is_init(void) { + return is_init; +} diff --git a/kernel/drivers/ps2ctrl.h b/kernel/drivers/ps2ctrl.h new file mode 100644 index 0000000..35b19e6 --- /dev/null +++ b/kernel/drivers/ps2ctrl.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +uint8_t ps2ctrl_in(void); +uint8_t ps2ctrl_in_status(void); +void ps2ctrl_out_cmd(uint8_t cmd); +void ps2ctrl_out_data(uint8_t data); + +void ps2ctrl_init(void); + +bool ps2ctrl_is_init(void); diff --git a/kernel/drivers/ps2kb.c b/kernel/drivers/ps2kb.c new file mode 100644 index 0000000..475f33b --- /dev/null +++ b/kernel/drivers/ps2kb.c @@ -0,0 +1,127 @@ +#include +#include +#include +#include "../term.h" +#include "../panic.h" +#include "../interrupt/pic.h" +#include +#include + +#include "ps2ctrl.h" +#include "ps2kb.h" +#include "keycodes.h" + +#define BUFFER_LEN 16 + +#define KEYCODE_ARRAY_LEN 0x84 + +static uint8_t scancodes[] = { +// 00/08 01/09 02/0A 03/0B 04/0C 05/0D 06/0E 07/0F +/*00*/ KEY_NONE, KEY_F9, KEY_NONE, KEY_F5, KEY_F3, KEY_F1, KEY_F2, KEY_F12, +/*08*/ KEY_NONE, KEY_F10, KEY_F8, KEY_F6, KEY_F4, KEY_TAB, KEY_BACKTICK, KEY_NONE, +/*10*/ KEY_NONE, KEY_L_ALT, KEY_L_SHIFT, KEY_NONE, KEY_L_CTRL, KEY_Q, KEY_1, KEY_NONE, +/*18*/ KEY_NONE, KEY_NONE, KEY_Z, KEY_S, KEY_A, KEY_W, KEY_2, KEY_NONE, +/*20*/ KEY_NONE, KEY_C, KEY_X, KEY_D, KEY_E, KEY_4, KEY_3, KEY_NONE, +/*28*/ KEY_NONE, KEY_SPACE, KEY_V, KEY_F, KEY_T, KEY_R, KEY_5, KEY_NONE, +/*30*/ KEY_NONE, KEY_N, KEY_B, KEY_H, KEY_G, KEY_Y, KEY_6, KEY_NONE, +/*38*/ KEY_NONE, KEY_NONE, KEY_M, KEY_J, KEY_U, KEY_7, KEY_8, KEY_NONE, +/*40*/ KEY_NONE, KEY_COMMA, KEY_K, KEY_I, KEY_O, KEY_0, KEY_9, KEY_NONE, +/*48*/ KEY_NONE, KEY_PERIOD, KEY_SLASH, KEY_L, KEY_SEMICOLON, KEY_P, KEY_MINUS, KEY_NONE, +/*50*/ KEY_NONE, KEY_NONE, KEY_QUOTE, KEY_NONE, KEY_L_BRACE, KEY_EQUAL, KEY_NONE, KEY_NONE, +/*58*/ KEY_CAPS_LOCK, KEY_R_SHIFT, KEY_ENTER, KEY_R_BRACE, KEY_NONE, KEY_BACKSLASH, KEY_NONE, KEY_NONE, +/*60*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_BACKSPACE, KEY_NONE, +/*68*/ KEY_NONE, KEY_NP_1, KEY_NONE, KEY_NP_4, KEY_NP_7, KEY_NONE, KEY_NONE, KEY_NONE, +/*70*/ KEY_NP_0, KEY_NP_PERIOD, KEY_NP_2, KEY_NP_5, KEY_NP_6, KEY_NP_8, KEY_ESCAPE, KEY_NUM_LOCK, +/*78*/ KEY_F11, KEY_NP_PLUS, KEY_NP_3, KEY_NP_MINUS, KEY_NP_ASTERISK, KEY_NP_9, KEY_SCROLL_LOCK, KEY_NONE, +/*80*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_F7, +}; +static uint8_t scancodes_ext[] = { +// 00/08 01/09 02/0A 03/0B 04/0C 05/0D 06/0E 07/0F +/*00*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, +/*08*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, +/*10*/ KEY_UNKNOWN, KEY_R_ALT, KEY_PRINT_SCREEN, KEY_NONE, KEY_R_CTRL, KEY_UNKNOWN, KEY_NONE, KEY_NONE, +/*18*/ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_L_META, +/*20*/ KEY_UNKNOWN, KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_R_META, +/*28*/ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_MENU, +/*30*/ KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_UNKNOWN, +/*38*/ KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_UNKNOWN, +/*40*/ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, +/*48*/ KEY_UNKNOWN, KEY_NONE, KEY_NP_SLASH, KEY_NONE, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE, +/*50*/ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, +/*58*/ KEY_NONE, KEY_NONE, KEY_NP_ENTER, KEY_NONE, KEY_NONE, KEY_NONE, KEY_UNKNOWN, KEY_NONE, +/*60*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, +/*68*/ KEY_NONE, KEY_END, KEY_NONE, KEY_LEFT, KEY_HOME, KEY_NONE, KEY_NONE, KEY_NONE, +/*70*/ KEY_INSERT, KEY_DELETE, KEY_DOWN, KEY_NONE, KEY_RIGHT, KEY_UP, KEY_NONE, KEY_NONE, +/*78*/ KEY_NONE, KEY_NONE, KEY_PAGE_DOWN, KEY_NONE, KEY_NONE, KEY_PAGE_UP, KEY_NONE, KEY_NONE, +/*80*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, +}; + +static struct Keycode last_keycode; + +static bool is_init = false; +static bool state_keyup = false; +static bool state_ext = false; + +void ps2kb_init(void) { + is_init = false; + pic_mask(1); + + uint8_t result; + + ps2ctrl_out_data(0xFF); + result = ps2ctrl_in(); + if(result != 0xFA) { + panic("Failed to reset PS/2 keyboard: expected 0xFA, got 0x%X\n", result); + } + result = ps2ctrl_in(); + if(result != 0xAA) { + panic("Failed to reset PS/2 keyboard: expected 0xAA, got 0x%X\n", result); + } + + ps2ctrl_out_data(0xF4); + result = ps2ctrl_in(); + if(result != 0xFA) { + panic("Failed to enable PS/2 keyboard: expected 0xFA, got 0x%X\n", result); + } + + pic_unmask(1); + is_init = true; +} + +void ps2kb_recv(void) { + if(!ps2ctrl_is_init() || !is_init) { + inb(0x60); + return; + } + uint8_t code = ps2ctrl_in(); + if (code == 0x00 || code == 0x0F) { + last_keycode.key = KEY_NONE; + last_keycode.flags = KC_FLAG_ERROR; + } else if(code == 0xF0) { + state_keyup = true; + } else if(code == 0xE0) { + state_ext = true; + } else if(code <= KEYCODE_ARRAY_LEN) { + uint8_t *scancode_table = state_ext ? scancodes_ext : scancodes; + uint8_t keycode = scancode_table[code]; + if(keycode != KEY_NONE) { + last_keycode.key = keycode; + last_keycode.flags = state_keyup ? KC_FLAG_KEY_UP : KC_FLAG_KEY_DOWN; + } + state_keyup = false; + state_ext = false; + } +} + +struct Keycode ps2kb_get(void) { + struct Keycode code; + if(is_init) { + code = last_keycode; + } else { + code.key = KEY_NONE; + code.flags = KC_FLAG_ERROR; + } + last_keycode.key = KEY_NONE; + last_keycode.flags = 0; + return code; +} diff --git a/kernel/drivers/ps2kb.h b/kernel/drivers/ps2kb.h new file mode 100644 index 0000000..e1a36c3 --- /dev/null +++ b/kernel/drivers/ps2kb.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include + +#include "keycodes.h" + +void ps2kb_init(void); + +void ps2kb_recv(void); +struct Keycode ps2kb_get(void); diff --git a/kernel/drivers/serial.c b/kernel/drivers/serial.c new file mode 100644 index 0000000..fbaa49e --- /dev/null +++ b/kernel/drivers/serial.c @@ -0,0 +1,39 @@ +#include +#include +#include "serial.h" +#include "../panic.h" + +#define PORT 0x3f8 // COM1 + +void serial_init(void) { + outb(PORT + 1, 0x00); // Disable all interrupts + outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) + outb(PORT + 0, 0x01); // Set divisor to 1 (lo byte) 38400 baud + outb(PORT + 1, 0x00); // (hi 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 serial returns same byte) + + // Check if serial is faulty (i.e: not same byte as sent) + uint8_t response = inb(PORT + 0); + if(response != 0xAE) { + panic("Serial is faulty: %X\n", response); + } + + // If serial is not faulty set it in normal operation mode + // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) + outb(PORT + 4, 0x0F); +} + +void serial_write(uint8_t a) { + while((inb(PORT + 5) & 0x20) != 0); + outb(PORT, a); +} + +void serial_write_s(const char* str) { + while(*str != '\0') { + serial_write(*str++); + } +} diff --git a/kernel/drivers/serial.h b/kernel/drivers/serial.h new file mode 100644 index 0000000..7bc1d77 --- /dev/null +++ b/kernel/drivers/serial.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +void serial_init(void); +void serial_write(uint8_t a); +void serial_write_s(const char* str); diff --git a/kernel/interrupt/idt.asm b/kernel/interrupt/idt.asm index 40d4521..b56c3f8 100644 --- a/kernel/interrupt/idt.asm +++ b/kernel/interrupt/idt.asm @@ -1,7 +1,7 @@ extern idt_exception_handler extern idt_pic_timer extern idt_pic_keyboard -extern idt_pic_handler +extern idt_pic_generic global isr_stub_table %macro ISRErrorStub 1 @@ -15,7 +15,7 @@ isr_stub_%+%1: %macro PICGeneric 1 isr_stub_%+%1: push dword %1 - call idt_pic_handler + call idt_pic_generic pop eax iret %endmacro @@ -23,7 +23,7 @@ isr_stub_%+%1: %macro PICTimer 1 isr_stub_%+%1: push dword %1 - call idt_pic_handler + call idt_pic_generic call idt_pic_timer pop eax iret @@ -32,7 +32,7 @@ isr_stub_%+%1: %macro PICKeyboard 1 isr_stub_%+%1: push dword %1 - call idt_pic_handler + call idt_pic_generic call idt_pic_keyboard pop eax iret @@ -51,6 +51,7 @@ isr_stub_%+%1: %endmacro section .text +align 8 %assign i 0 %rep 32 ISRErrorStub i @@ -79,6 +80,7 @@ PICGeneric 47 %endrep section .rodata +align 8 isr_stub_table: %assign i 0x00 %rep 256 diff --git a/kernel/interrupt/idt.c b/kernel/interrupt/idt.c index 92b9cae..01e0069 100644 --- a/kernel/interrupt/idt.c +++ b/kernel/interrupt/idt.c @@ -3,55 +3,71 @@ #include #include #include + #include "idt.h" -#include "../term.h" #include "pic.h" +#include "../term.h" +#include "../panic.h" +#include "../drivers/ps2kb.h" +#include "../drivers/ps2ctrl.h" static int timer = 0; -void idt_pic_handler(uint8_t exception) { - pic_eoi(exception - PIC_REMAP_OFFSET); +void idt_pic_generic(uint8_t exception) { + pic_eoi(exception - PIC_REMAP_OFFSET); } void idt_pic_timer(void) { - uint32_t state = term_save(); - term_setcol(0x0a); - char buf[20]; - itoa(timer, buf); - term_setpos(0, 20); - puts(" "); - term_setpos(0, 20); - puts(buf); - timer += 1; - term_load(state); + uint32_t state = term_save(); + term_setcol(0x0a); + term_setpos(60, 0); + puts(" "); + term_setpos(60, 0); + printf("%d", timer); + term_flush(); + timer += 1; + term_load(state); } void idt_pic_keyboard(void) { - uint8_t c = inb(0x60); - uint32_t state = term_save(); - term_setcol(0x0c); - term_setpos(0, 21); - puts(" "); - term_setpos(0, 21); - char buf[20]; - itoa(c, buf); - puts(buf); - term_load(state); + ps2kb_recv(); } void idt_exception_handler(uint8_t exception) { - switch(exception) { - case 0x00: - puts("Div by zero"); - break; - case 0x08: - puts("Double fault"); - break; - default: - puts("Error"); - break; - } - halt(); + char* msg; + switch(exception) { + case 0x00: + msg = "Division by zero"; + break; + case 0x02: + msg = "NMI"; + break; + case 0x04: + msg = "Overflow"; + break; + case 0x06: + msg = "invalid opcode"; + break; + case 0x08: + msg = "double fault"; + break; + case 0x0A: + msg = "invalid task state segment"; + break; + case 0x0C: + msg = "stack segment fault"; + break; + case 0x0D: + msg = "general protection fault"; + break; + case 0x0E: + msg = "page fault"; + break; + default: + msg = "unknown exception"; + break; + } + panic("E%u: %s", exception, msg); } __attribute__((aligned(0x10))) @@ -72,7 +88,7 @@ void idt_init(void) { idtr.base = (uintptr_t)&idt[0]; idtr.limit = (uint16_t)sizeof(struct IdtEntry) * IDT_SIZE - 1; - for(uint8_t i = 0; i < IDT_INTERRUPTS; i++) { + for(int i = 0; i < IDT_INTERRUPTS; i++) { set_descriptor(i, isr_stub_table[i], 0x8e); } diff --git a/kernel/interrupt/idt.h b/kernel/interrupt/idt.h index f0509a7..8c2f025 100644 --- a/kernel/interrupt/idt.h +++ b/kernel/interrupt/idt.h @@ -2,7 +2,7 @@ #include #define IDT_SIZE 256 -#define IDT_INTERRUPTS 48 +#define IDT_INTERRUPTS 256 struct IdtEntry { uint16_t isr_low; @@ -18,18 +18,18 @@ struct Idtr { } __attribute__((packed)); typedef enum { - IDT_FLAG_GATE_TASK = 0x5, - IDT_FLAG_GATE_16BIT_INT = 0x6, - IDT_FLAG_GATE_16BIT_TRAP = 0x7, - IDT_FLAG_GATE_32BIT_INT = 0xE, - IDT_FLAG_GATE_32BIT_TRAP = 0xF, + IDT_FLAG_GATE_TASK = 0x5, + IDT_FLAG_GATE_16BIT_INT = 0x6, + IDT_FLAG_GATE_16BIT_TRAP = 0x7, + IDT_FLAG_GATE_32BIT_INT = 0xE, + IDT_FLAG_GATE_32BIT_TRAP = 0xF, - IDT_FLAG_RING0 = (0 << 5), - IDT_FLAG_RING1 = (1 << 5), - IDT_FLAG_RING2 = (2 << 5), - IDT_FLAG_RING3 = (3 << 5), + IDT_FLAG_RING0 = (0 << 5), + IDT_FLAG_RING1 = (1 << 5), + IDT_FLAG_RING2 = (2 << 5), + IDT_FLAG_RING3 = (3 << 5), - IDT_FLAG_PRESENT = 0x80, + IDT_FLAG_PRESENT = 0x80, } IDTFlags; diff --git a/kernel/interrupt/pic.c b/kernel/interrupt/pic.c index 093b26b..dd5e2f6 100644 --- a/kernel/interrupt/pic.c +++ b/kernel/interrupt/pic.c @@ -9,74 +9,72 @@ void pic_remap(uint8_t offset) { - char a1 = inb(PIC1_DATA_PORT); - char a2 = inb(PIC2_DATA_PORT); - // control word 1 - // 0x11: initialize, enable ICW4 - outb(PIC1_COMMAND_PORT, 0x11); - io_wait(); - outb(PIC2_COMMAND_PORT, 0x11); - io_wait(); - // control word 2 - // interrupt offset - outb(PIC1_DATA_PORT, offset); - io_wait(); - outb(PIC2_DATA_PORT, offset + 8); - io_wait(); - // control word 3 - // primary pic: set which pin secondary is connected to - // (pin 2) - outb(PIC1_DATA_PORT, 0b00000100); - io_wait(); - outb(PIC2_DATA_PORT, 2); - io_wait(); - // control word 3 - // 0x01: enable 8086 mode - outb(PIC1_DATA_PORT, 0x01); - io_wait(); - outb(PIC2_DATA_PORT, 0x01); - io_wait(); - // clear data registers - outb(PIC1_DATA_PORT, a1); - outb(PIC2_DATA_PORT, a2); + char a1 = inb(PIC1_DATA_PORT); + char a2 = inb(PIC2_DATA_PORT); + // control word 1 + // 0x11: initialize, enable ICW4 + outb(PIC1_COMMAND_PORT, 0x11); + io_wait(); + outb(PIC2_COMMAND_PORT, 0x11); + io_wait(); + // control word 2 + // interrupt offset + outb(PIC1_DATA_PORT, offset); + io_wait(); + outb(PIC2_DATA_PORT, offset + 8); + io_wait(); + // control word 3 + // primary pic: set which pin secondary is connected to + // (pin 2) + outb(PIC1_DATA_PORT, 0b00000100); + io_wait(); + outb(PIC2_DATA_PORT, 2); + io_wait(); + // control word 3 + // 0x01: enable 8086 mode + outb(PIC1_DATA_PORT, 0x01); + io_wait(); + outb(PIC2_DATA_PORT, 0x01); + io_wait(); + // clear data registers + outb(PIC1_DATA_PORT, a1); + outb(PIC2_DATA_PORT, a2); } void pic_mask(int irq) { - uint8_t port; - if(irq < 8) { - port = PIC1_DATA_PORT; - } else { - irq -= 8; - port = PIC2_DATA_PORT; - } - uint8_t mask = inb(port); - outb(port, mask | (1 << irq)); + uint8_t port; + if(irq < 8) { + port = PIC1_DATA_PORT; + } else { + irq -= 8; + port = PIC2_DATA_PORT; + } + uint8_t mask = inb(port); + outb(port, mask | (1 << irq)); } void pic_unmask(int irq) { - uint8_t port; - if(irq < 8) { - port = PIC1_DATA_PORT; - } else { - irq -= 8; - port = PIC2_DATA_PORT; - } - uint8_t mask = inb(port); - outb(port, mask & ~(1 << irq)); + uint8_t port; + if(irq < 8) { + port = PIC1_DATA_PORT; + } else { + irq -= 8; + port = PIC2_DATA_PORT; + } + uint8_t mask = inb(port); + outb(port, mask & ~(1 << irq)); } -// completely disable the PIC -void pic_disable() { - outb(PIC1_DATA_PORT, 0xff); - io_wait(); - outb(PIC2_DATA_PORT, 0xff); - io_wait(); +void pic_disable(void) { + outb(PIC1_DATA_PORT, 0xff); + io_wait(); + outb(PIC2_DATA_PORT, 0xff); + io_wait(); } -// end of interrupt void pic_eoi(int irq) { - if(irq >= 8) { - outb(PIC2_COMMAND_PORT, 0x20); - } - outb(PIC1_COMMAND_PORT, 0x20); + if(irq >= 8) { + outb(PIC2_COMMAND_PORT, 0x20); + } + outb(PIC1_COMMAND_PORT, 0x20); } diff --git a/kernel/interrupt/pic.h b/kernel/interrupt/pic.h index cd2fae2..674c339 100644 --- a/kernel/interrupt/pic.h +++ b/kernel/interrupt/pic.h @@ -6,5 +6,5 @@ void pic_remap(uint8_t offset); void pic_mask(int irq); void pic_unmask(int irq); -void pic_disable(); +void pic_disable(void); void pic_eoi(int irq); diff --git a/kernel/main.c b/kernel/main.c index 08638d3..0f3fbca 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -1,22 +1,44 @@ #include +#include +#include "bootinfo.h" +#include "drivers/keycodes.h" +#include "drivers/ps2ctrl.h" +#include "drivers/ps2kb.h" +#include "drivers/serial.h" +#include "panic.h" #include "term.h" #include "interrupt/pic.h" #include "interrupt/idt.h" -extern void kmain(void) { - term_clear(); - term_setcol(0x0f); - puts("loading kernel\n"); - idt_init(); - puts("initialized idt\n"); - pic_remap(PIC_REMAP_OFFSET); - puts("remapped pic\n"); - int_enable(); - puts("enabled interrupts\n"); - outb(0x60, 0xF4); - puts("enabled keyboard\n"); +extern void kmain(void* boot_info) { + term_clear(); + term_setcol(0x0f); + puts("loading kernel\n"); + bootinfo_load(boot_info); + puts("loaded boot info\n"); + printf("cmdline: %s\n", bootinfo_get_cmdline()); + idt_init(); + puts("initialized idt\n"); + pic_remap(PIC_REMAP_OFFSET); + puts("remapped pic\n"); + serial_init(); + puts("initialized serial\n"); + ps2ctrl_init(); + puts("enabled ps/2 controller\n"); + ps2kb_init(); + puts("enabled keyboard\n"); - while(1) { - int_wait(); - } + while(1) { + int_wait(); + struct Keycode code = ps2kb_get(); + if(code.key != KEY_NONE) { + if(code.flags & KC_FLAG_ERROR) { + printf("error: %X\n", code.key); + } else if(code.flags & KC_FLAG_KEY_DOWN) { + printf("pressed: %X\n", code.key); + } else { + printf("released: %X\n", code.key); + } + } + } } diff --git a/kernel/panic.c b/kernel/panic.c new file mode 100644 index 0000000..9750fea --- /dev/null +++ b/kernel/panic.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include "term.h" +#include "panic.h" + +__attribute__((noreturn)) +void _panic_impl(char* msg, int line, char* file, ...) { + int_disable(); + printf("BBBBBBBB\n"); + va_list args; + va_start(args, file); + term_clear(); + term_setpos(0, 0); + term_setcol(0x0c); + puts("!!!PANIC!!!\n"); + term_setcol(0x0f); + vprintf(msg, args); + printf("\nin %s at line %d\n", file, line); + while(1) { + halt(); + } +} diff --git a/kernel/panic.h b/kernel/panic.h new file mode 100644 index 0000000..1fe29a4 --- /dev/null +++ b/kernel/panic.h @@ -0,0 +1,6 @@ +#pragma once + +#define panic(msg, ...) _panic_impl(msg, __LINE__, __FILE__ __VA_OPT__(,) __VA_ARGS__) + +__attribute__((noreturn)) +void _panic_impl(char* msg, int line, char* file, ...); diff --git a/kernel/start.asm b/kernel/start.asm index f37c503..65fb14b 100644 --- a/kernel/start.asm +++ b/kernel/start.asm @@ -4,32 +4,35 @@ bits 32 ; base, limit, access, flags %macro gdt_entry 4 - db %2 & 0xff - db (%2 >> 8) & 0xff - db %1 & 0xff - db (%1 >> 8) & 0xff - db (%1 >> 16) & 0xff - db %3 - db ((%2 >> 16) & 0x0f) | (%4 << 4) - db (%1 >> 24) & 0xff + db %2 & 0xff + db (%2 >> 8) & 0xff + db %1 & 0xff + db (%1 >> 8) & 0xff + db (%1 >> 16) & 0xff + db %3 + db ((%2 >> 16) & 0x0f) | (%4 << 4) + db (%1 >> 24) & 0xff %endmacro -section .multiboot_header +section .multiboot align 8 mb_start: +; header dd 0xe85250d6 dd 0 dd mb_end - mb_start dd 0x100000000 - (0xe85250d6 + (mb_end - mb_start)) +; null tag dw 0 dw 0 dd 8 +; mb_end: section .bss align 16 stack_start: - resb 16384 + resb 16384 stack_end: section .rodata @@ -40,27 +43,29 @@ gdt_entry 0, 0xFFFFF, 0x9A, 0xC gdt_entry 0, 0xFFFFF, 0x92, 0xC gdt_end: gdt_descriptor: - dw gdt_end - gdt_start - 1 - dd gdt_start + dw gdt_end - gdt_start - 1 + dd gdt_start section .text align 8 start: - cli - lgdt [gdt_descriptor] - jmp 0x08:after_lgdt + cli + lgdt [gdt_descriptor] + jmp 0x08:after_lgdt after_lgdt: - mov ax, 0x10 - mov ds, ax - mov ss, ax - mov es, ax - mov fs, ax - mov gs, ax - mov esp, stack_end - mov ebp, stack_end - call kmain - cli + mov ax, 0x10 + mov ds, ax + mov ss, ax + mov es, ax + mov fs, ax + mov gs, ax + mov esp, stack_end + mov ebp, stack_end + sti + push ebx + call kmain + cli halt: - hlt - jmp halt + hlt + jmp halt diff --git a/kernel/term.c b/kernel/term.c index 324565b..0dc65a4 100644 --- a/kernel/term.c +++ b/kernel/term.c @@ -1,12 +1,18 @@ +#include #include #include #include +#include +#include +#include + #include "term.h" -static uint16_t* screen = (uint16_t*)0xb8000; -static size_t x = 0; -static size_t y = 0; +static volatile uint16_t *screen = (uint16_t*)0xb8000; +static size_t term_x = 0; +static size_t term_y = 0; static uint8_t color = 0x0f; +static uint16_t screen_buf[TERM_W * TERM_H * 2]; static inline uint16_t screen_entry(char c, uint8_t col) { return (uint16_t)c | ((uint16_t)col << 8); @@ -15,49 +21,186 @@ static inline uint16_t screen_entry(char c, uint8_t col) { void putc(char c) { switch(c) { case '\n': - x = TERM_W; + term_x = TERM_W; break; case '\t': - if(x % 8 == 0) x += 8; - x += 7 - (x % 8); + if(term_x % 8 == 0) term_x += 8; + term_x += 7 - (term_x % 8); break; default: - screen[x + y * TERM_W] = screen_entry(c, color); - x += 1; + screen_buf[term_x + term_y * TERM_W] = screen_entry(c, color); + term_x += 1; break; } - if(x >= TERM_W) { - x = 0; - y += 1; + if(term_x >= TERM_W) { + term_x = 0; + term_y += 1; + } + if(term_y >= TERM_H) { + term_scroll(1); + } + if(c == '\n') { + term_flush(); } } -void puts(char* s) { - for(char* c = s; *c != '\0'; c++) { - putc(*c); +void puts(const char *s) { + for(; *s != '\0'; s++) { + putc(*s); } } +static uint8_t hex2i(char hex) { + if(hex < 'A') { + return hex - '0'; + } else if(hex < 'a') { + return hex - 'A' + 10; + } else { + return hex - 'a' + 10; + } +} + +static char i2d(int i, bool upper) { + if(i < 10) { + return '0' + i; + } else { + return 'a' + (i - 10) + (upper ? 'A' - 'a' : 0); + } +} + +static void itoa(int n, char *buf, int base, bool upper) { + if(n == 0) { + buf[0] = '0'; + buf[1] = '\0'; + return; + } + if(n < 0) { + n = -n; + buf[0] = '-'; + buf++; + } + char *start = buf; + while(n != 0) { + *buf++ = i2d(n % base, upper); + n /= base; + } + *buf-- = '\0'; + while(buf > start) { + char tmp = *start; + *start++ = *buf; + *buf-- = tmp; + } +} + +static void utoa(unsigned int n, char *buf, int base, bool upper) { + if(n == 0) { + buf[0] = '0'; + buf[1] = '\0'; + return; + } + char *start = buf; + while(n != 0) { + *buf++ = i2d(n % base, upper); + n /= base; + } + *buf-- = '\0'; + while(buf > start) { + char tmp = *start; + *start++ = *buf; + *buf-- = tmp; + } +} + +void vprintf(const char *fstr, va_list args) { + char buf[80]; + for(; *fstr != '\0'; fstr++) { + if(*fstr == '%') { + fstr++; + switch(*fstr) { + case '%': + putc('%'); + break; + case 's': + puts(va_arg(args, char*)); + break; + case 'd': + itoa(va_arg(args, int), buf, 10, false); + puts(buf); + break; + case 'u': + utoa(va_arg(args, unsigned int), buf, 10, false); + puts(buf); + break; + case 'x': + utoa(va_arg(args, unsigned int), buf, 16, false); + puts(buf); + break; + case 'X': + utoa(va_arg(args, unsigned int), buf, 16, true); + puts(buf); + break; + case '@': { + uint8_t hi = hex2i(*++fstr); + uint8_t lo = hex2i(*++fstr); + term_setcol((hi << 4) | lo); + break; + } + default: + break; + } + } else { + putc(*fstr); + } + } +} + +void printf(const char *fstr, ...) { + va_list args; + va_start(args, fstr); + vprintf(fstr, args); + va_end(args); +} + + void term_clear(void) { - memset(screen, 0, TERM_W * TERM_H * 2); + memset(screen_buf, 0, TERM_W * TERM_H * 2); } void term_setpos(size_t new_x, size_t new_y) { - x = new_x; - y = new_y; + term_x = new_x; + term_y = new_y; } void term_setcol(uint8_t new_col) { color = new_col; } +void term_scroll(ptrdiff_t lines) { + term_y -= lines; + if(lines == 0) return; + if(lines >= TERM_H || lines <= -TERM_H) { + term_clear(); + } else if(lines > 0) { + memmove(screen_buf, screen_buf + lines * TERM_W, 2 * (TERM_H - lines) * TERM_W); + memset(screen_buf + (TERM_H - lines) * TERM_W, 0, 2 * lines * TERM_W); + } else { + memmove(screen_buf + lines * TERM_W, screen_buf + lines, (TERM_H + lines) * TERM_W); + } +} + +void term_flush(void) { + int_disable(); + memcpy_volatile(screen, screen_buf, TERM_W * TERM_H * 2); + int_enable(); +} + uint32_t term_save(void) { - return color | ((x + y * TERM_W) << 8); + return color | ((term_x + term_y * TERM_W) << 8); } void term_load(uint32_t state) { color = state & 0xff; state >>= 8; - x = state % TERM_W; - y = state / TERM_W; + term_x = state % TERM_W; + term_y = state / TERM_W; } diff --git a/kernel/term.h b/kernel/term.h index 978051e..aeabe54 100644 --- a/kernel/term.h +++ b/kernel/term.h @@ -1,15 +1,20 @@ #pragma once #include +#include #include #define TERM_W 80 #define TERM_H 25 void putc(char c); -void puts(char* s); +void puts(const char* s); +void printf(const char* s, ...); +void vprintf(const char* s, va_list args); void term_clear(void); void term_setcol(uint8_t new_col); void term_setpos(size_t new_x, size_t new_y); uint32_t term_save(void); void term_load(uint32_t pos); +void term_scroll(ptrdiff_t lines); +void term_flush(void); diff --git a/libk/include/stdlib.h b/libk/include/stdlib.h index ec130e1..759d7a1 100644 --- a/libk/include/stdlib.h +++ b/libk/include/stdlib.h @@ -1,4 +1,3 @@ #pragma once int atoi(const char* s); -void itoa(int n, char* buf); diff --git a/libk/include/string.h b/libk/include/string.h index cc3f1d5..23c1fc5 100644 --- a/libk/include/string.h +++ b/libk/include/string.h @@ -6,3 +6,6 @@ int memcmp(const void *lhs, const void *rhs, size_t n); void *memcpy(void *restrict dst, const void *restrict src, size_t n); void *memmove(void *dst, const void *src, size_t n); void *memset(void *dest, int c, size_t n); + +char *strcpy(char *restrict dst, const char *restrict src); +char *strncpy(char *restrict dst, const char *restrict src, size_t n); diff --git a/libk/include/string_volatile.h b/libk/include/string_volatile.h new file mode 100644 index 0000000..4ffda00 --- /dev/null +++ b/libk/include/string_volatile.h @@ -0,0 +1,5 @@ +#include + +volatile void *memmove_volatile(volatile void *dst, const volatile void *src, size_t n); +volatile void *memset_volatile(volatile void *dest, int c, size_t n); +volatile void *memcpy_volatile(volatile void *restrict dst, const volatile void *restrict src, volatile size_t n); diff --git a/libk/stdlib.c b/libk/stdlib.c index d0a9bbb..43ed1a2 100644 --- a/libk/stdlib.c +++ b/libk/stdlib.c @@ -17,30 +17,3 @@ int atoi(const char* s) { } return neg ? -n : n; } - -void itoa(int n, char* buf) { - if(n < 0) { - n = -n; - *buf = '-'; - buf++; - } else if(n == 0) { - buf[0] = '0'; - buf[1] = '\0'; - return; - } - char* start = buf; - while(n > 0) { - *buf= n % 10 + '0'; - n /= 10; - buf++; - } - *buf = '\0'; - buf--; - while(start < buf) { - char tmp = *start; - *start = *buf; - *buf = tmp; - start++; - buf--; - } -} diff --git a/libk/string.c b/libk/string.c index 85dcdb2..d06722e 100644 --- a/libk/string.c +++ b/libk/string.c @@ -41,7 +41,25 @@ void *memmove(void *dst, const void *src, size_t n) { void *memset(void *dest, int c, size_t n) { unsigned char *d = dest; while(n--) { - *d = c; + *d++ = c; } return dest; } + +char *strcpy(char *restrict dst, const char *restrict src) { + while((*dst = *src) != '\0') { + dst++; + src++; + } + return dst; +} + +char *strncpy(char *restrict dst, const char *restrict src, size_t n) { + while((*dst = *src) != '\0' && n != 0) { + dst++; + src++; + n--; + } + memset(dst, 0, n); + return dst; +} diff --git a/libk/string_volatile.c b/libk/string_volatile.c new file mode 100644 index 0000000..bfd8c88 --- /dev/null +++ b/libk/string_volatile.c @@ -0,0 +1,36 @@ +#include +#include "include/string_volatile.h" + +volatile void *memmove_volatile(volatile void *dst, const volatile void *src, volatile size_t n) { + volatile char *d = dst; + volatile const char *s = src; + if(s < d) { + d += n; + s += n; + while(n--) { + *--d = *--s; + } + } else { + while(n--) { + *d++ = *s++; + } + } + return dst; +} + +volatile void *memset_volatile(volatile void *dest, int c, volatile size_t n) { + volatile unsigned char *d = dest; + while(n--) { + *d++ = c; + } + return dest; +} + +volatile void *memcpy_volatile(volatile void *restrict dst, const volatile void *restrict src, volatile size_t n) { + volatile char *d = dst; + volatile const char *s = src; + while(n--) { + *d++ = *s++; + } + return dst; +} diff --git a/libk/sys.c b/libk/sys.c index 8c3f7ba..be448b9 100644 --- a/libk/sys.c +++ b/libk/sys.c @@ -15,17 +15,17 @@ void io_wait(void) { } void int_enable(void) { - __asm__ volatile ("sti"); + __asm__ volatile ("sti"); } void int_disable(void) { - __asm__ volatile ("cli"); + __asm__ volatile ("cli"); } void int_wait(void) { - __asm__ volatile ("hlt"); + __asm__ volatile ("sti; hlt"); } void halt(void) { - __asm__ volatile ("cli; hlt"); + __asm__ volatile ("cli; hlt"); } diff --git a/linker.ld b/linker.ld index f59b18a..4e796e2 100644 --- a/linker.ld +++ b/linker.ld @@ -3,23 +3,23 @@ ENTRY(start) SECTIONS { . = 1M; - .boot : + .boot BLOCK(4K) : ALIGN(4K) { - *(.multiboot_header) + *(.multiboot) } - .rodata : + .rodata BLOCK(4K) : ALIGN(4K) { *(.rodata) } - .bss : - { - *(.bss) - } - - .text : + .text BLOCK(4K) : ALIGN(4K) { *(.text) } + + .bss BLOCK(4K) : ALIGN(4K) + { + *(.bss) + } }