This code implements an X86 legacy bios. It is intended to be 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. 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 tools/ 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/blob.16.s). The gcc "-fwhole-program" option is used to optimize the process so 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. 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. 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. 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. 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.