My current problem is: QEMU maps the BIOS ROM to two locations:
- Everything to 0xffff0000 (if the BIOS is 64KiB, not sure if larger).
- The last 64KiB to 0xf0000.
Code: Select all
Trace 0: 0x7f87d4000100 [ffff0000/00000000fffffff0/00000040/ff020e01]
EAX=00000000 EBX=00000000 ECX=00000000 EDX=00060fb1
ESI=00000000 EDI=00000000 EBP=00000000 ESP=00000000
EIP=0000fff0 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0000 00000000 0000ffff 00009300
CS =f000 ffff0000 0000ffff 00009b00
SS =0000 00000000 0000ffff 00009300
DS =0000 00000000 0000ffff 00009300
FS =0000 00000000 0000ffff 00009300
GS =0000 00000000 0000ffff 00009300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT= 00000000 0000ffff
IDT= 00000000 0000ffff
CR0=60000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000000 CCO=EFLAGS
EFER=0000000000000000
Code: Select all
.equ PML4_BASE, 0x0000
.equ PDPT_BASE, 0x1000
.equ PD_BASE , 0x2000
.equ PT_BASE , 0x3000
.equ GDT_BASE , 0x4000
.equ CODE64_BASE, 0x5000
.equ CODE32_BASE, 0xf000
.equ REAL_BIOS_BASE, 0xffff0000
...
. = GDT_BASE
gdt:
segm 0, 0, 0, 0 # null
segm 0, 0xfffff, 0b10011011, 0b1010 # code64 (access: P, S, E, RW, A) (flags: G, L)
segm 0, 0xfffff, 0b10010011, 0b1010 # data64 (access: P, S, RW, A) (flags: G, L)
segm 0, 0xfffff, 0b10011011, 0b1100 # code32 (access: P, S, E, RW, A) (flags: G, DS)
segm 0, 0xfffff, 0b10010011, 0b1100 # data32 (access: P, S, RW, A) (flags: G, DS)
segm 0xffff0000, 16, 0b10011011, 0b1100 # code32 (access: P, S, E, RW, A) (flags: G, DS)
gdt_end:
gdtr:
.word gdt_end - gdt - 1
.long 0xf0000 + GDT_BASE
...
. = CODE32_BASE
.code32
main32:
jmp (3*8):REAL_BIOS_BASE + CODE32_BASE + (main32_s - main32)
main32_s:
# https://wiki.osdev.org/Entering_Long_Mode_Directly
mov eax, REAL_BIOS_BASE + PML4_BASE
mov cr3, eax
mov eax, 0b10100000 # PAE, PGE
mov cr4, eax
mov ecx, 0xc0000080 # IA32_EFER
rdmsr
or eax, (1 << 11) | (1 << 8) | (1 << 0) # NXE, LME, SCE
wrmsr
mov eax, 0x80000001 # PG, PE
mov cr0, eax
jmp (1*8):REAL_BIOS_BASE + CODE64_BASE
. = 0xfff0
.code16
_start:
lgdt cs:[gdtr]
mov al, 1 # PE
mov cr0, eax
jmp (5*8):CODE32_BASE
Issue now is:
Code: Select all
...
.section .init32, "x"
main32_trampoline:
jmp (3*8):main32
.section .init, "x"
.code16
_start:
lgdt cs:[gdtr]
mov al, 1 # PE
mov cr0, eax
jmp (5*8):main32_trampoline
Code: Select all
/tmp/qemubios.o: in function `_start':
(.init+0x4): relocation truncated to fit: R_X86_64_16 against `.text'+4030
(.init+0xc): relocation truncated to fit: R_X86_64_16 against `.init32'
My current linker script is:
Code: Select all
OUTPUT_FORMAT("binary")
MEMORY {
rom (rx) : org = 0xffff0000, l = 0x10000
init32 (x) : org = 0xffffffe0, l = 0x10
init (x) : org = 0xfffffff0, l = 0x10
}
SECTIONS {
/DISCARD/ : { *(.note .note*) }
.text : AT(0xffff0000) {
*(.text .text*)
} > rom =0
.init32 : AT(0xffffffe0) {
*(.init32 .init32*)
} > init32 =0
.init : AT(0xfffffff0) {
KEEP(*(.init .init*))
} > init =0
}
====================
In the meantime, I got things to work with:
Code: Select all
.section .gdt, "a"
gdt:
segm 0, 0, 0, 0 # null
segm 0, 0xfffff, 0b10011011, 0b1010 # code64 (access: P, S, E, RW, A) (flags: G, L)
segm 0, 0xfffff, 0b10010011, 0b1010 # data64 (access: P, S, RW, A) (flags: G, L)
segm 0, 0xfffff, 0b10011011, 0b1100 # code32 (access: P, S, E, RW, A) (flags: G, DS)
segm 0, 0xfffff, 0b10010011, 0b1100 # data32 (access: P, S, RW, A) (flags: G, DS)
segm 0xffff0000, 16, 0b10011011, 0b1100 # code32 (access: P, S, E, RW, A) (flags: G, DS)
gdt_end:
.section .gdtr, "a"
gdtr:
.word gdt_end - gdt - 1
.long LDFIX_gdt
.byte 0xcc
.section .init32, "ax"
.code32
main32_trampoline:
jmp (3*8):main32
.section .init, "ax"
.code16
_start:
lgdt cs:[LDFIX_gdtr]
mov al, 1 # PE
mov cr0, eax
jmp (5*8):LDFIX_main32_trampoline
Code: Select all
OUTPUT_FORMAT("binary")
MEMORY {
rom (rx) : org = 0xffff0000, l = 0x10000
gdt (r) : org = 0xffffffb0, l = 8*6
gdtr (r) : org = 0xffffffe0, l = 8
init32 (x) : org = 0xffffffe8, l = 8
init (x) : org = 0xfffffff0, l = 16
}
LDFIX_gdt = 0xfffb0;
LDFIX_gdtr = 0xffe0;
LDFIX_main32_trampoline = 0xffe8;
SECTIONS {
/DISCARD/ : { *(.note .note*) } /* **** OFF */
.text : AT(0xffff0000) {
*(.text .text*)
} > rom =0
.gdt : AT(0xffffffb0) {
KEEP(*(.gdt))
} > gdt =0
.gdtr : AT(0xffffffe0) {
KEEP(*(.gdtr))
} > gdtr =0
.init32 : AT(0xffffffe8) {
KEEP(*(.init32))
} > init32 =0
.init : AT(0xfffffff0) {
KEEP(*(.init))
} > init =0
}

