1The SeaBIOS code is required to support multiple x86 CPU memory
2models. This requirement impacts the code layout and internal storage
3of SeaBIOS.
4
5x86 Memory Models
6=================
7
8The x86 line of CPUs has evolved over many years. The original 8086
9chip used 16bit pointers and could only address 1 megabyte of memory.
10The 80286 CPU still used 16bit pointers, but could address up to 16
11megabytes of memory. The 80386 chips could process 32bit instructions
12and could access up to 4 gigabyte of memory. The most recent x86 chips
13can process 64bit instructions and access 16 exabytes of ram.
14
15During the evolution of the x86 CPUs from the 8086 to the 80386 the
16BIOS was extended to handle calls in the various modes that the CPU
17implemented.
18
19This section outlines the five different x86 CPU execution and memory
20access models that SeaBIOS supports.
21
2216bit real mode
23---------------
24
25This mode is a
26[segmented](http://en.wikipedia.org/wiki/Memory_segmentation) memory
27mode invoked by callers. The CPU defaults to executing 16bit
28instructions. Callers typically invoke the BIOS by issuing an "int x"
29instruction which causes a software
30[interrupt](http://en.wikipedia.org/wiki/Interrupt) that is handled by
31the BIOS. The SeaBIOS code also handles hardware interrupts in this
32mode. SeaBIOS can only access the first 1 megabyte of memory in this
33mode, but it can access any part of that first megabyte.
34
3516bit bigreal mode
36------------------
37
38This mode is a segmented memory mode that is used for [option
39roms](http://en.wikipedia.org/wiki/Option_ROM). The CPU defaults to
40executing 16bit instructions and segmented memory accesses are still
41used. However, the segment limits are increased so that the entire
42first 4 gigabytes of memory is fully accessible. Callers can invoke
43all the [16bit real mode](#16bit_real_mode) functions while in this
44mode and can also invoke the Post Memory Manager (PMM) functions that
45are available during option rom execution.
46
4716bit protected mode
48--------------------
49
50CPU execution in this mode is similar to [16bit real
51mode](#16bit_real_mode). The CPU defaults to executing 16bit
52instructions. However, each segment register indexes a "descriptor
53table", and it is difficult or impossible to know what the physical
54address of each segment is. Generally speaking, the BIOS can only
55access code and data in the f-segment. The PCIBIOS, APM BIOS, and PNP
56BIOS all have documented 16bit protected mode entry points.
57
58Some old code may attempt to invoke the standard [16bit real
59mode](#16bit_real_mode) entry points while in 16bit protected
60mode. The PCI BIOS specification explicitly requires that the legacy
61"int 1a" real mode entry point support 16bit protected mode calls if
62they are for the PCI BIOS. Callers of other legacy entry points in
63protected mode have not been observed and SeaBIOS does not support
64them.
65
6632bit segmented mode
67--------------------
68
69In this mode the processor runs in 32bit mode, but the segment
70registers may have a limit and may have a non-zero offset. In effect,
71this mode has all of the limitations of [16bit protected
72mode](#16bit_protected_mode) - the main difference between the modes
73is that the processor defaults to executing 32bit instructions. In
74addition to these limitations, callers may also run the SeaBIOS code
75at varying virtual addresses and so the code must support code
76relocation. The PCI BIOS specification and APM BIOS specification
77define 32bit segmented mode interfaces.
78
7932bit flat mode
80---------------
81
82In this mode the processor defaults to executing 32bit instructions,
83and all segment registers have an offset of zero and allow access to
84the entire first 4 gigabytes of memory. This is the only "sane" mode
85for 32bit code - modern compilers and modern operating systems will
86generally only support this mode (when running 32bit code).
87Ironically, it's the only mode that is not strictly required for a
88BIOS to support. SeaBIOS uses this mode internally to support the POST
89and BOOT [phases of execution](Execution and code flow).
90
91code16gcc
92=========
93
94In order to produce code that can run when the processor is in a 16bit
95mode, SeaBIOS uses the
96[binutils](http://en.wikipedia.org/wiki/GNU_Binutils) ".code16gcc"
97assembler flag. This instructs the assembler to emit extra prefix
98opcodes so that the 32bit code produced by
99[gcc](http://en.wikipedia.org/wiki/GNU_Compiler_Collection) will run
100even when the processor is in 16bit mode. Note that gcc always
101produces 32bit code - it does not know about the ".code16gcc" flag and
102does not know that the code will run in a 16bit mode.
103
104SeaBIOS uses the same code for all of the 16bit modes ([16bit real
105mode](#16bit_real_mode), [16bit bigreal mode](#16bit_bigreal_mode),
106and [16bit protected mode](#16bit_protected_mode)) and that code is
107assembled using ".code16gcc". SeaBIOS is careful to use segment
108registers properly so that the same code can run in the different
10916bit modes that it needs to support.
110
111C code mode flags
112=================
113
114Two compile time flags are available to determine the memory model the
115code is intended for: MODE16 and MODESEGMENT. When compiling for the
11616 bit modes, MODE16 is true and MODESEGMENT is true. In 32bit
117segmented mode, MODE16 is false and MODESEGMENT is true. In 32bit flat
118mode both MODE16 and MODESEGMENT are false.
119
120Common memory used at run-time
121==============================
122
123There are several memory areas that the SeaBIOS "runtime"
124[phase](Execution and code flow) makes use of:
125
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
131  with legacy systems.
132
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
137  legacy systems.
138
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
147  with legacy systems.
148
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.
160
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
167  calls.
168
169All of the above areas are also read/writable during the SeaBIOS
170initialization phase and are accessible when in 32bit flat mode.
171
172Segmented mode memory access
173============================
174
175The assembler entry functions for segmented mode calls (all modes
176except [32bit flat mode](#32bit_flat_mode)) will arrange
177to 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
179on the stack and C pointers to data located on the stack to work as
180normal.
181
182However, all code running in segmented mode must wrap non-stack memory
183accesses in special macros. These macros ensure the correct segment
184register is used. Failure to use the correct macro will result in an
185incorrect memory access that will likely cause hard to find errors.
186
187There are three low-level memory access macros:
188
189* GET_VAR / SET_VAR : Accesses a variable using the specified segment
190  register. This isn't typically used directly by C code.
191
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.
194
195* GET_FLATPTR / SET_FLATPTR : 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.
199
200Since most memory accesses are to [common memory used at
201run-time](#Common_memory_used_at_run-time), several helper
202macros are also available.
203
204* GET_IDT / SET_IDT : Access the interrupt descriptor table (IDT).
205
206* GET_BDA / SET_BDA : Access the BIOS Data Area (BDA).
207
208* GET_EBDA / SET_EBDA : Access the Extended BIOS Data Area (EBDA).
209
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.)
213
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.)
217
218Memory available during initialization
219======================================
220
221During the POST [phase](Execution and code flow) the code
222can fully access the first 4 gigabytes of memory. However, memory
223accesses are generally limited to the [common memory used at
224run-time](#Common_memory_used_at_run-time) and areas
225allocated at runtime via one of the malloc calls:
226
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.
235
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.
243
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.
249
250The "tmplow" and "tmphigh" regions are only available during the
251initialization phase. Any access (either read or write) after
252completion of the initialization phase can result in difficult to find
253errors.
254