notes.txt revision ea18eebe4b48f0b8dac8abfa45b1f8d677b4a731
Notes on BIOS usage
-------------------
- DOS (including 6.22/7.1) does not need INT 15h or INT 1Ah. Most other
operating systems require INT 15h to detect installed memory.
- OS/2 (WSeB/MCP/ACP) and Windows 98 SE are some of the very few operating
systems which use the El Torito floppy emulation.
- Keystroke check (INT 16h, fn 01h/10h) always enables interrupts on return.
DOS POWER.EXE depends on that in some situations.
- MS-DOS 6.2/V is a rare user of the INT 15h keyboard intercept routines.
- Some software uses the model byte at F000:FFFE to determine the system
type (PC-DOS 3.0, Norton Utilities 8). Other software first tries INT 15h,
fn C0h instead (PC-DOS 3.1, MSD).
- DOS 4.01 (both IBM and Microsoft) calls INT 13h to read from disk with less
than 100 bytes of stack space early in the boot sequence.
- Very few guests use the 32-bit PCI BIOS interface. One is OS/2 (but falls
back), another is Etherboot.
- OS/2 is the only known guest which can run the 16-bit PCI BIOS in protected
mode (but only if the 32-bit PCI BIOS is unavailable).
- Any disk reads which use bus-master DMA (AHCI, IDE BM) must use VDS
(Virtual DMA Services) when present. Otherwise any reads/writes when the
real mode addresses don't map directly to physical addresses will fail
horribly. DOS 6.x with EMM386 is a good testcase (esp. loading drivers
into UMBs).
- Many older OSes (especially UNIX based) require the FDPT to contain
physical ATA disk geometry; for that reason, disks smaller than ~500MB are
easiest to use. Otherwise a "large" BIOS disk option would be required.
- Some really old OSes (Xenix circa 1986-7) do not understand the EBDA idea
and clear the memory. For those, the FDPT must be in the BIOS ROM area, or
the OS will destroy it (even when it's at 0:300 in the IVT).
- Windows 98 SE boot CD uses 32-bit registers in real mode and will fail in
mysterious ways if BIOS trashes high bits of EAX (and likely others).
protected mode APM interface, and Windows 9x uses the 32-bit protected mode
APM interface.
- Windows 98 is one of the few APM 1.2 users; Windows 95 uses APM 1.1, while
newer systems prefer ACPI.
Notes on BIOS implementation
----------------------------
- To return values from functions not declared as __interrupt, the arguments
may need to be declared volatile (not ideal, but does the job).
- The way the POST code selectively clears or doesn't clear memory
is extremely suspect and will need reworking.
- Need to review string routines wrt direction flag (should be OK now).
- Need to review CMOS access wrt interrupts (possible index reg change by
an interrupt handler).
- The POST code zeroes the entire BDA, and then various bits zero specific
parts of the BDA again. That's a waste of time.
- After a reset, all interrupts are unmasked. Not sure if that's OK.
- BCC mishandles the following (where buf is an uint8_t array):
lba=buf[0x2B]*0x1000000+buf[0x2A]*0x10000+buf[0x29]*0x100+buf[0x28];
The buf[x]*100 expression should end up being of type signed int, which
causes the sign to be incorrectly propagated. BCC incorrectly keeps
the type unsigned.
- The PCI BIOS services are implemented in C, compiled twice as 16-bit and
32-bit code. This reduces the development effort and significantly lowers
the risk of discrepancies between 16-bit and 32-bit implementation. Care
must be taken because the 16-bit implementation can be executed in both
real and protected mode.
- APM can be in theory implemented only once for real, 16-bit protected and
32-bit protected mode. Unfortunately this is very inconvenient in C since
the default stack size changes between 16-bit and 32-bit callers. Therefore
real mode APM (which supports most functions) is implemented in C and
protected-mode APM is written in assembler for both 16-bit and 32-bit calls,
with a small 32->16 thunk.
Code size notes (code as of 7/6/2011):
The following values are the size of the _TEXT segment, i.e. only C code;
data defined in C is not included, neither are assembly modules.
Options: Size (hex):
-------- -----------
-0 -zu -s -oas -ecc 631A
-3 -zu -s -oas -ecc 5C1E
-0 -zu -s -oas 578A
-3 -zu -s -oas 5452
Both generating 386 code and using register-based calling convention for
internal functions brings significant size savings (15% when combined).