1This page provides a high-level description of some of the major code 2phases that SeaBIOS transitions through and general information on 3overall code flow. 4 5SeaBIOS code phases 6=================== 7 8The SeaBIOS code goes through a few distinct code phases during its 9execution lifecycle. Understanding these code phases can help when 10reading and enhancing the code. 11 12POST phase 13---------- 14 15The Power On Self Test (POST) phase is the initialization phase of the 16BIOS. This phase is entered when SeaBIOS first starts execution. The 17goal of the phase is to initialize internal state, initialize external 18interfaces, detect and setup hardware, and to then start the boot 19phase. 20 21On emulators, this phase starts when the CPU starts execution in 16bit 22mode at 0xFFFF0000:FFF0. The emulators map the SeaBIOS binary to this 23address, and SeaBIOS arranges for romlayout.S:reset_vector() to be 24present there. This code calls romlayout.S:entry_post() which then 25calls post.c:handle_post() in 32bit mode. 26 27On coreboot, the build arranges for romlayout.S:entry_elf() to be 28called in 32bit mode. This then calls post.c:handle_post(). 29 30On CSM, the build arranges for romlayout.S:entry_csm() to be called 31(in 16bit mode). This then calls csm.c:handle_csm() in 32bit mode. 32Unlike on the emulators and coreboot, the SeaBIOS CSM POST phase is 33orchestrated with UEFI and there are several calls back and forth 34between SeaBIOS and UEFI via handle_csm() throughout the POST 35process. 36 37The POST phase itself has several sub-phases. 38 39* The "preinit" sub-phase: code run prior to [code relocation](Linking overview#Code relocation). 40* The "init" sub-phase: code to initialize internal variables and 41 interfaces. 42* The "setup" sub-phase: code to setup hardware and drivers. 43* The "prepboot" sub-phase: code to finalize interfaces and prepare 44 for the boot phase. 45 46At completion of the POST phase, SeaBIOS invokes an "int 0x19" 47software interrupt in 16bit mode which begins the boot phase. 48 49Boot phase 50---------- 51 52The goal of the boot phase is to load the first portion of the 53operating system's boot loader into memory and start execution of that 54boot loader. This phase starts when a software interrupt ("int 0x19" 55or "int 0x18") is invoked. The code flow starts in 16bit mode in 56romlayout.S:entry_19() or romlayout.S:entry_18() which then 57transition to 32bit mode and call boot.c:handle_19() or 58boot.c:handle_18(). 59 60The boot phase is technically also part of the "runtime" phase of 61SeaBIOS. It is typically invoked immediately after the POST phase, 62but it can also be invoked by an operating system or be invoked 63multiple times in an attempt to find a valid boot media. Although the 64boot phase C code runs in 32bit mode it does not have write access to 65the 0x0f0000-0x100000 memory region and can not call the various 66malloc_X() calls. See [Memory Model](Memory Model) for 67more information. 68 69Main runtime phase 70------------------ 71 72The main runtime phase occurs after the boot phase starts the 73operating system. Once in this phase, the SeaBIOS code may be invoked 74by the operating system using various 16bit and 32bit calls. The goal 75of this phase is to support these legacy calling interfaces and to 76provide compatibility with BIOS standards. There are multiple entry 77points for the BIOS - see the entry_XXX() assembler functions in 78romlayout.S. 79 80Callers use most of these legacy entry points by setting up a 81particular CPU register state, invoking the BIOS, and then inspecting 82the returned CPU register state. To handle this, SeaBIOS will backup 83the current register state into a "struct bregs" (see romlayout.S, 84entryfuncs.S, and bregs.h) on call entry and then pass this struct to 85the C code. The C code can then inspect the register state and modify 86it. The assembler entry functions will then restore the (possibly 87modified) register state from the "struct bregs" on return to the 88caller. 89 90Resume and reboot 91----------------- 92 93As noted above, on emulators SeaBIOS handles the 0xFFFF0000:FFF0 94machine startup execution vector. This vector is also called on 95machine faults and on some machine "resume" events. It can also be 96called (as 0xF0000:FFF0) by software as a request to reboot the 97machine (on emulators, coreboot, and CSM). 98 99The SeaBIOS "resume and reboot" code handles these calls and attempts 100to determine the desired action of the caller. Code flow starts in 10116bit mode in romlayout.S:reset_vector() which calls 102romlayout.S:entry_post() which calls romlayout.S:entry_resume() which 103calls resume.c:handle_resume(). Depending on the request the 104handle_resume() code may transition to 32bit mode. 105 106Technically this code is part of the "runtime" phase, so even though 107parts of it run in 32bit mode it still has the same limitations of the 108runtime phase. 109 110Threads 111======= 112 113Internally SeaBIOS implements a simple cooperative multi-tasking 114system. The system works by giving each "thread" its own stack, and 115the system round-robins between these stacks whenever a thread issues 116a yield() call. This "threading" system may be more appropriately 117described as [coroutines](http://en.wikipedia.org/wiki/Coroutine). 118These "threads" do not run on multiple CPUs and are not preempted, so 119atomic memory accesses and complex locking is not required. 120 121The goal of these threads is to reduce overall boot time by 122parallelizing hardware delays. (For example, by allowing the wait for 123an ATA hard drive to spin-up and respond to commands to occur in 124parallel with the wait for a PS/2 keyboard to respond to a setup 125command.) These hardware setup threads are only available during the 126"setup" sub-phase of the [POST phase](#POST_phase). 127 128The code that implements threads is in stacks.c. 129 130Hardware interrupts 131=================== 132 133The SeaBIOS C code always runs with hardware interrupts disabled. All 134of the C code entry points (see romlayout.S) are careful to explicitly 135disable hardware interrupts (via "cli"). Because running with 136interrupts disabled increases interrupt latency, any C code that could 137loop for a significant amount of time (more than about 1 ms) should 138periodically call yield(). The yield() call will briefly enable 139hardware interrupts to occur, then disable interrupts, and then resume 140execution of the C code. 141 142There are two main reasons why SeaBIOS always runs C code with 143interrupts disabled. The first reason is that external software may 144override the default SeaBIOS handlers that are called on a hardware 145interrupt event. Indeed, it is common for DOS based applications to do 146this. These legacy third party interrupt handlers may have 147undocumented expectations (such as stack location and stack size) and 148may attempt to call back into the various SeaBIOS software services. 149Greater compatibility and more reproducible results can be achieved by 150only permitting hardware interrupts at specific points (via yield() 151calls). The second reason is that much of SeaBIOS runs in 32bit mode. 152Attempting to handle interrupts in both 16bit mode and 32bit mode and 153switching between modes to delegate those interrupts is an unneeded 154complexity. Although disabling interrupts can increase interrupt 155latency, this only impacts legacy systems where the small increase in 156interrupt latency is unlikely to be noticeable. 157 158Extra 16bit stack 159================= 160 161SeaBIOS implements 16bit real mode handlers for both hardware 162interrupts and software request "interrupts". In a traditional BIOS, 163these requests would use the caller's stack space. However, the 164minimum amount of space the caller must provide has not been 165standardized and very old DOS programs have been observed to allocate 166very small amounts of stack space (100 bytes or less). 167 168By default, SeaBIOS now switches to its own stack on most 16bit real 169mode entry points. This extra stack space is allocated in ["low 170memory"](Memory Model). It ensures SeaBIOS uses a minimal amount of a 171callers stack (typically no more than 16 bytes) for these legacy 172calls. (More recently defined BIOS interfaces such as those that 173support 16bit protected and 32bit protected mode calls standardize a 174minimum stack size with adequate space, and SeaBIOS generally will not 175use its extra stack in these cases.) 176 177The code to implement this stack "hopping" is in romlayout.S and in 178stacks.c. 179