I think I am not the kinda person who should work on this stuffs since nothing works for me. Some days ago i've asked for loading the second stage bootloader from the first stage one and now I've got the same problem but with the kernel and the 2° bootloader. I've done a bit of copy and paste from various examples and tutorial online but is should theoretically work... I don't really know what it is the problem in all of this code. The only thing that I'm enough sure is that is the part where the kernel is loaded to memory. This is the loader.asm:
org 0x8000
bits 16
jmp load
%include "include/io.inc"
%include "include/mem.inc"
%include "include/globals.inc"
%include "include/a20.inc"
%include "include/cpuid.inc"
%include "include/gdt.inc"
%include "include/fat12.inc"
%include "include/memory.inc"
%include "include/tts.inc"
%include "include/paging.inc"
load:
.init:
cli
; Clear all general purpose registers.
xor ax, ax
xor bx, bx
xor cx, cx
xor dx, dx
xor si, si
xor di, di
xor bp, bp
; Initialize all segment registers to zero.
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; Initialize the stack pointer.
mov sp, Mem.Stack.Top
BiosPrint String.Loading
.enableA20:
call EnableA20
BiosPrint String.Status.A20Enabled
.detect64BitMode:
call HasCPUID
jnc error.noCPUID
; Is the processor info function supported?
mov eax, 0x80000000 ; Get Highest Extended Function Supported
cpuid
cmp eax, 0x80000001
jb error.no64BitMode
; Use processor info function to see if 64-bit mode is supported.
mov eax, 0x80000001 ; Extended Processor Info and Feature Bits
cpuid
test edx, (1 << 29) ; 64-bit mode bit
jz error.no64BitMode
; Clear 32-bit register values.
xor eax, eax
xor edx, edx
BiosPrint String.Status.CPU64Detected
.enableSSE:
; Load CPU feature flags into ecx and edx.
mov eax, 1
cpuid
; Check for FXSAVE/FXRSTOR support.
test edx, (1 << 24)
jz error.noFXinst
; Check for SSE1 support.
test edx, (1 << 25)
jz error.noSSE
; Check for SSE2 support.
test edx, (1 << 26)
jz error.noSSE2
; Enable hardware FPU with monitoring.
mov eax, cr0
and eax, ~(1 << 2) ; turn off CR0.EM bit (x87 FPU is present)
or eax, (1 << 1) ; turn on CR0.MP bit (monitor FPU)
mov cr0, eax
; Make sure FXSAVE/FXRSTOR instructions save the contents of the FPU
; MMX, XMM and MXCSR registers. Enable the use of SSE instructions.
; And indicate that the kernel is capable of handling SIMD floating-
; point exceptions.
mov eax, cr4
or eax, (1 << 9) | (1 << 10) ; CR4.OFXSR, CR4.OSXMMEXCPT
mov cr4, eax
BiosPrint String.Status.SSEEnabled
.loadKernel:
sti
lgdt [GDT32.Table.Pointer]
call LoadKernel
jc error.kernelLoadFailed
cli
BiosPrint String.Status.KernelLoaded
.readLayout:
call ReadMemLayout
BiosPrint String.Status.MemoryLayoutReaded
.wipeMemory:
cld
push es
; Wipe the real mode BIOS IVT.
xor ax, ax
mov es, ax
xor di, Mem.BIOS.IVT
mov cx, Mem.BIOS.IVT.Size
rep stosb
; Wipe the real mode BIOS data area.
mov di, Mem.BIOS.Data
mov cx, Mem.BIOS.Data.Size
rep stosb
; Wipe the stage-1 boot loader.
mov di, Mem.Loader1
mov cx, Mem.Loader1.Size
rep stosb
; Wipe the temporary 32-bit protected mode stack.
mov ax, Mem.Stack32.Temp.Bottom >> 4
mov es, ax
xor ax, ax
xor di, di
mov cx, Mem.Stack32.Temp.Top - Mem.Stack32.Temp.Bottom
rep stosb
; Restore original es register.
pop es
.setupGDT64:
; Copy the GDT to its memory layout location.
mov si, GDT64.Table
mov di, Mem.GDT
mov cx, GDT64.Table.Size
shr cx, 1
rep movsw
.setupTSS:
; Copy the TSS entry to its target memory location.
mov si, TSS64.Entry
mov di, Mem.TSS64
mov cx, TSS64.Entry.Size
shr cx, 1
rep movsw
.setupPageTables:
; Create page tables that identity-map the first 10MiB of memory. This
; should be more than enough to hold the kernel and its stacks.
call SetupPageTables
; Enable PAE paging.
mov eax, cr4
or eax, (1 << 5) ; CR4.PAE
mov cr4, eax
.enable64BitMode:
; Enable 64-bit mode and syscall/sysret.
mov ecx, 0xc0000080 ; Extended Feature Enable Register (EFER)
rdmsr
or eax, (1 << 8) | (1 << 0)
wrmsr
; Enable paging and protected mode.
mov eax, cr0
or eax, (1 << 31) | (1 << 0) ; CR0.PG, CR0.PE
mov cr0, eax
; Enable global pages
mov eax, cr4
or eax, (1 << 7) ; CR4.PGE
mov cr4, eax
; Load the 64-bit GDT.
lgdt [GDT64.Table.Pointer]
; Do a long jump using the new GDT, which forces the switch to 64-bit
; mode.
jmp GDT64.Selector.Kernel.Code : .launch64
bits 64
.launch64
; Save CPU feature bits into global memory block
mov eax, 1
cpuid
mov [Globals.CPUFeatureBitsECX], ecx
mov [Globals.CPUFeatureBitsEDX], edx
; Wipe the real mode stack.
xor eax, eax
mov rdi, Mem.Stack.Bottom
mov ecx, Mem.Stack.Top - Mem.Stack.Bottom
rep stosb
; Load the mandatory 64-bit task state segment.
mov ax, GDT64.Selector.TSS
ltr ax
; Set up the data segment registers. Note that in 64-bit mode the CPU
; treats cs, ds, es, and ss as zero regardless of what we store there.
; (gs and fs are exceptions; they can be used as real segment
; registers.)
mov ax, GDT64.Selector.Kernel.Data
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; Set the kernel stack pointer.
mov rsp, Mem.Kernel.Stack.Top
; Initialize all general purpose registers.
xor rax, rax
xor rbx, rbx
xor rcx, rcx
xor rdx, rdx
xor rdi, rdi
xor rsi, rsi
xor rbp, rbp
xor r8, r8
xor r9, r9
xor r10, r10
xor r11, r11
xor r12, r12
xor r13, r13
xor r14, r14
xor r15, r15
; Do a jump to the kernel's entry point.
jmp Mem.Kernel.Code
jmp $
bits 16
error:
.A20:
BiosPrint String.Error.A20
jmp .hang
.noCPUID:
BiosPrint String.Error.NoCPUID
jmp .hang
.no64BitMode:
BiosPrint String.Error.No64BitMode
jmp .hang
.noFXinst:
BiosPrint String.Error.NoFXinst
jmp .hang
.noSSE:
BiosPrint String.Error.NoSSE
jmp .hang
.noSSE2:
BiosPrint String.Error.NoSSE2
jmp .hang
.kernelNotFound:
BiosPrint String.Error.KernelNotFound
jmp .hang
.kernelLoadFailed:
BiosPrint String.Error.KernelLoadFailed
jmp .hang
.hang:
cli
hlt
jmp .hang
ImageName db "KERNEL SYS"
String.Loading db "Loading...", 13, 10, 0
String.Status.A20Enabled db "A20 line enabled", 13, 10, 0
String.Status.CPU64Detected db "64-bit CPU detected", 13, 10, 0
String.Status.SSEEnabled db "SSE enabled", 13, 10, 0
String.Status.KernelLoaded db "Kernel loaded", 13, 10, 0
String.Status.MemoryLayoutReaded db "Memory layout readed", 13, 10, 0
String.Status.JumpingToKernel db "Jumping to kernel", 13, 10, 0
String.Error.A20 db "A20 line not enabled", 13, 10, 0
String.Error.NoCPUID db "CPUID not supported", 13, 10, 0
String.Error.No64BitMode db "CPU is not 64-bit", 13, 10, 0
String.Error.NoFXinst db "No FXSAVE/FXRSTOR", 13, 10, 0
String.Error.NoSSE db "No SSE support", 13, 10, 0
String.Error.NoSSE2 db "No SSE2 support", 13, 10, 0
String.Error.KernelNotFound db "Kernel not found", 13, 10, 0
String.Error.KernelLoadFailed db "Kernel load failed", 13, 10, 0
LoadKernel:
; Preserve registers.
push es
pusha
call LoadRoot
mov bx, Mem.Kernel.LoadBuffer >> 4
xor bp, bp
mov si, ImageName
call LoadFile
mov [LoadKernel.SectorsToCopy], cx ; save size of kernel
cmp ax, 0
jne error.kernelNotFound
.prepareProtected32Mode:
; Disable interrupts until we're out of protected mode and back into
; real mode, since we're not setting up a new interrupt table.
cli
; Enable protected mode.
mov eax, cr0
or eax, (1 << 0) ; CR.PE
mov cr0, eax
; Do a far jump to switch to 32-bit protected mode.
jmp GDT32.Selector.Code32 : .switchToProtected32Mode
bits 32
.switchToProtected32Mode:
; Initialize all data segment registers with the 32-bit protected mode
; data segment selector.
mov ax, GDT32.Selector.Data32
mov ds, ax
mov es, ax
mov ss, ax
; Create a temporary stack used only while in protected mode.
; (probably not necessary since interrupts are disabled)
mov esp, Mem.Stack32.Temp.Top
.copyChunk:
; Set up a copy from lower memory to upper memory using the number of
; sectors.
xor ecx, ecx
xor esi, esi
xor edi, edi
mov bx, [LoadKernel.SectorsToCopy]
mov cx, bx
shl ecx, 11 ; multiply by sector size (2048)
mov esi, Mem.Kernel.LoadBuffer
mov edi, [LoadKernel.TargetPointer]
; Advance counters and pointers.
add [LoadKernel.TargetPointer], ecx
add [LoadKernel.CurrentSector], bx
; Copy the chunk.
cld
shr ecx, 2 ; divide by 4 since we're copying dwords.
rep movsd
.prepareProtected16Mode:
; Before we can switch back to real mode, we have to switch to
; 16-bit protected mode.
jmp GDT32.Selector.Code16 : .switchToProtected16Mode
bits 16
.switchToProtected16Mode:
; Initialize all data segment registers with the 16-bit protected mode
; data segment selector.
mov ax, GDT32.Selector.Data16
mov ds, ax
mov es, ax
mov ss, ax
.prepareRealMode:
; Disable protected mode.
mov eax, cr0
and eax, ~(1 << 0) ; CR0.PE
mov cr0, eax
; Do a far jump to switch back to real mode.
jmp 0x0000 : .switchToRealMode
.switchToRealMode:
; Restore real mode data segment registers.
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
; Restore the real mode stack pointer.
xor esp, esp
mov sp, [LoadKernel.StackPointer]
; Enable interrupts again.
sti
.checkCompletion:
; Check if the copy is complete.
mov ax, [LoadKernel.LastSector]
mov bx, [LoadKernel.CurrentSector]
cmp ax, bx
je .success
.success:
; Clear carry on success.
clc
.done:
; Wipe the sector load buffer.
mov ax, Mem.Kernel.LoadBuffer >> 4
mov es, ax
xor ax, ax
xor di, di
mov cx, Mem.Kernel.LoadBuffer.Size - 1
rep stosb
inc cx
stosb
; Clear upper word of 32-bit registers we used.
xor eax, eax
xor ecx, ecx
xor esi, esi
xor edi, edi
; Restore registers.
popa
pop es
ret
;-----------------------------------------------------------------------------
; LoadKernel state variables
;-----------------------------------------------------------------------------
align 4
LoadKernel.TargetPointer dd Mem.Kernel.Image
LoadKernel.CurrentSector dw 0
LoadKernel.LastSector dw 0
LoadKernel.SectorsToCopy dw 0
LoadKernel.StackPointer dw 0
For all the include files I'll link my git repo since they are a lot https://github.com/Bonfra04/BonsOS/tree/master/boot/include
I've tried to debug with bosch but the only thing I've discovered is thet the function LoadKernel
never returns but if i stick a print before the ret
instruction it executes it.
PS: in the repo exists the boot.asm file witch is the first stage bootloader to load this one.
User contributions licensed under CC BY-SA 3.0