Assignment 3 (only src and notes)
This commit is contained in:
0
notes/work-summary-2026-04-11-to-14.md
Normal file
0
notes/work-summary-2026-04-11-to-14.md
Normal file
@@ -63,6 +63,10 @@ add_executable(uiaos-kernel
|
|||||||
src/kernel.c
|
src/kernel.c
|
||||||
src/gdt.c
|
src/gdt.c
|
||||||
src/terminal.c
|
src/terminal.c
|
||||||
|
src/idt.c
|
||||||
|
src/interrupt.c
|
||||||
|
src/interrupt.asm
|
||||||
|
src/keyboard.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,6 @@ struct GdtDescriptor {
|
|||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
void gdtInitialize(void);
|
void GdtInitialize(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
24
src/OSDev_18/include/kernel/idt.h
Normal file
24
src/OSDev_18/include/kernel/idt.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef KERNEL_IDT_H
|
||||||
|
#define KERNEL_IDT_H
|
||||||
|
|
||||||
|
#include <libc/stdint.h>
|
||||||
|
|
||||||
|
#define IDT_ENTRIES 256
|
||||||
|
|
||||||
|
struct IdtEntry{
|
||||||
|
uint16_t interrupt_low;
|
||||||
|
uint16_t kernel_cs;
|
||||||
|
uint8_t reserved;
|
||||||
|
uint8_t attributes;
|
||||||
|
uint16_t interrupt_high;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct Idtr {
|
||||||
|
uint16_t limit;
|
||||||
|
uint32_t base;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
void IdtInitialize(void);
|
||||||
|
void IdtSetDescriptor(uint8_t vector, uint32_t interrupt, uint8_t flags);
|
||||||
|
|
||||||
|
#endif
|
||||||
54
src/OSDev_18/include/kernel/interrupt.h
Normal file
54
src/OSDev_18/include/kernel/interrupt.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#ifndef KERNEL_INTERRUPT_H
|
||||||
|
#define KERNEL_INTERRUPT_H
|
||||||
|
|
||||||
|
#include <libc/stdint.h>
|
||||||
|
|
||||||
|
#define IRQ0 32
|
||||||
|
#define IRQ1 33
|
||||||
|
#define IRQ2 34
|
||||||
|
#define IRQ3 35
|
||||||
|
#define IRQ4 36
|
||||||
|
#define IRQ5 37
|
||||||
|
#define IRQ6 38
|
||||||
|
#define IRQ7 39
|
||||||
|
#define IRQ8 40
|
||||||
|
#define IRQ9 41
|
||||||
|
#define IRQ10 42
|
||||||
|
#define IRQ11 43
|
||||||
|
#define IRQ12 44
|
||||||
|
#define IRQ13 45
|
||||||
|
#define IRQ14 46
|
||||||
|
#define IRQ15 47
|
||||||
|
|
||||||
|
struct Registers {
|
||||||
|
uint32_t ds;
|
||||||
|
|
||||||
|
uint32_t edi;
|
||||||
|
uint32_t esi;
|
||||||
|
uint32_t ebp;
|
||||||
|
uint32_t esp;
|
||||||
|
uint32_t ebx;
|
||||||
|
uint32_t edx;
|
||||||
|
uint32_t ecx;
|
||||||
|
uint32_t eax;
|
||||||
|
|
||||||
|
uint32_t int_no;
|
||||||
|
uint32_t err_code;
|
||||||
|
|
||||||
|
uint32_t eip;
|
||||||
|
uint32_t cs;
|
||||||
|
uint32_t eflags;
|
||||||
|
uint32_t useresp;
|
||||||
|
uint32_t ss;
|
||||||
|
};
|
||||||
|
|
||||||
|
void PicSendEoi(uint8_t irqNum);
|
||||||
|
void PicRemap(void);
|
||||||
|
|
||||||
|
void IsrHandler(struct Registers* registers);
|
||||||
|
void IrqHandler(struct Registers* registers);
|
||||||
|
|
||||||
|
typedef void (*InterruptHandler)(struct Registers* registers);
|
||||||
|
void RegisterInterruptHandler(uint8_t iNum, InterruptHandler handler);
|
||||||
|
|
||||||
|
#endif
|
||||||
20
src/OSDev_18/include/kernel/io.h
Normal file
20
src/OSDev_18/include/kernel/io.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef KERNEL_IO_H
|
||||||
|
#define KERNEL_IO_H
|
||||||
|
|
||||||
|
#include <libc/stdint.h>
|
||||||
|
|
||||||
|
static inline void OutPortByte(uint16_t port, uint8_t val) {
|
||||||
|
__asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t InPortByte(uint16_t port) {
|
||||||
|
uint8_t ret;
|
||||||
|
__asm__ volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void IoWait(void) {
|
||||||
|
__asm__ volatile ("outb %%al, $0x80" : : "a"(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
11
src/OSDev_18/include/kernel/keyboard.h
Normal file
11
src/OSDev_18/include/kernel/keyboard.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef KERNEL_KEYBOARD_H
|
||||||
|
#define KERNEL_KEYBOARD_H
|
||||||
|
|
||||||
|
#include <kernel/interrupt.h>
|
||||||
|
|
||||||
|
#define KEYBOARD_DATA_PORT 0x60
|
||||||
|
#define KEYBOARD_BUFFER_SIZE 256
|
||||||
|
|
||||||
|
void KeyboardHandler(struct Registers* registers);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -23,14 +23,16 @@ enum vga_colour{
|
|||||||
VGA_COLOR_WHITE = 15,
|
VGA_COLOR_WHITE = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t vgaEntryColour(enum vga_colour fg, enum vga_colour bg);
|
uint8_t VgaEntryColour(enum vga_colour fg, enum vga_colour bg);
|
||||||
uint16_t vgaEntry(unsigned char uc, uint8_t color);
|
uint16_t VgaEntry(unsigned char uc, uint8_t color);
|
||||||
|
|
||||||
void terminalEntryAt(char c, uint8_t colour, size_t x, size_t y);
|
void TerminalEntryAt(char c, uint8_t colour, size_t x, size_t y);
|
||||||
void terminalInitialize(void);
|
void TerminalInitialize(void);
|
||||||
void terminalSetColour(uint8_t colour);
|
void TerminalSetColour(uint8_t colour);
|
||||||
void terminalPutChar(char c);
|
void TerminalUpdateCursor(void);
|
||||||
void terminalWrite(const char* data, size_t size);
|
void TerminalPutChar(char c);
|
||||||
void terminalWriteString(const char* data);
|
void TerminalWrite(const char* data, size_t size);
|
||||||
|
void TerminalWriteString(const char* data);
|
||||||
|
void TerminalWriteUInt(uint32_t num);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
%define GDT_CODE_SELECTOR 0x08
|
%define GDT_CODE_SELECTOR 0x08
|
||||||
%define GDT_DATA_SELECTOR 0x10
|
%define GDT_DATA_SELECTOR 0x10
|
||||||
|
|
||||||
global gdtFlush
|
global GdtFlush
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
bits 32
|
bits 32
|
||||||
|
|
||||||
gdtFlush:
|
GdtFlush:
|
||||||
mov eax, [esp + 4]
|
mov eax, [esp + 4]
|
||||||
lgdt [eax]
|
lgdt [eax]
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
static struct GdtEntry gdtEntries[3];
|
static struct GdtEntry gdtEntries[3];
|
||||||
static struct GdtDescriptor gdtDescriptor;
|
static struct GdtDescriptor gdtDescriptor;
|
||||||
|
|
||||||
extern void gdtFlush(uint32_t gdtDescriptorAddress);
|
extern void GdtFlush(uint32_t gdtDescriptorAddress);
|
||||||
|
|
||||||
static void gdtSetEntry(
|
static void GdtSetEntry(
|
||||||
uint32_t index,
|
uint32_t index,
|
||||||
uint32_t base,
|
uint32_t base,
|
||||||
uint32_t limit,
|
uint32_t limit,
|
||||||
@@ -22,17 +22,17 @@ static void gdtSetEntry(
|
|||||||
gdtEntries[index].access = access;
|
gdtEntries[index].access = access;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gdtInitialize(void) {
|
void GdtInitialize(void) {
|
||||||
gdtDescriptor.size = sizeof(gdtEntries) - 1;
|
gdtDescriptor.size = sizeof(gdtEntries) - 1;
|
||||||
gdtDescriptor.offset = (uint32_t)&gdtEntries;
|
gdtDescriptor.offset = (uint32_t)&gdtEntries;
|
||||||
|
|
||||||
gdtSetEntry(0, 0, 0, 0, 0);
|
GdtSetEntry(0, 0, 0, 0, 0);
|
||||||
|
|
||||||
// Kernel code segment: base 0, 4 GiB span, ring 0, executable, readable
|
// Kernel code segment: base 0, 4 GiB span, ring 0, executable, readable
|
||||||
gdtSetEntry(1, 0, 0x000FFFFF, 0x9A, 0xCF);
|
GdtSetEntry(1, 0, 0x000FFFFF, 0x9A, 0xCF);
|
||||||
|
|
||||||
// Kernel data segment: base 0, 4 GiB span, ring 0, writable
|
// Kernel data segment: base 0, 4 GiB span, ring 0, writable
|
||||||
gdtSetEntry(2, 0, 0x000FFFFF, 0x92, 0xCF);
|
GdtSetEntry(2, 0, 0x000FFFFF, 0x92, 0xCF);
|
||||||
|
|
||||||
gdtFlush((uint32_t)&gdtDescriptor);
|
GdtFlush((uint32_t)&gdtDescriptor);
|
||||||
}
|
}
|
||||||
39
src/OSDev_18/src/idt.c
Normal file
39
src/OSDev_18/src/idt.c
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#include <kernel/idt.h>
|
||||||
|
#include <kernel/gdt.h>
|
||||||
|
#include <kernel/interrupt.h>
|
||||||
|
#include <libc/stdbool.h>
|
||||||
|
|
||||||
|
static struct IdtEntry idt[IDT_ENTRIES];
|
||||||
|
static struct Idtr idtr;
|
||||||
|
|
||||||
|
void IdtSetDescriptor(uint8_t vector, uint32_t interrupt, uint8_t flags) {
|
||||||
|
struct IdtEntry* descriptor = &idt[vector];
|
||||||
|
|
||||||
|
descriptor->interrupt_low = (uint32_t)interrupt & 0xFFFF;
|
||||||
|
descriptor->kernel_cs = GDT_CODE_SELECTOR;
|
||||||
|
descriptor->attributes = flags;
|
||||||
|
descriptor->interrupt_high = (uint32_t)interrupt >> 16;
|
||||||
|
descriptor->reserved = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void* isr_stub_table[];
|
||||||
|
extern void* irq_stub_table[];
|
||||||
|
|
||||||
|
void IdtInitialize(void) {
|
||||||
|
idtr.base = (uint32_t)&idt[0];
|
||||||
|
idtr.limit = (uint16_t)sizeof(struct IdtEntry) * IDT_ENTRIES - 1;
|
||||||
|
|
||||||
|
for (uint8_t iNum = 0; iNum < 32; iNum++) {
|
||||||
|
IdtSetDescriptor(iNum, (uint32_t)isr_stub_table[iNum], 0x8E);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t iNum = 32; iNum < 48; iNum++) {
|
||||||
|
IdtSetDescriptor(iNum, (uint32_t)irq_stub_table[iNum - 32], 0x8E);
|
||||||
|
}
|
||||||
|
|
||||||
|
PicRemap();
|
||||||
|
|
||||||
|
__asm__ volatile ("lidt %0" : : "m"(idtr));
|
||||||
|
__asm__ volatile ("sti");
|
||||||
|
}
|
||||||
|
|
||||||
130
src/OSDev_18/src/interrupt.asm
Normal file
130
src/OSDev_18/src/interrupt.asm
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
extern IsrHandler
|
||||||
|
extern IrqHandler
|
||||||
|
|
||||||
|
isr_common_stub:
|
||||||
|
pusha
|
||||||
|
mov ax, ds
|
||||||
|
push eax
|
||||||
|
mov ax, 0x10
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
push esp
|
||||||
|
call IsrHandler
|
||||||
|
add esp, 4
|
||||||
|
pop eax
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
popa
|
||||||
|
add esp, 8
|
||||||
|
iret
|
||||||
|
|
||||||
|
irq_common_stub:
|
||||||
|
pusha
|
||||||
|
mov ax, ds
|
||||||
|
push eax
|
||||||
|
mov ax, 0x10
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
push esp
|
||||||
|
call IrqHandler
|
||||||
|
add esp, 4
|
||||||
|
pop eax
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
popa
|
||||||
|
add esp, 8
|
||||||
|
iret
|
||||||
|
|
||||||
|
%macro isr_no_err_stub 1
|
||||||
|
isr_stub_%+%1:
|
||||||
|
push dword 0
|
||||||
|
push dword %1
|
||||||
|
jmp isr_common_stub
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro isr_err_stub 1
|
||||||
|
isr_stub_%+%1:
|
||||||
|
push dword %1
|
||||||
|
jmp isr_common_stub
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro irq_stub 1
|
||||||
|
irq_stub_%+%1:
|
||||||
|
push dword 0
|
||||||
|
push dword (32 + %1)
|
||||||
|
jmp irq_common_stub
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
irq_stub 0
|
||||||
|
irq_stub 1
|
||||||
|
irq_stub 2
|
||||||
|
irq_stub 3
|
||||||
|
irq_stub 4
|
||||||
|
irq_stub 5
|
||||||
|
irq_stub 6
|
||||||
|
irq_stub 7
|
||||||
|
irq_stub 8
|
||||||
|
irq_stub 9
|
||||||
|
irq_stub 10
|
||||||
|
irq_stub 11
|
||||||
|
irq_stub 12
|
||||||
|
irq_stub 13
|
||||||
|
irq_stub 14
|
||||||
|
irq_stub 15
|
||||||
|
|
||||||
|
global isr_stub_table
|
||||||
|
isr_stub_table:
|
||||||
|
%assign i 0
|
||||||
|
%rep 32
|
||||||
|
dd isr_stub_%+i
|
||||||
|
%assign i i+1
|
||||||
|
%endrep
|
||||||
|
|
||||||
|
global irq_stub_table
|
||||||
|
irq_stub_table:
|
||||||
|
%assign i 0
|
||||||
|
%rep 16
|
||||||
|
dd irq_stub_%+i
|
||||||
|
%assign i i+1
|
||||||
|
%endrep
|
||||||
114
src/OSDev_18/src/interrupt.c
Normal file
114
src/OSDev_18/src/interrupt.c
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
#include <kernel/interrupt.h>
|
||||||
|
#include <kernel/terminal.h>
|
||||||
|
#include <kernel/io.h>
|
||||||
|
|
||||||
|
#define PIC1_COMMAND 0x20
|
||||||
|
#define PIC1_DATA 0x21
|
||||||
|
#define PIC2_COMMAND 0xA0
|
||||||
|
#define PIC2_DATA 0xA1
|
||||||
|
#define PIC_EOI 0x20
|
||||||
|
|
||||||
|
static InterruptHandler interruptHandlers[256];
|
||||||
|
|
||||||
|
const char* isrMessages[] = {
|
||||||
|
"Division By Zero",
|
||||||
|
"Debug",
|
||||||
|
"Non Maskable 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 Floating-Point Exception",
|
||||||
|
"Alignment Check",
|
||||||
|
"Machine Check",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved"
|
||||||
|
};
|
||||||
|
|
||||||
|
void PicSendEoi(uint8_t irqNum) {
|
||||||
|
if (irqNum >= 8) {
|
||||||
|
OutPortByte(PIC2_COMMAND, PIC_EOI);
|
||||||
|
}
|
||||||
|
OutPortByte(PIC1_COMMAND, PIC_EOI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PicRemap(void) {
|
||||||
|
OutPortByte(PIC1_COMMAND, 0x11);
|
||||||
|
OutPortByte(PIC2_COMMAND, 0x11);
|
||||||
|
|
||||||
|
OutPortByte(PIC1_DATA, 0x20);
|
||||||
|
OutPortByte(PIC2_DATA, 0x28);
|
||||||
|
|
||||||
|
OutPortByte(PIC1_DATA, 0x04);
|
||||||
|
OutPortByte(PIC2_DATA, 0x02);
|
||||||
|
|
||||||
|
OutPortByte(PIC1_DATA, 0x01);
|
||||||
|
OutPortByte(PIC2_DATA, 0x01);
|
||||||
|
|
||||||
|
OutPortByte(PIC1_DATA, 0x00);
|
||||||
|
OutPortByte(PIC2_DATA, 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IsrHandler(struct Registers* registers) {
|
||||||
|
TerminalWriteString("\n=== INTERRUPT RECEIVED ===\n");
|
||||||
|
|
||||||
|
TerminalWriteString("Interrupt Number: ");
|
||||||
|
TerminalWriteUInt(registers->int_no);
|
||||||
|
TerminalWriteString("\n");
|
||||||
|
|
||||||
|
TerminalWriteString("Message: ");
|
||||||
|
if (registers->int_no < 32) {
|
||||||
|
TerminalWriteString(isrMessages[registers->int_no]);
|
||||||
|
} else {
|
||||||
|
TerminalWriteString("Unknown Interrupt");
|
||||||
|
}
|
||||||
|
TerminalWriteString("\n");
|
||||||
|
|
||||||
|
TerminalWriteString("Error Code: ");
|
||||||
|
TerminalWriteUInt(registers->err_code);
|
||||||
|
TerminalWriteString("\n");
|
||||||
|
|
||||||
|
TerminalWriteString("==========================\n");
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
__asm__ volatile("cli; hlt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterInterruptHandler(uint8_t iNum, InterruptHandler handler) {
|
||||||
|
interruptHandlers[iNum] = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IrqHandler(struct Registers* registers) {
|
||||||
|
uint8_t irqNum = (uint8_t)(registers->int_no - 32);
|
||||||
|
|
||||||
|
if (interruptHandlers[registers->int_no] != 0) {
|
||||||
|
interruptHandlers[registers->int_no](registers);
|
||||||
|
} else if (irqNum != 0) {
|
||||||
|
TerminalWriteString("IRQ triggered: ");
|
||||||
|
TerminalWriteUInt(irqNum);
|
||||||
|
TerminalWriteString("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
PicSendEoi(irqNum);
|
||||||
|
}
|
||||||
@@ -1,12 +1,16 @@
|
|||||||
#include <libc/stdint.h>
|
#include <libc/stdint.h>
|
||||||
#include <kernel/terminal.h>
|
#include <kernel/terminal.h>
|
||||||
#include <kernel/gdt.h>
|
#include <kernel/gdt.h>
|
||||||
|
#include <kernel/idt.h>
|
||||||
|
#include <kernel/interrupt.h>
|
||||||
|
#include <kernel/keyboard.h>
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
gdtInitialize();
|
TerminalInitialize();
|
||||||
|
GdtInitialize();
|
||||||
|
IdtInitialize();
|
||||||
|
|
||||||
terminalInitialize();
|
RegisterInterruptHandler(IRQ1, KeyboardHandler);
|
||||||
terminalWriteString("Hello, World!\n");
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
__asm__ volatile("hlt");
|
__asm__ volatile("hlt");
|
||||||
|
|||||||
43
src/OSDev_18/src/keyboard.c
Normal file
43
src/OSDev_18/src/keyboard.c
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#include <kernel/keyboard.h>
|
||||||
|
#include <kernel/interrupt.h>
|
||||||
|
#include <kernel/io.h>
|
||||||
|
#include <kernel/terminal.h>
|
||||||
|
#include <libc/stdint.h>
|
||||||
|
|
||||||
|
static uint32_t index = 0;
|
||||||
|
static uint8_t keyboardBuffer[KEYBOARD_BUFFER_SIZE];
|
||||||
|
|
||||||
|
static const char scancodeToAscii[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,
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
void KeyboardHandler(struct Registers* registers) {
|
||||||
|
(void) registers;
|
||||||
|
|
||||||
|
uint8_t scancode = InPortByte(KEYBOARD_DATA_PORT);
|
||||||
|
|
||||||
|
if (index < KEYBOARD_BUFFER_SIZE) {
|
||||||
|
keyboardBuffer[index] = scancode;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scancode & 0x80) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scancode < 128) {
|
||||||
|
char ascii = scancodeToAscii[scancode];
|
||||||
|
|
||||||
|
if (ascii != 0) {
|
||||||
|
TerminalPutChar(ascii);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <kernel/gdt.h>
|
#include <kernel/gdt.h>
|
||||||
#include <kernel/terminal.h>
|
#include <kernel/terminal.h>
|
||||||
|
#include <kernel/io.h>
|
||||||
|
|
||||||
const size_t VGA_HEIGHT = 25;
|
const size_t VGA_HEIGHT = 25;
|
||||||
const size_t VGA_WIDTH = 80;
|
const size_t VGA_WIDTH = 80;
|
||||||
@@ -11,44 +12,55 @@ static uint8_t terminal_colour;
|
|||||||
static uint16_t* terminal_buffer = (uint16_t*) 0xB8000;
|
static uint16_t* terminal_buffer = (uint16_t*) 0xB8000;
|
||||||
|
|
||||||
// Builds the colour byte
|
// Builds the colour byte
|
||||||
uint8_t vgaEntryColour(enum vga_colour fg, enum vga_colour bg) {
|
uint8_t VgaEntryColour(enum vga_colour fg, enum vga_colour bg) {
|
||||||
return fg | bg << 4;
|
return fg | bg << 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builds the full cell
|
// Builds the full cell
|
||||||
uint16_t vgaEntry(unsigned char uc, uint8_t color) {
|
uint16_t VgaEntry(unsigned char uc, uint8_t color) {
|
||||||
return (uint16_t) uc | (uint16_t) color << 8;
|
return (uint16_t) uc | (uint16_t) color << 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminalEntryAt(char c, uint8_t colour, size_t x, size_t y){
|
void TerminalEntryAt(char c, uint8_t colour, size_t x, size_t y){
|
||||||
size_t index = y * VGA_WIDTH + x;
|
size_t index = y * VGA_WIDTH + x;
|
||||||
terminal_buffer[index] = vgaEntry(c, colour);
|
terminal_buffer[index] = VgaEntry(c, colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminalInitialize(void) {
|
void TerminalInitialize(void) {
|
||||||
terminal_row = 0;
|
terminal_row = 0;
|
||||||
terminal_column = 0;
|
terminal_column = 0;
|
||||||
terminal_colour = vgaEntryColour(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
|
terminal_colour = VgaEntryColour(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
|
||||||
terminal_buffer = (uint16_t*) 0xB8000;
|
terminal_buffer = (uint16_t*) 0xB8000;
|
||||||
|
|
||||||
for (size_t y = 0; y < VGA_HEIGHT; y++) {
|
for (size_t y = 0; y < VGA_HEIGHT; y++) {
|
||||||
for (size_t x = 0; x < VGA_WIDTH; x++) {
|
for (size_t x = 0; x < VGA_WIDTH; x++) {
|
||||||
terminalEntryAt(' ', terminal_colour, x, y);
|
TerminalEntryAt(' ', terminal_colour, x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminalSetColour(uint8_t colour) {
|
void TerminalSetColour(uint8_t colour) {
|
||||||
terminal_colour = colour;
|
terminal_colour = colour;
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminalPutChar(char c) {
|
void TerminalUpdateCursor(void) {
|
||||||
|
uint16_t pos = (uint16_t)(terminal_row * VGA_WIDTH + terminal_column);
|
||||||
|
|
||||||
|
OutPortByte(0x3D4, 0x0F);
|
||||||
|
OutPortByte(0x3D5, (uint8_t)(pos & 0xFF));
|
||||||
|
|
||||||
|
OutPortByte(0x3D4, 0x0E);
|
||||||
|
OutPortByte(0x3D5, (uint8_t)((pos >> 8) & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerminalPutChar(char c) {
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
terminal_column = 0;
|
terminal_column = 0;
|
||||||
terminal_row++;
|
terminal_row++;
|
||||||
|
TerminalUpdateCursor();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
terminalEntryAt(c, terminal_colour,terminal_column, terminal_row);
|
TerminalEntryAt(c, terminal_colour,terminal_column, terminal_row);
|
||||||
terminal_column++;
|
terminal_column++;
|
||||||
|
|
||||||
if (terminal_column == VGA_WIDTH) {
|
if (terminal_column == VGA_WIDTH) {
|
||||||
@@ -59,21 +71,48 @@ void terminalPutChar(char c) {
|
|||||||
if (terminal_row == VGA_HEIGHT) {
|
if (terminal_row == VGA_HEIGHT) {
|
||||||
terminal_row = 0;
|
terminal_row = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TerminalUpdateCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminalWrite(const char* data, size_t size) {
|
void TerminalWrite(const char* data, size_t size) {
|
||||||
for (size_t i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
terminalPutChar(data[i]);
|
TerminalPutChar(data[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminalWriteString(const char* data) {
|
void TerminalWriteString(const char* data) {
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
while (data[len] != '\0') {
|
while (data[len] != '\0') {
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
terminalWrite(data, len);
|
TerminalWrite(data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerminalWriteUInt(uint32_t num) {
|
||||||
|
if (num == 0) {
|
||||||
|
TerminalPutChar('0');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[10];
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
while (num > 0) {
|
||||||
|
buffer[i++] = '0' + (num % 10);
|
||||||
|
num /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t j = 0; j < i / 2; j++) {
|
||||||
|
char temp = buffer[j];
|
||||||
|
buffer[j] = buffer[i - j - 1];
|
||||||
|
buffer[i - j - 1] = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t j = 0; j < i; j++) {
|
||||||
|
TerminalPutChar(buffer[j]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user