Seabios protected mode transition

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
alexeikom
Posts: 5
Joined: Fri Dec 30, 2016 5:03 am

Seabios protected mode transition

Post by alexeikom »

Exploring the seabios code, I've some question regarding the transition to protected mode.

The documentation says:
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....
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.
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
...
In ljmpl $SEG32_MODE32_CS, $(BUILD_BIOS_ADDR + 1f), SEG32_MODE32_CS selects the gdt record with value 00CF 9B00 0000 FFFF‬.
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
Octocontrabass
Member
Member
Posts: 5581
Joined: Mon Mar 25, 2013 7:01 pm

Re: Seabios protected mode transition

Post by Octocontrabass »

alexeikom wrote:Looks like the ROM is mapped to two locations?
Correct.

The exact mapping will depend on which emulator you're using and how it's configured, but typically the highest 64kB of the ROM is mapped just below 1MB, and the entire ROM is mapped just below 4GB.
Post Reply