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