...
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
#include "interrupts.h"
|
||||
#include "vga.h"
|
||||
#include "kernel.h"
|
||||
#include "util.h"
|
||||
|
||||
#define PIC1_COMMAND 0x20
|
||||
@@ -8,24 +6,6 @@
|
||||
#define PIC2_COMMAND 0xA0
|
||||
#define PIC2_DATA 0xA1
|
||||
|
||||
void pic_remap()
|
||||
{
|
||||
outb(PIC1_COMMAND, 0x11);
|
||||
outb(PIC2_COMMAND, 0x11);
|
||||
|
||||
outb(PIC1_DATA, 32);
|
||||
outb(PIC2_DATA, 40);
|
||||
|
||||
outb(PIC1_DATA, 4);
|
||||
outb(PIC2_DATA, 2);
|
||||
|
||||
outb(PIC1_DATA, 1);
|
||||
outb(PIC2_DATA, 1);
|
||||
|
||||
outb(PIC1_DATA, 0);
|
||||
outb(PIC2_DATA, 0);
|
||||
}
|
||||
|
||||
static const char* exception_messages[32] = {
|
||||
"divide by zero",
|
||||
"debug",
|
||||
@@ -61,14 +41,52 @@ static const char* exception_messages[32] = {
|
||||
"reserved",
|
||||
};
|
||||
|
||||
static irq_handler_t irq_handlers[16] = {0};
|
||||
|
||||
bool cpu_has_apic() {
|
||||
uint32_t eax, edx;
|
||||
cpuid(1, &eax, &edx);
|
||||
return (edx & CPUID_FEAT_EDX_APIC) != 0;
|
||||
}
|
||||
|
||||
void enable_apic() {
|
||||
uint64_t apic_base = rdmsr(0x1B);
|
||||
apic_base |= (1 << 11);
|
||||
wrmsr(0x1B, apic_base);
|
||||
kprintf("APIC enabled\n");
|
||||
}
|
||||
|
||||
void remap_pic()
|
||||
{
|
||||
outb(PIC1_COMMAND, 0x11);
|
||||
outb(PIC2_COMMAND, 0x11);
|
||||
|
||||
outb(PIC1_DATA, 32);
|
||||
outb(PIC2_DATA, 40);
|
||||
|
||||
outb(PIC1_DATA, 4);
|
||||
outb(PIC2_DATA, 2);
|
||||
|
||||
outb(PIC1_DATA, 1);
|
||||
outb(PIC2_DATA, 1);
|
||||
|
||||
outb(PIC1_DATA, 0);
|
||||
outb(PIC2_DATA, 0);
|
||||
kprintf("PIC remapped\n");
|
||||
}
|
||||
|
||||
void disable_pic() {
|
||||
outb(PIC1_DATA, 0xFF);
|
||||
outb(PIC2_DATA, 0xFF);
|
||||
kprintf("PIC disabled\n");
|
||||
}
|
||||
|
||||
void handle_exception(const isr_frame_t* frame)
|
||||
{
|
||||
kprintf("exception[%d]: %s, error code: %d\n", frame->int_no, exception_messages[frame->int_no], frame->err_code);
|
||||
kpanic();
|
||||
}
|
||||
|
||||
static irq_handler_t irq_handlers[16] = {0};
|
||||
|
||||
void register_irq_handler(uint8_t irq, irq_handler_t handler)
|
||||
{
|
||||
if (irq >= 16)
|
||||
@@ -78,6 +96,7 @@ void register_irq_handler(uint8_t irq, irq_handler_t handler)
|
||||
else
|
||||
{
|
||||
irq_handlers[irq] = handler;
|
||||
kprintf("Registered irq handler at vector %d\n", irq);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "kernel.h"
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct
|
||||
@@ -13,16 +14,22 @@ typedef struct
|
||||
|
||||
typedef void (*irq_handler_t)(const isr_frame_t*);
|
||||
|
||||
void pic_remap();
|
||||
void remap_pic();
|
||||
void disable_pic();
|
||||
|
||||
bool cpu_has_apic();
|
||||
void enable_apic();
|
||||
|
||||
void register_irq_handler(uint8_t irq, irq_handler_t handler);
|
||||
|
||||
static inline void enable_interrupts()
|
||||
{
|
||||
__asm__ volatile("sti");
|
||||
kprintf("Interrupts enabled\n");
|
||||
}
|
||||
|
||||
static inline void disable_interrupts()
|
||||
{
|
||||
__asm__ volatile("cli");
|
||||
kprintf("Interrupts disabled\n");
|
||||
}
|
||||
14
src/kernel.c
14
src/kernel.c
@@ -4,7 +4,7 @@
|
||||
#include "string.h"
|
||||
#include "vga.h"
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include "multiboot.h"
|
||||
|
||||
void handle_keypress(const keyboard_event_t* event)
|
||||
{
|
||||
@@ -14,12 +14,18 @@ void handle_keypress(const keyboard_event_t* event)
|
||||
}
|
||||
}
|
||||
|
||||
void kmain()
|
||||
void kmain(multiboot_info_t* multiboot_info)
|
||||
{
|
||||
vga_clear();
|
||||
pic_remap();
|
||||
remap_pic();
|
||||
|
||||
if (cpu_has_apic())
|
||||
{
|
||||
disable_pic();
|
||||
enable_apic();
|
||||
}
|
||||
|
||||
enable_interrupts();
|
||||
init_keyboard();
|
||||
register_keypress_handler(handle_keypress);
|
||||
|
||||
kprintf("Welcome to nub OS\n");
|
||||
|
||||
@@ -2,6 +2,18 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MULTIBOOT_FLAG_MEMIFO 0b0000000000001
|
||||
#define MULTIBOOT_FLAG_BOOT_DEVICE 0b0000000000010
|
||||
#define MULTIBOOT_FLAG_CMDLINE 0b0000000000100
|
||||
#define MULTIBOOT_FLAG_MODINFO 0b0000000001000
|
||||
#define MULTIBOOT_FLAG_MMAP 0b0000001000000
|
||||
#define MULTIBOOT_FLAG_DRIVES 0b0000010000000
|
||||
#define MULTIBOOT_FLAG_CONFIG_TABLE 0b0000100000000
|
||||
#define MULTIBOOT_FLAG_BOOTLOADER_NAME 0b0001000000000
|
||||
#define MULTIBOOT_FLAG_APM_TABLE 0b0010000000000
|
||||
#define MULTIBOOT_FLAG_VBEINFO 0b0100000000000
|
||||
#define MULTIBOOT_FLAG_FRAMEBUFFER_INFO 0b1000000000000
|
||||
|
||||
typedef struct multiboot_info
|
||||
{
|
||||
uint32_t flags; // required
|
||||
|
||||
@@ -14,7 +14,7 @@ section .multiboot
|
||||
|
||||
section .bss
|
||||
align 16
|
||||
resb 16384
|
||||
resb 32768
|
||||
stack_top:
|
||||
|
||||
section .bss
|
||||
@@ -37,6 +37,11 @@ section .data
|
||||
dq gdt64
|
||||
.end:
|
||||
|
||||
section .data
|
||||
align 8
|
||||
multiboot_info:
|
||||
dq 0
|
||||
|
||||
section .text
|
||||
bits 32
|
||||
_start:
|
||||
@@ -48,6 +53,9 @@ section .text
|
||||
cmp eax, 0x2BADB002
|
||||
jne error
|
||||
|
||||
; Save multiboot info pointer for later
|
||||
mov [multiboot_info], ebx
|
||||
|
||||
; Check if cpuid is available by flipping bit 21
|
||||
; in the eflags register and checking if the cpu flipped it back
|
||||
pushfd
|
||||
@@ -93,10 +101,10 @@ section .text
|
||||
mov eax, pd
|
||||
or eax, 0x03
|
||||
mov [pdpt], eax
|
||||
; Fill pd with 2MB entries
|
||||
; Map first 32 2mb pages for the kernel for a total of 64mb
|
||||
mov edi, pd
|
||||
mov eax, 0x83
|
||||
mov ecx, 512
|
||||
mov ecx, 32
|
||||
.setup_pd:
|
||||
mov [edi], eax
|
||||
add eax, 0x200000
|
||||
@@ -195,6 +203,7 @@ section .text
|
||||
lidt [idt64_descriptor]
|
||||
|
||||
; Finally, we call in to c
|
||||
mov rdi, [multiboot_info]
|
||||
call kmain
|
||||
.hang:
|
||||
hlt
|
||||
|
||||
81
src/util.h
81
src/util.h
@@ -2,6 +2,71 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum {
|
||||
CPUID_FEAT_ECX_SSE3 = 1 << 0,
|
||||
CPUID_FEAT_ECX_PCLMUL = 1 << 1,
|
||||
CPUID_FEAT_ECX_DTES64 = 1 << 2,
|
||||
CPUID_FEAT_ECX_MONITOR = 1 << 3,
|
||||
CPUID_FEAT_ECX_DS_CPL = 1 << 4,
|
||||
CPUID_FEAT_ECX_VMX = 1 << 5,
|
||||
CPUID_FEAT_ECX_SMX = 1 << 6,
|
||||
CPUID_FEAT_ECX_EST = 1 << 7,
|
||||
CPUID_FEAT_ECX_TM2 = 1 << 8,
|
||||
CPUID_FEAT_ECX_SSSE3 = 1 << 9,
|
||||
CPUID_FEAT_ECX_CID = 1 << 10,
|
||||
CPUID_FEAT_ECX_SDBG = 1 << 11,
|
||||
CPUID_FEAT_ECX_FMA = 1 << 12,
|
||||
CPUID_FEAT_ECX_CX16 = 1 << 13,
|
||||
CPUID_FEAT_ECX_XTPR = 1 << 14,
|
||||
CPUID_FEAT_ECX_PDCM = 1 << 15,
|
||||
CPUID_FEAT_ECX_PCID = 1 << 17,
|
||||
CPUID_FEAT_ECX_DCA = 1 << 18,
|
||||
CPUID_FEAT_ECX_SSE4_1 = 1 << 19,
|
||||
CPUID_FEAT_ECX_SSE4_2 = 1 << 20,
|
||||
CPUID_FEAT_ECX_X2APIC = 1 << 21,
|
||||
CPUID_FEAT_ECX_MOVBE = 1 << 22,
|
||||
CPUID_FEAT_ECX_POPCNT = 1 << 23,
|
||||
CPUID_FEAT_ECX_TSC = 1 << 24,
|
||||
CPUID_FEAT_ECX_AES = 1 << 25,
|
||||
CPUID_FEAT_ECX_XSAVE = 1 << 26,
|
||||
CPUID_FEAT_ECX_OSXSAVE = 1 << 27,
|
||||
CPUID_FEAT_ECX_AVX = 1 << 28,
|
||||
CPUID_FEAT_ECX_F16C = 1 << 29,
|
||||
CPUID_FEAT_ECX_RDRAND = 1 << 30,
|
||||
CPUID_FEAT_ECX_HYPERVISOR = 1 << 31,
|
||||
|
||||
CPUID_FEAT_EDX_FPU = 1 << 0,
|
||||
CPUID_FEAT_EDX_VME = 1 << 1,
|
||||
CPUID_FEAT_EDX_DE = 1 << 2,
|
||||
CPUID_FEAT_EDX_PSE = 1 << 3,
|
||||
CPUID_FEAT_EDX_TSC = 1 << 4,
|
||||
CPUID_FEAT_EDX_MSR = 1 << 5,
|
||||
CPUID_FEAT_EDX_PAE = 1 << 6,
|
||||
CPUID_FEAT_EDX_MCE = 1 << 7,
|
||||
CPUID_FEAT_EDX_CX8 = 1 << 8,
|
||||
CPUID_FEAT_EDX_APIC = 1 << 9,
|
||||
CPUID_FEAT_EDX_SEP = 1 << 11,
|
||||
CPUID_FEAT_EDX_MTRR = 1 << 12,
|
||||
CPUID_FEAT_EDX_PGE = 1 << 13,
|
||||
CPUID_FEAT_EDX_MCA = 1 << 14,
|
||||
CPUID_FEAT_EDX_CMOV = 1 << 15,
|
||||
CPUID_FEAT_EDX_PAT = 1 << 16,
|
||||
CPUID_FEAT_EDX_PSE36 = 1 << 17,
|
||||
CPUID_FEAT_EDX_PSN = 1 << 18,
|
||||
CPUID_FEAT_EDX_CLFLUSH = 1 << 19,
|
||||
CPUID_FEAT_EDX_DS = 1 << 21,
|
||||
CPUID_FEAT_EDX_ACPI = 1 << 22,
|
||||
CPUID_FEAT_EDX_MMX = 1 << 23,
|
||||
CPUID_FEAT_EDX_FXSR = 1 << 24,
|
||||
CPUID_FEAT_EDX_SSE = 1 << 25,
|
||||
CPUID_FEAT_EDX_SSE2 = 1 << 26,
|
||||
CPUID_FEAT_EDX_SS = 1 << 27,
|
||||
CPUID_FEAT_EDX_HTT = 1 << 28,
|
||||
CPUID_FEAT_EDX_TM = 1 << 29,
|
||||
CPUID_FEAT_EDX_IA64 = 1 << 30,
|
||||
CPUID_FEAT_EDX_PBE = 1 << 31
|
||||
};
|
||||
|
||||
static inline void outb(uint16_t port, uint8_t val)
|
||||
{
|
||||
__asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port));
|
||||
@@ -17,4 +82,20 @@ static inline uint8_t inb(uint16_t port)
|
||||
static inline void io_wait()
|
||||
{
|
||||
outb(0x80, 0);
|
||||
}
|
||||
|
||||
static inline void cpuid(uint32_t code, uint32_t* a, uint32_t* d) {
|
||||
__asm__ volatile("cpuid" : "=a"(*a), "=d"(*d) : "a"(code) : "ecx", "ebx");
|
||||
}
|
||||
|
||||
static inline uint64_t rdmsr(uint32_t msr) {
|
||||
uint32_t lo, hi;
|
||||
__asm__ volatile("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr));
|
||||
return ((uint64_t)hi << 32) | lo;
|
||||
}
|
||||
|
||||
static inline void wrmsr(uint32_t msr, uint64_t value) {
|
||||
uint32_t lo = (uint32_t)value;
|
||||
uint32_t hi = (uint32_t)(value >> 32);
|
||||
__asm__ volatile("wrmsr" : : "c"(msr), "a"(lo), "d"(hi));
|
||||
}
|
||||
10
src/vga.c
10
src/vga.c
@@ -31,8 +31,8 @@ void vga_put_char(char character, uint8_t color)
|
||||
}
|
||||
case '\t':
|
||||
{
|
||||
uint8_t remainter = cursor_col % 4;
|
||||
cursor_col += remainter == 0 ? 4 : remainter;
|
||||
uint8_t remainder = 4 - (cursor_col % 4);
|
||||
cursor_col += remainder;
|
||||
break;
|
||||
}
|
||||
case '\b':
|
||||
@@ -86,13 +86,13 @@ void vga_put_char(char character, uint8_t color)
|
||||
{
|
||||
for (size_t col = 0; col < COLUMNS; col++)
|
||||
{
|
||||
vga_buffer[COLUMNS * row - 1 + col] = vga_buffer[COLUMNS * row + col];
|
||||
vga_buffer[COLUMNS * (row - 1) + col] = vga_buffer[COLUMNS * row + col];
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t col = 0; col < COLUMNS; col++)
|
||||
{
|
||||
vga_buffer[ROWS - 1 + col] = (vga_char_t){
|
||||
vga_buffer[COLUMNS * (ROWS - 1) + col] = (vga_char_t){
|
||||
.character = ' ',
|
||||
.color = VGA_DEFAULT_COLOR,
|
||||
};
|
||||
@@ -108,7 +108,7 @@ void vga_clear()
|
||||
{
|
||||
for (size_t col = 0; col < COLUMNS; col++)
|
||||
{
|
||||
vga_buffer[COLUMNS * row - 1 + col] = (vga_char_t){
|
||||
vga_buffer[COLUMNS * row + col] = (vga_char_t){
|
||||
.character = ' ',
|
||||
.color = VGA_DEFAULT_COLOR,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user