From ecf636f2797647d5dfc38a4562cae53fe275217d Mon Sep 17 00:00:00 2001 From: Nic Gaffney Date: Tue, 6 Feb 2024 04:58:35 -0600 Subject: Interrupts + basic keyboard driver --- bochs/dblog.txt | 29 ++++++++-------- bochs/log.txt | 50 +++++++++++++-------------- src/boot/boot.s | 4 +-- src/include/gdt.h | 6 ---- src/include/idt.h | 2 +- src/include/isr.h | 10 ++++++ src/include/print.h | 2 ++ src/include/str.h | 1 + src/kernel/exceptions.c | 9 +++++ src/kernel/gdt.c | 52 ---------------------------- src/kernel/idt.c | 23 ------------- src/kernel/kernel.c | 55 ++++++++--------------------- src/kernel/keyboard/compile_flags.txt | 1 + src/kernel/keyboard/isr.c | 49 ++++++++++++++++++++++++++ src/kernel/keyboard/isr_wrap.s | 8 +++++ src/kernel/keyboard/pic.c | 65 +++++++++++++++++++++++++++++++++++ src/kernel/print.c | 32 +++++++++++++++-- src/kernel/stub_table.asm | 33 ------------------ src/kernel/tables/compile_flags.txt | 1 + src/kernel/tables/gdt.c | 52 ++++++++++++++++++++++++++++ src/kernel/tables/idt.c | 27 +++++++++++++++ src/kernel/tables/stub.s | 53 ++++++++++++++++++++++++++++ src/utils/str.c | 12 +++++-- tests/debug.rc | 7 ++-- 24 files changed, 378 insertions(+), 205 deletions(-) create mode 100644 src/include/isr.h create mode 100644 src/kernel/exceptions.c delete mode 100644 src/kernel/gdt.c delete mode 100644 src/kernel/idt.c create mode 100644 src/kernel/keyboard/compile_flags.txt create mode 100644 src/kernel/keyboard/isr.c create mode 100644 src/kernel/keyboard/isr_wrap.s delete mode 100644 src/kernel/stub_table.asm create mode 100644 src/kernel/tables/compile_flags.txt create mode 100644 src/kernel/tables/gdt.c create mode 100644 src/kernel/tables/idt.c create mode 100644 src/kernel/tables/stub.s diff --git a/bochs/dblog.txt b/bochs/dblog.txt index 95f70d9..72abe57 100644 --- a/bochs/dblog.txt +++ b/bochs/dblog.txt @@ -2,15 +2,15 @@ Next at t=0 (0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b ; ea5be000f0 c (0) Magic breakpoint -Next at t=75345490 -(0) [0x0000001008af] 0008:00000000001008af (unk. ctxt): cli ; fa -info cpu +Next at t=76673186 +(0) [0x000000100d0b] 0008:0000000000100d0b (unk. ctxt): call .-2928 (0x001001a0) ; e890f4ffff +info cpu CPU0: -rax: 00000000_00000000 +rax: 00000000_00000010 rbx: 00000000_00010000 -rcx: 00000000_0000000f -rdx: 00000000_000b8f9e -rsp: 00000000_00107030 +rcx: 00000000_00008e00 +rdx: 00000000_00000008 +rsp: 00000000_00107830 rbp: 00000000_00000000 rsi: 00000000_00000000 rdi: 00000000_00000000 @@ -22,8 +22,8 @@ r12: 00000000_00000000 r13: 00000000_00000000 r14: 00000000_00000000 r15: 00000000_00000000 -rip: 00000000_001008af -eflags 0x00000002: id vip vif ac vm rf nt IOPL=0 of df if tf sf zf af pf cf +rip: 00000000_00100d0b +eflags 0x00000202: id vip vif ac vm rf nt IOPL=0 of df IF tf sf zf af pf cf MM[0]: 00000000_00000000 MM[1]: 00000000_00000000 MM[2]: 00000000_00000000 @@ -33,14 +33,13 @@ MM[5]: 00000000_00000000 MM[6]: 00000000_00000000 MM[7]: 00000000_00000000 The CPU doesn't support AVX state ! -info gdt +info gdt 0 2 Global Descriptor Table (base=0x0000000000000000, limit=23): GDT[0x0000]=??? descriptor hi=0x00000000, lo=0x00000000 GDT[0x0008]=Code segment, base=0x00000000, limit=0x3fffffff, Execute/Read, Non-Conforming, Accessed, 32-bit GDT[0x0010]=Data segment, base=0x00000000, limit=0x3fffffff, Read/Write, Accessed -You can list individual entries with 'info gdt [NUM]' or groups with 'info gdt [NUM] [NUM]' -info idt -Interrupt Descriptor Table (base=0x000000000007fffe, limit=0): -You can list individual entries with 'info idt [NUM]' or groups with 'info idt [NUM] [NUM]' +info idt 0x21 +Interrupt Descriptor Table (base=0x0000000000103030, limit=2047): +IDT[0x21]=32-Bit Interrupt Gate target=0x0008:0x00100d30, DPL=0 exit -(0).[75345490] [0x0000001008af] 0008:00000000001008af (unk. ctxt): cli ; fa +(0).[76673186] [0x000000100d0b] 0008:0000000000100d0b (unk. ctxt): call .-2928 (0x001001a0) ; e890f4ffff diff --git a/bochs/log.txt b/bochs/log.txt index 0d53794..a06ac96 100644 --- a/bochs/log.txt +++ b/bochs/log.txt @@ -40,7 +40,7 @@ 00000000000i[USBCTL] Pluggable USB devices 00000000000i[USBCTL] floppy mouse tablet keypad keyboard hub disk cdrom 00000000000i[USBCTL] printer -00000000000i[MEM0 ] allocated memory at 0x7f2d9a15d010. after alignment, vector=0x7f2d9a15e000 +00000000000i[MEM0 ] allocated memory at 0x7fbf95b90010. after alignment, vector=0x7fbf95b91000 00000000000i[MEM0 ] 32.00MB 00000000000i[MEM0 ] mem block size = 0x00020000, blocks=256 00000000000i[MEM0 ] rom at 0xfffe0000/131072 ('/usr/share/bochs/BIOS-bochs-latest') @@ -56,7 +56,7 @@ 00000000000i[DEV ] PIIX3 PCI-to-ISA bridge present at device 1, function 0 00000000000i[PLUGIN] init_dev of 'cmos' plugin device by virtual method 00000000000i[CMOS ] Using local time for initial clock -00000000000i[CMOS ] Setting initial clock to: Wed Jan 24 16:03:24 2024 (time0=1706133804) +00000000000i[CMOS ] Setting initial clock to: Tue Feb 6 04:57:41 2024 (time0=1707217061) 00000000000i[PLUGIN] init_dev of 'dma' plugin device by virtual method 00000000000i[DMA ] channel 4 used by cascade 00000000000i[PLUGIN] init_dev of 'pic' plugin device by virtual method @@ -80,7 +80,7 @@ 00000000000i[CD1 ] load cdrom with path='out/gftos.iso' 00000000000i[CD1 ] Opening image file as a cd. 00000000000i[HD ] Media present in CD-ROM drive -00000000000i[HD ] Capacity is 10140 sectors (19.80 MB) +00000000000i[HD ] Capacity is 11322 sectors (22.11 MB) 00000000000i[PLUGIN] init_dev of 'pci_ide' plugin device by virtual method 00000000000i[DEV ] PIIX3 PCI IDE controller present at device 1, function 1 00000000000i[PLUGIN] init_dev of 'unmapped' plugin device by virtual method @@ -230,25 +230,25 @@ 00001540420i[VBIOS ] VGABios $Id: vgabios.c 288 2021-05-28 19:05:28Z vruppert $ 00001543145i[VBIOS ] VBE Bios $Id: vbe.c 292 2021-06-03 12:24:22Z vruppert $ 00005159561i[BIOS ] IDE time out -00017586850i[BIOS ] Booting from 07c0:0000 -00075345490i[CPU0 ] [75345490] Stopped on MAGIC BREAKPOINT -00075345490i[ ] dbg: Quit -00075345490i[CPU0 ] CPU is in protected mode (active) -00075345490i[CPU0 ] CS.mode = 32 bit -00075345490i[CPU0 ] SS.mode = 32 bit -00075345490i[CPU0 ] EFER = 0x00000000 -00075345490i[CPU0 ] | EAX=00000000 EBX=00010000 ECX=0000000f EDX=000b8f9e -00075345490i[CPU0 ] | ESP=00107030 EBP=00000000 ESI=00000000 EDI=00000000 -00075345490i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df if tf sf zf af pf cf -00075345490i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D -00075345490i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 3fffffff 1 1 -00075345490i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 3fffffff 1 1 -00075345490i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 3fffffff 1 1 -00075345490i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 3fffffff 1 1 -00075345490i[CPU0 ] | FS:0010( 0002| 0| 0) 00000000 3fffffff 1 1 -00075345490i[CPU0 ] | GS:0010( 0002| 0| 0) 00000000 3fffffff 1 1 -00075345490i[CPU0 ] | EIP=001008af (001008af) -00075345490i[CPU0 ] | CR0=0x60000011 CR2=0x00000000 -00075345490i[CPU0 ] | CR3=0x00000000 CR4=0x00000000 -00075345490i[CMOS ] Last time is 1706133822 (Wed Jan 24 16:03:42 2024) -00075345490i[SIM ] quit_sim called with exit code 0 +00017608938i[BIOS ] Booting from 07c0:0000 +00076673186i[CPU0 ] [76673186] Stopped on MAGIC BREAKPOINT +00076673186i[ ] dbg: Quit +00076673186i[CPU0 ] CPU is in protected mode (active) +00076673186i[CPU0 ] CS.mode = 32 bit +00076673186i[CPU0 ] SS.mode = 32 bit +00076673186i[CPU0 ] EFER = 0x00000000 +00076673186i[CPU0 ] | EAX=00000010 EBX=00010000 ECX=00008e00 EDX=00000008 +00076673186i[CPU0 ] | ESP=00107830 EBP=00000000 ESI=00000000 EDI=00000000 +00076673186i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df IF tf sf zf af pf cf +00076673186i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D +00076673186i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 3fffffff 1 1 +00076673186i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 3fffffff 1 1 +00076673186i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 3fffffff 1 1 +00076673186i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 3fffffff 1 1 +00076673186i[CPU0 ] | FS:0010( 0002| 0| 0) 00000000 3fffffff 1 1 +00076673186i[CPU0 ] | GS:0010( 0002| 0| 0) 00000000 3fffffff 1 1 +00076673186i[CPU0 ] | EIP=00100d0b (00100d0b) +00076673186i[CPU0 ] | CR0=0x60000011 CR2=0x00000000 +00076673186i[CPU0 ] | CR3=0x00000000 CR4=0x00000000 +00076673186i[CMOS ] Last time is 1707217080 (Tue Feb 6 04:58:00 2024) +00076673186i[SIM ] quit_sim called with exit code 0 diff --git a/src/boot/boot.s b/src/boot/boot.s index 8df5c6b..dbb4052 100644 --- a/src/boot/boot.s +++ b/src/boot/boot.s @@ -48,13 +48,13 @@ _start: call get_idtr lidt [idtr] sti + xchg bx, bx [bits 32] extern kernel_main call kernel_main - ; BOCHS - xchg bx, bx + cli diff --git a/src/include/gdt.h b/src/include/gdt.h index 8cc2542..b8d219a 100644 --- a/src/include/gdt.h +++ b/src/include/gdt.h @@ -16,12 +16,6 @@ typedef struct GDTR { uint32_t offset; } __attribute__((packed)) GDTR_t; -// typedef struct GDT { -// Segment_Descriptor_t nulldesc; -// Segment_Descriptor_t codedesc; -// Segment_Descriptor_t datadesc; -// } __attribute__((packed)) GDT_t; - typedef Segment_Descriptor_t *GDT_t; uint16_t make_code(uint8_t priv, uint8_t dc, uint8_t rw); diff --git a/src/include/idt.h b/src/include/idt.h index 78d736b..4724042 100644 --- a/src/include/idt.h +++ b/src/include/idt.h @@ -9,6 +9,6 @@ typedef struct Gate_Descriptor { uint16_t offset_high; } __attribute__((packed)) Gate_Descriptor_t; -void make_gate(uint32_t offset, uint8_t attrs, uint8_t vec); +void make_gate(void *isr, uint8_t attrs, uint8_t vec); void get_idtr(); diff --git a/src/include/isr.h b/src/include/isr.h new file mode 100644 index 0000000..4380e45 --- /dev/null +++ b/src/include/isr.h @@ -0,0 +1,10 @@ +#pragma once +#include +void PIC_init(int offset1, int offset2); +void PIC_disable(void); +uint16_t PIC_irr(void); +uint16_t PIC_isr(void); +void PIC_send(uint8_t irq, uint16_t cmd); +void IRQ_mask(uint8_t line); +void IRQ_unmask(uint8_t line); +void wrap_keyboard_handler(); diff --git a/src/include/print.h b/src/include/print.h index 3b94c6e..eeecfec 100644 --- a/src/include/print.h +++ b/src/include/print.h @@ -23,6 +23,8 @@ enum { }; // Prototypes +void update_cursor(); +void delete_char(); void print_clear(); void print_char(char); void print_str(char *); diff --git a/src/include/str.h b/src/include/str.h index 4e84e9c..bf7fd07 100644 --- a/src/include/str.h +++ b/src/include/str.h @@ -3,3 +3,4 @@ char *itoa(int, char *, int); size_t strlen(const char *); char *str_reverse(char *); +int isalpha(int); diff --git a/src/kernel/exceptions.c b/src/kernel/exceptions.c new file mode 100644 index 0000000..ded9e9b --- /dev/null +++ b/src/kernel/exceptions.c @@ -0,0 +1,9 @@ +#include "print.h" + +__attribute__((noreturn)) void exception_handler(void); +void exception_handler() { + print_set_color(PRINT_COLOR_RED, PRINT_COLOR_BLACK); + print_clear(); + printf("KERNEL EXCEPTION"); + __asm__ volatile("cli; hlt"); +} diff --git a/src/kernel/gdt.c b/src/kernel/gdt.c deleted file mode 100644 index 406b40c..0000000 --- a/src/kernel/gdt.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "gdt.h" -#include - -GDT_t table = 0x0; -extern GDTR_t gdtr; -void get_gdtr() { - uint32_t base = 0x0000; - - table[0] = make_descriptor(0, 0, 0); - table[1] = make_descriptor(base, 0x3FFFF, make_code(0, 0, 1)); - table[2] = make_descriptor(base, 0x3FFFF, make_data(0, 0, 1)); - - gdtr.size = sizeof(Segment_Descriptor_t) * 3 - 1; - gdtr.offset = base; -} - -uint16_t make_code(uint8_t priv, uint8_t dc, uint8_t rw) { - uint16_t access = 0; - access |= (1 << 7); - access |= (priv << 5); - access |= (0b11 << 3); - access |= (dc << 2); - access |= (rw << 1); // 10 - access <<= 8; - access |= FLAG; - return access; -} - -uint16_t make_data(uint8_t priv, uint8_t dc, uint8_t rw) { - uint16_t access = 0; - access |= (1 << 7); - access |= (priv << 5); - access |= (0b10 << 3); - access |= (dc << 2); - access |= (rw << 1); // 10 - access <<= 8; - access |= FLAG; - return access; -} - -Segment_Descriptor_t make_descriptor(uint32_t base, uint32_t limit, - uint16_t access_flag) { - uint16_t lim_low = limit; - uint16_t base_low = base; - uint8_t base_mid = (base >> 16); - uint8_t access_byte = access_flag >> 8; - uint8_t lim_flag = ((access_flag << 4) | (limit >> 16)); - uint8_t base_high = (base >> 24); - return (Segment_Descriptor_t){ - lim_low, base_low, base_mid, access_byte, lim_flag, base_high, - }; -} diff --git a/src/kernel/idt.c b/src/kernel/idt.c deleted file mode 100644 index 2805889..0000000 --- a/src/kernel/idt.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "idt.h" -#include "gdt.h" -#include - -static Gate_Descriptor_t idt[256]; -extern GDTR_t idtr; - -void get_idtr() { - idtr.offset = (uintptr_t)&idt[0]; - idtr.size = sizeof(Gate_Descriptor_t) * 256 - 1; - for (uint8_t vec = 0; vec < 32; vec++) { - make_gate(stub_table[vec], 0x8E, vec); - } -} - -void make_gate(uint32_t offset, uint8_t attrs, uint8_t vec) { - Gate_Descriptor_t *descriptor = &idt[vec]; - - descriptor->offset_low = offset & 0xFFFF; - descriptor->attrs = (0b1000 << 4) | attrs; - descriptor->offset_high = offset >> 16, descriptor->segment_selector = 0x08; - descriptor->reserved = 0; -} diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index b582e85..7dd3deb 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,5 +1,9 @@ -#include "kernel.h" +#include "asm.h" +#include "gdt.h" +#include "isr.h" #include "print.h" +extern GDTR_t idtr; +extern GDTR_t gdtr; #if defined(__linux__) #error "Not using cross compiler!" @@ -10,49 +14,20 @@ #error "Must use ix86-elf compiler" #endif -void motd() { - char *empty_row = " " - " \n"; - empty_row[0] = (char)186; - empty_row[79] = (char)186; - - printf("%c", 201); - for (int i = 0; i < 78; i++) - printf("%c", 205); - printf("%c\n", 187); - - printf(empty_row); - - printf("%c", 186); - for (int i = 0; i < 78 / 2 - 17 / 2; i++) - printf(" "); - printf("Welcome to gftos!"); - for (int i = 0; i < 78 / 2 - 17 / 2 - 1; i++) - printf(" "); - printf("%c\n", 186); - - for (int i = 0; i < 21; i++) { - printf(empty_row); - } - - printf("%c", 200); - for (int i = 0; i < 78; i++) - printf("%c", 205); - printf("%c", 188); -} - -void kernel_panic(const char *error) { - print_set_color(PRINT_COLOR_BLACK, PRINT_COLOR_RED); - print_clear(); - printf(" PANIC! ERROR: %s", error); - for (;;) - ; -} +void motd() { printf("Welcome to gftos!\n=================\n"); } void kernel_main(void) { + PIC_init(0x20, 0xA0); + IRQ_mask(0); + + print_set_color(PRINT_COLOR_PINK, PRINT_COLOR_DARK_GRAY); print_clear(); motd(); - /* kernel_panic("test_panic."); */ + for (;;) { + update_cursor(); + asm("hlt"); + } + // for (int r = 0; r < 24; r++) { // for (int c = 0; c < 80; c += 3) { // int color = (r + c) % 15 + 1; diff --git a/src/kernel/keyboard/compile_flags.txt b/src/kernel/keyboard/compile_flags.txt new file mode 100644 index 0000000..2af49c7 --- /dev/null +++ b/src/kernel/keyboard/compile_flags.txt @@ -0,0 +1 @@ +-I../../include/ diff --git a/src/kernel/keyboard/isr.c b/src/kernel/keyboard/isr.c new file mode 100644 index 0000000..223bf9f --- /dev/null +++ b/src/kernel/keyboard/isr.c @@ -0,0 +1,49 @@ +#include "asm.h" +#include "print.h" +#include "str.h" +#include +static uint8_t shift_held = 0; +static uint8_t capslock = 0; + +void keyboard_handler() { + const char *scancodes = + "??1234567890-=?\tqwertyuiop[]\n?asdfghjkl;'`?\\zxcvbnm,./?*? "; + const char *SCANCODES = + "\?\?!@#$%^&*()_+?\tQWERTYUIOP{}\n?ASDFGHJKL:\"~?|ZXCVBNM<>??*? "; + + unsigned char sc = inb(0x60); + + uint8_t isheld = shift_held != 0; + char c = ((isheld | capslock) & !(isheld & capslock)) ? SCANCODES[sc] + : scancodes[sc]; + + if (capslock & (!isheld) && !isalpha(c)) + c = scancodes[sc]; + if (isheld && !isalpha(c)) + c = SCANCODES[sc]; + + if (sc < 0x59 && scancodes[sc] != '?') + printf("%c", c); + + switch (sc) { + case 0x2A: + shift_held |= 0b10; + break; + case 0x36: + shift_held |= 0b01; + break; + case 0xAA: + shift_held &= 0b01; + break; + case 0xB6: + shift_held &= 0b10; + break; + case 0x0E: + delete_char(); + break; + case 0x3A: + capslock = !capslock; + break; + } + outb(0x20, 0x20); +} diff --git a/src/kernel/keyboard/isr_wrap.s b/src/kernel/keyboard/isr_wrap.s new file mode 100644 index 0000000..6f6c58b --- /dev/null +++ b/src/kernel/keyboard/isr_wrap.s @@ -0,0 +1,8 @@ +extern keyboard_handler +extern wrap_keyboard_handler +wrap_keyboard_handler: + pushad + cld + call keyboard_handler + popad + iret diff --git a/src/kernel/keyboard/pic.c b/src/kernel/keyboard/pic.c index 0c81629..e1b4fb3 100644 --- a/src/kernel/keyboard/pic.c +++ b/src/kernel/keyboard/pic.c @@ -1 +1,66 @@ #include "asm.h" +#include +#define PIC1 0x20 +#define PIC2 0xA0 +#define PIC1_COMMAND PIC1 +#define PIC1_DATA (PIC1 + 1) +#define PIC2_COMMAND PIC2 +#define PIC2_DATA (PIC2 + 1) + +void PIC_init(int offset1, int offset2) { + uint8_t a1, a2; + + a1 = inb(PIC1_DATA); + a2 = inb(PIC2_DATA); + + outb(PIC1_COMMAND, 0x11); // Init PIC1 + io_wait(); + outb(PIC2_COMMAND, 0x11); // Init PIC2 + io_wait(); + outb(PIC1_DATA, offset1); // ICW2: Master PIC vector offset + io_wait(); + outb(PIC2_DATA, offset2); // ICW2: Slave PIC vector offset + io_wait(); + outb(PIC1_DATA, 4); + io_wait(); + outb(PIC2_DATA, 2); + io_wait(); + outb(PIC1_DATA, 0x01); + io_wait(); + outb(PIC2_DATA, 0x01); + io_wait(); + + outb(PIC1_DATA, a1); // restore saved masks. + outb(PIC2_DATA, a2); +} + +void IRQ_mask(uint8_t line) { + uint16_t port = line < 8 ? PIC1_DATA : PIC2_DATA; + line = line > 8 ? line - 8 : line; + uint8_t val = inb(port) | (1 << line); + outb(port, val); +} + +void IRQ_unmask(uint8_t line) { + uint16_t port = line < 8 ? PIC1_DATA : PIC2_DATA; + line = line > 8 ? line - 8 : line; + uint8_t val = inb(port) & ~(1 << line); + outb(port, val); +} + +void PIC_disable(void) { + outb(PIC1_DATA, 0xff); + outb(PIC2_DATA, 0xff); +} + +uint16_t PIC_irr(void) { + outb(PIC1_COMMAND, 0x0a); + outb(PIC2_COMMAND, 0x0a); + return (inb(PIC2_COMMAND) << 8) | inb(PIC1_COMMAND); +} + +uint16_t PIC_isr(void) { + outb(PIC1_COMMAND, 0x0b); + outb(PIC2_COMMAND, 0x0b); + return (inb(PIC2_COMMAND) << 8) | inb(PIC1_COMMAND); +} diff --git a/src/kernel/print.c b/src/kernel/print.c index d5e8790..7a54c7b 100644 --- a/src/kernel/print.c +++ b/src/kernel/print.c @@ -1,9 +1,12 @@ #include "print.h" +#include "asm.h" #include "str.h" #include +#include // Constants static const size_t NUM_COLS = 80; static const size_t NUM_ROWS = 25; +static uint8_t cursor = 0; // Char struct struct Char { @@ -34,6 +37,18 @@ void clear_row(size_t row) { } } +void delete_char() { + if (col == 0) { + row--; + col = NUM_COLS; + } + col--; + buffer[col + NUM_COLS * row] = (struct Char){ + ' ', + color, + }; +} + // Call clear_row for every row void print_clear() { for (size_t i = 0; i < NUM_ROWS; i++) { @@ -62,6 +77,15 @@ void print_newline() { clear_row(NUM_ROWS - 1); } +void update_cursor() { + uint16_t pos = col + NUM_COLS * row; + + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t)(pos & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF)); +} + // printchar void print_char(char character) { // If \n, call newline @@ -76,7 +100,7 @@ void print_char(char character) { } // if cols is too large, overflow - if (col > NUM_COLS) { + if (col >= NUM_COLS) { print_newline(); } @@ -105,7 +129,7 @@ void print_set_color(uint8_t foreground, uint8_t background) { void printf(const char *str, ...) { va_list args; va_start(args, str); - char temp_str[256]; + char temp_str[256] = ""; for (size_t i = 0; str[i] != '\0'; ++i) { if (str[i] == '%') { @@ -114,6 +138,10 @@ void printf(const char *str, ...) { case 'd': print_str(itoa(va_arg(args, int), temp_str, 10)); break; + case 'x': + print_str("0x"); + print_str(itoa(va_arg(args, int), temp_str, 16)); + break; case 's': print_str(va_arg(args, char *)); break; diff --git a/src/kernel/stub_table.asm b/src/kernel/stub_table.asm deleted file mode 100644 index 9901cea..0000000 --- a/src/kernel/stub_table.asm +++ /dev/null @@ -1,33 +0,0 @@ -extern exception_handler -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_err_stub 0 -isr_no_err_stub 0 -isr_err_stub 0 -isr_err_stub 0 -isr_err_stub 0 -isr_err_stub 0 -isr_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_no_err_stub 0 -isr_err_stub 0 -isr_no_err_stub 0 diff --git a/src/kernel/tables/compile_flags.txt b/src/kernel/tables/compile_flags.txt new file mode 100644 index 0000000..2af49c7 --- /dev/null +++ b/src/kernel/tables/compile_flags.txt @@ -0,0 +1 @@ +-I../../include/ diff --git a/src/kernel/tables/gdt.c b/src/kernel/tables/gdt.c new file mode 100644 index 0000000..9c65152 --- /dev/null +++ b/src/kernel/tables/gdt.c @@ -0,0 +1,52 @@ +#include "gdt.h" +#include + +GDT_t table = 0x0; +extern GDTR_t gdtr; +void get_gdtr() { + uint32_t base = (uint32_t)table; + + table[0] = make_descriptor(base, 0, 0); + table[1] = make_descriptor(base, 0x3FFFF, make_code(0, 0, 1)); + table[2] = make_descriptor(base, 0x3FFFF, make_data(0, 0, 1)); + + gdtr.size = sizeof(Segment_Descriptor_t) * 3 - 1; + gdtr.offset = base; +} + +uint16_t make_code(uint8_t priv, uint8_t dc, uint8_t rw) { + uint16_t access = 0; + access |= (1 << 7); + access |= (priv << 5); + access |= (0b11 << 3); + access |= (dc << 2); + access |= (rw << 1); // 10 + access <<= 8; + access |= FLAG; + return access; +} + +uint16_t make_data(uint8_t priv, uint8_t dc, uint8_t rw) { + uint16_t access = 0; + access |= (1 << 7); + access |= (priv << 5); + access |= (0b10 << 3); + access |= (dc << 2); + access |= (rw << 1); // 10 + access <<= 8; + access |= FLAG; + return access; +} + +Segment_Descriptor_t make_descriptor(uint32_t base, uint32_t limit, + uint16_t access_flag) { + uint16_t lim_low = limit; + uint16_t base_low = base; + uint8_t base_mid = (base >> 16); + uint8_t access_byte = access_flag >> 8; + uint8_t lim_flag = ((access_flag << 4) | (limit >> 16)); + uint8_t base_high = (base >> 24); + return (Segment_Descriptor_t){ + lim_low, base_low, base_mid, access_byte, lim_flag, base_high, + }; +} diff --git a/src/kernel/tables/idt.c b/src/kernel/tables/idt.c new file mode 100644 index 0000000..01a6776 --- /dev/null +++ b/src/kernel/tables/idt.c @@ -0,0 +1,27 @@ +#include "idt.h" +#include "gdt.h" +#include "isr.h" +#include + +__attribute__((aligned(0x10))) static Gate_Descriptor_t idt[256]; +extern GDTR_t idtr; +extern void *isr_stub_table; + +void get_idtr() { + idtr.offset = (uintptr_t)&idt[0]; + idtr.size = sizeof(Gate_Descriptor_t) * 256 - 1; + for (uint8_t vec = 0; vec < 32; vec++) { + make_gate(((void **)(isr_stub_table))[vec], 0x8E, vec); + } + make_gate(wrap_keyboard_handler, 0x8E, 0x21); +} + +void make_gate(void *isr, uint8_t attrs, uint8_t vec) { + Gate_Descriptor_t *descriptor = &idt[vec]; + + descriptor->offset_low = (uint32_t)isr & 0xFFFF; + descriptor->attrs = (0b1000 << 4) | attrs; + descriptor->offset_high = (uint32_t)isr >> 16; + descriptor->segment_selector = 0x08; + descriptor->reserved = 0; +} diff --git a/src/kernel/tables/stub.s b/src/kernel/tables/stub.s new file mode 100644 index 0000000..11e457a --- /dev/null +++ b/src/kernel/tables/stub.s @@ -0,0 +1,53 @@ + +%macro isr_err_stub 1 +isr_stub_%+%1: + call exception_handler + iret +%endmacro +%macro isr_no_err_stub 1 +isr_stub_%+%1: + call exception_handler + iret +%endmacro + +extern exception_handler +isr_no_err_stub 0 +isr_no_err_stub 1 +isr_no_err_stub 2 +isr_no_err_stub 3 +isr_no_err_stub 4 +isr_no_err_stub 5 +isr_no_err_stub 6 +isr_no_err_stub 7 +isr_err_stub 8 +isr_no_err_stub 9 +isr_err_stub 10 +isr_err_stub 11 +isr_err_stub 12 +isr_err_stub 13 +isr_err_stub 14 +isr_no_err_stub 15 +isr_no_err_stub 16 +isr_err_stub 17 +isr_no_err_stub 18 +isr_no_err_stub 19 +isr_no_err_stub 20 +isr_no_err_stub 21 +isr_no_err_stub 22 +isr_no_err_stub 23 +isr_no_err_stub 24 +isr_no_err_stub 25 +isr_no_err_stub 26 +isr_no_err_stub 27 +isr_no_err_stub 28 +isr_no_err_stub 29 +isr_err_stub 30 +isr_no_err_stub 31 + +global isr_stub_table +isr_stub_table: +%assign i 0 +%rep 32 + dd isr_stub_%+i +%assign i i+1 +%endrep diff --git a/src/utils/str.c b/src/utils/str.c index 9a7acb0..362f797 100644 --- a/src/utils/str.c +++ b/src/utils/str.c @@ -8,6 +8,8 @@ size_t strlen(const char *str) { return size; } +int isalpha(int c) { return (c > 64 && c < 91) || (c > 96 && c < 123); } + char *str_reverse(char *str) { char *str_ptr = str; size_t size = strlen(str); @@ -24,8 +26,14 @@ char *str_reverse(char *str) { char *itoa(int num, char *str, int base) { char *str_ptr = str; - for (; num;) { - *str_ptr++ = num % base + 48; + if (num == 0) + return "0"; + if (num < 0) { + *str_ptr++ = '-'; + num *= -1; + } + while (num) { + *str_ptr++ = num % base + (num % base > 9 ? 55 : 48); num /= base; } str_reverse(str); diff --git a/tests/debug.rc b/tests/debug.rc index e2225a1..16caa13 100644 --- a/tests/debug.rc +++ b/tests/debug.rc @@ -1,6 +1,5 @@ c -info cpu -info gdt -info idt +info cpu +info gdt 0 2 +info idt 0x21 exit - -- cgit v1.2.3