Loading kernel from second stage bootloader

-2

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.

assembly
x86
bootloader
osdev
fat
asked on Stack Overflow Jul 3, 2020 by Bonfra • edited Jul 3, 2020 by Michael Petch

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0