Update README file with more information on using the bios.
[people/mcb30/legacybios.git] / README
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/rom.bin" contains the processed bios image.
6
7 The build requires gcc v4.1 or later.  Some buggy versions of gcc have
8 issues with the '-combine' compiler option - in particular, recent
9 versions of Ubuntu are affected.  One can use "make AVOIDCOMBINE=1" to
10 get around this.
11
12
13 Testing of images:
14
15 To test the bios under bochs, one will need to instruct bochs to use
16 the new bios image.  Use the 'romimage' option - for example:
17
18 bochs -q 'floppya: 1_44=myfdimage.img' 'romimage: file=out/rom.bin'
19
20 To test under qemu, one will need to create a directory with all the
21 bios images and then overwrite the main bios image.  For example:
22
23 cp /usr/share/qemu/*.bin mybiosdir/
24 cp out/rom.bin mybiosdir/bios.bin
25
26 Once this is setup, one can instruct qemu to use the newly created
27 directory for rom images.  For example:
28
29 qemu -L mybiosdir/ -fda myfdimage.img
30
31
32 The following payloads have been tested:
33
34 Freedos - see http://www.freedos.org/ .  Useful tests include: booting
35 from installation cdrom, installing to hard drive and floppy, making
36 sure hard drive and floppy boots then work.  It is also useful to take
37 the bootable floppy and hard-drive images, write them to an el-torito
38 bootable cdrom using the Linux mkisofs utility, and then boot those
39 cdrom images.
40
41 Linux - useful hard drive image available from
42 http://fabrice.bellard.free.fr/qemu/linux-0.2.img.bz2 .  It is also
43 useful to test standard distribution bootup and live cdroms.
44
45 NetBSD - useful hard drive image available from
46 http://nopid.free.fr/small.ffs.bz2 .  It is also useful to test
47 standard distribution installation cdroms.
48
49
50 Overview of files:
51
52 The src/ directory contains the bios source code.  Several of the
53 files are compiled twice - once for 16bit mode and once for 32bit
54 mode.  The gcc compile option '-fwhole-program' is used to remove code
55 that is not needed for a particular mode.  (In the code, one can use
56 the macros 'VISIBLE16' and 'VISIBLE32' to instruct a symbol to be
57 outputted in 16bit and 32bit mode respectively.)
58
59 The tools/ directory contains helper utilities for manipulating and
60 building the final rom.
61
62 The out/ directory is created by the build process - it contains all
63 temporary and final files.
64
65
66 Build overview:
67
68 The 16bit code is compiled via gcc to assembler (file out/blob.16.s).
69 The gcc "-fwhole-program" option is used to optimize the process so
70 that gcc can efficiently compile and discard unneeded code.
71
72 This resulting assembler code is pulled into romlayout.S.  The gas
73 option ".code16gcc" is used prior to including the gcc generated
74 assembler - this option enables gcc to generate valid 16 bit code.
75 The romlayout.S also defines all the mandatory bios visible memory
76 locations.
77
78 The post code (post.c) is entered, via the function _start(), in 32bit
79 mode.  The 16bit post vector (in romlayout.S) transitions the cpu into
80 32 bit mode before calling the post.c code.
81
82 In the last step of compilation, the 32 bit code is merged into the 16
83 bit code so that one binary file contains both.  Currently, both 16bit
84 and 32bit code will be located in the 64K block at segment 0xf000.
85
86
87 GCC 16 bit limitations:
88
89 Although the 16bit code is compiled with gcc, developers need to be
90 aware of the environment.  In particular, global variables _must_ be
91 treated specially.
92
93 The code has full access to stack variables and general purpose
94 registers.  The entry code in romlayout.S will push the original
95 registers on the stack before calling the C code and then pop them off
96 (including any required changes) before returning from the interrupt.
97 Changes to CS, DS, and ES segment registers in C code is also safe.
98 Changes to other segment registers (SS, FS, GS) need to be restored
99 manually.
100
101 Stack variables (and pointers to stack variables) work as they
102 normally do in standard C code.
103
104 However, variables stored outside the stack need to be accessed via
105 the GET_VAR and SET_VAR macros (or one of the helper macros described
106 below).  This is due to the 16bit segment nature of the X86 cpu when
107 it is in "real mode".  The C entry code will set DS and SS to point to
108 the stack segment.  Variables not on the stack need to be accessed via
109 an explicit segment register.  Global constants (loaded into 0xf000)
110 can be accessed via the CS segment register.  Any other access
111 requires altering one of the other segment registers (usually ES) and
112 then accessing the variable via that segment register.
113
114 There are three low-level ways to access a remote variable:
115 GET/SET_VAR, GET/SET_FARVAR, and GET/SET_FARPTR.  The first set takes
116 an explicit segment descriptor (eg, "CS") and offset.  The second set
117 will take a segment id and offset, set ES to the segment, and then
118 make the access via the ES segment.  The last method is similar to the
119 second, except it takes a pointer that would be valid in 32-bit mode
120 instead of a segment/offset pair.
121
122 Most BIOS variables are stored in the "BDA" or "EBDA" memory areas.
123 Because this is common, two sets of helper macros (GET/SET_BDA and
124 GET/SET_EBDA) are available to simplify these accesses.
125
126
127 GCC 16 bit stack limitations:
128
129 Another limitation of gcc is its use of 32-bit temporaries.  Gcc will
130 allocate 32-bits of space for every variable - even if that variable
131 is only defined as a 'u8' or 'u16'.  If one is not careful, using too
132 much stack space can break old DOS applications.
133
134 There does not appear to be explicit documentation on the minimum
135 stack space available for bios calls.  However, Freedos has been
136 observed to call into the bios with less than 150 bytes of stack space
137 available.
138
139 Note that the post code and boot code (irq 18/19) do not have a stack
140 limitation because the entry points for these functions reset the
141 stack to a known state.  Only the general purpose 16-bit service entry
142 points are affected.
143
144 There are some ways to reduce stack usage: making sure functions are
145 tail-recursive often helps, reducing the number of parameters passed
146 to functions often helps, sometimes reordering variable declarations
147 helps, inlining of functions can sometimes help, and passing of packed
148 structures can also help.
149
150
151 Debugging the bios:
152
153 The bios will output information messages to a special debug port.
154 Under qemu, one can view these messages by enabling the '#define
155 DEBUG_BIOS' definition in 'qemu/hw/pc.c'.  Once this is done (and qemu
156 is recompiled), one should see status messages on the console.
157
158 The gdb-server mechanism of qemu is also useful.  One can use gdb with
159 qemu to debug system images.  To use this, add '-s -S' to the qemu
160 command line.  For example:
161
162 qemu -L mybiosdir/ -fda myfdimage.img -s -S
163
164 Then, in another session, run gdb with either out/rom16.o (to debug
165 bios 16bit code) or out/rom32.o (to debug bios 32bit code).  For
166 example:
167
168 gdb out/rom16.o
169
170 Once in gdb, use the command "target remote localhost:1234" to have
171 gdb connect to qemu.  See the qemu documentation for more information
172 on using gdb and qemu in this mode.  Note that gdb seems to get
173 breakpoints confused when the cpu is in 16-bit real mode.  This makes
174 stepping through the program difficult (though 'step instruction'
175 still works).  Also, one may need to set 16bit break points at both
176 the cpu address and memory address (eg, break *0x1234 ; break
177 *0xf1234).