The README file and README.CSM file have gotten a bit out of date. Instead of maintaining technical information in the README file, point new users to the SeaBIOS wiki. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>1.8-stable
parent
73fe49aef4
commit
64b7614976
2 changed files with 11 additions and 198 deletions
@ -1,182 +1,17 @@ |
||||
This code implements an X86 legacy bios. It is intended to be |
||||
compiled using standard gnu tools (eg, gas and gcc). |
||||
Welcome to the SeaBIOS project! This project implements an X86 legacy |
||||
bios that is built with standard GNU tools. |
||||
|
||||
To build for QEMU, one should be able to run "make" in the main |
||||
directory. The resulting file "out/bios.bin" contains the processed |
||||
bios image. To build for coreboot, please see the coreboot wiki. To |
||||
build for CSM, please see README.CSM. |
||||
Please see build and developer information at: |
||||
|
||||
http://seabios.org/Developer_Documentation |
||||
|
||||
Testing of images: |
||||
For the impatient, SeaBIOS is built for QEMU and tested on QEMU with: |
||||
|
||||
To test the bios under bochs, one will need to instruct bochs to use |
||||
the new bios image. Use the 'romimage' option - for example: |
||||
make |
||||
qemu -bios out/bios.bin |
||||
|
||||
bochs -q 'floppya: 1_44=myfdimage.img' 'romimage: file=out/bios.bin' |
||||
SeaBIOS can be configured with kconfig. To change the default |
||||
configuration one can run "make menuconfig" prior to running "make". |
||||
|
||||
To test under qemu, one will need to create a directory with all the |
||||
bios images and then overwrite the main bios image. For example: |
||||
|
||||
cp /usr/share/qemu/*.bin mybiosdir/ |
||||
cp out/bios.bin mybiosdir/ |
||||
cp out/*.aml mybiosdir/ |
||||
|
||||
Once this is setup, one can instruct qemu to use the newly created |
||||
directory for rom images. For example: |
||||
|
||||
qemu -L mybiosdir/ -fda myfdimage.img |
||||
|
||||
|
||||
Overview of files: |
||||
|
||||
The src/ directory contains the bios source code. Several of the |
||||
files are compiled twice - once for 16bit mode and once for 32bit |
||||
mode. (The build system will remove code that is not needed for a |
||||
particular mode.) |
||||
|
||||
The vgasrc/ directory contains code for VGA BIOS implementations. |
||||
This code is separate from the main BIOS code in the src/ directory. |
||||
It produces a VGA BIOS rom in out/vgabios.bin. The VGA BIOS code is |
||||
always compiled in 16bit mode. |
||||
|
||||
The scripts/ directory contains helper utilities for manipulating and |
||||
building the final rom. |
||||
|
||||
The out/ directory is created by the build process - it contains all |
||||
temporary and final files. |
||||
|
||||
|
||||
Build overview: |
||||
|
||||
The 16bit code is compiled via gcc to assembler (file out/ccode.16.s). |
||||
The gcc "-fwhole-program" and "-ffunction-sections -fdata-sections" |
||||
options are used to optimize the process so that gcc can efficiently |
||||
compile and discard unneeded code. (In the code, one can use the |
||||
macros 'VISIBLE16' and 'VISIBLE32FLAT' to instruct a symbol to be |
||||
outputted in 16bit and 32bit mode respectively.) |
||||
|
||||
This resulting assembler code is pulled into romlayout.S. The gas |
||||
option ".code16gcc" is used prior to including the gcc generated |
||||
assembler - this option enables gcc to generate valid 16 bit code. |
||||
|
||||
The post code (post.c) is entered, via the function handle_post(), in |
||||
32bit mode. The 16bit post vector (in romlayout.S) transitions the |
||||
cpu into 32 bit mode before calling the post.c code. |
||||
|
||||
In the last step of compilation, the 32 bit code is merged into the 16 |
||||
bit code so that one binary file contains both. Currently, both 16bit |
||||
and 32bit code will be located in the memory at 0xe0000-0xfffff. |
||||
|
||||
|
||||
GCC 16 bit limitations: |
||||
|
||||
Although the 16bit code is compiled with gcc, developers need to be |
||||
aware of the environment. In particular, global variables _must_ be |
||||
treated specially. |
||||
|
||||
The code has full access to stack variables and general purpose |
||||
registers. The entry code in romlayout.S will push the original |
||||
registers on the stack before calling the C code and then pop them off |
||||
(including any required changes) before returning from the interrupt. |
||||
Changes to CS, DS, and ES segment registers in C code is also safe. |
||||
Changes to other segment registers (SS, FS, GS) need to be restored |
||||
manually. |
||||
|
||||
Stack variables (and pointers to stack variables) work as they |
||||
normally do in standard C code. |
||||
|
||||
However, variables stored outside the stack need to be accessed via |
||||
the GET_VAR and SET_VAR macros (or one of the helper macros described |
||||
below). This is due to the 16bit segment nature of the X86 cpu when |
||||
it is in "real mode". The C entry code will set DS and SS to point to |
||||
the stack segment. Variables not on the stack need to be accessed via |
||||
an explicit segment register. Any other access requires altering one |
||||
of the other segment registers (usually ES) and then accessing the |
||||
variable via that segment register. |
||||
|
||||
There are three low-level ways to access a remote variable: |
||||
GET/SET_VAR, GET/SET_FARVAR, and GET/SET_FLATPTR. The first set takes |
||||
an explicit segment descriptor (eg, "CS") and offset. The second set |
||||
will take a segment id and offset, set ES to the segment id, and then |
||||
make the access via the ES segment. The last method is similar to the |
||||
second, except it takes a pointer that would be valid in 32-bit flat |
||||
mode instead of a segment/offset pair. |
||||
|
||||
Most BIOS variables are stored in global variables, the "BDA", or |
||||
"EBDA" memory areas. Because this is common, three sets of helper |
||||
macros (GET_GLOBAL, GET/SET_BDA, and GET/SET_EBDA) are available to |
||||
simplify these accesses. Also, an area in the 0xc0000-0xf0000 memory |
||||
range is made available for internal BIOS run-time variables that are |
||||
marked with the VARLOW attribute. These variables can then be |
||||
accessed with the GET/SET_LOW macros. |
||||
|
||||
Global variables defined in the C code can be read in 16bit mode if |
||||
the variable declaration is marked with VAR16, VARFSEG, or VAR16FIXED. |
||||
The GET_GLOBAL macro will then allow read access to the variable. |
||||
Global variables are stored in the 0xf000 segment. Because the |
||||
f-segment is marked read-only during run-time, the 16bit code is not |
||||
permitted to change the value of 16bit variables. Code running in |
||||
32bit mode can not access variables with VAR16, but can access |
||||
variables marked with VARFSEG, VARLOW, VAR16FIXED, or with no marking |
||||
at all. The 32bit code can use the GET_GLOBAL macros, but they are |
||||
not required. |
||||
|
||||
|
||||
GCC 16 bit stack limitations: |
||||
|
||||
Another limitation of gcc is its use of 32-bit temporaries. Gcc will |
||||
allocate 32-bits of space for every variable - even if that variable |
||||
is only defined as a 'u8' or 'u16'. If one is not careful, using too |
||||
much stack space can break old DOS applications. |
||||
|
||||
There does not appear to be explicit documentation on the minimum |
||||
stack space available for bios calls. However, Freedos has been |
||||
observed to call into the bios with less than 150 bytes available. |
||||
|
||||
Note that the post code and boot code (irq 18/19) do not have a stack |
||||
limitation because the entry points for these functions transition the |
||||
cpu to 32bit mode and reset the stack to a known state. Only the |
||||
general purpose 16-bit service entry points are affected. |
||||
|
||||
There are some ways to reduce stack usage: making sure functions are |
||||
tail-recursive often helps, reducing the number of parameters passed |
||||
to functions often helps, sometimes reordering variable declarations |
||||
helps, inlining of functions can sometimes help, and passing of packed |
||||
structures can also help. It is also possible to transition to/from |
||||
an extra stack stored in the EBDA using the stack_hop helper function. |
||||
|
||||
Some useful stats: the overhead for the entry to a bios handler that |
||||
takes a 'struct bregs' is 42 bytes of stack space (6 bytes from |
||||
interrupt insn, 32 bytes to store registers, and 4 bytes for call |
||||
insn). An entry to an ISR handler without args takes 30 bytes (6 + 20 |
||||
+ 4). |
||||
|
||||
|
||||
Debugging the bios: |
||||
|
||||
The bios will output information messages to a special debug port. |
||||
Under qemu, one can view these messages by adding '-chardev |
||||
stdio,id=seabios -device isa-debugcon,iobase=0x402,chardev=seabios' to |
||||
the qemu command line. Once this is done, one should see status |
||||
messages on the console. |
||||
|
||||
The gdb-server mechanism of qemu is also useful. One can use gdb with |
||||
qemu to debug system images. To use this, add '-s -S' to the qemu |
||||
command line. For example: |
||||
|
||||
qemu -L mybiosdir/ -fda myfdimage.img -s -S |
||||
|
||||
Then, in another session, run gdb with either out/rom16.o (to debug |
||||
bios 16bit code) or out/rom32.o (to debug bios 32bit code). For |
||||
example: |
||||
|
||||
gdb out/rom16.o |
||||
|
||||
Once in gdb, use the command "target remote localhost:1234" to have |
||||
gdb connect to qemu. See the qemu documentation for more information |
||||
on using gdb and qemu in this mode. Note that gdb seems to get |
||||
breakpoints confused when the cpu is in 16-bit real mode. This makes |
||||
stepping through the program difficult (though 'step instruction' |
||||
still works). Also, one may need to set 16bit break points at both |
||||
the cpu address and memory address (eg, break *0x1234 ; break |
||||
*0xf1234). |
||||
For other types of builds, and for more detailed developer |
||||
documentation, please see the online documentation listed above. |
||||
|
@ -1,22 +0,0 @@ |
||||
Enabling CONFIG_CSM allows SeaBIOS to be built as a Compatibility Support |
||||
Module for use with the OMVF/EDK-II UEFI firmware. |
||||
|
||||
It will provide "legacy" BIOS services for booting non-EFI operating |
||||
systems and will also allow OVMF to display on otherwise unsupported |
||||
video hardware by using the traditional VGA BIOS. |
||||
|
||||
Windows 2008r2 is known to use INT 10h BIOS calls even when booted via |
||||
EFI, and the presence of a CSM makes this work as expected too. |
||||
|
||||
Having built SeaBIOS with CONFIG_CSM, you should be able to drop the |
||||
result (out/Csm16.bin) into your OVMF build tree at |
||||
OvmfPkg/Csm/Csm16/Csm16.bin and then build OVMF with 'build -D |
||||
CSM_ENABLE'. The SeaBIOS binary will be included as a discrete file |
||||
within the 'Flash Volume' which is created, and there are tools which |
||||
will extract it and allow it to be replaced; satisfying the |
||||
requirements of the LGPL licence. |
||||
|
||||
A patch to OVMF is required, to prevent it from marking the region from |
||||
0xC0000-0xFFFFF as read-only before invoking our Legacy16Boot method. See |
||||
http://www.sourceforge.net/mailarchive/forum.php?thread_name=50FD7290.9060003%40redhat.com&forum_name=edk2-devel |
||||
|
Loading…
Reference in new issue