Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why BIOS need to compare a value in (seemly) randomized address to zero in the second instruction?

I am trying to learn operating system by diving into the low-level details of it. And the course I'm now on is MIT 6.828 Operating System Engineering. The lab asks students to trace into the BIOS for a few instructions. The first three assembly instructions of BIOS list as folllows:

0xffff0:    ljmp    $0xf000,$0xe05b
0xfe05b:    cmpl    $0x0,%cs:0x6c48
0xfe062:    jne     0xfd2e1

What I can't figure out is the second one: cmpl $0x0,%cs:0x6c48 . What does it do? Why need this condition before jmp to a specific place? I have searched on the web for a while, but still can't find an explanation. And what's trickier is that I find different people get different addresses to compare to, like 0x6ac8, 0x65a4 or 0x6c48 here.

like image 702
Bicheng Avatar asked Dec 25 '19 14:12

Bicheng


1 Answers

What exactly that comparison does will depend on the BIOS manufacturer, but it is clearly some flag for POST (Power on Self Test) processing. Some BIOSes may have completely different code that doesn't look anything like those instructions. Since you are using QEMU, the default BIOS being used is SeaBIOS. That cmpl is to determine if a reboot or a resume is being done:

As noted above, on emulators SeaBIOS handles the 0xFFFF0000:FFF0 machine startup execution vector. This vector is also called on machine faults and on some machine "resume" events. It can also be called (as 0xF0000:FFF0) by software as a request to reboot the machine (on emulators, coreboot, and CSM).

The SeaBIOS "resume and reboot" code handles these calls and attempts to determine the desired action of the caller. Code flow starts in 16bit mode in romlayout.S:reset_vector() which calls romlayout.S:entry_post() which calls romlayout.S:entry_resume() which calls resume.c:handle_resume(). Depending on the request the handle_resume() code may transition to 32bit mode.

You can look at the source code for the SeaBIOS for the entry_post code which is where the jmp $0xf000,$0xe05b takes you: .

        ORG 0xe05b
entry_post:
        cmpl $0, %cs:HaveRunPost                // Check for resume/reboot
        jnz entry_resume
        ENTRY_INTO32 _cfunc32flat_handle_post   // Normal entry point

If the 32-bit value at %cs:HaveRunPost is not zero then it is a resume operation, otherwise it is a reboot operation. The address of HaveRunPost or any internal BIOS variables may differ between one version of a SeaBIOS to another. This may because of changes to code between versions; compiler/compiler options used to build the ROM; BIOS features chosen etc.

like image 127
Michael Petch Avatar answered Sep 23 '22 16:09

Michael Petch