Update README file with more information on using the bios.
authorKevin O'Connor <kevin@koconnor.net>
Sun, 30 Mar 2008 15:07:42 +0000 (11:07 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Sun, 30 Mar 2008 15:07:42 +0000 (11:07 -0400)
README

diff --git a/README b/README
index ce80499f93c37e9ec9f35fa937f1ea8cb340700c..0ca5f1b469063817315cd406c67153a57337aa4a 100644 (file)
--- a/README
+++ b/README
@@ -4,16 +4,57 @@ compiled using standard gnu tools (eg, gas and gcc).
 To build, one should be able to run "make" in the main directory.  The
 resulting file "out/rom.bin" contains the processed bios image.
 
-The code has been successfully compiled with gcc 4.1.2 and gas
-2.17.50.0.18.
+The build requires gcc v4.1 or later.  Some buggy versions of gcc have
+issues with the '-combine' compiler option - in particular, recent
+versions of Ubuntu are affected.  One can use "make AVOIDCOMBINE=1" to
+get around this.
+
+
+Testing of images:
+
+To test the bios under bochs, one will need to instruct bochs to use
+the new bios image.  Use the 'romimage' option - for example:
+
+bochs -q 'floppya: 1_44=myfdimage.img' 'romimage: file=out/rom.bin'
+
+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/rom.bin mybiosdir/bios.bin
+
+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
+
+
+The following payloads have been tested:
+
+Freedos - see http://www.freedos.org/ .  Useful tests include: booting
+from installation cdrom, installing to hard drive and floppy, making
+sure hard drive and floppy boots then work.  It is also useful to take
+the bootable floppy and hard-drive images, write them to an el-torito
+bootable cdrom using the Linux mkisofs utility, and then boot those
+cdrom images.
+
+Linux - useful hard drive image available from
+http://fabrice.bellard.free.fr/qemu/linux-0.2.img.bz2 .  It is also
+useful to test standard distribution bootup and live cdroms.
+
+NetBSD - useful hard drive image available from
+http://nopid.free.fr/small.ffs.bz2 .  It is also useful to test
+standard distribution installation cdroms.
 
 
 Overview of files:
 
-The src/ directory contains the bios source code.  The post.c code is
-compiled in 32bit mode.  The output.c code is compiled twice - once in
-16bit mode and once in 32bit mode.  The remaining c files are compiled
-in 16bit mode.
+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 gcc compile option '-fwhole-program' is used to remove code
+that is not needed for a particular mode.  (In the code, one can use
+the macros 'VISIBLE16' and 'VISIBLE32' to instruct a symbol to be
+outputted in 16bit and 32bit mode respectively.)
 
 The tools/ directory contains helper utilities for manipulating and
 building the final rom.
@@ -30,17 +71,17 @@ that gcc can efficiently compile and discard unneeded code.
 
 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 be used to generate valid 16
-bit code.  The romlayout.S also defines all the mandatory bios visible
-memory locations.
+assembler - this option enables gcc to generate valid 16 bit code.
+The romlayout.S also defines all the mandatory bios visible memory
+locations.
 
-The post code (post.c) is written in 32bits.  The 16bit post vector
-(in romlayout.S) transitions the cpu into 32 bit mode before calling
-the initialization code in post.c.
+The post code (post.c) is entered, via the function _start(), 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, the compiled 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 64K block at segment 0xf000.
+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 64K block at segment 0xf000.
 
 
 GCC 16 bit limitations:
@@ -61,11 +102,76 @@ 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.  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.
-Global constant definitions (those in 0xf000) can be accessed via the
-CS segment register.  Any other access requires altering one of the
-other segment registers (usually ES) and then accessing the variable
-via that segment register.
+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.  Global constants (loaded into 0xf000)
+can be accessed via the CS 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_FARPTR.  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, 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 mode
+instead of a segment/offset pair.
+
+Most BIOS variables are stored in the "BDA" or "EBDA" memory areas.
+Because this is common, two sets of helper macros (GET/SET_BDA and
+GET/SET_EBDA) are available to simplify these accesses.
+
+
+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 of stack space
+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 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.
+
+
+Debugging the bios:
+
+The bios will output information messages to a special debug port.
+Under qemu, one can view these messages by enabling the '#define
+DEBUG_BIOS' definition in 'qemu/hw/pc.c'.  Once this is done (and qemu
+is recompiled), 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).