diff --git a/README.md b/README.md index 52a1395..fabc1d9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +Call me Terry Davis because... actually please don't. I have visions: aspirations, not hallucinations :p + # bootle hobby kernel written in rust. It's just for playing around... for now :p @@ -16,11 +18,18 @@ run with `nix run git+https://git.mtgmonkey.net/andromeda/bootler#bootler` +------ 0x00100000 ------+ | hardware, bios stuff | +------ 0x00080000 ------+ -| free | +| | +| | +------ 0x00010200 ------+ -| kernel (kernel.asm) | +| x86_64 kernel | +------ 0x00010000 ------+ -| free | +| | +| | ++------ 0x00009000 ------+ +| IDT | ++------ 0x00008000 ------+ +| | +| | +------ 0x00007E00 ------+ | bootloader (boot.asm) | +------ 0x00007C00 ------+ @@ -34,7 +43,8 @@ run with `nix run git+https://git.mtgmonkey.net/andromeda/bootler#bootler` +------ 0x00002000 ------+ | PML4T | +------ 0x00001000 ------+ -| free | +| | +| | +------ 0x00000500 ------+ | bios stuff | +------ 0x00000000 ------+ diff --git a/asm/boot.asm b/asm/boot.asm index 29e807c..5291d58 100644 --- a/asm/boot.asm +++ b/asm/boot.asm @@ -12,6 +12,13 @@ KERNEL_LOAD_ADDR_ES equ 0x1000 ; kernel to be loaded at es * 0x10 + 0x0000 PAGE_TABLE_LOAD_ADDR equ 0x1000 ; start of page table; 4 * pt size PAGE_TABLE_SIZE equ 0x1000 ; size of page table in bytes +; 64 bit IDT stuff +IDT_ADDR equ 0x8000 ; bottom of IDT +IDT_SIZE equ 0x1000 ; size of IDT + +IDT_SEGMENT equ 0x0008 ; gdt code segment to jump to for idt calls + +; magic numbers and things A20_LINE_ENABLE equ 0x2401 ; magic number in ax to enable a20 line with 0x15 BIOS_INT_DISK_OP equ 0x13 BIOS_INT_MEMORY_OP equ 0x15 @@ -42,7 +49,7 @@ cld ; activate a20 mov ax, A20_LINE_ENABLE int BIOS_INT_MEMORY_OP -jc error_a20_line +jc error mov si, msg_a20_line call print @@ -59,7 +66,7 @@ xor bx, bx ; read disk mov ah, 0x02 int BIOS_INT_DISK_OP -jc error_disk_read +jc error mov si, msg_disk_read call print @@ -143,17 +150,11 @@ lm_load: jmp 0x08:lm_start -error_a20_line: +error: mov si, .msg call print - jmp done - .msg db "err a20 line", 0x00 - -error_disk_read: - mov si, .msg - call print - jmp done - .msg db "err disk read", 0x00 + .msg db "err ", 0x00 + ret done: hlt @@ -172,11 +173,6 @@ print: popad ret -; TODO make real idt -empty_idt: - dw 0 ; length - dd 0 ; base - ; TODO make readable (yoinked from https://wiki.osdev.org/Entering_Long_Mode_Directly) gdt_data: dq 0x0000000000000000 @@ -201,11 +197,89 @@ lm_start: ; set up serial device ; TODO poll and whatnot (in rust??) mov dx, 0x3F8 + + ; qemu -no-graphic overlaps serial and bios output without this + mov al, 0x0D + out dx, al + mov al, 0x0A + out dx, al + + ; initialize IDT at IDT_ADDR + call idt_init + + int3 ; silly test jmp KERNEL_LOAD_ADDR_ES * 0x10 +idt_init: + ; clear space for idt + mov rdi, IDT_ADDR + push di + mov rcx, IDT_SIZE / 4 + xor rax, rax + cld + rep stosd ; clear double word for each rcx + pop di + + push rdx ; dx contains the output device + ; nothing between here and the `pop rdx` will be able to print + + ; breakpoint + mov rdi, 0x8E ; present, no dpl, interrupt + mov rsi, 0x03 ; breakpoint interrupt + lea rdx, [int_hdl_dummy] + call mk_idt_entry + + pop rdx ; get back dx output device + + lidt [idt_descriptor] + + ret + +int_hdl_dummy: + mov rsi, .msg + call lm_print + iretq + .msg db "INTdummy", 0x0D, 0x0A, 0x00 + +; rdi = flags +; rsi = entry number +; rdx -> handler +mk_idt_entry: + mov rax, rdx + mov rcx, rsi + + shl rcx, 4 ; offset = entry number * 16 + add rcx, IDT_ADDR + + mov word [rcx + 0], ax ; offset + mov word [rcx + 2], IDT_SEGMENT ; code segment + mov word [rcx + 5], di + mov byte [rcx + 4], 0 ; IST (0 = none) + shr rax, 16 + mov word [rcx + 6], ax ; offset + shr rax, 16 + mov dword [rcx + 8], eax ; offset + mov dword [rcx + 12], 0 ; reserved + ret + +lm_print: + .loop + mov al, [rsi] + test al, al + jz .done + out dx, al + inc si + jmp .loop + .done: + ret + +idt_descriptor: + dw IDT_SIZE - 1 ; size + dq IDT_ADDR ; start + msg_a20_line db "a20 line", 0x0D, 0x0A, 0x00 -msg_disk_read db "disk read", 0x0D, 0x0A, 0x00 +msg_disk_read db "disk", 0x0D, 0x0A, 0x00 times 510-($-$$) db 0 ; 2 bytes less now db 0x55 diff --git a/src/lib.rs b/src/lib.rs index f942513..18bb65c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,12 +5,11 @@ use core::panic::PanicInfo; #[unsafe(no_mangle)] pub extern "C" fn _start() -> ! { - // 'k' - print("kernel\n"); - loop {} + welcome_serial(); + halt() } -fn print(s: &str) { +fn print_serial(s: &str) { let mut bytes = s.bytes(); while let Some(b) = bytes.next() { unsafe {core::arch::asm!( @@ -20,8 +19,33 @@ fn print(s: &str) { }; } +fn println_serial(s: &str) { + print_serial(s); + print_serial("\n"); +} + +fn welcome_serial() { + print_serial(ANSI_PINK); + println_serial("\nWelcome to Bootle OS"); + println_serial("All code GPL licensed and freely available on git.mtgmonkey.net"); + print_serial("Enjoy your time! Press "); print_serial(ANSI_RED); print_serial("ctrl+a x"); print_serial(ANSI_PINK); println_serial(" to escape Qemu"); + print_serial(ANSI_CLEAR); +} + #[panic_handler] fn panic(_: &PanicInfo) -> ! { - print("panicked"); - loop {} + print_serial("panicked"); + halt() } + +fn halt() -> ! { + unsafe {core::arch::asm!( + "hlt" + )}; + halt() +} + +const ANSI_CLEAR: &str = "\x1b[0m"; +const ANSI_RED: &str = "\x1b[31m"; +const ANSI_PINK: &str = "\x1b[35m"; +const ANSI_GREEN: &str = "\x1b[32m";