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]
|
||||
start:
|
||||
mov esp, _sys_stack
|
||||
jmp stublet
|
||||
mov esp, _sys_stack ; Stack pointer!
|
||||
jmp stublet ; This has a purpse. I don't know what it is, but there is one.
|
||||
|
||||
ALIGN 4
|
||||
mboot:
|
||||
ALIGN 4 ; 4KB alignment, required by GRUB.
|
||||
mboot: ; This is all magic, and all of it required for GRUB to see our stuff.
|
||||
MULTIBOOT_ALIGN equ 1<<0
|
||||
MULTIBOOT_MEM equ 1<<1
|
||||
MULTIBOOT_AOUT equ 1<<16
|
||||
|
@ -25,23 +25,60 @@ mboot:
|
|||
dd end
|
||||
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
|
||||
call kernel_main
|
||||
jmp $
|
||||
|
||||
[GLOBAL load_gdt] ; Allows the C code to call gdt_flush().
|
||||
[GLOBAL load_gdt]
|
||||
[EXTERN gp]
|
||||
load_gdt:
|
||||
lgdt [gp] ; Load the new GDT pointer
|
||||
|
||||
mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
|
||||
mov ds, ax ; Load all data segment selectors
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
jmp 0x08:flush ; 0x08 is the offset to our code segment: Far jump!
|
||||
jmp 0x08:flush
|
||||
flush:
|
||||
ret
|
||||
|
||||
|
@ -121,7 +158,7 @@ IRQ 13, 45
|
|||
IRQ 14, 46
|
||||
IRQ 15, 47
|
||||
|
||||
extern fault_handler
|
||||
[EXTERN fault_handler]
|
||||
|
||||
isr_common:
|
||||
pusha
|
||||
|
@ -149,7 +186,7 @@ isr_common:
|
|||
add esp, 8
|
||||
iret
|
||||
|
||||
extern irq_handler
|
||||
[EXTERN irq_handler]
|
||||
|
||||
irq_common:
|
||||
pusha
|
||||
|
@ -176,11 +213,12 @@ irq_common:
|
|||
iret
|
||||
|
||||
[GLOBAL idt_load]
|
||||
[EXTERN idtp]
|
||||
idt_load:
|
||||
mov eax, [esp+4]
|
||||
lidt [eax]
|
||||
ret
|
||||
|
||||
|
||||
|
||||
SECTION .bss
|
||||
resb 8192
|
||||
_sys_stack:
|
||||
|
|
|
@ -14,7 +14,7 @@ static size_t terminal_column;
|
|||
|
||||
static uint8_t current_color;
|
||||
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) {
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ enum vga_colors {
|
|||
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
|
||||
#include <stddef.h>
|
||||
|
||||
/* A temporary file, to get the system compiling. */
|
||||
|
||||
size_t strlen(const char*);
|
||||
|
||||
unsigned char inb(unsigned short);
|
||||
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
|
||||
/* A temporary file, to get the system compiling. */
|
||||
|
||||
size_t strlen(const char*);
|
||||
|
||||
unsigned char inb(unsigned short);
|
||||
|
||||
void outb(unsigned short, unsigned char);
|
||||
|
||||
void memcpy(void*, void*, size_t);
|
||||
|
@ -19,3 +19,5 @@ void int_to_ascii(int, char*);
|
|||
void int_to_hex(int, 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);
|
||||
|
||||
idt_set_gate(0, (unsigned)isr0, 0x08, 0x8E);
|
||||
idt_set_gate(1, (unsigned)isr1, 0x08, 0x8E);
|
||||
idt_set_gate(2, (unsigned)isr2, 0x08, 0x8E);
|
||||
idt_set_gate(3, (unsigned)isr3, 0x08, 0x8E);
|
||||
idt_set_gate(4, (unsigned)isr4, 0x08, 0x8E);
|
||||
idt_set_gate(5, (unsigned)isr5, 0x08, 0x8E);
|
||||
idt_set_gate(6, (unsigned)isr6, 0x08, 0x8E);
|
||||
idt_set_gate(7, (unsigned)isr7, 0x08, 0x8E);
|
||||
idt_set_gate(1, (unsigned)isr1, 0x08, 0x8E);
|
||||
idt_set_gate(2, (unsigned)isr2, 0x08, 0x8E);
|
||||
idt_set_gate(3, (unsigned)isr3, 0x08, 0x8E);
|
||||
idt_set_gate(4, (unsigned)isr4, 0x08, 0x8E);
|
||||
idt_set_gate(5, (unsigned)isr5, 0x08, 0x8E);
|
||||
idt_set_gate(6, (unsigned)isr6, 0x08, 0x8E);
|
||||
idt_set_gate(7, (unsigned)isr7, 0x08, 0x8E);
|
||||
|
||||
idt_set_gate(8, (unsigned)isr8, 0x08, 0x8E);
|
||||
idt_set_gate(9, (unsigned)isr9, 0x08, 0x8E);
|
||||
idt_set_gate(10, (unsigned)isr10, 0x08, 0x8E);
|
||||
idt_set_gate(11, (unsigned)isr11, 0x08, 0x8E);
|
||||
idt_set_gate(12, (unsigned)isr12, 0x08, 0x8E);
|
||||
idt_set_gate(13, (unsigned)isr13, 0x08, 0x8E);
|
||||
idt_set_gate(14, (unsigned)isr14, 0x08, 0x8E);
|
||||
idt_set_gate(15, (unsigned)isr15, 0x08, 0x8E);
|
||||
idt_set_gate(8, (unsigned)isr8, 0x08, 0x8E);
|
||||
idt_set_gate(9, (unsigned)isr9, 0x08, 0x8E);
|
||||
idt_set_gate(10, (unsigned)isr10, 0x08, 0x8E);
|
||||
idt_set_gate(11, (unsigned)isr11, 0x08, 0x8E);
|
||||
idt_set_gate(12, (unsigned)isr12, 0x08, 0x8E);
|
||||
idt_set_gate(13, (unsigned)isr13, 0x08, 0x8E);
|
||||
idt_set_gate(14, (unsigned)isr14, 0x08, 0x8E);
|
||||
idt_set_gate(15, (unsigned)isr15, 0x08, 0x8E);
|
||||
|
||||
idt_set_gate(16, (unsigned)isr16, 0x08, 0x8E);
|
||||
idt_set_gate(17, (unsigned)isr17, 0x08, 0x8E);
|
||||
idt_set_gate(18, (unsigned)isr18, 0x08, 0x8E);
|
||||
idt_set_gate(19, (unsigned)isr19, 0x08, 0x8E);
|
||||
idt_set_gate(20, (unsigned)isr20, 0x08, 0x8E);
|
||||
idt_set_gate(21, (unsigned)isr21, 0x08, 0x8E);
|
||||
idt_set_gate(22, (unsigned)isr22, 0x08, 0x8E);
|
||||
idt_set_gate(23, (unsigned)isr23, 0x08, 0x8E);
|
||||
idt_set_gate(16, (unsigned)isr16, 0x08, 0x8E);
|
||||
idt_set_gate(17, (unsigned)isr17, 0x08, 0x8E);
|
||||
idt_set_gate(18, (unsigned)isr18, 0x08, 0x8E);
|
||||
idt_set_gate(19, (unsigned)isr19, 0x08, 0x8E);
|
||||
idt_set_gate(20, (unsigned)isr20, 0x08, 0x8E);
|
||||
idt_set_gate(21, (unsigned)isr21, 0x08, 0x8E);
|
||||
idt_set_gate(22, (unsigned)isr22, 0x08, 0x8E);
|
||||
idt_set_gate(23, (unsigned)isr23, 0x08, 0x8E);
|
||||
|
||||
idt_set_gate(24, (unsigned)isr24, 0x08, 0x8E);
|
||||
idt_set_gate(25, (unsigned)isr25, 0x08, 0x8E);
|
||||
idt_set_gate(26, (unsigned)isr26, 0x08, 0x8E);
|
||||
idt_set_gate(27, (unsigned)isr27, 0x08, 0x8E);
|
||||
idt_set_gate(28, (unsigned)isr28, 0x08, 0x8E);
|
||||
idt_set_gate(29, (unsigned)isr29, 0x08, 0x8E);
|
||||
idt_set_gate(30, (unsigned)isr30, 0x08, 0x8E);
|
||||
idt_set_gate(31, (unsigned)isr31, 0x08, 0x8E);
|
||||
idt_set_gate(24, (unsigned)isr24, 0x08, 0x8E);
|
||||
idt_set_gate(25, (unsigned)isr25, 0x08, 0x8E);
|
||||
idt_set_gate(26, (unsigned)isr26, 0x08, 0x8E);
|
||||
idt_set_gate(27, (unsigned)isr27, 0x08, 0x8E);
|
||||
idt_set_gate(28, (unsigned)isr28, 0x08, 0x8E);
|
||||
idt_set_gate(29, (unsigned)isr29, 0x08, 0x8E);
|
||||
idt_set_gate(30, (unsigned)isr30, 0x08, 0x8E);
|
||||
idt_set_gate(31, (unsigned)isr31, 0x08, 0x8E);
|
||||
|
||||
idt_load();
|
||||
irq_install();
|
||||
|
@ -139,4 +139,4 @@ void irq_handler(registers_t *r) {
|
|||
outb(0xA0, 0x20);
|
||||
|
||||
outb(0x20, 0x20);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,51 +1,87 @@
|
|||
/////////////////////////////
|
||||
/// ///
|
||||
/// Team Kitty, 2019 ///
|
||||
/// ProjectRED ///
|
||||
/// ///
|
||||
/////////////////////////////
|
||||
|
||||
//#include <stdio.h>
|
||||
|
||||
#include <kernel/tty.h>
|
||||
//#include <stdio.h>
|
||||
|
||||
#include <kernel/tty.h>
|
||||
#include <kernel/descriptor_tables.h>
|
||||
#include <kernel/serial.h>
|
||||
|
||||
#include <kernel/serial.h>
|
||||
|
||||
void gdb_end() {} /* GDB Debugging stump */
|
||||
|
||||
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();
|
||||
|
||||
// Prepare the serial console.
|
||||
/* Prepare the serial line for our debug output. */
|
||||
init_serial();
|
||||
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();
|
||||
|
||||
/* puts: writes a line to the terminal. */
|
||||
puts("GDT Ready.");
|
||||
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");
|
||||
term_writes("IDT...");
|
||||
idt_install();
|
||||
puts("IDT Ready.");
|
||||
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");
|
||||
term_writes("Timer...");
|
||||
timer_install();
|
||||
puts("Timer Ready.");
|
||||
|
||||
serial_print(0x3F8, "[INFO] All subsystems ready. Printing message.\r\n");
|
||||
|
||||
//Print a copyright message.
|
||||
term_writes("(c)");
|
||||
term_setcolor(GREEN);
|
||||
term_writes(" Project");
|
||||
term_setcolor(RED);
|
||||
term_writes("RED");
|
||||
term_setcolor(WHITE);
|
||||
serial_print(0x3F8, "[INFO] All subsystems ready. Printing message.\r\n");
|
||||
|
||||
/* Everything is ready; print a pretty message. */
|
||||
term_writes("\n(c)");
|
||||
term_setcolor(GREEN);
|
||||
term_writes(" Project");
|
||||
term_setcolor(RED);
|
||||
term_writes("RED");
|
||||
term_setcolor(WHITE);
|
||||
term_writes(", 2019\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);
|
||||
serial_print(0x3F8, "[DEBUG] Survived the error!\r\n");
|
||||
|
||||
for(;;) {}
|
||||
return 0;
|
||||
|
||||
/* A stub causing a Divide by Zero error. */
|
||||
//serial_print(0x3F8, "[DEBUG] Attempting a Divide by Zero error.\r\n");
|
||||
//char div = (5 / 0);
|
||||
//serial_print(0x3F8, "[DEBUG] Survived the error!\r\n");
|
||||
|
||||
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) {
|
||||
char* src_c = (char*)src;
|
||||
char* dest_c = (char*)dest;
|
||||
char* dest_c = (char*)dest;
|
||||
|
||||
for(size_t i = 0; i < n; 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) {
|
||||
empty_string(string);
|
||||
|
||||
|
@ -101,4 +113,4 @@ void empty_string(char* string) {
|
|||
for(size_t i = 0; i < len + 1; i++) {
|
||||
string[i] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user