Annotation of qemu/roms/seabios/README, revision 1.1.1.2

1.1       root        1: This code implements an X86 legacy bios.  It is intended to be
                      2: compiled using standard gnu tools (eg, gas and gcc).
                      3: 
                      4: To build, one should be able to run "make" in the main directory.  The
                      5: resulting file "out/bios.bin" contains the processed bios image.
                      6: 
                      7: 
                      8: Testing of images:
                      9: 
                     10: To test the bios under bochs, one will need to instruct bochs to use
                     11: the new bios image.  Use the 'romimage' option - for example:
                     12: 
                     13: bochs -q 'floppya: 1_44=myfdimage.img' 'romimage: file=out/bios.bin'
                     14: 
                     15: To test under qemu, one will need to create a directory with all the
                     16: bios images and then overwrite the main bios image.  For example:
                     17: 
                     18: cp /usr/share/qemu/*.bin mybiosdir/
                     19: cp out/bios.bin mybiosdir/
                     20: 
                     21: Once this is setup, one can instruct qemu to use the newly created
                     22: directory for rom images.  For example:
                     23: 
                     24: qemu -L mybiosdir/ -fda myfdimage.img
                     25: 
                     26: 
                     27: Overview of files:
                     28: 
                     29: The src/ directory contains the bios source code.  Several of the
                     30: files are compiled twice - once for 16bit mode and once for 32bit
                     31: mode.  (The build system will remove code that is not needed for a
                     32: particular mode.)
                     33: 
                     34: The tools/ directory contains helper utilities for manipulating and
                     35: building the final rom.
                     36: 
                     37: The out/ directory is created by the build process - it contains all
                     38: temporary and final files.
                     39: 
                     40: 
                     41: Build overview:
                     42: 
                     43: The 16bit code is compiled via gcc to assembler (file out/ccode.16.s).
                     44: The gcc "-fwhole-program" and "-ffunction-sections -fdata-sections"
                     45: options are used to optimize the process so that gcc can efficiently
                     46: compile and discard unneeded code.  (In the code, one can use the
1.1.1.2 ! root       47: macros 'VISIBLE16' and 'VISIBLE32FLAT' to instruct a symbol to be
1.1       root       48: outputted in 16bit and 32bit mode respectively.)
                     49: 
                     50: This resulting assembler code is pulled into romlayout.S.  The gas
                     51: option ".code16gcc" is used prior to including the gcc generated
                     52: assembler - this option enables gcc to generate valid 16 bit code.
                     53: 
1.1.1.2 ! root       54: The post code (post.c) is entered, via the function handle_post(), in
        !            55: 32bit mode.  The 16bit post vector (in romlayout.S) transitions the
        !            56: cpu into 32 bit mode before calling the post.c code.
1.1       root       57: 
                     58: In the last step of compilation, the 32 bit code is merged into the 16
                     59: bit code so that one binary file contains both.  Currently, both 16bit
1.1.1.2 ! root       60: and 32bit code will be located in the memory at 0xe0000-0xfffff.
1.1       root       61: 
                     62: 
                     63: GCC 16 bit limitations:
                     64: 
                     65: Although the 16bit code is compiled with gcc, developers need to be
                     66: aware of the environment.  In particular, global variables _must_ be
                     67: treated specially.
                     68: 
                     69: The code has full access to stack variables and general purpose
                     70: registers.  The entry code in romlayout.S will push the original
                     71: registers on the stack before calling the C code and then pop them off
                     72: (including any required changes) before returning from the interrupt.
                     73: Changes to CS, DS, and ES segment registers in C code is also safe.
                     74: Changes to other segment registers (SS, FS, GS) need to be restored
                     75: manually.
                     76: 
                     77: Stack variables (and pointers to stack variables) work as they
                     78: normally do in standard C code.
                     79: 
                     80: However, variables stored outside the stack need to be accessed via
                     81: the GET_VAR and SET_VAR macros (or one of the helper macros described
                     82: below).  This is due to the 16bit segment nature of the X86 cpu when
                     83: it is in "real mode".  The C entry code will set DS and SS to point to
                     84: the stack segment.  Variables not on the stack need to be accessed via
                     85: an explicit segment register.  Any other access requires altering one
                     86: of the other segment registers (usually ES) and then accessing the
                     87: variable via that segment register.
                     88: 
                     89: There are three low-level ways to access a remote variable:
                     90: GET/SET_VAR, GET/SET_FARVAR, and GET/SET_FLATPTR.  The first set takes
                     91: an explicit segment descriptor (eg, "CS") and offset.  The second set
                     92: will take a segment id and offset, set ES to the segment id, and then
                     93: make the access via the ES segment.  The last method is similar to the
                     94: second, except it takes a pointer that would be valid in 32-bit flat
                     95: mode instead of a segment/offset pair.
                     96: 
                     97: Most BIOS variables are stored in global variables, the "BDA", or
                     98: "EBDA" memory areas.  Because this is common, three sets of helper
                     99: macros (GET/SET_GLOBAL, GET/SET_BDA, and GET/SET_EBDA) are available
                    100: to simplify these accesses.
                    101: 
                    102: Global variables defined in the C code can be read in 16bit mode if
                    103: the variable declaration is marked with VAR16, VAR16VISIBLE,
                    104: VAR16EXPORT, or VAR16FIXED.  The GET_GLOBAL macro will then allow read
                    105: access to the variable.  Global variables are stored in the 0xf000
                    106: segment, and their values are persistent across soft resets.  Because
                    107: the f-segment is marked read-only during run-time, the 16bit code is
                    108: not permitted to change the value of 16bit variables (use of the
                    109: SET_GLOBAL macro from 16bit mode will cause a link error).  Code
                    110: running in 32bit mode can not access variables with VAR16, but can
                    111: access variables marked with VAR16VISIBLE, VAR16EXPORT, VAR16FIXED, or
                    112: with no marking at all.  The 32bit code can use the GET/SET_GLOBAL
                    113: macros, but they are not required.
                    114: 
                    115: 
                    116: GCC 16 bit stack limitations:
                    117: 
                    118: Another limitation of gcc is its use of 32-bit temporaries.  Gcc will
                    119: allocate 32-bits of space for every variable - even if that variable
                    120: is only defined as a 'u8' or 'u16'.  If one is not careful, using too
                    121: much stack space can break old DOS applications.
                    122: 
                    123: There does not appear to be explicit documentation on the minimum
                    124: stack space available for bios calls.  However, Freedos has been
                    125: observed to call into the bios with less than 150 bytes available.
                    126: 
                    127: Note that the post code and boot code (irq 18/19) do not have a stack
                    128: limitation because the entry points for these functions transition the
                    129: cpu to 32bit mode and reset the stack to a known state.  Only the
                    130: general purpose 16-bit service entry points are affected.
                    131: 
                    132: There are some ways to reduce stack usage: making sure functions are
                    133: tail-recursive often helps, reducing the number of parameters passed
                    134: to functions often helps, sometimes reordering variable declarations
                    135: helps, inlining of functions can sometimes help, and passing of packed
                    136: structures can also help.  It is also possible to transition to/from
                    137: an extra stack stored in the EBDA using the stack_hop helper function.
                    138: 
                    139: Some useful stats: the overhead for the entry to a bios handler that
                    140: takes a 'struct bregs' is 42 bytes of stack space (6 bytes from
                    141: interrupt insn, 32 bytes to store registers, and 4 bytes for call
                    142: insn).  An entry to an ISR handler without args takes 30 bytes (6 + 20
                    143: + 4).
                    144: 
                    145: 
                    146: Debugging the bios:
                    147: 
                    148: The bios will output information messages to a special debug port.
1.1.1.2 ! root      149: Under qemu, one can view these messages by adding '-chardev
        !           150: stdio,id=seabios -device isa-debugcon,iobase=0x402,chardev=seabios' to
        !           151: the qemu command line.  Once this is done, one should see status
        !           152: messages on the console.
1.1       root      153: 
                    154: The gdb-server mechanism of qemu is also useful.  One can use gdb with
                    155: qemu to debug system images.  To use this, add '-s -S' to the qemu
                    156: command line.  For example:
                    157: 
                    158: qemu -L mybiosdir/ -fda myfdimage.img -s -S
                    159: 
                    160: Then, in another session, run gdb with either out/rom16.o (to debug
                    161: bios 16bit code) or out/rom32.o (to debug bios 32bit code).  For
                    162: example:
                    163: 
                    164: gdb out/rom16.o
                    165: 
                    166: Once in gdb, use the command "target remote localhost:1234" to have
                    167: gdb connect to qemu.  See the qemu documentation for more information
                    168: on using gdb and qemu in this mode.  Note that gdb seems to get
                    169: breakpoints confused when the cpu is in 16-bit real mode.  This makes
                    170: stepping through the program difficult (though 'step instruction'
                    171: still works).  Also, one may need to set 16bit break points at both
                    172: the cpu address and memory address (eg, break *0x1234 ; break
                    173: *0xf1234).

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.