commit f5bdd46c928f314671dc5e934424bcfb4254a6e1
parent 1d8bcba8689f039b3aaafab83d124d205e2d327f
Author: Christos Margiolis <christos@margiolis.net>
Date: Sat, 24 Apr 2021 22:51:01 +0300
Set up ISR, IDT, added basic PS/2 keyboard and timer drivers
Diffstat:
13 files changed, 880 insertions(+), 5 deletions(-)
diff --git a/Makefile b/Makefile
@@ -8,3 +8,4 @@ run:
clean:
rm -rf ${TGTDIR}
+ cd boot && make clean && cd ..
diff --git a/boot/Makefile b/boot/Makefile
@@ -14,7 +14,11 @@ SRC = *.c *.asm
OBJ = loader.o \
kernel.o \
string.o \
- tty.o
+ tty.o \
+ idt.o \
+ int.o \
+ kbd.o \
+ timer.o
all: options ${BIN}
@@ -33,7 +37,7 @@ ${BIN}: ${OBJ}
dd if=/dev/zero bs=1000000 count=1 >> ${KERNEL_BIN}
cat ${BOOT_BIN} ${KERNEL_BIN} > $@
-c.o:
+.c.o:
${CC} -c ${CFLAGS} $<
.asm.o:
diff --git a/boot/boot.asm b/boot/boot.asm
@@ -157,6 +157,7 @@ lm_check:
lm_fail:
popa
call kernel_exec
+ jmp $ ; Safety hang.
; We'll check for (and switch to) Long Mode here.
lm_enter:
diff --git a/boot/extern.h b/boot/extern.h
@@ -8,4 +8,49 @@
#include "tty.h"
#include "string.h"
+static inline uint8_t
+inb(uint16_t port)
+{
+ uint8_t res;
+
+ __asm__ __volatile__ ("in %%dx, %%al" : "=a" (res) : "d" (port));
+ return res;
+}
+
+static inline void
+outb(uint8_t v, uint16_t port)
+{
+ __asm__ __volatile__ ("out %%al, %%dx" : : "a" (v), "d" (port));
+}
+
+static inline uint16_t
+inw(uint16_t port)
+{
+ uint16_t res;
+
+ __asm__ __volatile__ ("in %%dx, %%ax" : "=a" (res) : "d" (port));
+ return res;
+}
+
+static inline void
+outw(uint16_t v, uint16_t port)
+{
+ __asm__ __volatile__ ("out %%ax, %%dx" : : "a" (v), "d" (port));
+}
+
+static inline uint32_t
+inl(uint16_t port)
+{
+ uint32_t res;
+
+ __asm__ __volatile__ ("in %%dx, %%eax" : "=a" (res) : "d" (port));
+ return res;
+}
+
+static inline void
+outl(uint32_t v, uint16_t port)
+{
+ __asm__ __volatile__ ("out %%eax, %%dx" : : "a" (v), "d" (port));
+}
+
#endif /* _KERNEL_EXTERN_H */
diff --git a/boot/idt.c b/boot/idt.c
@@ -0,0 +1,168 @@
+#include "extern.h"
+#include "idt.h"
+
+static void idt_set_gate(uint8_t, uint32_t);
+
+static struct idt_gate idt[N_INT];
+static struct idt_reg idtr;
+static void *irq_routines[16] = {NULL};
+
+/* Exception messages for the first 32 ISRs. */
+static const char *except[] = {
+ "Division By Zero Exception",
+ "Debug Exception",
+ "Non Maskable Interrupt Exception",
+ "Breakpoint Exception",
+ "Into Detected Overflow Exception",
+ "Out of Bounds Exception",
+ "Invalid Opcode Exception",
+ "No Coprocessor Exception",
+ "Double Fault Exception",
+ "Coprocessor Segment Overrun Exception",
+ "Bad TSS Exception",
+ "Segment Not Present Exception",
+ "Stack Fault Exception",
+ "General Protection Fault Exception",
+ "Page Fault Exception",
+ "Unknown Interrupt Exception",
+ "Coprocessor Fault Exception",
+ "Alignment Check Exception (486+)",
+ "Machine Check Exception (Pentium/586+)",
+ "Reserved Exception",
+ "Reserved Exception",
+ "Reserved Exception",
+ "Reserved Exception",
+ "Reserved Exception",
+ "Reserved Exception",
+ "Reserved Exception",
+ "Reserved Exception",
+ "Reserved Exception",
+ "Reserved Exception",
+ "Reserved Exception",
+ "Reserved Exception",
+ "Reserved Exception",
+};
+
+static void
+idt_set_gate(uint8_t n, uint32_t ptr)
+{
+ idt[n].off_lo = ptr & 0xffff;
+ idt[n].sel = KERN_CODESEG;
+ idt[n].zero = 0;
+ idt[n].attr = 0x8e; /* The gate is present and is running in kernel mode. */
+ idt[n].off_hi = (ptr >> 16) & 0xffff;
+}
+
+void
+idt_init(void)
+{
+ /* Set up the ISRs */
+ idt_set_gate(0, (uint32_t)isr0);
+ idt_set_gate(1, (uint32_t)isr1);
+ idt_set_gate(2, (uint32_t)isr2);
+ idt_set_gate(3, (uint32_t)isr3);
+ idt_set_gate(4, (uint32_t)isr4);
+ idt_set_gate(5, (uint32_t)isr5);
+ idt_set_gate(6, (uint32_t)isr6);
+ idt_set_gate(7, (uint32_t)isr7);
+ idt_set_gate(8, (uint32_t)isr8);
+ idt_set_gate(9, (uint32_t)isr9);
+ idt_set_gate(10, (uint32_t)isr10);
+ idt_set_gate(11, (uint32_t)isr11);
+ idt_set_gate(12, (uint32_t)isr12);
+ idt_set_gate(13, (uint32_t)isr13);
+ idt_set_gate(14, (uint32_t)isr14);
+ idt_set_gate(15, (uint32_t)isr15);
+ idt_set_gate(16, (uint32_t)isr16);
+ idt_set_gate(17, (uint32_t)isr17);
+ idt_set_gate(18, (uint32_t)isr18);
+ idt_set_gate(19, (uint32_t)isr19);
+ idt_set_gate(20, (uint32_t)isr20);
+ idt_set_gate(21, (uint32_t)isr21);
+ idt_set_gate(22, (uint32_t)isr22);
+ idt_set_gate(23, (uint32_t)isr23);
+ idt_set_gate(24, (uint32_t)isr24);
+ idt_set_gate(25, (uint32_t)isr25);
+ idt_set_gate(26, (uint32_t)isr26);
+ idt_set_gate(27, (uint32_t)isr27);
+ idt_set_gate(28, (uint32_t)isr28);
+ idt_set_gate(29, (uint32_t)isr29);
+ idt_set_gate(30, (uint32_t)isr30);
+ idt_set_gate(31, (uint32_t)isr31);
+
+ /* Remap the PIC */
+ /* TODO: explain.*/
+ outb(0x11, 0x20);
+ outb(0x11, 0xa0);
+ outb(0x20, 0x21);
+ outb(0x28, 0xa1);
+ outb(0x04, 0x21);
+ outb(0x02, 0xa1);
+ outb(0x01, 0x21);
+ outb(0x01, 0xa1);
+ outb(0x00, 0x21);
+ outb(0x00, 0xa1);
+
+ /* Set up the IRQs */
+ idt_set_gate(32, (uint32_t)irq0);
+ idt_set_gate(33, (uint32_t)irq1);
+ idt_set_gate(34, (uint32_t)irq2);
+ idt_set_gate(35, (uint32_t)irq3);
+ idt_set_gate(36, (uint32_t)irq4);
+ idt_set_gate(37, (uint32_t)irq5);
+ idt_set_gate(38, (uint32_t)irq6);
+ idt_set_gate(39, (uint32_t)irq7);
+ idt_set_gate(40, (uint32_t)irq8);
+ idt_set_gate(41, (uint32_t)irq9);
+ idt_set_gate(42, (uint32_t)irq10);
+ idt_set_gate(43, (uint32_t)irq11);
+ idt_set_gate(44, (uint32_t)irq12);
+ idt_set_gate(45, (uint32_t)irq13);
+ idt_set_gate(46, (uint32_t)irq14);
+ idt_set_gate(47, (uint32_t)irq15);
+
+ /* https://wiki.osdev.org/Interrupt_Descriptor_Table#Location_and_Size */
+ idtr.base = (uint32_t)&idt;
+ idtr.limit = N_INT * sizeof(struct idt_gate) - 1;
+ /* Load the IDT */
+ __asm__ __volatile__ ("lidtl (%0)" : : "r" (&idtr));
+}
+
+/* TODO: add comments */
+void
+isr_handler(struct reg *r)
+{
+ /* XXX: 31? */
+ if (r->intno < 32) {
+ tty_write(except[r->intno]);
+ tty_write(". System halted...\n");
+ __asm__ __volatile__ ("hlt");
+ }
+}
+
+/* TODO: add comments */
+void
+irq_handler(struct reg *r)
+{
+ void (*handler)(struct reg *);
+
+ if ((handler = irq_routines[r->intno - 32]) != 0)
+ handler(r);
+ if (r->intno >= 40)
+ outb(0x20, 0xa0);
+ outb(0x20, 0x20);
+}
+
+/* TODO: add comments */
+void
+irq_add_handler(uint8_t irqno, void (*handler)(struct reg *r))
+{
+ irq_routines[irqno] = handler;
+}
+
+/* TODO: add comments */
+void
+irq_rm_handler(uint8_t irqno)
+{
+ irq_routines[irqno] = NULL;
+}
diff --git a/boot/idt.h b/boot/idt.h
@@ -0,0 +1,109 @@
+#ifndef _KERNEL_IDT_H
+#define _KERNEL_IDT_H
+
+#define N_INT 256 /* There are 256 interrupts in total. */
+#define KERN_CODESEG 0x08 /* Kernel code segment. */
+
+struct idt_reg {
+ uint16_t limit; /* Points at &IDT. */
+ uint32_t base; /* Points at the end of the IDT. */
+} __attribute__((packed));
+
+/* IA-32 */
+struct idt_gate {
+ uint16_t off_lo;
+ uint16_t sel;
+ uint8_t zero;
+ uint8_t attr;
+ uint16_t off_hi;
+} __attribute__((packed));
+
+
+/* This will be populated by isr_common_stub. */
+struct reg {
+ /* Segment registers. Will be poped last. */
+ uint32_t gs;
+ uint32_t fs;
+ uint32_t es;
+ uint32_t ds;
+ /* General purpose registers. Pushed by `pusha`. */
+ uint32_t edi;
+ uint32_t esi;
+ uint32_t ebp;
+ uint32_t esp;
+ uint32_t ebx;
+ uint32_t edx;
+ uint32_t ecx;
+ uint32_t eax;
+ /* ISR info. Pushed by `push byte`. */
+ uint32_t intno;
+ uint32_t err;
+ /* Pushed by the processor. */
+ uint32_t eip;
+ uint32_t cs;
+ uint32_t eflags;
+ uint32_t uesp;
+ uint32_t ss;
+};
+
+/* `kernel_main` calls this. */
+extern void idt_init(void);
+
+extern void isr_handler(struct reg *);
+extern void irq_handler(struct reg *);
+extern void irq_add_handler(uint8_t, void (*)(struct reg *));
+extern void irq_rm_handler(uint8_t);
+
+/* The first 32 ISRs are reserved for exceptions. */
+extern void isr0(void);
+extern void isr1(void);
+extern void isr2(void);
+extern void isr3(void);
+extern void isr4(void);
+extern void isr5(void);
+extern void isr6(void);
+extern void isr7(void);
+extern void isr8(void);
+extern void isr9(void);
+extern void isr10(void);
+extern void isr11(void);
+extern void isr12(void);
+extern void isr13(void);
+extern void isr14(void);
+extern void isr15(void);
+extern void isr16(void);
+extern void isr17(void);
+extern void isr18(void);
+extern void isr19(void);
+extern void isr20(void);
+extern void isr21(void);
+extern void isr22(void);
+extern void isr23(void);
+extern void isr24(void);
+extern void isr25(void);
+extern void isr26(void);
+extern void isr27(void);
+extern void isr28(void);
+extern void isr29(void);
+extern void isr30(void);
+extern void isr31(void);
+
+/* IRQs */
+extern void irq0(void);
+extern void irq1(void);
+extern void irq2(void);
+extern void irq3(void);
+extern void irq4(void);
+extern void irq5(void);
+extern void irq6(void);
+extern void irq7(void);
+extern void irq8(void);
+extern void irq9(void);
+extern void irq10(void);
+extern void irq11(void);
+extern void irq12(void);
+extern void irq13(void);
+extern void irq14(void);
+extern void irq15(void);
+
+#endif /* _KERNEL_IDT_H */
diff --git a/boot/int.asm b/boot/int.asm
@@ -0,0 +1,440 @@
+[extern isr_handler]
+[extern irq_handler]
+
+; ISRs
+global isr0
+global isr1
+global isr2
+global isr3
+global isr4
+global isr5
+global isr6
+global isr7
+global isr8
+global isr9
+global isr10
+global isr11
+global isr12
+global isr13
+global isr14
+global isr15
+global isr16
+global isr17
+global isr18
+global isr19
+global isr20
+global isr21
+global isr22
+global isr23
+global isr24
+global isr25
+global isr26
+global isr27
+global isr28
+global isr29
+global isr30
+global isr31
+
+; IRQs
+global irq0
+global irq1
+global irq2
+global irq3
+global irq4
+global irq5
+global irq6
+global irq7
+global irq8
+global irq9
+global irq10
+global irq11
+global irq12
+global irq13
+global irq14
+global irq15
+
+; ================== ISR ======================
+
+; 0 - Division By Zero
+isr0:
+ cli
+ push byte 0
+ push byte 0
+ jmp isr_common_stub
+
+; 1 - Debug
+isr1:
+ cli
+ push byte 0
+ push byte 1
+ jmp isr_common_stub
+
+; 2 - Non Maskable Interrupt
+isr2:
+ cli
+ push byte 0
+ push byte 2
+ jmp isr_common_stub
+
+; 3 - Breakpoint
+isr3:
+ cli
+ push byte 0
+ push byte 3
+ jmp isr_common_stub
+
+; 4 - Into Detected Overflow
+isr4:
+ cli
+ push byte 0
+ push byte 4
+ jmp isr_common_stub
+
+; 5 - Out of Bounds
+isr5:
+ cli
+ push byte 0
+ push byte 5
+ jmp isr_common_stub
+
+; 6 - Invalid Opcode
+isr6:
+ cli
+ push byte 0
+ push byte 6
+ jmp isr_common_stub
+
+; 7 - No Coprocessor
+isr7:
+ cli
+ push byte 0
+ push byte 7
+ jmp isr_common_stub
+
+; 8 - Double Fault (with error code)
+isr8:
+ cli
+ push byte 8
+ jmp isr_common_stub
+
+; 9 - Coprocessor Segment Overrrun
+isr9:
+ cli
+ push byte 0
+ push byte 9
+ jmp isr_common_stub
+
+; 10 - Bad TSS (with error code)
+isr10:
+ cli
+ push byte 10
+ jmp isr_common_stub
+
+; 11 - Segment Not Present (with error code)
+isr11:
+ cli
+ push byte 11
+ jmp isr_common_stub
+
+; 12 - Stack Fault (with error code)
+isr12:
+ cli
+ push byte 12
+ jmp isr_common_stub
+
+; 13 - General Protection Fault (with error code)
+isr13:
+ cli
+ push byte 13
+ jmp isr_common_stub
+
+; 14 - Page Fault (with error code)
+isr14:
+ cli
+ push byte 14
+ jmp isr_common_stub
+
+; 15 - Unkown Interrupt
+isr15:
+ cli
+ push byte 0
+ push byte 15
+ jmp isr_common_stub
+
+; 16 - Coprocessor Fault
+isr16:
+ cli
+ push byte 0
+ push byte 16
+ jmp isr_common_stub
+
+; 17 - Alignment Check (486+)
+isr17:
+ cli
+ push byte 0
+ push byte 17
+ jmp isr_common_stub
+
+; 18 - Machine Check (Pentium/586+)
+isr18:
+ cli
+ push byte 0
+ push byte 18
+ jmp isr_common_stub
+
+; 19 - Reserved
+isr19:
+ cli
+ push byte 0
+ push byte 19
+ jmp isr_common_stub
+
+; 20 - Reserved
+isr20:
+ cli
+ push byte 0
+ push byte 20
+ jmp isr_common_stub
+
+; 21 - Reserved
+isr21:
+ cli
+ push byte 0
+ push byte 21
+ jmp isr_common_stub
+
+; 22 - Reserved
+isr22:
+ cli
+ push byte 0
+ push byte 22
+ jmp isr_common_stub
+
+; 23 - Reserved
+isr23:
+ cli
+ push byte 0
+ push byte 23
+ jmp isr_common_stub
+
+; 24 - Reserved
+isr24:
+ cli
+ push byte 0
+ push byte 24
+ jmp isr_common_stub
+
+; 25 - Reserved
+isr25:
+ cli
+ push byte 0
+ push byte 25
+ jmp isr_common_stub
+
+; 26 - Reserved
+isr26:
+ cli
+ push byte 0
+ push byte 26
+ jmp isr_common_stub
+
+; 27 - Reserved
+isr27:
+ cli
+ push byte 0
+ push byte 27
+ jmp isr_common_stub
+
+; 28 - Reserved
+isr28:
+ cli
+ push byte 0
+ push byte 28
+ jmp isr_common_stub
+
+; 29 - Reserved
+isr29:
+ cli
+ push byte 0
+ push byte 29
+ jmp isr_common_stub
+
+; 30 - Reserved
+isr30:
+ cli
+ push byte 0
+ push byte 30
+ jmp isr_common_stub
+
+; 31 - Reserved
+isr31:
+ cli
+ push byte 0
+ push byte 31
+ jmp isr_common_stub
+
+; ================== IRQ ======================
+
+; 32 - Programmable Interrupt Timer
+irq0:
+ cli
+ push byte 0
+ push byte 32
+ jmp irq_common_stub
+
+; 33 - Keyboard
+irq1:
+ cli
+ push byte 0
+ push byte 33
+ jmp irq_common_stub
+
+; 34 Cascade (used internally by the two PICs, never raised)
+irq2:
+ cli
+ push byte 0
+ push byte 34
+ jmp irq_common_stub
+
+; 35 - COM2 (if enabled)
+irq3:
+ cli
+ push byte 0
+ push byte 35
+ jmp irq_common_stub
+
+; 36 - COM1 (if enabled)
+irq4:
+ cli
+ push byte 0
+ push byte 36
+ jmp irq_common_stub
+
+; 37 - LPT2 (if enabled)
+irq5:
+ cli
+ push byte 0
+ push byte 37
+ jmp irq_common_stub
+
+; 38 - Floppy Disk
+irq6:
+ cli
+ push byte 0
+ push byte 38
+ jmp irq_common_stub
+
+; 39 - LPT1
+irq7:
+ cli
+ push byte 0
+ push byte 39
+ jmp irq_common_stub
+
+; 40 - CMOS real-time clock (if enabled)
+irq8:
+ cli
+ push byte 0
+ push byte 40
+ jmp irq_common_stub
+
+; 41 - Peripherals / Legacy SCSI / NIC
+irq9:
+ cli
+ push byte 0
+ push byte 41
+ jmp irq_common_stub
+
+; 42 - Peripherals / SCSI / NIC
+irq10:
+ cli
+ push byte 0
+ push byte 42
+ jmp irq_common_stub
+
+; 43 - Peripherals / SCSI / NIC
+irq11:
+ cli
+ push byte 0
+ push byte 43
+ jmp irq_common_stub
+
+; 44 - PS2 Mouse
+irq12:
+ cli
+ push byte 0
+ push byte 44
+ jmp irq_common_stub
+
+; 45 - FPU / Coprocessor / Inter-processor
+irq13:
+ cli
+ push byte 0
+ push byte 45
+ jmp irq_common_stub
+
+; 46 - Primary ATA Hard Disk
+irq14:
+ cli
+ push byte 0
+ push byte 46
+ jmp irq_common_stub
+
+; 47 - Secondary ATA Hard Disk
+irq15:
+ cli
+ push byte 0
+ push byte 47
+ jmp irq_common_stub
+
+; Save the processor state, call the C fault handler and restore the stack frame.
+isr_common_stub:
+ pusha
+ push ds
+ push es
+ push fs
+ push gs
+ mov ax, 0x10 ; Kernel data segment descriptor.
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov eax, esp ; Push the stack.
+ push eax
+ mov eax, isr_handler
+ call eax
+ pop eax
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ popa
+ add esp, 8 ; Clean up ISR info.
+ sti
+ iret
+
+; Call the C handler and restore the stack frame.
+irq_common_stub:
+ pusha
+ push ds
+ push es
+ push fs
+ push gs
+ mov ax, 0x10
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov eax, esp
+ push eax
+ mov eax, irq_handler
+ call eax
+ pop eax
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ popa
+ add esp, 8
+ sti
+ iret
diff --git a/boot/kbd.c b/boot/kbd.c
@@ -0,0 +1,65 @@
+#include "extern.h"
+#include "idt.h"
+
+static void kbd_callback(struct reg *);
+
+static unsigned char kbdus[128] = {
+ 0, /* Error */
+ 27, /* Escape */
+ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
+ '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p',
+ '[', ']', '\n',
+ 0, /* Control */
+ 'a', 's', 'd', 'f', 'g',
+ 'h', 'j', 'k', 'l', ';', '\'', '`',
+ 0, /* Left Shift */
+ '\\', 'z', 'x',
+ 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
+ 0, /* Right Shift */
+ '*',
+ 0, /* Alt */
+ ' ',
+ 0, /* Caps Lock */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F1-F10 */
+ 0, /* Num Lock */
+ 0, /* Scroll Lock */
+ 0, /* Home Key */
+ 0, /* Up Arrow */
+ 0, /* Page Up */
+ '-',
+ 0, /* Left Arrow */
+ 0,
+ 0, /* Right Arrow */
+ '+',
+ 0, /* End Key */
+ 0, /* Down Arrow */
+ 0, /* Page Down */
+ 0, /* Insert Key */
+ 0, /* Delete Key */
+ 0, 0, 0,
+ 0, 0, /* F11, F12 */
+ 0, /* The rest are undefined */
+};
+
+static void
+kbd_callback(struct reg *r)
+{
+ uint8_t sc;
+
+ /* TODO: backspace */
+ if ((sc = inb(0x60)) & 0x80) {
+ } else {
+ tty_putc(kbdus[sc]);
+ }
+ (void)r;
+}
+
+/*
+ * Send `kbd_callback` to the `irq_routines` array to be called
+ * for IRQ 1.
+ */
+void
+kbd_init(void)
+{
+ irq_add_handler(1, kbd_callback);
+}
diff --git a/boot/kbd.h b/boot/kbd.h
@@ -0,0 +1,3 @@
+#include "extern.h"
+
+extern void kbd_init(void);
diff --git a/boot/kernel.c b/boot/kernel.c
@@ -1,8 +1,17 @@
#include "extern.h"
+#include "idt.h"
+#include "kbd.h"
+#include "timer.h"
void
kernel_main(void)
{
tty_init();
+ idt_init();
+ timer_init(50);
+ kbd_init();
+ /* Enable interrupts so that the IRQs can work now. */
+ __asm__ __volatile__ ("sti");
tty_write("Nothing to see here yet. At least it booted.\n");
+ __asm__ __volatile__ ("hlt");
}
diff --git a/boot/timer.c b/boot/timer.c
@@ -0,0 +1,24 @@
+#include "extern.h"
+#include "idt.h"
+
+static void timer_callback(struct reg *);
+
+static uint32_t timer_ticks = 0;
+
+static void
+timer_callback(struct reg *r)
+{
+ timer_ticks++;
+ (void)r;
+}
+
+void
+timer_init(uint32_t hz)
+{
+ uint32_t div = 1193180 / hz;
+
+ irq_add_handler(0, timer_callback);
+ outb(0x36, 0x43);
+ outb((uint8_t)(div & 0xff), 0x40);
+ outb((uint8_t)((div >> 8) & 0xff), 0x40);
+}
diff --git a/boot/timer.h b/boot/timer.h
@@ -0,0 +1,6 @@
+#ifndef _KERNEL_TIMER_H
+#define _KERNEL_TIMER_H
+
+extern void timer_init(uint32_t);
+
+#endif /* _KERNEL_TIMER_H */
diff --git a/boot/tty.c b/boot/tty.c
@@ -12,7 +12,7 @@ tty_init(void)
tty.row = 0;
tty.col = 0;
- tty.color = _COLOR(VGA_LIGHT_GREY, VGA_BLUE);
+ tty.color = _COLOR(VGA_GREEN, VGA_BLACK);
tty.buf = (uint16_t *)0xb8000;
for (x = 0; x < VGA_COLS; x++)
for (y = 0; y < VGA_ROWS; y++)
@@ -42,12 +42,12 @@ tty_putc(char c)
}
if (tty.row >= VGA_ROWS) {
- tty.row++;
+ tty.row = 0;
tty.col = 0;
}
if (tty.col >= VGA_COLS) {
+ tty.row++;
tty.col = 0;
- tty.row = 0;
}
}