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 |
|
---|
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.
|
---|
10 |
|
---|
11 | - NetWare 5.1 is one of the *extremely* few users of El Torito hard disk
|
---|
12 | emulation.
|
---|
13 |
|
---|
14 | - Keystroke check (INT 16h, fn 01h/11h) always enables interrupts on return.
|
---|
15 | DOS POWER.EXE depends on that in some situations.
|
---|
16 |
|
---|
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 |
|
---|
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 |
|
---|
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
|
---|
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.
|
---|
36 |
|
---|
37 | - Very few guests use the 32-bit PCI BIOS interface. One is OS/2 (but falls
|
---|
38 | back), another is Etherboot.
|
---|
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 |
|
---|
43 | - NetWare 6.x is the only known guest which uses the PCI BIOS service to read
|
---|
44 | the IRQ routing table.
|
---|
45 |
|
---|
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 |
|
---|
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).
|
---|
56 |
|
---|
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.
|
---|
60 |
|
---|
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 |
|
---|
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 |
|
---|
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 |
|
---|
75 | - Windows NT (including XP) uses INT 13h/08h to obtain the DPT for each floppy
|
---|
76 | drive. NT assumes a 13-byte DPT which includes the number of tracks. NT will
|
---|
77 | refuse to read more tracks than the DPT specifies and formats as many tracks
|
---|
78 | as the DPT specifies.
|
---|
79 |
|
---|
80 | - Windows 98 SE boot CD uses 32-bit registers in real mode and will fail in
|
---|
81 | mysterious ways if BIOS trashes high bits of EAX (and likely others).
|
---|
82 |
|
---|
83 | - PC DOS 6.x/7.x QCONFIG is a rare user of INT 16h fn 0Ah (read keyboard ID).
|
---|
84 |
|
---|
85 | - DOS POWER.EXE uses the real mode APM interface, Windows 3.1 POWER.DRV and
|
---|
86 | OS/2 APM.SYS use the 16-bit protected mode APM interface, and Windows 9x
|
---|
87 | uses the 32-bit protected mode APM interface.
|
---|
88 |
|
---|
89 | - Windows 98 is one of the few APM 1.2 users; Windows 95 uses APM 1.1, while
|
---|
90 | newer systems prefer ACPI.
|
---|
91 |
|
---|
92 | - Windows 3.1 Standard mode violates the APM specifications and calls into
|
---|
93 | APM with CPL=3, causing the HLT instruction to fault if used. 386 Enhanced
|
---|
94 | mode Windows 3.1 calls into APM with CPL=3.
|
---|
95 |
|
---|
96 | - QNX4 calls 16-bit protected-mode PCI BIOS in an environment where ESP is
|
---|
97 | 16-bit but SS is a 32-bit stack segment. In such environments, using the
|
---|
98 | ENTER/LEAVE sequence is fatal if the high word of EBP is non-zero (which
|
---|
99 | it will be with QNX 4.25). LEAVE propagates the high word of EBP into ESP
|
---|
100 | with fatal consequences.
|
---|
101 |
|
---|
102 | - Plan 9 also runs 16-bit code with a 32-bit stack segment, except Plan 9
|
---|
103 | thinks it counts as real mode. Same ENTER/LEAVE problem as above.
|
---|
104 |
|
---|
105 | - AIX 1.3 is a rare user of INT 15h/89h (switch to protected mode) service.
|
---|
106 |
|
---|
107 | - IBM OS/2 1.0/1.1 (but not other versions!) attempt to execute a 286 LOADALL
|
---|
108 | instruction. LOADALL must be emulated for OS/2 to work properly. HIMEM.SYS
|
---|
109 | version 2.03 and later also contains 286 LOADALL code but this will not be
|
---|
110 | executed on 386+ processors.
|
---|
111 |
|
---|
112 | - IBM and Microsoft OS/2 1.0 use CMOS shutdown status 9 to get back from
|
---|
113 | protected mode without having called INT 15h/87h at all. That makes the
|
---|
114 | status 9 handling a public interface (just like codes 5 and 0Ah) which
|
---|
115 | has to be compatible with other BIOS implementations.
|
---|
116 |
|
---|
117 | - Windows NT 3.5 and 3.51 with MPS HAL requires that INT 15h/E820h return the
|
---|
118 | I/O APIC range as reserved, or not return any ranges at all just below 4GB.
|
---|
119 | Otherwise the NT kernel will crash early during init due to confusion about
|
---|
120 | the top of memory.
|
---|
121 |
|
---|
122 | - Darwin x86 6.0.2 ISO (darwinx86-602.iso) has a bizarre boot sector (using
|
---|
123 | El Torito hard disk emulation) with the first five bytes being zero. It
|
---|
124 | appears to be valid despite the oddity.
|
---|
125 |
|
---|
126 | - Darwin 6.0.2 also uses an El Torito emulated hard disk. In addition, if
|
---|
127 | INT 13h/41h succeeds, Darwin uses INT13X to read from the emulated drive.
|
---|
128 |
|
---|
129 | - Symantec Ghost 11.5 bootable CD also uses El Torito hard disk emulation,
|
---|
130 | uses INT13X without checking for support, and crashes if INT13X is not
|
---|
131 | supported on the emulated drive.
|
---|
132 |
|
---|
133 |
|
---|
134 | 286 BIOS
|
---|
135 | --------
|
---|
136 |
|
---|
137 | For testing purposes, it's quite useful to have a BIOS that can run in a
|
---|
138 | classic PC/AT environment with a 286 CPU. This forces various changes, not
|
---|
139 | always obvious:
|
---|
140 |
|
---|
141 | - C code can be easily compiled to produce 286-compatible object code
|
---|
142 |
|
---|
143 | - 32-bit BIOS services such as APM or PCI BIOS are irrelevant
|
---|
144 |
|
---|
145 | - PCI cannot be supported because it requires 32-bit port I/O
|
---|
146 |
|
---|
147 | - AHCI cannot be supported because it requires 32-bit port I/O and PCI
|
---|
148 |
|
---|
149 | - Switching to protected mode must be done using LMSW instead of CR0
|
---|
150 |
|
---|
151 | - Switching back to real mode must reset the CPU (currently triple fault)
|
---|
152 | and regain control by setting up the CMOS shutdown status byte
|
---|
153 |
|
---|
154 |
|
---|
155 |
|
---|
156 | Notes on BIOS implementation
|
---|
157 | ----------------------------
|
---|
158 |
|
---|
159 | - To return values from functions not declared as __interrupt, the arguments
|
---|
160 | may need to be declared volatile (not ideal, but does the job).
|
---|
161 |
|
---|
162 | - The way the POST code selectively clears or doesn't clear memory
|
---|
163 | is extremely suspect and will need reworking.
|
---|
164 |
|
---|
165 | - Need to review string routines wrt direction flag (should be OK now).
|
---|
166 |
|
---|
167 | - Need to review CMOS access wrt interrupts (possible index reg change by
|
---|
168 | an interrupt handler).
|
---|
169 |
|
---|
170 | - The POST code zeroes the entire BDA, and then various bits zero specific
|
---|
171 | parts of the BDA again. That's a waste of time.
|
---|
172 |
|
---|
173 | - After a reset, all interrupts are unmasked. Not sure if that's OK.
|
---|
174 |
|
---|
175 | - BCC mishandles the following (where buf is an uint8_t array):
|
---|
176 | lba=buf[0x2B]*0x1000000+buf[0x2A]*0x10000+buf[0x29]*0x100+buf[0x28];
|
---|
177 | The buf[x]*100 expression should end up being of type signed int, which
|
---|
178 | causes the sign to be incorrectly propagated. BCC incorrectly keeps
|
---|
179 | the type unsigned.
|
---|
180 |
|
---|
181 | - The PCI BIOS services are implemented in C, compiled twice as 16-bit and
|
---|
182 | 32-bit code. This reduces the development effort and significantly lowers
|
---|
183 | the risk of discrepancies between 16-bit and 32-bit implementation. Care
|
---|
184 | must be taken because the 16-bit implementation can be executed in both
|
---|
185 | real and protected mode.
|
---|
186 |
|
---|
187 | - APM can be in theory implemented only once for real, 16-bit protected and
|
---|
188 | 32-bit protected mode. Unfortunately this is very inconvenient in C since
|
---|
189 | the default stack size changes between 16-bit and 32-bit callers. Therefore
|
---|
190 | real mode APM (which supports most functions) is implemented in C and
|
---|
191 | protected-mode APM is written in assembler for both 16-bit and 32-bit calls,
|
---|
192 | with a small 32->16 thunk.
|
---|
193 |
|
---|
194 | - The -of switch can be used to avoid generating ENTER/LEAVE instructions.
|
---|
195 | This appears to be an undocumented and perhaps unintentional side effect.
|
---|
196 |
|
---|
197 |
|
---|
198 | Code size notes (code as of 7/6/2011):
|
---|
199 |
|
---|
200 | The following values are the size of the _TEXT segment, i.e. only C code;
|
---|
201 | data defined in C is not included, neither are assembly modules.
|
---|
202 |
|
---|
203 | Options: Size (hex):
|
---|
204 | -------- -----------
|
---|
205 | -0 -zu -s -oas -ecc 631A
|
---|
206 | -3 -zu -s -oas -ecc 5C1E
|
---|
207 | -0 -zu -s -oas 578A
|
---|
208 | -3 -zu -s -oas 5452
|
---|
209 |
|
---|
210 | Both generating 386 code and using register-based calling convention for
|
---|
211 | internal functions brings significant size savings (15% when combined).
|
---|