I created a boot strap loader, which does nothing more than load a binary from the root directory called LOADER.BIN at 0100h:0000h.
The plan is that LOADER.BIN is then responsible for enabling the A20 line, loading the GDT, switching to PMode, setting up an IDT, setting up task descriptors, enabling paging and all that other equally messy stuff. It would then load the kernel from disk etc.
SO FAR, I have it enabling the A20 line, loading a GDT, then switching to p-mode. But right after the switch, I get a kernel stack fault followed by a hardware reboot. Here's my loader code:
Code: Select all
[bits 16]
[extern c_main]
; Set up the segment registers to 0x0100, where the kernel is loaded
mov ax, 0x0100
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; Create a stack
cli
mov ss, ax
mov sp, 0xFFFF
sti
; enable the A20 gate
cli
call enableA20
sti
; Load the global descriptor table
mov si, LoadingGDT
mov bl, GREEN_TXT
call DisplayMessage
cli
lgdt [cs:gdt]
sti
mov si, LoadedGDT
mov bl, GREEN_TXT
call DisplayMessage
; Switch to protected mode
mov si, SwitchingToPM
mov bl, GREEN_TXT
call DisplayMessage
; Disable all interrupts, including NMIs
cli
in al, 0x70
or al, 0x80
out 0x70, al
mov ecx, cr0
inc cx
mov cr0, ecx
; Flush the instruction cache
;
; NOTE: I have no idea where the 0x08 is coming from.
; I copied it from some other code, and hope it works
; I think it's something to do with the segment descriptors
;
jmp 0x08:clear_pipe
[bits 32]
clear_pipe:
; Set up the segments and the stack
;
; NOTE: I am not entirely sure about this (mainly because it CRASHES around here)
;
mov ax, 0x08
mov ds, ax
mov ss, ax
mov esp, 0x090000
; This is where I would then set up interrupt tables, and whatever else
; then call c_main
jmp $
[bits 16]
; Other code like DisplayMessage and EnableA20 goes here
; it all seems to work fine.
gdt start_gdt
flat_code desc 0, 0xFFBFF, D_CODE + D_READ + D_BIG + D_BIG_LIM
flat_data desc 0, 0xFFFFF, D_DATA + D_WRITE + D_BIG + D_BIG_LIM
end_gdt
It manages to enable the A20 gate ok, then I think the GDT is loaded ok, and the switch to P-Mode successful. However, after I see the "- Switching to Protected Mode (PM)" message (see full loader source), then it faults. I'm guessing I've messed something up with the segment registers, or perhaps it was the jump into the 32 bit code to clear the instruction pipeline (jmp 0x08:clear_pipe)? I really don't know.
What I want to achieve at the moment, is simply being able to link my kernel.c and my loader.asm together, then have the loader call the "main" function in the kernel, just after switching to protected mode. Once I get that working, I think I can move on and start figuring out interrupt descriptor tables and working p-mode. I can't call my c-function until it at least...well....doesn't crash after switching to p-mode, so I'm at a dead end here.
I attached the entire source for the loader program
So if anybody has any idea what's wrong with it, or better yet how to fix it and get it working then I'd very much appreciate it, thanks.