Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protected Mode Addressing

I am trying out boot loader development tutorials. I am able to read stage2 boot loader using FAT12 conventions. Now I am trying to load kernel in real mode and later copy it to 0x0100000 address.

I am getting triple fault while copying + jumping to 0x0100000. Basically I am not able figure out how to access or jump to 0x0100000.

My code works when I use

IMAGE_PMODE_BASE equ 0x1000
IMAGE_RMODE_BASE equ 0x1000

krnl32.bin: boot/kernel_entry.o ${OBJ}
    i386-elf-ld -o $@ -Ttext 0x01000 $^ --oformat binary

What is it I am missing ? I read about descriptor: offset addressing in protected mode, it says DESC: OFFSET(16 bit). Also offset is multiplied with 4KB using granularity setting in GDT.

I have set up gdt like this:

gdt_start: 
    dd 0                ; null descriptor
    dd 0 

; gdt code:             ; code descriptor
    dw 0FFFFh           ; limit low
    dw 0                ; base low
    db 0                ; base middle
    db 10011010b        ; access
    db 11001111b        ; granularity
    db 0                ; base high

; gdt data:             ; data descriptor
    dw 0FFFFh           ; limit low (Same as code)10:56 AM 7/8/2007
    dw 0                ; base low
    db 0                ; base middle
    db 10010010b        ; access
    db 11001111b        ; granularity
    db 0                ; base high

end_of_gdt:
toc: 
    dw end_of_gdt - gdt_start - 1   ; limit (Size of GDT)
    dd gdt_start            ; base of GDT

; give the descriptor offsets names

NULL_DESC equ 0
CODE_DESC equ 0x8
DATA_DESC equ 0x10

I am linking kernel as below:

krnl32.bin: boot/kernel_entry.o ${OBJ}
    i386-elf-ld -o $@ -Ttext 0x0100000 $^ --oformat binary

Stage 2 boot loader

[bits 16]
[org 0x500]

jmp main

%include "boot/stage2/print16.s"
%include "boot/stage2/print32.s"
%include "boot/stage2/floppy16_driver.s"
%include "boot/stage2/fat12.s"
%include "boot/stage2/gdt.s"
%include "boot/stage2/a20.s"

;*******************************************************
;   Data Section
;*******************************************************

msgFailure db 0x0D, 0x0A, "Failed", 0x00
welcomeMessage db 0x0D, 0x0A, "Landed in STAGE TWO...", 0x00
enableA20Msg db 0x0D, 0x0A, "Enabled A20. Installed GDT", 0x00
ImageName     db "KRNL32  BIN"
ImageSize     db 0
IMAGE_PMODE_BASE equ 0xffff
IMAGE_RMODE_BASE equ 0x1000


main:
    ;-------------------------------;
    ;   Setup segments and stack    ;
    ;-------------------------------;

    cli                    ; clear interrupts
    xor     ax, ax             ; null segments
    mov     ds, ax
    mov     es, ax
    mov     ax, 0x0000         ; stack begins at 0x9000-0xffff
    mov     ss, ax
    mov     sp, 0xFFFF
    sti                    ; enable interrupts

    mov si, welcomeMessage
    call Print16

    call    _EnableA20
    call    InstallGDT
    sti
    mov si, enableA20Msg
    call Print16

    call    LoadRoot
    mov     ebx, 0
    mov     ebp, IMAGE_RMODE_BASE
    mov     esi, ImageName
    call    LoadFile        ; load our file
    mov     dword [ImageSize], ecx
    cmp     ax, 0
    je      EnterStage3
    mov     si, msgFailure
    call    Print16
    mov     ah, 0
    int     0x16                    ; await keypress
    int     0x19                    ; warm boot computer

    jmp $;

EnterStage3:

    cli   
    mov eax, cr0
    or  eax, 1
    mov cr0, eax

    jmp CODE_DESC:Stage3           


[bits 32]
Stage3:
    mov ax, DATA_DESC       ; set data segments to data selector (0x10)
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov esp, 90000h     ; stack begins from 90000h

CopyImage:
    mov eax, dword [ImageSize]
    movzx   ebx, word [bpbBytesPerSector]
    mul ebx
    mov ebx, 4
    div ebx
    cld
    mov    esi, IMAGE_RMODE_BASE
    mov edi, IMAGE_PMODE_BASE
    mov ecx, eax
    rep movsd                   ; copy image to its protected mode address
    jmp IMAGE_PMODE_BASE
    jmp $; 
like image 700
zero Avatar asked Dec 31 '25 09:12

zero


1 Answers

You set up a GDT that has a 32-bit Descriptor for code and 32-bit descriptor for data. In protected mode the registers CS/DS/ES/SS/FS/GS are no longer segment registers in the sense they were seen in real mode. In protected mode they contain a selector that points to an entry in the GDT (or an LDT). This code loads the data registers:

mov ax, DATA_DESC       ; set data segments to data selector (0x10)
mov ds, ax
mov ss, ax
mov es, ax

You can't set the CS register like this. A FAR jmp can set both the code segment selector you want and sets the offset in one instruction. That is what this instruction does:

jmp CODE_DESC:Stage3

Your GDT is set up with code and data descriptors that are a 4gb flat memory model where the base is 0x00000000 and limit is 0xffffffff. This means once in protected mode and you are using selectors that point at these descriptors you can access all memory directly from 0x00000000 to 0xffffffff. This means that all you need to do is jmp 0x100000 to jump to memory address 0x100000. In your code you'll want to use 0x100000 as not only the place to jump to but also the memory location your memory copy uses as its base.

With that in mind, the simple fix is to change:

IMAGE_PMODE_BASE equ 0x1000

to:

IMAGE_PMODE_BASE equ 0x100000
like image 130
Michael Petch Avatar answered Jan 04 '26 20:01

Michael Petch



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!