Fixes and improvements.
Including a new, rewritten and restructured boot.s file, plus automagical Protected Mode.
This commit is contained in:
parent
dbce420e56
commit
022884e20d
|
@ -1,12 +1,12 @@
|
||||||
[BITS 32]
|
[BITS 32] ;... somehow.
|
||||||
|
|
||||||
[GLOBAL start]
|
[GLOBAL start]
|
||||||
start:
|
start:
|
||||||
mov esp, _sys_stack
|
mov esp, _sys_stack ; Stack pointer!
|
||||||
jmp stublet
|
jmp stublet ; This has a purpse. I don't know what it is, but there is one.
|
||||||
|
|
||||||
ALIGN 4
|
ALIGN 4 ; 4KB alignment, required by GRUB.
|
||||||
mboot:
|
mboot: ; This is all magic, and all of it required for GRUB to see our stuff.
|
||||||
MULTIBOOT_ALIGN equ 1<<0
|
MULTIBOOT_ALIGN equ 1<<0
|
||||||
MULTIBOOT_MEM equ 1<<1
|
MULTIBOOT_MEM equ 1<<1
|
||||||
MULTIBOOT_AOUT equ 1<<16
|
MULTIBOOT_AOUT equ 1<<16
|
||||||
|
@ -25,23 +25,60 @@ mboot:
|
||||||
dd end
|
dd end
|
||||||
dd start
|
dd start
|
||||||
|
|
||||||
stublet:
|
stublet: ; Where the kernel stuff goes.
|
||||||
|
|
||||||
|
;=====================================
|
||||||
|
;===Priority: 32 bit Protected Mode===
|
||||||
|
;=====================================
|
||||||
|
|
||||||
|
cli ; Interrupts be gone!
|
||||||
|
|
||||||
|
xor cx, cx ; CX - GP, useful here.
|
||||||
|
kbempty:
|
||||||
|
in al, 64h ; Read keyboard status
|
||||||
|
test al, 02h ; Check if the buffer is full
|
||||||
|
loopnz kbempty ; Wait until it is
|
||||||
|
mov al, 0d1h ; Prepare a message
|
||||||
|
out 64h, al ; And then send it to the keyboard (controller)
|
||||||
|
kbempty2:
|
||||||
|
in al, 64h ; Read the status again
|
||||||
|
test al, 02h ; Check if it's processed our message
|
||||||
|
loopnz kbempty2 ; And wait until it has
|
||||||
|
mov al, 0dfh ; Prepare a different message, telling it to enable A20
|
||||||
|
out 60h, al ; Send the message
|
||||||
|
mov cx, 14h ; Restore the value of CX
|
||||||
|
wait_kb: ; Insinuate a 25uS delay to allow the processor to catch up
|
||||||
|
out 0edh, ax
|
||||||
|
loop wait_kb
|
||||||
|
|
||||||
|
mov eax, cr0 ; Read the control register
|
||||||
|
or al, 1 ; Set bit 1: protected mode
|
||||||
|
mov cr0, eax ; Set the control register back
|
||||||
|
jmp $+2 ; Clear the queue
|
||||||
|
nop ; (jump straight to kernel)
|
||||||
|
nop
|
||||||
|
|
||||||
|
;==================================
|
||||||
|
;===32-bit Protected Mode active===
|
||||||
|
;==================================
|
||||||
|
; Call the kernel
|
||||||
|
|
||||||
EXTERN kernel_main
|
EXTERN kernel_main
|
||||||
call kernel_main
|
call kernel_main
|
||||||
jmp $
|
jmp $
|
||||||
|
|
||||||
[GLOBAL load_gdt] ; Allows the C code to call gdt_flush().
|
[GLOBAL load_gdt]
|
||||||
[EXTERN gp]
|
[EXTERN gp]
|
||||||
load_gdt:
|
load_gdt:
|
||||||
lgdt [gp] ; Load the new GDT pointer
|
lgdt [gp] ; Load the new GDT pointer
|
||||||
|
|
||||||
mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
|
mov ax, 0x10
|
||||||
mov ds, ax ; Load all data segment selectors
|
mov ds, ax
|
||||||
mov es, ax
|
mov es, ax
|
||||||
mov fs, ax
|
mov fs, ax
|
||||||
mov gs, ax
|
mov gs, ax
|
||||||
mov ss, ax
|
mov ss, ax
|
||||||
jmp 0x08:flush ; 0x08 is the offset to our code segment: Far jump!
|
jmp 0x08:flush
|
||||||
flush:
|
flush:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
@ -121,7 +158,7 @@ IRQ 13, 45
|
||||||
IRQ 14, 46
|
IRQ 14, 46
|
||||||
IRQ 15, 47
|
IRQ 15, 47
|
||||||
|
|
||||||
extern fault_handler
|
[EXTERN fault_handler]
|
||||||
|
|
||||||
isr_common:
|
isr_common:
|
||||||
pusha
|
pusha
|
||||||
|
@ -149,7 +186,7 @@ isr_common:
|
||||||
add esp, 8
|
add esp, 8
|
||||||
iret
|
iret
|
||||||
|
|
||||||
extern irq_handler
|
[EXTERN irq_handler]
|
||||||
|
|
||||||
irq_common:
|
irq_common:
|
||||||
pusha
|
pusha
|
||||||
|
@ -176,11 +213,12 @@ irq_common:
|
||||||
iret
|
iret
|
||||||
|
|
||||||
[GLOBAL idt_load]
|
[GLOBAL idt_load]
|
||||||
|
[EXTERN idtp]
|
||||||
idt_load:
|
idt_load:
|
||||||
mov eax, [esp+4]
|
|
||||||
lidt [eax]
|
lidt [eax]
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
SECTION .bss
|
SECTION .bss
|
||||||
resb 8192
|
resb 8192
|
||||||
_sys_stack:
|
_sys_stack:
|
||||||
|
|
|
@ -14,7 +14,7 @@ static size_t terminal_column;
|
||||||
|
|
||||||
static uint8_t current_color;
|
static uint8_t current_color;
|
||||||
static uint16_t* term_buffer;
|
static uint16_t* term_buffer;
|
||||||
static uint16_t* const vga_buffer = (uint16_t*)0xB8000;
|
volatile uint16_t* vga_buffer = (uint16_t*)0xB8000;
|
||||||
|
|
||||||
void screen_initialize(void) {
|
void screen_initialize(void) {
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@ enum vga_colors {
|
||||||
WHITE = 15
|
WHITE = 15
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline uint8_t vga_color_set(enum vga_colors fg, enum vga_colors bg) { return fg | bg << 4; }
|
static inline uint8_t vga_color_set(enum vga_colors fg, enum vga_colors bg) { return bg << 4 | fg; }
|
||||||
|
|
||||||
static inline uint16_t vga_entry(unsigned char uc, uint8_t color) { return (uint16_t)uc | (uint16_t)color << 8; }
|
static inline uint16_t vga_entry(uint8_t uc, uint8_t color) { return color << 8 | uc; }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
/* A temporary file, to get the system compiling. */
|
/* A temporary file, to get the system compiling. */
|
||||||
|
|
||||||
size_t strlen(const char*);
|
size_t strlen(const char*);
|
||||||
|
|
||||||
unsigned char inb(unsigned short);
|
unsigned char inb(unsigned short);
|
||||||
|
|
||||||
void outb(unsigned short, unsigned char);
|
void outb(unsigned short, unsigned char);
|
||||||
|
|
||||||
void memcpy(void*, void*, size_t);
|
void memcpy(void*, void*, size_t);
|
||||||
|
@ -19,3 +19,5 @@ void int_to_ascii(int, char*);
|
||||||
void int_to_hex(int, char*);
|
void int_to_hex(int, char*);
|
||||||
|
|
||||||
void empty_string(char*);
|
void empty_string(char*);
|
||||||
|
|
||||||
|
char* itoc(size_t);
|
||||||
|
|
64
kernel/idt.c
64
kernel/idt.c
|
@ -38,40 +38,40 @@ void idt_install() {
|
||||||
memset(&idt, 0, sizeof(struct idt_entry) * 256);
|
memset(&idt, 0, sizeof(struct idt_entry) * 256);
|
||||||
|
|
||||||
idt_set_gate(0, (unsigned)isr0, 0x08, 0x8E);
|
idt_set_gate(0, (unsigned)isr0, 0x08, 0x8E);
|
||||||
idt_set_gate(1, (unsigned)isr1, 0x08, 0x8E);
|
idt_set_gate(1, (unsigned)isr1, 0x08, 0x8E);
|
||||||
idt_set_gate(2, (unsigned)isr2, 0x08, 0x8E);
|
idt_set_gate(2, (unsigned)isr2, 0x08, 0x8E);
|
||||||
idt_set_gate(3, (unsigned)isr3, 0x08, 0x8E);
|
idt_set_gate(3, (unsigned)isr3, 0x08, 0x8E);
|
||||||
idt_set_gate(4, (unsigned)isr4, 0x08, 0x8E);
|
idt_set_gate(4, (unsigned)isr4, 0x08, 0x8E);
|
||||||
idt_set_gate(5, (unsigned)isr5, 0x08, 0x8E);
|
idt_set_gate(5, (unsigned)isr5, 0x08, 0x8E);
|
||||||
idt_set_gate(6, (unsigned)isr6, 0x08, 0x8E);
|
idt_set_gate(6, (unsigned)isr6, 0x08, 0x8E);
|
||||||
idt_set_gate(7, (unsigned)isr7, 0x08, 0x8E);
|
idt_set_gate(7, (unsigned)isr7, 0x08, 0x8E);
|
||||||
|
|
||||||
idt_set_gate(8, (unsigned)isr8, 0x08, 0x8E);
|
idt_set_gate(8, (unsigned)isr8, 0x08, 0x8E);
|
||||||
idt_set_gate(9, (unsigned)isr9, 0x08, 0x8E);
|
idt_set_gate(9, (unsigned)isr9, 0x08, 0x8E);
|
||||||
idt_set_gate(10, (unsigned)isr10, 0x08, 0x8E);
|
idt_set_gate(10, (unsigned)isr10, 0x08, 0x8E);
|
||||||
idt_set_gate(11, (unsigned)isr11, 0x08, 0x8E);
|
idt_set_gate(11, (unsigned)isr11, 0x08, 0x8E);
|
||||||
idt_set_gate(12, (unsigned)isr12, 0x08, 0x8E);
|
idt_set_gate(12, (unsigned)isr12, 0x08, 0x8E);
|
||||||
idt_set_gate(13, (unsigned)isr13, 0x08, 0x8E);
|
idt_set_gate(13, (unsigned)isr13, 0x08, 0x8E);
|
||||||
idt_set_gate(14, (unsigned)isr14, 0x08, 0x8E);
|
idt_set_gate(14, (unsigned)isr14, 0x08, 0x8E);
|
||||||
idt_set_gate(15, (unsigned)isr15, 0x08, 0x8E);
|
idt_set_gate(15, (unsigned)isr15, 0x08, 0x8E);
|
||||||
|
|
||||||
idt_set_gate(16, (unsigned)isr16, 0x08, 0x8E);
|
idt_set_gate(16, (unsigned)isr16, 0x08, 0x8E);
|
||||||
idt_set_gate(17, (unsigned)isr17, 0x08, 0x8E);
|
idt_set_gate(17, (unsigned)isr17, 0x08, 0x8E);
|
||||||
idt_set_gate(18, (unsigned)isr18, 0x08, 0x8E);
|
idt_set_gate(18, (unsigned)isr18, 0x08, 0x8E);
|
||||||
idt_set_gate(19, (unsigned)isr19, 0x08, 0x8E);
|
idt_set_gate(19, (unsigned)isr19, 0x08, 0x8E);
|
||||||
idt_set_gate(20, (unsigned)isr20, 0x08, 0x8E);
|
idt_set_gate(20, (unsigned)isr20, 0x08, 0x8E);
|
||||||
idt_set_gate(21, (unsigned)isr21, 0x08, 0x8E);
|
idt_set_gate(21, (unsigned)isr21, 0x08, 0x8E);
|
||||||
idt_set_gate(22, (unsigned)isr22, 0x08, 0x8E);
|
idt_set_gate(22, (unsigned)isr22, 0x08, 0x8E);
|
||||||
idt_set_gate(23, (unsigned)isr23, 0x08, 0x8E);
|
idt_set_gate(23, (unsigned)isr23, 0x08, 0x8E);
|
||||||
|
|
||||||
idt_set_gate(24, (unsigned)isr24, 0x08, 0x8E);
|
idt_set_gate(24, (unsigned)isr24, 0x08, 0x8E);
|
||||||
idt_set_gate(25, (unsigned)isr25, 0x08, 0x8E);
|
idt_set_gate(25, (unsigned)isr25, 0x08, 0x8E);
|
||||||
idt_set_gate(26, (unsigned)isr26, 0x08, 0x8E);
|
idt_set_gate(26, (unsigned)isr26, 0x08, 0x8E);
|
||||||
idt_set_gate(27, (unsigned)isr27, 0x08, 0x8E);
|
idt_set_gate(27, (unsigned)isr27, 0x08, 0x8E);
|
||||||
idt_set_gate(28, (unsigned)isr28, 0x08, 0x8E);
|
idt_set_gate(28, (unsigned)isr28, 0x08, 0x8E);
|
||||||
idt_set_gate(29, (unsigned)isr29, 0x08, 0x8E);
|
idt_set_gate(29, (unsigned)isr29, 0x08, 0x8E);
|
||||||
idt_set_gate(30, (unsigned)isr30, 0x08, 0x8E);
|
idt_set_gate(30, (unsigned)isr30, 0x08, 0x8E);
|
||||||
idt_set_gate(31, (unsigned)isr31, 0x08, 0x8E);
|
idt_set_gate(31, (unsigned)isr31, 0x08, 0x8E);
|
||||||
|
|
||||||
idt_load();
|
idt_load();
|
||||||
irq_install();
|
irq_install();
|
||||||
|
@ -139,4 +139,4 @@ void irq_handler(registers_t *r) {
|
||||||
outb(0xA0, 0x20);
|
outb(0xA0, 0x20);
|
||||||
|
|
||||||
outb(0x20, 0x20);
|
outb(0x20, 0x20);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,51 +1,87 @@
|
||||||
|
/////////////////////////////
|
||||||
|
/// ///
|
||||||
|
/// Team Kitty, 2019 ///
|
||||||
|
/// ProjectRED ///
|
||||||
|
/// ///
|
||||||
|
/////////////////////////////
|
||||||
|
|
||||||
//#include <stdio.h>
|
//#include <stdio.h>
|
||||||
|
|
||||||
#include <kernel/tty.h>
|
#include <kernel/tty.h>
|
||||||
#include <kernel/descriptor_tables.h>
|
#include <kernel/descriptor_tables.h>
|
||||||
#include <kernel/serial.h>
|
#include <kernel/serial.h>
|
||||||
|
|
||||||
|
void gdb_end() {} /* GDB Debugging stump */
|
||||||
|
|
||||||
int kernel_main(void) {
|
int kernel_main(void) {
|
||||||
// Prepare the screen, and blank it out.
|
/* The kernel is started in 32-bit protected mode by the ASM. */
|
||||||
|
/* Here, we start by enabling the screen, then loading a GDT and IDT into the actual places they need to be. */
|
||||||
|
|
||||||
|
/* Black the screen out. */
|
||||||
screen_initialize();
|
screen_initialize();
|
||||||
|
|
||||||
// Prepare the serial console.
|
/* Prepare the serial line for our debug output. */
|
||||||
init_serial();
|
init_serial();
|
||||||
serial_print(0x3F8, "[INFO] Serial ready.\r\n");
|
serial_print(0x3F8, "[INFO] Serial ready.\r\n");
|
||||||
|
|
||||||
// Prepare the GDT
|
|
||||||
serial_print(0x3F8, "[INFO] Beginning GDT subroutine.\r\n");
|
serial_print(0x3F8, "[INFO] Beginning GDT subroutine.\r\n");
|
||||||
|
|
||||||
|
/* term_writes: writes a string to the terminal. */
|
||||||
|
term_writes("GDT...");
|
||||||
|
|
||||||
|
/* Prepares the Global Descriptor Table, called from gdt.c */
|
||||||
gdt_install();
|
gdt_install();
|
||||||
|
|
||||||
|
/* puts: writes a line to the terminal. */
|
||||||
|
puts("GDT Ready.");
|
||||||
serial_print(0x3F8, "[INFO] GDT subroutine complete.\r\n");
|
serial_print(0x3F8, "[INFO] GDT subroutine complete.\r\n");
|
||||||
|
|
||||||
// Prepare interrupts
|
/* Prepare the Interrupt Descriptor Table. */
|
||||||
serial_print(0x3F8, "[INFO] Beginning IDT subroutine.\r\n");
|
serial_print(0x3F8, "[INFO] Beginning IDT subroutine.\r\n");
|
||||||
|
term_writes("IDT...");
|
||||||
idt_install();
|
idt_install();
|
||||||
|
puts("IDT Ready.");
|
||||||
serial_print(0x3F8, "[INFO] IDT subroutine complete.\r\n[INFO] Enabling interrupts.\r\n");
|
serial_print(0x3F8, "[INFO] IDT subroutine complete.\r\n[INFO] Enabling interrupts.\r\n");
|
||||||
asm volatile("sti");
|
|
||||||
|
|
||||||
|
gdb_end(); /* The first important step. Waypoint it for gdb debugging. */
|
||||||
|
|
||||||
|
term_writes("Memory available:");
|
||||||
|
/* TODO: implement check_a20, which double-triple checks the state of the A20 line. */
|
||||||
|
|
||||||
|
//if(check_a20())
|
||||||
|
puts(" 4GB");
|
||||||
|
serial_print(0x3F8, "[INFO] A20 enabled. 4GB memory available.");
|
||||||
|
|
||||||
|
/* The first important thing: start the system clock immediately. */
|
||||||
serial_print(0x3F8, "[INFO] Starting System Clock.\r\n");
|
serial_print(0x3F8, "[INFO] Starting System Clock.\r\n");
|
||||||
|
term_writes("Timer...");
|
||||||
timer_install();
|
timer_install();
|
||||||
|
puts("Timer Ready.");
|
||||||
|
|
||||||
serial_print(0x3F8, "[INFO] All subsystems ready. Printing message.\r\n");
|
serial_print(0x3F8, "[INFO] All subsystems ready. Printing message.\r\n");
|
||||||
|
|
||||||
//Print a copyright message.
|
/* Everything is ready; print a pretty message. */
|
||||||
term_writes("(c)");
|
term_writes("\n(c)");
|
||||||
term_setcolor(GREEN);
|
term_setcolor(GREEN);
|
||||||
term_writes(" Project");
|
term_writes(" Project");
|
||||||
term_setcolor(RED);
|
term_setcolor(RED);
|
||||||
term_writes("RED");
|
term_writes("RED");
|
||||||
term_setcolor(WHITE);
|
term_setcolor(WHITE);
|
||||||
term_writes(", 2019\n");
|
term_writes(", 2019\n");
|
||||||
|
|
||||||
serial_print(0x3F8, "[INFO] All operations complete. Checking for other tasks...\r\n");
|
serial_print(0x3F8, "[INFO] All operations complete. Checking for other tasks...\r\n");
|
||||||
|
|
||||||
for(size_t i = 0; i < 3000; i++) {}
|
/* Here are a series of tests for the ANSI escape code and CSI implementations. */
|
||||||
|
term_writes("\x1b[BA"); /* Down a line, then A. */
|
||||||
|
|
||||||
serial_print(0x3F8, "[DEBUG] Attempting a Divide by Zero error.\r\n");
|
|
||||||
//term_putchar(5/0);
|
/* A stub causing a Divide by Zero error. */
|
||||||
serial_print(0x3F8, "[DEBUG] Survived the error!\r\n");
|
//serial_print(0x3F8, "[DEBUG] Attempting a Divide by Zero error.\r\n");
|
||||||
|
//char div = (5 / 0);
|
||||||
for(;;) {}
|
//serial_print(0x3F8, "[DEBUG] Survived the error!\r\n");
|
||||||
return 0;
|
|
||||||
|
gdb_end(); /* Everything is done. The last debug routine. */
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ void outb(unsigned short port, unsigned char data) {
|
||||||
|
|
||||||
void memcpy(void* dest, void* src, size_t n) {
|
void memcpy(void* dest, void* src, size_t n) {
|
||||||
char* src_c = (char*)src;
|
char* src_c = (char*)src;
|
||||||
char* dest_c = (char*)dest;
|
char* dest_c = (char*)dest;
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
for(size_t i = 0; i < n; i++) {
|
||||||
dest_c[i] = src_c[i];
|
dest_c[i] = src_c[i];
|
||||||
|
@ -75,6 +75,18 @@ void int_to_ascii(int num, char* string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* itoc(size_t num) {
|
||||||
|
char* result;
|
||||||
|
size_t tmp_value;
|
||||||
|
do {
|
||||||
|
tmp_value = num;
|
||||||
|
num /= 10;
|
||||||
|
*result++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - num * 10)];
|
||||||
|
}while (num);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void int_to_hex(int num, char* string) {
|
void int_to_hex(int num, char* string) {
|
||||||
empty_string(string);
|
empty_string(string);
|
||||||
|
|
||||||
|
@ -101,4 +113,4 @@ void empty_string(char* string) {
|
||||||
for(size_t i = 0; i < len + 1; i++) {
|
for(size_t i = 0; i < len + 1; i++) {
|
||||||
string[i] = '\0';
|
string[i] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user