1 The SeaBIOS code is required to support multiple x86 CPU memory
2 models. This requirement impacts the code layout and internal storage
8 The x86 line of CPUs has evolved over many years. The original 8086
9 chip used 16bit pointers and could only address 1 megabyte of memory.
10 The 80286 CPU still used 16bit pointers, but could address up to 16
11 megabytes of memory. The 80386 chips could process 32bit instructions
12 and could access up to 4 gigabyte of memory. The most recent x86 chips
13 can process 64bit instructions and access 16 exabytes of ram.
15 During the evolution of the x86 CPUs from the 8086 to the 80386 the
16 BIOS was extended to handle calls in the various modes that the CPU
19 This section outlines the five different x86 CPU execution and memory
20 access models that SeaBIOS supports.
26 [segmented](http://en.wikipedia.org/wiki/Memory_segmentation) memory
27 mode invoked by callers. The CPU defaults to executing 16bit
28 instructions. Callers typically invoke the BIOS by issuing an "int x"
29 instruction which causes a software
30 [interrupt](http://en.wikipedia.org/wiki/Interrupt) that is handled by
31 the BIOS. The SeaBIOS code also handles hardware interrupts in this
32 mode. SeaBIOS can only access the first 1 megabyte of memory in this
33 mode, but it can access any part of that first megabyte.
38 This mode is a segmented memory mode that is used for [option
39 roms](http://en.wikipedia.org/wiki/Option_ROM). The CPU defaults to
40 executing 16bit instructions and segmented memory accesses are still
41 used. However, the segment limits are increased so that the entire
42 first 4 gigabytes of memory is fully accessible. Callers can invoke
43 all the [16bit real mode](#16bit_real_mode) functions while in this
44 mode and can also invoke the Post Memory Manager (PMM) functions that
45 are available during option rom execution.
50 CPU execution in this mode is similar to [16bit real
51 mode](#16bit_real_mode). The CPU defaults to executing 16bit
52 instructions. However, each segment register indexes a "descriptor
53 table", and it is difficult or impossible to know what the physical
54 address of each segment is. Generally speaking, the BIOS can only
55 access code and data in the f-segment. The PCIBIOS, APM BIOS, and PNP
56 BIOS all have documented 16bit protected mode entry points.
58 Some old code may attempt to invoke the standard [16bit real
59 mode](#16bit_real_mode) entry points while in 16bit protected
60 mode. The PCI BIOS specification explicitly requires that the legacy
61 "int 1a" real mode entry point support 16bit protected mode calls if
62 they are for the PCI BIOS. Callers of other legacy entry points in
63 protected mode have not been observed and SeaBIOS does not support
69 In this mode the processor runs in 32bit mode, but the segment
70 registers may have a limit and may have a non-zero offset. In effect,
71 this mode has all of the limitations of [16bit protected
72 mode](#16bit_protected_mode) - the main difference between the modes
73 is that the processor defaults to executing 32bit instructions. In
74 addition to these limitations, callers may also run the SeaBIOS code
75 at varying virtual addresses and so the code must support code
76 relocation. The PCI BIOS specification and APM BIOS specification
77 define 32bit segmented mode interfaces.
82 In this mode the processor defaults to executing 32bit instructions,
83 and all segment registers have an offset of zero and allow access to
84 the entire first 4 gigabytes of memory. This is the only "sane" mode
85 for 32bit code - modern compilers and modern operating systems will
86 generally only support this mode (when running 32bit code).
87 Ironically, it's the only mode that is not strictly required for a
88 BIOS to support. SeaBIOS uses this mode internally to support the POST
89 and BOOT [phases of execution](Execution and code flow).
94 In order to produce code that can run when the processor is in a 16bit
95 mode, SeaBIOS uses the
96 [binutils](http://en.wikipedia.org/wiki/GNU_Binutils) ".code16gcc"
97 assembler flag. This instructs the assembler to emit extra prefix
98 opcodes so that the 32bit code produced by
99 [gcc](http://en.wikipedia.org/wiki/GNU_Compiler_Collection) will run
100 even when the processor is in 16bit mode. Note that gcc always
101 produces 32bit code - it does not know about the ".code16gcc" flag and
102 does not know that the code will run in a 16bit mode.
104 SeaBIOS uses the same code for all of the 16bit modes ([16bit real
105 mode](#16bit_real_mode), [16bit bigreal mode](#16bit_bigreal_mode),
106 and [16bit protected mode](#16bit_protected_mode)) and that code is
107 assembled using ".code16gcc". SeaBIOS is careful to use segment
108 registers properly so that the same code can run in the different
109 16bit modes that it needs to support.
114 Two compile time flags are available to determine the memory model the
115 code is intended for: MODE16 and MODESEGMENT. When compiling for the
116 16 bit modes, MODE16 is true and MODESEGMENT is true. In 32bit
117 segmented mode, MODE16 is false and MODESEGMENT is true. In 32bit flat
118 mode both MODE16 and MODESEGMENT are false.
120 Common memory used at run-time
121 ==============================
123 There are several memory areas that the SeaBIOS "runtime"
124 [phase](Execution and code flow) makes use of:
126 * 0x000000-0x000400: Interrupt descriptor table (IDT). This area
127 defines 256 interrupt vectors as defined by the Intel CPU
128 specification for 16bit irq handlers. This area is read/writable at
129 runtime and can be accessed from 16bit real mode and 16bit bigreal
130 mode calls. SeaBIOS only uses this area to maintain compatibility
133 * 0x000400-0x000500: BIOS Data Area (BDA). This area contains various
134 legacy flags and attributes. The area is read/writable at runtime
135 and can be accessed from 16bit real mode and 16bit bigreal mode
136 calls. SeaBIOS only uses this area to maintain compatibility with
139 * 0x09FC00-0x0A0000 (typical): Extended BIOS Data Area (EBDA). This
140 area contains a few legacy flags and attributes. The area is
141 typically located at 0x9FC00, but it can be moved by option roms, by
142 legacy operating systems, and by SeaBIOS if
143 CONFIG_MALLOC_UPPERMEMORY is not set. Its actual location is
144 determined by a pointer in the BDA. The area is read/writable at
145 runtime and can be accessed from 16bit real mode and 16bit bigreal
146 mode calls. SeaBIOS only uses this area to maintain compatibility
149 * 0x0E0000-0x0F0000 (typical): "low" memory. This area is used for
150 custom read/writable storage internal to SeaBIOS. The area is
151 read/writable at runtime and can be accessed from 16bit real mode
152 and 16bit bigreal mode calls. The area is typically located at the
153 end of the e-segment, but the build may position it anywhere in the
154 0x0C0000-0x0F0000 region. However, if CONFIG_MALLOC_UPPERMEMORY is
155 not set, then this region is between 0x090000-0x0A0000. Space is
156 allocated in this region by either marking a global variable with
157 the "VARLOW" flag or by calling malloc_low() during
158 initialization. The area can be grown dynamically (via malloc_low),
159 but it will never exceed 64K.
161 * 0x0F0000-0x100000: The BIOS segment. This area is used for both
162 runtime code and static variables. Space is allocated in this region
163 by either marking a global variable with VAR16, one of the VARFSEG
164 flags, or by calling malloc_fseg() during initialization. The area
165 is read-only at runtime and can be accessed from 16bit real mode,
166 16bit bigreal mode, 16bit protected mode, and 32bit segmented mode
169 All of the above areas are also read/writable during the SeaBIOS
170 initialization phase and are accessible when in 32bit flat mode.
172 Segmented mode memory access
173 ============================
175 The assembler entry functions for segmented mode calls (all modes
176 except [32bit flat mode](#32bit_flat_mode)) will arrange
177 to set the data segment (%ds) to be the same as the stack segment
178 (%ss) before calling any C code. This permits all C variables located
179 on the stack and C pointers to data located on the stack to work as
182 However, all code running in segmented mode must wrap non-stack memory
183 accesses in special macros. These macros ensure the correct segment
184 register is used. Failure to use the correct macro will result in an
185 incorrect memory access that will likely cause hard to find errors.
187 There are three low-level memory access macros:
189 * GET_VAR / SET_VAR : Accesses a variable using the specified segment
190 register. This isn't typically used directly by C code.
192 * GET_FARVAR / SET_FARVAR : Assigns the extra segment (%es) to the
193 given segment id and then performs the given memory access via %es.
195 * GET_FLATVAR / SET_FLATVAR : These macros take a 32bit pointer,
196 construct a segment/offset pair valid in real mode, and then perform
197 the given access. These macros must not be used in 16bit protected
198 mode or 32bit segmented mode.
200 Since most memory accesses are to [common memory used at
201 run-time](#Common_memory_used_at_run-time), several helper
202 macros are also available.
204 * GET_IDT / SET_IDT : Access the interrupt descriptor table (IDT).
206 * GET_BDA / SET_BDA : Access the BIOS Data Area (BDA).
208 * GET_EBDA / SET_EBDA : Access the Extended BIOS Data Area (EBDA).
210 * GET_LOW / SET_LOW : Access internal variables marked with
211 VARLOW. (There are also related macros GET_LOWFLAT / SET_LOWFLAT for
212 accessing storage allocated with malloc_low).
214 * GET_GLOBAL : Access internal variables marked with the VAR16 or
215 VARFSEG flags. (There is also the related macro GET_GLOBALFLAT for
216 accessing storage allocated with malloc_fseg).
218 Memory available during initialization
219 ======================================
221 During the POST [phase](Execution and code flow) the code
222 can fully access the first 4 gigabytes of memory. However, memory
223 accesses are generally limited to the [common memory used at
224 run-time](#Common_memory_used_at_run-time) and areas
225 allocated at runtime via one of the malloc calls:
227 * malloc_high : Permanent high-memory zone. This area is used for
228 custom read/writable storage internal to SeaBIOS. The area is
229 located at the top of the first 4 gigabytes of ram. It is commonly
230 used for storing standard tables accessed by the operating system at
231 runtime (ACPI, SMBIOS, and MPTable) and for DMA buffers used by
232 hardware drivers. The area is read/writable at runtime and an entry
233 in the e820 memory map is used to reserve it. When running on an
234 emulator that has only 1 megabyte of ram this zone will be empty.
236 * malloc_tmphigh : Temporary high-memory zone. This area is used for
237 custom read/writable storage during the SeaBIOS initialization
238 phase. The area generally starts after the first 1 megabyte of ram
239 (0x100000) and ends prior to the Permanent high-memory zone. When
240 running on an emulator that has only 1 megabyte of ram this zone
241 will be empty. The area is not reserved from the operating system,
242 so it must not be accessed after the SeaBIOS initialization phase.
244 * malloc_tmplow : Temporary low-memory zone. This area is used for
245 custom read/writable storage during the SeaBIOS initialization
246 phase. The area resides between 0x07000-0x90000. The area is not
247 reserved from the operating system and by specification it is
248 required to be zero'd at the end of the initialization phase.
250 The "tmplow" and "tmphigh" regions are only available during the
251 initialization phase. Any access (either read or write) after
252 completion of the initialization phase can result in difficult to find