[NTVDM]
[reactos.git] / reactos / subsystems / ntvdm / bios / bios32 / bios32.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: bios32.c
5 * PURPOSE: VDM 32-bit BIOS
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #define NDEBUG
12
13 /* For BIOS Version number */
14 #include <reactos/buildno.h>
15
16 #include "emulator.h"
17 #include "cpu/cpu.h" // for EMULATOR_FLAG_CF
18 #include "int32.h"
19 // #include "bop.h"
20
21 #include "../bios.h"
22 #include "../rom.h"
23 #include "bios32.h"
24 #include "bios32p.h"
25 #include "kbdbios32.h"
26 #include "vidbios32.h"
27 #include "moubios32.h"
28
29 #include "io.h"
30 #include "hardware/cmos.h"
31 #include "hardware/pic.h"
32 #include "hardware/timer.h"
33
34 /* PRIVATE VARIABLES **********************************************************/
35
36 CALLBACK16 BiosContext;
37
38 /*
39
40 Bochs BIOS, see rombios.h
41 =========================
42
43 // model byte 0xFC = AT
44 #define SYS_MODEL_ID 0xFC
45 #define SYS_SUBMODEL_ID 0x00
46 #define BIOS_REVISION 1
47 #define BIOS_CONFIG_TABLE 0xe6f5
48
49 #ifndef BIOS_BUILD_DATE
50 # define BIOS_BUILD_DATE "06/23/99"
51 #endif
52
53 // 1K of base memory used for Extended Bios Data Area (EBDA)
54 // EBDA is used for PS/2 mouse support, and IDE BIOS, etc.
55 #define EBDA_SEG 0x9FC0
56 #define EBDA_SIZE 1 // In KiB
57 #define BASE_MEM_IN_K (640 - EBDA_SIZE)
58
59
60 See rombios.c
61 =============
62
63 ROM BIOS compatibility entry points:
64 ===================================
65 $e05b ; POST Entry Point
66 $e2c3 ; NMI Handler Entry Point
67 $e3fe ; INT 13h Fixed Disk Services Entry Point
68 $e401 ; Fixed Disk Parameter Table
69 $e6f2 ; INT 19h Boot Load Service Entry Point
70 $e6f5 ; Configuration Data Table
71 $e729 ; Baud Rate Generator Table
72 $e739 ; INT 14h Serial Communications Service Entry Point
73 $e82e ; INT 16h Keyboard Service Entry Point
74 $e987 ; INT 09h Keyboard Service Entry Point
75 $ec59 ; INT 13h Diskette Service Entry Point
76 $ef57 ; INT 0Eh Diskette Hardware ISR Entry Point
77 $efc7 ; Diskette Controller Parameter Table
78 $efd2 ; INT 17h Printer Service Entry Point
79 $f045 ; INT 10 Functions 0-Fh Entry Point
80 $f065 ; INT 10h Video Support Service Entry Point
81 $f0a4 ; MDA/CGA Video Parameter Table (INT 1Dh)
82 $f841 ; INT 12h Memory Size Service Entry Point
83 $f84d ; INT 11h Equipment List Service Entry Point
84 $f859 ; INT 15h System Services Entry Point
85 $fa6e ; Character Font for 320x200 & 640x200 Graphics (lower 128 characters)
86 $fe6e ; INT 1Ah Time-of-day Service Entry Point
87 $fea5 ; INT 08h System Timer ISR Entry Point
88 $fef3 ; Initial Interrupt Vector Offsets Loaded by POST
89 $ff53 ; IRET Instruction for Dummy Interrupt Handler
90 $ff54 ; INT 05h Print Screen Service Entry Point
91 $fff0 ; Power-up Entry Point
92 $fff5 ; ASCII Date ROM was built - 8 characters in MM/DD/YY
93 $fffe ; System Model ID
94
95 */
96
97 /*
98 * See Ralf Brown: http://www.ctyme.com/intr/rb-1594.htm#Table515
99 * for more information.
100 */
101 #define BIOS_MODEL 0xFC // PC-AT
102 #define BIOS_SUBMODEL 0x01 // AT models 319,339 8 MHz, Enh Keyb, 3.5"
103 #define BIOS_REVISION 0x00
104 // FIXME: Find a nice PS/2 486 + 487 BIOS combination!
105
106 /*
107 * WARNING! For compatibility purposes the string "IBM" should be at F000:E00E .
108 * Some programs alternatively look at "COPR. IBM" that is at F000:E008 .
109 */
110 static const CHAR BiosCopyright[] = "0000000 NTVDM IBM Compatible 486 32-bit BIOS Copyright (C) ReactOS Team 1996-2014";
111 static const CHAR BiosVersion[] = "ReactOS NTVDM 32-bit BIOS "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")";
112 static const CHAR BiosDate[] = "06/17/13";
113
114 C_ASSERT(sizeof(BiosCopyright)-1 <= 0x5B); // Ensures that we won't overflow on the POST Code starting at F000:E05B
115 C_ASSERT(sizeof(BiosDate)-1 == 0x08);
116
117 /* 16-bit bootstrap code at F000:FFF0 */
118 static BYTE Bootstrap[] =
119 {
120 0xEA, // jmp far ptr
121 0x5B, 0xE0, 0x00, 0xF0, // F000:E05B
122 };
123
124 /*
125 * Normally at F000:E05B there is the POST that finally calls the bootstrap
126 * interrupt. It should also check the value of Bda->SoftReset. Since we do
127 * all the POST in 32 bit from the start, we just place there the bootstrap
128 * interrupt call.
129 */
130 static BYTE PostCode[] =
131 {
132 0xCD, 0x19, // int 0x19, the bootstrap loader interrupt
133 // LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_UNSIMULATE
134 };
135
136
137 /* PRIVATE FUNCTIONS **********************************************************/
138
139 static VOID WINAPI BiosException(LPWORD Stack)
140 {
141 /* Get the exception number and call the emulator API */
142 BYTE ExceptionNumber = LOBYTE(Stack[STACK_INT_NUM]);
143 EmulatorException(ExceptionNumber, Stack);
144 }
145
146 static VOID WINAPI BiosMiscService(LPWORD Stack)
147 {
148 switch (getAH())
149 {
150 /* Keyboard intercept */
151 case 0x4F:
152 {
153 /* CF should be set but let's just set it again just in case */
154 /* Do not modify AL (the hardware scan code), but set CF to continue processing */
155 // setCF(1);
156 Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
157 break;
158 }
159
160 /* Wait */
161 case 0x86:
162 {
163 /*
164 * Interval in microseconds in CX:DX
165 * See Ralf Brown: http://www.ctyme.com/intr/rb-1525.htm
166 * for more information.
167 */
168 Sleep(MAKELONG(getDX(), getCX()));
169
170 /* Clear CF */
171 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
172
173 break;
174 }
175
176 /* Copy Extended Memory */
177 case 0x87:
178 {
179 DWORD Count = (DWORD)getCX() * 2;
180 PFAST486_GDT_ENTRY Gdt = (PFAST486_GDT_ENTRY)SEG_OFF_TO_PTR(getES(), getSI());
181 DWORD SourceBase = Gdt[2].Base + (Gdt[2].BaseMid << 16) + (Gdt[2].BaseHigh << 24);
182 DWORD SourceLimit = Gdt[2].Limit + (Gdt[2].LimitHigh << 16);
183 DWORD DestBase = Gdt[3].Base + (Gdt[3].BaseMid << 16) + (Gdt[3].BaseHigh << 24);
184 DWORD DestLimit = Gdt[3].Limit + (Gdt[3].LimitHigh << 16);
185
186 /* Check for flags */
187 if (Gdt[2].Granularity) SourceLimit = (SourceLimit << 12) | 0xFFF;
188 if (Gdt[3].Granularity) DestLimit = (DestLimit << 12) | 0xFFF;
189
190 if ((Count > SourceLimit) || (Count > DestLimit))
191 {
192 setAX(0x80);
193 Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
194
195 break;
196 }
197
198 /* Copy */
199 RtlMoveMemory((PVOID)((ULONG_PTR)BaseAddress + DestBase),
200 (PVOID)((ULONG_PTR)BaseAddress + SourceBase),
201 Count);
202
203 setAX(ERROR_SUCCESS);
204 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
205 break;
206 }
207
208 /* Get Extended Memory Size */
209 case 0x88:
210 {
211 UCHAR Low, High;
212
213 /*
214 * Return the (usable) extended memory (after 1 MB)
215 * size in kB from CMOS.
216 */
217 IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_ACTUAL_EXT_MEMORY_LOW);
218 Low = IOReadB(CMOS_DATA_PORT);
219 IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_ACTUAL_EXT_MEMORY_HIGH);
220 High = IOReadB(CMOS_DATA_PORT);
221 setAX(MAKEWORD(Low, High));
222
223 /* Clear CF */
224 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
225
226 break;
227 }
228
229 /* Get Configuration */
230 case 0xC0:
231 {
232 /* Return the BIOS ROM Configuration Table address in ES:BX */
233 // The BCT is found at F000:E6F5 for 100% compatible BIOSes.
234 setES(BIOS_SEGMENT);
235 setBX(0xE6F5);
236
237 /* Call successful; clear CF */
238 setAH(0x00);
239 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
240
241 break;
242 }
243
244 /* Return Extended-Bios Data-Area Segment Address (PS) */
245 case 0xC1:
246 {
247 // Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
248 // setES(???);
249
250 /* We do not support EBDA yet */
251 Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
252
253 break;
254 }
255
256 /* Pointing Device BIOS Interface (PS) */
257 case 0xC2:
258 {
259 DPRINT1("INT 15h, AH = C2h must be implemented in order to support vendor mouse drivers\n");
260 break;
261 }
262
263 default:
264 {
265 DPRINT1("BIOS Function INT 15h, AH = 0x%02X NOT IMPLEMENTED\n",
266 getAH());
267 }
268 }
269 }
270
271 static VOID WINAPI BiosRomBasic(LPWORD Stack)
272 {
273 /* ROM Basic is unsupported, display a message to the user */
274 DisplayMessage(L"NTVDM doesn't support ROM Basic. The VDM is closing.");
275
276 /* Stop the VDM */
277 EmulatorTerminate();
278 return;
279 }
280
281 static VOID WINAPI BiosBootstrapLoader(LPWORD Stack)
282 {
283 /*
284 * In real bioses one loads the bootsector read from a diskette
285 * or from a disk, to 0000:7C00 and then one runs it.
286 * Since we are 32-bit VM and we hardcode our DOS at the moment,
287 * just call the DOS 32-bit initialization code.
288 */
289
290 DPRINT1("BiosBootstrapLoader -->\n");
291
292 DPRINT1("<-- BiosBootstrapLoader\n");
293 }
294
295 static VOID WINAPI BiosTimeService(LPWORD Stack)
296 {
297 switch (getAH())
298 {
299 case 0x00:
300 {
301 /* Set AL to 1 if midnight had passed, 0 otherwise */
302 setAL(Bda->MidnightPassed ? 0x01 : 0x00);
303
304 /* Return the tick count in CX:DX */
305 setCX(HIWORD(Bda->TickCounter));
306 setDX(LOWORD(Bda->TickCounter));
307
308 /* Reset the midnight flag */
309 Bda->MidnightPassed = FALSE;
310
311 break;
312 }
313
314 case 0x01:
315 {
316 /* Set the tick count to CX:DX */
317 Bda->TickCounter = MAKELONG(getDX(), getCX());
318
319 /* Reset the midnight flag */
320 Bda->MidnightPassed = FALSE;
321
322 break;
323 }
324
325 default:
326 {
327 DPRINT1("BIOS Function INT 1Ah, AH = 0x%02X NOT IMPLEMENTED\n",
328 getAH());
329 }
330 }
331 }
332
333 static VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack)
334 {
335 /* Increase the system tick count */
336 Bda->TickCounter++;
337 }
338
339
340 // From SeaBIOS
341 static VOID PicSetIRQMask(USHORT off, USHORT on)
342 {
343 UCHAR pic1off = off, pic1on = on, pic2off = off>>8, pic2on = on>>8;
344 IOWriteB(PIC_MASTER_DATA, (IOReadB(PIC_MASTER_DATA) & ~pic1off) | pic1on);
345 IOWriteB(PIC_SLAVE_DATA , (IOReadB(PIC_SLAVE_DATA ) & ~pic2off) | pic2on);
346 }
347
348 // From SeaBIOS
349 VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func)
350 {
351 UCHAR vector;
352
353 PicSetIRQMask(1 << hwirq, 0);
354 if (hwirq < 8)
355 vector = BIOS_PIC_MASTER_INT + hwirq;
356 else
357 vector = BIOS_PIC_SLAVE_INT + hwirq - 8;
358
359 RegisterBiosInt32(vector, func);
360 }
361
362
363 VOID PicIRQComplete(LPWORD Stack)
364 {
365 /* Get the interrupt number */
366 BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]);
367
368 /*
369 * If this was a PIC IRQ, send an End-of-Interrupt to the PIC.
370 */
371
372 if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8)
373 {
374 /* It was an IRQ from the master PIC */
375 IOWriteB(PIC_MASTER_CMD, PIC_OCW2_EOI);
376 }
377 else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8)
378 {
379 /* It was an IRQ from the slave PIC */
380 IOWriteB(PIC_SLAVE_CMD , PIC_OCW2_EOI);
381 IOWriteB(PIC_MASTER_CMD, PIC_OCW2_EOI);
382 }
383 }
384
385 static VOID WINAPI BiosHandleMasterPicIRQ(LPWORD Stack)
386 {
387 BYTE IrqNumber;
388
389 IOWriteB(PIC_MASTER_CMD, PIC_OCW3_READ_ISR /* == 0x0B */);
390 IrqNumber = IOReadB(PIC_MASTER_CMD);
391
392 DPRINT("Master - IrqNumber = 0x%02X\n", IrqNumber);
393
394 PicIRQComplete(Stack);
395 }
396
397 static VOID WINAPI BiosHandleSlavePicIRQ(LPWORD Stack)
398 {
399 BYTE IrqNumber;
400
401 IOWriteB(PIC_SLAVE_CMD, PIC_OCW3_READ_ISR /* == 0x0B */);
402 IrqNumber = IOReadB(PIC_SLAVE_CMD);
403
404 DPRINT("Slave - IrqNumber = 0x%02X\n", IrqNumber);
405
406 PicIRQComplete(Stack);
407 }
408
409 // Timer IRQ 0
410 static VOID WINAPI BiosTimerIrq(LPWORD Stack)
411 {
412 /*
413 * Perform the system timer interrupt.
414 *
415 * Do not call directly BiosSystemTimerInterrupt(Stack);
416 * because some programs may hook only BIOS_SYS_TIMER_INTERRUPT
417 * for their purpose...
418 */
419 /** EmulatorInterrupt(BIOS_SYS_TIMER_INTERRUPT); **/
420 Int32Call(&BiosContext, BIOS_SYS_TIMER_INTERRUPT);
421 PicIRQComplete(Stack);
422 }
423
424
425 static VOID BiosHwSetup(VOID)
426 {
427 /* Initialize the master and the slave PICs (cascade mode) */
428 IOWriteB(PIC_MASTER_CMD, PIC_ICW1 | PIC_ICW1_ICW4);
429 IOWriteB(PIC_SLAVE_CMD , PIC_ICW1 | PIC_ICW1_ICW4);
430
431 /*
432 * Set the interrupt vector offsets for each PIC
433 * (base IRQs: 0x08-0x0F for IRQ 0-7, 0x70-0x77 for IRQ 8-15)
434 */
435 IOWriteB(PIC_MASTER_DATA, BIOS_PIC_MASTER_INT);
436 IOWriteB(PIC_SLAVE_DATA , BIOS_PIC_SLAVE_INT );
437
438 /* Tell the master PIC that there is a slave PIC at IRQ 2 */
439 IOWriteB(PIC_MASTER_DATA, 1 << 2);
440 /* Tell the slave PIC its cascade identity */
441 IOWriteB(PIC_SLAVE_DATA , 2);
442
443 /* Make sure both PICs are in 8086 mode */
444 IOWriteB(PIC_MASTER_DATA, PIC_ICW4_8086);
445 IOWriteB(PIC_SLAVE_DATA , PIC_ICW4_8086);
446
447 /* Clear the masks for both PICs */
448 // IOWriteB(PIC_MASTER_DATA, 0x00);
449 // IOWriteB(PIC_SLAVE_DATA , 0x00);
450 /* Disable all IRQs */
451 IOWriteB(PIC_MASTER_DATA, 0xFF);
452 IOWriteB(PIC_SLAVE_DATA , 0xFF);
453
454
455 /* Initialize PIT Counter 0 */
456 IOWriteB(PIT_COMMAND_PORT, 0x34);
457 IOWriteB(PIT_DATA_PORT(0), 0x00);
458 IOWriteB(PIT_DATA_PORT(0), 0x00);
459
460 /* Initialize PIT Counter 1 */
461 IOWriteB(PIT_COMMAND_PORT, 0x74);
462 IOWriteB(PIT_DATA_PORT(1), 0x00);
463 IOWriteB(PIT_DATA_PORT(1), 0x00);
464
465 /* Initialize PIT Counter 2 */
466 IOWriteB(PIT_COMMAND_PORT, 0xB4);
467 IOWriteB(PIT_DATA_PORT(2), 0x00);
468 IOWriteB(PIT_DATA_PORT(2), 0x00);
469
470 EnableHwIRQ(0, BiosTimerIrq);
471 }
472
473 static VOID InitializeBiosInt32(VOID)
474 {
475 USHORT i;
476
477 /* Initialize the callback context */
478 InitializeContext(&BiosContext, BIOS_SEGMENT, 0x0000);
479
480 /* Register the default BIOS 32-bit Interrupts */
481 for (i = 0x00; i <= 0xFF; i++)
482 {
483 RegisterBiosInt32(i, NULL);
484 }
485
486 /* Initialize the exception vector interrupts to a default Exception handler */
487 for (i = 0; i < 8; i++)
488 RegisterBiosInt32(i, BiosException);
489
490 /* Initialize HW vector interrupts to a default HW handler */
491 for (i = BIOS_PIC_MASTER_INT; i < BIOS_PIC_MASTER_INT + 8; i++)
492 RegisterBiosInt32(i, BiosHandleMasterPicIRQ);
493 for (i = BIOS_PIC_SLAVE_INT ; i < BIOS_PIC_SLAVE_INT + 8; i++)
494 RegisterBiosInt32(i, BiosHandleSlavePicIRQ);
495
496 /* Initialize software vector handlers */
497 RegisterBiosInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService );
498 RegisterBiosInt32(BIOS_MEMORY_SIZE , BiosGetMemorySize );
499 RegisterBiosInt32(BIOS_MISC_INTERRUPT , BiosMiscService );
500 RegisterBiosInt32(BIOS_ROM_BASIC , BiosRomBasic );
501 RegisterBiosInt32(BIOS_BOOTSTRAP_LOADER , BiosBootstrapLoader );
502 RegisterBiosInt32(BIOS_TIME_INTERRUPT , BiosTimeService );
503 RegisterBiosInt32(BIOS_SYS_TIMER_INTERRUPT, BiosSystemTimerInterrupt);
504
505 /* Some interrupts are in fact addresses to tables */
506 ((PULONG)BaseAddress)[0x1E] = (ULONG)NULL;
507 ((PULONG)BaseAddress)[0x41] = (ULONG)NULL;
508 ((PULONG)BaseAddress)[0x46] = (ULONG)NULL;
509 ((PULONG)BaseAddress)[0x48] = (ULONG)NULL;
510 ((PULONG)BaseAddress)[0x49] = (ULONG)NULL;
511 }
512
513 static VOID InitializeBiosInfo(VOID)
514 {
515 RtlZeroMemory(Bct, sizeof(*Bct));
516
517 Bct->Length = sizeof(*Bct);
518 Bct->Model = BIOS_MODEL;
519 Bct->SubModel = BIOS_SUBMODEL;
520 Bct->Revision = BIOS_REVISION;
521 Bct->Feature[0] = 0x70; // At the moment we don't support "wait for external event (INT 15/AH=41h)", we also don't have any "extended BIOS area allocated (usually at top of RAM)"; see http://www.ctyme.com/intr/rb-1594.htm#Table510
522 Bct->Feature[1] = 0x00; // We don't support anything from here; see http://www.ctyme.com/intr/rb-1594.htm#Table511
523 Bct->Feature[2] = 0x00;
524 Bct->Feature[3] = 0x00;
525 Bct->Feature[4] = 0x00;
526 }
527
528 static VOID InitializeBiosData(VOID)
529 {
530 UCHAR Low, High;
531
532 /* System BIOS Copyright */
533 RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE000), BiosCopyright, sizeof(BiosCopyright)-1);
534
535 /* System BIOS Version */
536 RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE080), BiosVersion, sizeof(BiosVersion)-1); // FIXME: or E061, or E100 ??
537
538 /* System BIOS Date */
539 RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF5), BiosDate, sizeof(BiosDate)-1);
540
541 /* System BIOS Model (same as Bct->Model) */
542 *(PBYTE)(SEG_OFF_TO_PTR(0xF000, 0xFFFE)) = BIOS_MODEL;
543
544 /* Initialize the BDA contents */
545 RtlZeroMemory(Bda, sizeof(*Bda));
546 Bda->EquipmentList = BIOS_EQUIPMENT_LIST;
547
548 /*
549 * Retrieve the conventional memory size
550 * in kB from CMOS, typically 640 kB.
551 */
552 IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_BASE_MEMORY_LOW);
553 Low = IOReadB(CMOS_DATA_PORT);
554 IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_BASE_MEMORY_HIGH);
555 High = IOReadB(CMOS_DATA_PORT);
556 Bda->MemorySize = MAKEWORD(Low, High);
557 }
558
559 /* PUBLIC FUNCTIONS ***********************************************************/
560
561 /*
562 * The BIOS POST (Power On-Self Test)
563 */
564 BOOLEAN Bios32Initialize(VOID)
565 {
566 BOOLEAN Success;
567
568 /* Initialize the stack */
569 // That's what says IBM... (stack at 30:00FF going downwards)
570 // setSS(0x0000);
571 // setSP(0x0400);
572 setSS(0x0050); // Stack at 50:0400, going downwards
573 setSP(0x0400);
574
575 /* Set data segment */
576 setDS(BDA_SEGMENT);
577
578 /* Initialize the BDA and the BIOS ROM Information */
579 InitializeBiosData();
580 InitializeBiosInfo();
581
582 /* Register the BIOS 32-bit Interrupts */
583 InitializeBiosInt32();
584
585 /* Initialize platform hardware (PIC/PIT chips, ...) */
586 BiosHwSetup();
587
588 /* Initialize the Keyboard, Video and Mouse BIOS */
589 if (!KbdBios32Initialize() || !VidBios32Initialize() || !MouseBios32Initialize())
590 return FALSE;
591
592 ///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
593
594 /* Load some ROMs */
595 Success = LoadRom("boot.bin", (PVOID)0xE0000, NULL);
596 DPRINT1("Test ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
597
598 SearchAndInitRoms(&BiosContext);
599
600 /* Bootstrap code */
601 RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE05B), PostCode , sizeof(PostCode ));
602 RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF0), Bootstrap, sizeof(Bootstrap));
603
604 /* We are done */
605 return TRUE;
606 }
607
608 VOID Bios32Cleanup(VOID)
609 {
610 MouseBios32Cleanup();
611 VidBios32Cleanup();
612 KbdBios32Cleanup();
613 }
614
615 /* EOF */