The documentation says:
This means that the BIOS ROM is mapped to 256 KiB below the 4GB memory bound. And the PC starts in real mode with CS=0xf000 and IP=0xfff0.On emulators, this phase starts when the CPU starts execution in 16bit mode at 0xFFFF0000:FFF0. The emulators map the SeaBIOS binary to this address, and SeaBIOS arranges for romlayout.S:reset_vector() to be present there....
From the 'reset_vector' label (at 0xffff0) we jump to 'entry_post' and from there to 'transition32' label (all these are in romlayout.S). This is the code:
Code: Select all
...
transition32:
// Disable irqs (and clear direction flag)
cli
cld
// Disable nmi
movl %eax, %ecx
movl $CMOS_RESET_CODE|NMI_DISABLE_BIT, %eax
outb %al, $PORT_CMOS_INDEX
inb $PORT_CMOS_DATA, %al
// enable a20
inb $PORT_A20, %al
orb $A20_ENABLE_BIT, %al
outb %al, $PORT_A20
movl %ecx, %eax
transition32_nmi_off:
// Set segment descriptors
lidtw %cs:pmode_IDT_info
lgdtw %cs:rombios32_gdt_48
// Enable protected mode
movl %cr0, %ecx
andl $~(CR0_PG|CR0_CD|CR0_NW), %ecx
orl $CR0_PE, %ecx
movl %ecx, %cr0
// start 32bit protected mode code
ljmpl $SEG32_MODE32_CS, $(BUILD_BIOS_ADDR + 1f)
.code32
// init data segments
1: movl $SEG32_MODE32_DS, %ecx
movw %cx, %ds
movw %cx, %es
movw %cx, %ss
movw %cx, %fs
movw %cx, %gs
jmpl *%edx
...
This is a flat code segment with base=0 and limit=0xfffff which spans the whole 4GB of memory. The "+1f " expands to 0xfcf6c and that is where the code with label "1:" is present.
But this jumps to absolute address base+offset=0x0+0xfcf6c which is below 1MB. The BIOS code located in base+offset=0x0+0xffffcf6c=0xffffcf6c. Then where do we jump?
What am I missing? I'm debugging seabios with qemu + gdb. When reading memory in gdb I get 0xfcf6c = 0xffffcf6c. Looks like the ROM is mapped to two locations? Is this something like QEMU BIOS shadowing? Didn't find a lot about that in google...
Would be grateful for an explanation!
Alexei