[38699] | 1 |
|
---|
| 2 | Notes on BIOS usage
|
---|
| 3 | -------------------
|
---|
| 4 |
|
---|
| 5 | - DOS (including 6.22/7.1) does not need INT 15h or INT 1Ah. Most other
|
---|
| 6 | operating systems require INT 15h to detect installed memory.
|
---|
| 7 |
|
---|
[39611] | 8 | - OS/2 (WSeB/MCP/ACP) and Windows 98 SE are some of the very few operating
|
---|
| 9 | systems which use the El Torito floppy emulation.
|
---|
[38699] | 10 |
|
---|
[43681] | 11 | - NetWare 5.1 is one of the *extremely* few users of El Torito hard disk
|
---|
| 12 | emulation.
|
---|
| 13 |
|
---|
[67785] | 14 | - Keystroke check (INT 16h, fn 01h/11h) always enables interrupts on return.
|
---|
[40721] | 15 | DOS POWER.EXE depends on that in some situations.
|
---|
| 16 |
|
---|
[67785] | 17 | - IBM DOS J5.00/V is even worse and does a far jump into INT 16h/11h after
|
---|
| 18 | pushing garbage on the stack. Using IRET directly may change IOPL, set
|
---|
| 19 | TF, change direction flag, etc. We have to use or simulate RETF 2 instead.
|
---|
| 20 |
|
---|
[67694] | 21 | - MS-DOS 5.0/V setup assumes that INT 13h always returns with interrupts
|
---|
| 22 | enabled.
|
---|
| 23 |
|
---|
| 24 | - INT 15h also always returns with interrupts enabled (even for unsupported
|
---|
| 25 | functions).
|
---|
| 26 |
|
---|
[38699] | 27 | - MS-DOS 6.2/V is a rare user of the INT 15h keyboard intercept routines.
|
---|
| 28 |
|
---|
| 29 | - Some software uses the model byte at F000:FFFE to determine the system
|
---|
| 30 | type (PC-DOS 3.0, Norton Utilities 8). Other software first tries INT 15h,
|
---|
| 31 | fn C0h instead (PC-DOS 3.1, MSD).
|
---|
| 32 |
|
---|
| 33 | - DOS 4.01 (both IBM and Microsoft) calls INT 13h to read from disk with less
|
---|
[60610] | 34 | than 100 bytes of stack space early in the boot sequence. This tends to be
|
---|
| 35 | a problem especially for the SATA and SCSI code paths.
|
---|
[38699] | 36 |
|
---|
[41547] | 37 | - Very few guests use the 32-bit PCI BIOS interface. One is OS/2 (but falls
|
---|
| 38 | back), another is Etherboot.
|
---|
[38699] | 39 |
|
---|
| 40 | - OS/2 is the only known guest which can run the 16-bit PCI BIOS in protected
|
---|
| 41 | mode (but only if the 32-bit PCI BIOS is unavailable).
|
---|
| 42 |
|
---|
[45881] | 43 | - NetWare 6.x is the only known guest which uses the PCI BIOS service to read
|
---|
| 44 | the IRQ routing table.
|
---|
| 45 |
|
---|
[87784] | 46 | - NetWare 6.5 boot CD is a rare user of INT 15h/86h, asking for 1,000,000
|
---|
| 47 | microsecond (1 second) delays. The initial NW 6.5 release boots to Caldera
|
---|
| 48 | DOS and does not exhibit this behavior. NetWare 6.5 SP2 and later boots
|
---|
| 49 | straight to NetWare and uses the 1-second sleep.
|
---|
| 50 |
|
---|
[38899] | 51 | - Any disk reads which use bus-master DMA (AHCI, IDE BM) must use VDS
|
---|
| 52 | (Virtual DMA Services) when present. Otherwise any reads/writes when the
|
---|
| 53 | real mode addresses don't map directly to physical addresses will fail
|
---|
| 54 | horribly. DOS 6.x with EMM386 is a good testcase (esp. loading drivers
|
---|
| 55 | into UMBs).
|
---|
[38699] | 56 |
|
---|
[39340] | 57 | - Many older OSes (especially UNIX based) require the FDPT to contain
|
---|
| 58 | physical ATA disk geometry; for that reason, disks smaller than ~500MB are
|
---|
| 59 | easiest to use. Otherwise a "large" BIOS disk option would be required.
|
---|
[38899] | 60 |
|
---|
[77117] | 61 | - Older NetWare IDE disk drivers (IDE.DSK from 1993, likely older as well)
|
---|
| 62 | fall into the same category. If FDPT contains logical geometry, NetWare
|
---|
| 63 | malfunctions. NetWare 3.x/4.x is unusual in that it boots from a DOS
|
---|
| 64 | partition using BIOS, and only later switches to its own disk drivers.
|
---|
| 65 | NetWare reportedly understands FDPT cylinder values over 1024, but requires
|
---|
| 66 | physical disk geometry in the FDPT (only up to 16 heads).
|
---|
| 67 |
|
---|
[39340] | 68 | - Some really old OSes (Xenix circa 1986-7) do not understand the EBDA idea
|
---|
| 69 | and clear the memory. For those, the FDPT must be in the BIOS ROM area, or
|
---|
| 70 | the OS will destroy it (even when it's at 0:300 in the IVT).
|
---|
| 71 |
|
---|
[76791] | 72 | - NetWare 2.15 has a similar restriction, the FDPT must explicitly point above
|
---|
| 73 | segment address C800 or the NetWare AT disk driver abends.
|
---|
| 74 |
|
---|
[100366] | 75 | - NetWare 286 2.0a SFT II uses INT 41h/46h vector to obtain the FDPT, but
|
---|
| 76 | at least in protected mode, assumes that those vectors must point into
|
---|
| 77 | the F000h segment.
|
---|
| 78 |
|
---|
[104194] | 79 | - NetWare 2.0a INSTALL and VREPAIR utilities run in real mode but have their
|
---|
| 80 | own ATA disk driver. Like NetWare itself, the utilities obtain drive
|
---|
| 81 | geometry from the FDPT, but unlike NetWare, they assume that the drive
|
---|
| 82 | already had the correct geometry set during POST and that INT 13h/00h
|
---|
| 83 | will keep it in place by executing INITIALIZE DRIVE PARAMETERS.
|
---|
| 84 | NB: The BIOS itself always uses LBA and thus does not depend on the
|
---|
| 85 | drive's current CHS geometry at all.
|
---|
| 86 |
|
---|
[48069] | 87 | - Windows NT (including XP) uses INT 13h/08h to obtain the DPT for each floppy
|
---|
| 88 | drive. NT assumes a 13-byte DPT which includes the number of tracks. NT will
|
---|
| 89 | refuse to read more tracks than the DPT specifies and formats as many tracks
|
---|
| 90 | as the DPT specifies.
|
---|
| 91 |
|
---|
[39611] | 92 | - Windows 98 SE boot CD uses 32-bit registers in real mode and will fail in
|
---|
| 93 | mysterious ways if BIOS trashes high bits of EAX (and likely others).
|
---|
[39340] | 94 |
|
---|
[40150] | 95 | - PC DOS 6.x/7.x QCONFIG is a rare user of INT 16h fn 0Ah (read keyboard ID).
|
---|
[39611] | 96 |
|
---|
[76968] | 97 | - DOS POWER.EXE uses the real mode APM interface, Windows 3.1 POWER.DRV and
|
---|
| 98 | OS/2 APM.SYS use the 16-bit protected mode APM interface, and Windows 9x
|
---|
| 99 | uses the 32-bit protected mode APM interface.
|
---|
[42791] | 100 |
|
---|
[42770] | 101 | - Windows 98 is one of the few APM 1.2 users; Windows 95 uses APM 1.1, while
|
---|
| 102 | newer systems prefer ACPI.
|
---|
[40150] | 103 |
|
---|
[76968] | 104 | - Windows 3.1 Standard mode violates the APM specifications and calls into
|
---|
| 105 | APM with CPL=3, causing the HLT instruction to fault if used. 386 Enhanced
|
---|
[100483] | 106 | mode Windows 3.1 calls into APM with CPL=0.
|
---|
[76968] | 107 |
|
---|
[100483] | 108 | - DR-DOS 5.0/6.0 EMM386.SYS does handle HLT instructions executed by real-mode
|
---|
| 109 | code, but does not halt the CPU and just continues execution.
|
---|
| 110 |
|
---|
[46234] | 111 | - QNX4 calls 16-bit protected-mode PCI BIOS in an environment where ESP is
|
---|
| 112 | 16-bit but SS is a 32-bit stack segment. In such environments, using the
|
---|
| 113 | ENTER/LEAVE sequence is fatal if the high word of EBP is non-zero (which
|
---|
| 114 | it will be with QNX 4.25). LEAVE propagates the high word of EBP into ESP
|
---|
| 115 | with fatal consequences.
|
---|
[42770] | 116 |
|
---|
[46234] | 117 | - Plan 9 also runs 16-bit code with a 32-bit stack segment, except Plan 9
|
---|
| 118 | thinks it counts as real mode. Same ENTER/LEAVE problem as above.
|
---|
| 119 |
|
---|
[49286] | 120 | - AIX 1.3 is a rare user of INT 15h/89h (switch to protected mode) service.
|
---|
[100366] | 121 | NetWare 286 2.0a is another.
|
---|
[46234] | 122 |
|
---|
[49286] | 123 | - IBM OS/2 1.0/1.1 (but not other versions!) attempt to execute a 286 LOADALL
|
---|
| 124 | instruction. LOADALL must be emulated for OS/2 to work properly. HIMEM.SYS
|
---|
| 125 | version 2.03 and later also contains 286 LOADALL code but this will not be
|
---|
| 126 | executed on 386+ processors.
|
---|
| 127 |
|
---|
[60610] | 128 | - IBM and Microsoft OS/2 1.0 use CMOS shutdown status 9 to get back from
|
---|
| 129 | protected mode without having called INT 15h/87h at all. That makes the
|
---|
| 130 | status 9 handling a public interface (just like codes 5 and 0Ah) which
|
---|
| 131 | has to be compatible with other BIOS implementations.
|
---|
| 132 |
|
---|
[59354] | 133 | - Windows NT 3.5 and 3.51 with MPS HAL requires that INT 15h/E820h return the
|
---|
| 134 | I/O APIC range as reserved, or not return any ranges at all just below 4GB.
|
---|
| 135 | Otherwise the NT kernel will crash early during init due to confusion about
|
---|
| 136 | the top of memory.
|
---|
[49286] | 137 |
|
---|
[69703] | 138 | - Darwin x86 6.0.2 ISO (darwinx86-602.iso) has a bizarre boot sector (using
|
---|
| 139 | El Torito hard disk emulation) with the first five bytes being zero. It
|
---|
| 140 | appears to be valid despite the oddity.
|
---|
[59354] | 141 |
|
---|
[70333] | 142 | - Darwin 6.0.2 also uses an El Torito emulated hard disk. In addition, if
|
---|
| 143 | INT 13h/41h succeeds, Darwin uses INT13X to read from the emulated drive.
|
---|
| 144 |
|
---|
| 145 | - Symantec Ghost 11.5 bootable CD also uses El Torito hard disk emulation,
|
---|
| 146 | uses INT13X without checking for support, and crashes if INT13X is not
|
---|
| 147 | supported on the emulated drive.
|
---|
| 148 |
|
---|
| 149 |
|
---|
[60610] | 150 | 286 BIOS
|
---|
| 151 | --------
|
---|
| 152 |
|
---|
| 153 | For testing purposes, it's quite useful to have a BIOS that can run in a
|
---|
| 154 | classic PC/AT environment with a 286 CPU. This forces various changes, not
|
---|
| 155 | always obvious:
|
---|
| 156 |
|
---|
| 157 | - C code can be easily compiled to produce 286-compatible object code
|
---|
| 158 |
|
---|
| 159 | - 32-bit BIOS services such as APM or PCI BIOS are irrelevant
|
---|
| 160 |
|
---|
| 161 | - PCI cannot be supported because it requires 32-bit port I/O
|
---|
| 162 |
|
---|
| 163 | - AHCI cannot be supported because it requires 32-bit port I/O and PCI
|
---|
| 164 |
|
---|
| 165 | - Switching to protected mode must be done using LMSW instead of CR0
|
---|
| 166 |
|
---|
| 167 | - Switching back to real mode must reset the CPU (currently triple fault)
|
---|
| 168 | and regain control by setting up the CMOS shutdown status byte
|
---|
| 169 |
|
---|
| 170 |
|
---|
| 171 |
|
---|
[38699] | 172 | Notes on BIOS implementation
|
---|
| 173 | ----------------------------
|
---|
| 174 |
|
---|
| 175 | - To return values from functions not declared as __interrupt, the arguments
|
---|
| 176 | may need to be declared volatile (not ideal, but does the job).
|
---|
| 177 |
|
---|
| 178 | - The way the POST code selectively clears or doesn't clear memory
|
---|
| 179 | is extremely suspect and will need reworking.
|
---|
| 180 |
|
---|
| 181 | - Need to review string routines wrt direction flag (should be OK now).
|
---|
| 182 |
|
---|
| 183 | - Need to review CMOS access wrt interrupts (possible index reg change by
|
---|
| 184 | an interrupt handler).
|
---|
| 185 |
|
---|
| 186 | - The POST code zeroes the entire BDA, and then various bits zero specific
|
---|
| 187 | parts of the BDA again. That's a waste of time.
|
---|
| 188 |
|
---|
| 189 | - After a reset, all interrupts are unmasked. Not sure if that's OK.
|
---|
| 190 |
|
---|
| 191 | - BCC mishandles the following (where buf is an uint8_t array):
|
---|
| 192 | lba=buf[0x2B]*0x1000000+buf[0x2A]*0x10000+buf[0x29]*0x100+buf[0x28];
|
---|
| 193 | The buf[x]*100 expression should end up being of type signed int, which
|
---|
| 194 | causes the sign to be incorrectly propagated. BCC incorrectly keeps
|
---|
| 195 | the type unsigned.
|
---|
| 196 |
|
---|
[42770] | 197 | - The PCI BIOS services are implemented in C, compiled twice as 16-bit and
|
---|
| 198 | 32-bit code. This reduces the development effort and significantly lowers
|
---|
| 199 | the risk of discrepancies between 16-bit and 32-bit implementation. Care
|
---|
| 200 | must be taken because the 16-bit implementation can be executed in both
|
---|
| 201 | real and protected mode.
|
---|
[38699] | 202 |
|
---|
[42770] | 203 | - APM can be in theory implemented only once for real, 16-bit protected and
|
---|
| 204 | 32-bit protected mode. Unfortunately this is very inconvenient in C since
|
---|
| 205 | the default stack size changes between 16-bit and 32-bit callers. Therefore
|
---|
| 206 | real mode APM (which supports most functions) is implemented in C and
|
---|
| 207 | protected-mode APM is written in assembler for both 16-bit and 32-bit calls,
|
---|
| 208 | with a small 32->16 thunk.
|
---|
[38699] | 209 |
|
---|
[46234] | 210 | - The -of switch can be used to avoid generating ENTER/LEAVE instructions.
|
---|
| 211 | This appears to be an undocumented and perhaps unintentional side effect.
|
---|
[42770] | 212 |
|
---|
[46234] | 213 |
|
---|
[38699] | 214 | Code size notes (code as of 7/6/2011):
|
---|
| 215 |
|
---|
| 216 | The following values are the size of the _TEXT segment, i.e. only C code;
|
---|
| 217 | data defined in C is not included, neither are assembly modules.
|
---|
| 218 |
|
---|
| 219 | Options: Size (hex):
|
---|
| 220 | -------- -----------
|
---|
| 221 | -0 -zu -s -oas -ecc 631A
|
---|
| 222 | -3 -zu -s -oas -ecc 5C1E
|
---|
| 223 | -0 -zu -s -oas 578A
|
---|
| 224 | -3 -zu -s -oas 5452
|
---|
| 225 |
|
---|
| 226 | Both generating 386 code and using register-based calling convention for
|
---|
| 227 | internal functions brings significant size savings (15% when combined).
|
---|