2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
5 * PURPOSE: VDM 32-bit BIOS
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
9 /* INCLUDES *******************************************************************/
13 /* For BIOS Version number */
14 #include <reactos/buildno.h>
17 #include "cpu/cpu.h" // for EMULATOR_FLAG_CF
25 #include "kbdbios32.h"
26 #include "vidbios32.h"
27 #include "moubios32.h"
30 #include "hardware/cmos.h"
31 #include "hardware/pic.h"
32 #include "hardware/timer.h"
34 /* PRIVATE VARIABLES **********************************************************/
36 CALLBACK16 BiosContext
;
40 Bochs BIOS, see rombios.h
41 =========================
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
49 #ifndef BIOS_BUILD_DATE
50 # define BIOS_BUILD_DATE "06/23/99"
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)
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
98 * See Ralf Brown: http://www.ctyme.com/intr/rb-1594.htm#Table515
99 * for more information.
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!
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 .
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";
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);
117 /* 16-bit bootstrap code at F000:FFF0 */
118 static BYTE Bootstrap
[] =
121 0x5B, 0xE0, 0x00, 0xF0, // F000:E05B
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
130 static BYTE PostCode
[] =
132 LOBYTE(EMULATOR_BOP
), HIBYTE(EMULATOR_BOP
), BOP_RESET
, // Call BIOS POST
133 0xCD, 0x19, // INT 0x19, the bootstrap loader interrupt
134 // LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_UNSIMULATE
138 /* PRIVATE FUNCTIONS **********************************************************/
140 static VOID WINAPI
BiosException(LPWORD Stack
)
142 /* Get the exception number and call the emulator API */
143 BYTE ExceptionNumber
= LOBYTE(Stack
[STACK_INT_NUM
]);
144 EmulatorException(ExceptionNumber
, Stack
);
147 static VOID WINAPI
BiosMiscService(LPWORD Stack
)
151 /* Keyboard intercept */
154 /* CF should be set but let's just set it again just in case */
155 /* Do not modify AL (the hardware scan code), but set CF to continue processing */
157 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
165 * Interval in microseconds in CX:DX
166 * See Ralf Brown: http://www.ctyme.com/intr/rb-1525.htm
167 * for more information.
170 // HACK: For now, use the Win32 API (that takes time in milliseconds).
171 Sleep(MAKELONG(getDX(), getCX()) / 1000);
174 Stack
[STACK_FLAGS
] &= ~EMULATOR_FLAG_CF
;
179 /* Copy Extended Memory */
182 DWORD Count
= (DWORD
)getCX() * 2;
183 PFAST486_GDT_ENTRY Gdt
= (PFAST486_GDT_ENTRY
)SEG_OFF_TO_PTR(getES(), getSI());
184 DWORD SourceBase
= Gdt
[2].Base
+ (Gdt
[2].BaseMid
<< 16) + (Gdt
[2].BaseHigh
<< 24);
185 DWORD SourceLimit
= Gdt
[2].Limit
+ (Gdt
[2].LimitHigh
<< 16);
186 DWORD DestBase
= Gdt
[3].Base
+ (Gdt
[3].BaseMid
<< 16) + (Gdt
[3].BaseHigh
<< 24);
187 DWORD DestLimit
= Gdt
[3].Limit
+ (Gdt
[3].LimitHigh
<< 16);
189 /* Check for flags */
190 if (Gdt
[2].Granularity
) SourceLimit
= (SourceLimit
<< 12) | 0xFFF;
191 if (Gdt
[3].Granularity
) DestLimit
= (DestLimit
<< 12) | 0xFFF;
193 if ((Count
> SourceLimit
) || (Count
> DestLimit
))
196 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
202 RtlMoveMemory((PVOID
)((ULONG_PTR
)BaseAddress
+ DestBase
),
203 (PVOID
)((ULONG_PTR
)BaseAddress
+ SourceBase
),
206 setAX(ERROR_SUCCESS
);
207 Stack
[STACK_FLAGS
] &= ~EMULATOR_FLAG_CF
;
211 /* Get Extended Memory Size */
217 * Return the (usable) extended memory (after 1 MB)
218 * size in kB from CMOS.
220 IOWriteB(CMOS_ADDRESS_PORT
, CMOS_REG_ACTUAL_EXT_MEMORY_LOW
);
221 Low
= IOReadB(CMOS_DATA_PORT
);
222 IOWriteB(CMOS_ADDRESS_PORT
, CMOS_REG_ACTUAL_EXT_MEMORY_HIGH
);
223 High
= IOReadB(CMOS_DATA_PORT
);
224 setAX(MAKEWORD(Low
, High
));
227 Stack
[STACK_FLAGS
] &= ~EMULATOR_FLAG_CF
;
232 /* Get Configuration */
235 /* Return the BIOS ROM Configuration Table address in ES:BX */
236 // The BCT is found at F000:E6F5 for 100% compatible BIOSes.
240 /* Call successful; clear CF */
242 Stack
[STACK_FLAGS
] &= ~EMULATOR_FLAG_CF
;
247 /* Return Extended-Bios Data-Area Segment Address (PS) */
250 // Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
253 /* We do not support EBDA yet */
254 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
259 /* Pointing Device BIOS Interface (PS) */
262 DPRINT1("INT 15h, AH = C2h must be implemented in order to support vendor mouse drivers\n");
268 DPRINT1("BIOS Function INT 15h, AH = 0x%02X NOT IMPLEMENTED\n",
274 static VOID WINAPI
BiosRomBasic(LPWORD Stack
)
276 /* ROM Basic is unsupported, display a message to the user */
277 DisplayMessage(L
"NTVDM doesn't support ROM Basic. The VDM is closing.");
285 VOID
DosBootsectorInitialize(VOID
);
287 static VOID WINAPI
BiosBootstrapLoader(LPWORD Stack
)
290 * In real BIOSes one loads the bootsector read from a diskette
291 * or from a disk, copy it to 0000:7C00 and then boot it.
292 * Since we are 32-bit VM and we hardcode our DOS at the moment,
293 * just call the DOS 32-bit initialization code.
296 DPRINT1("BiosBootstrapLoader -->\n");
299 DosBootsectorInitialize();
302 * Position CPU to 0000:7C00 to boot the OS.
304 * Since we are called via the INT32 mechanism, we need to correctly set
305 * CS:IP, not by changing the current one (otherwise the interrupt could
306 * not be clean up and return properly), but by changing the CS:IP in the
307 * stack, so that when the interrupt returns, the modified CS:IP is popped
308 * off the stack and the CPU is correctly repositioned.
310 Stack
[STACK_CS
] = 0x0000;
311 Stack
[STACK_IP
] = 0x7C00;
313 DPRINT1("<-- BiosBootstrapLoader\n");
316 static VOID WINAPI
BiosTimeService(LPWORD Stack
)
322 /* Set AL to 1 if midnight had passed, 0 otherwise */
323 setAL(Bda
->MidnightPassed
? 0x01 : 0x00);
325 /* Return the tick count in CX:DX */
326 setCX(HIWORD(Bda
->TickCounter
));
327 setDX(LOWORD(Bda
->TickCounter
));
329 /* Reset the midnight flag */
330 Bda
->MidnightPassed
= FALSE
;
337 /* Set the tick count to CX:DX */
338 Bda
->TickCounter
= MAKELONG(getDX(), getCX());
340 /* Reset the midnight flag */
341 Bda
->MidnightPassed
= FALSE
;
348 DPRINT1("BIOS Function INT 1Ah, AH = 0x%02X NOT IMPLEMENTED\n",
354 static VOID WINAPI
BiosSystemTimerInterrupt(LPWORD Stack
)
356 /* Increase the system tick count */
362 static VOID
PicSetIRQMask(USHORT off
, USHORT on
)
364 UCHAR pic1off
= off
, pic1on
= on
, pic2off
= off
>>8, pic2on
= on
>>8;
365 IOWriteB(PIC_MASTER_DATA
, (IOReadB(PIC_MASTER_DATA
) & ~pic1off
) | pic1on
);
366 IOWriteB(PIC_SLAVE_DATA
, (IOReadB(PIC_SLAVE_DATA
) & ~pic2off
) | pic2on
);
370 VOID
EnableHwIRQ(UCHAR hwirq
, EMULATOR_INT32_PROC func
)
374 PicSetIRQMask(1 << hwirq
, 0);
376 vector
= BIOS_PIC_MASTER_INT
+ hwirq
;
378 vector
= BIOS_PIC_SLAVE_INT
+ hwirq
- 8;
380 RegisterBiosInt32(vector
, func
);
384 VOID
PicIRQComplete(LPWORD Stack
)
386 /* Get the interrupt number */
387 BYTE IntNum
= LOBYTE(Stack
[STACK_INT_NUM
]);
390 * If this was a PIC IRQ, send an End-of-Interrupt to the PIC.
393 if (IntNum
>= BIOS_PIC_MASTER_INT
&& IntNum
< BIOS_PIC_MASTER_INT
+ 8)
395 /* It was an IRQ from the master PIC */
396 IOWriteB(PIC_MASTER_CMD
, PIC_OCW2_EOI
);
398 else if (IntNum
>= BIOS_PIC_SLAVE_INT
&& IntNum
< BIOS_PIC_SLAVE_INT
+ 8)
400 /* It was an IRQ from the slave PIC */
401 IOWriteB(PIC_SLAVE_CMD
, PIC_OCW2_EOI
);
402 IOWriteB(PIC_MASTER_CMD
, PIC_OCW2_EOI
);
406 static VOID WINAPI
BiosHandleMasterPicIRQ(LPWORD Stack
)
410 IOWriteB(PIC_MASTER_CMD
, PIC_OCW3_READ_ISR
/* == 0x0B */);
411 IrqNumber
= IOReadB(PIC_MASTER_CMD
);
413 DPRINT("Master - IrqNumber = 0x%02X\n", IrqNumber
);
415 PicIRQComplete(Stack
);
418 static VOID WINAPI
BiosHandleSlavePicIRQ(LPWORD Stack
)
422 IOWriteB(PIC_SLAVE_CMD
, PIC_OCW3_READ_ISR
/* == 0x0B */);
423 IrqNumber
= IOReadB(PIC_SLAVE_CMD
);
425 DPRINT("Slave - IrqNumber = 0x%02X\n", IrqNumber
);
427 PicIRQComplete(Stack
);
431 static VOID WINAPI
BiosTimerIrq(LPWORD Stack
)
434 * Perform the system timer interrupt.
436 * Do not call directly BiosSystemTimerInterrupt(Stack);
437 * because some programs may hook only BIOS_SYS_TIMER_INTERRUPT
438 * for their purpose...
440 /** EmulatorInterrupt(BIOS_SYS_TIMER_INTERRUPT); **/
441 Int32Call(&BiosContext
, BIOS_SYS_TIMER_INTERRUPT
);
442 PicIRQComplete(Stack
);
446 static VOID
BiosHwSetup(VOID
)
448 /* Initialize the master and the slave PICs (cascade mode) */
449 IOWriteB(PIC_MASTER_CMD
, PIC_ICW1
| PIC_ICW1_ICW4
);
450 IOWriteB(PIC_SLAVE_CMD
, PIC_ICW1
| PIC_ICW1_ICW4
);
453 * Set the interrupt vector offsets for each PIC
454 * (base IRQs: 0x08-0x0F for IRQ 0-7, 0x70-0x77 for IRQ 8-15)
456 IOWriteB(PIC_MASTER_DATA
, BIOS_PIC_MASTER_INT
);
457 IOWriteB(PIC_SLAVE_DATA
, BIOS_PIC_SLAVE_INT
);
459 /* Tell the master PIC that there is a slave PIC at IRQ 2 */
460 IOWriteB(PIC_MASTER_DATA
, 1 << 2);
461 /* Tell the slave PIC its cascade identity */
462 IOWriteB(PIC_SLAVE_DATA
, 2);
464 /* Make sure both PICs are in 8086 mode */
465 IOWriteB(PIC_MASTER_DATA
, PIC_ICW4_8086
);
466 IOWriteB(PIC_SLAVE_DATA
, PIC_ICW4_8086
);
468 /* Clear the masks for both PICs */
469 // IOWriteB(PIC_MASTER_DATA, 0x00);
470 // IOWriteB(PIC_SLAVE_DATA , 0x00);
471 /* Disable all IRQs */
472 IOWriteB(PIC_MASTER_DATA
, 0xFF);
473 IOWriteB(PIC_SLAVE_DATA
, 0xFF);
476 /* Initialize PIT Counter 0 - Mode 2, 16bit binary count */
477 // NOTE: Some BIOSes set it to Mode 3 instead.
478 IOWriteB(PIT_COMMAND_PORT
, 0x34);
479 // 18.2Hz refresh rate
480 IOWriteB(PIT_DATA_PORT(0), 0x00);
481 IOWriteB(PIT_DATA_PORT(0), 0x00);
483 /* Initialize PIT Counter 1 - Mode 2, 8bit binary count */
484 IOWriteB(PIT_COMMAND_PORT
, 0x54);
485 // DRAM refresh every 15ms: http://www.cs.dartmouth.edu/~spl/Academic/Organization/docs/PC%20Timer%208253.html
486 IOWriteB(PIT_DATA_PORT(1), 18);
488 /* Initialize PIT Counter 2 - Mode 3, 16bit binary count */
489 IOWriteB(PIT_COMMAND_PORT
, 0xB6);
491 IOWriteB(PIT_DATA_PORT(2), 0x97);
492 IOWriteB(PIT_DATA_PORT(2), 0x0A);
494 EnableHwIRQ(0, BiosTimerIrq
);
497 static VOID
InitializeBiosInt32(VOID
)
501 /* Initialize the callback context */
502 InitializeContext(&BiosContext
, BIOS_SEGMENT
, 0x0000);
504 /* Register the default BIOS 32-bit Interrupts */
505 for (i
= 0x00; i
<= 0xFF; i
++)
507 RegisterBiosInt32(i
, NULL
);
510 /* Initialize the exception vector interrupts to a default Exception handler */
511 for (i
= 0; i
< 8; i
++)
512 RegisterBiosInt32(i
, BiosException
);
514 /* Initialize HW vector interrupts to a default HW handler */
515 for (i
= BIOS_PIC_MASTER_INT
; i
< BIOS_PIC_MASTER_INT
+ 8; i
++)
516 RegisterBiosInt32(i
, BiosHandleMasterPicIRQ
);
517 for (i
= BIOS_PIC_SLAVE_INT
; i
< BIOS_PIC_SLAVE_INT
+ 8; i
++)
518 RegisterBiosInt32(i
, BiosHandleSlavePicIRQ
);
520 /* Initialize software vector handlers */
521 RegisterBiosInt32(BIOS_EQUIPMENT_INTERRUPT
, BiosEquipmentService
);
522 RegisterBiosInt32(BIOS_MEMORY_SIZE
, BiosGetMemorySize
);
523 RegisterBiosInt32(BIOS_MISC_INTERRUPT
, BiosMiscService
);
524 RegisterBiosInt32(BIOS_ROM_BASIC
, BiosRomBasic
);
525 RegisterBiosInt32(BIOS_BOOTSTRAP_LOADER
, BiosBootstrapLoader
);
526 RegisterBiosInt32(BIOS_TIME_INTERRUPT
, BiosTimeService
);
527 RegisterBiosInt32(BIOS_SYS_TIMER_INTERRUPT
, BiosSystemTimerInterrupt
);
529 /* Some interrupts are in fact addresses to tables */
530 ((PULONG
)BaseAddress
)[0x1E] = (ULONG
)NULL
;
531 ((PULONG
)BaseAddress
)[0x41] = (ULONG
)NULL
;
532 ((PULONG
)BaseAddress
)[0x46] = (ULONG
)NULL
;
533 ((PULONG
)BaseAddress
)[0x48] = (ULONG
)NULL
;
534 ((PULONG
)BaseAddress
)[0x49] = (ULONG
)NULL
;
537 static VOID
InitializeBiosData(VOID
)
541 /* Initialize the BDA contents */
542 RtlZeroMemory(Bda
, sizeof(*Bda
));
543 Bda
->EquipmentList
= BIOS_EQUIPMENT_LIST
;
546 * Retrieve the conventional memory size
547 * in kB from CMOS, typically 640 kB.
549 IOWriteB(CMOS_ADDRESS_PORT
, CMOS_REG_BASE_MEMORY_LOW
);
550 Low
= IOReadB(CMOS_DATA_PORT
);
551 IOWriteB(CMOS_ADDRESS_PORT
, CMOS_REG_BASE_MEMORY_HIGH
);
552 High
= IOReadB(CMOS_DATA_PORT
);
553 Bda
->MemorySize
= MAKEWORD(Low
, High
);
556 static VOID
InitializeBiosInfo(VOID
)
558 RtlZeroMemory(Bct
, sizeof(*Bct
));
560 Bct
->Length
= sizeof(*Bct
);
561 Bct
->Model
= BIOS_MODEL
;
562 Bct
->SubModel
= BIOS_SUBMODEL
;
563 Bct
->Revision
= BIOS_REVISION
;
564 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
565 Bct
->Feature
[1] = 0x00; // We don't support anything from here; see http://www.ctyme.com/intr/rb-1594.htm#Table511
566 Bct
->Feature
[2] = 0x00;
567 Bct
->Feature
[3] = 0x00;
568 Bct
->Feature
[4] = 0x00;
574 * The BIOS POST (Power On-Self Test)
581 DPRINT1("Bios32Post\n");
583 /* Initialize the stack */
584 // That's what says IBM... (stack at 30:00FF going downwards)
587 setSS(0x0050); // Stack at 50:0400, going downwards
590 /* Set data segment */
593 /* Initialize the BDA and the BIOS ROM Information */
594 InitializeBiosData();
595 InitializeBiosInfo();
598 * Initialize IVT and hardware
601 /* Register the BIOS 32-bit Interrupts */
602 InitializeBiosInt32();
604 /* Initialize platform hardware (PIC/PIT chips, ...) */
607 /* Initialize the Keyboard, Video and Mouse BIOS */
608 if (!KbdBios32Initialize() || !VidBios32Initialize() || !MouseBios32Initialize())
618 /* Initialize the Keyboard and Video BIOS */
619 if (!KbdBiosInitialize() || !VidBiosInitialize())
627 ///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
630 Success
= LoadRom("boot.bin", (PVOID
)0xE0000, NULL
);
631 DPRINT1("Test ROM loading %s ; GetLastError() = %u\n", Success
? "succeeded" : "failed", GetLastError());
633 SearchAndInitRoms(&BiosContext
);
636 * End of the 32-bit POST portion. We then fall back into 16-bit where
637 * the rest of the POST code is executed, typically calling INT 19h
642 static VOID WINAPI
Bios32ResetBop(LPWORD Stack
)
644 DPRINT1("Bios32ResetBop\n");
646 /* Disable interrupts */
649 // FIXME: Check the word at 0040h:0072h (Bda->SoftReset) and do one of the
650 // following actions:
651 // - if the word is 1234h, perform a warm reboot (aka. Ctrl-Alt-Del);
652 // - if the word is 0000h, perform a cold reboot (aka. Reset).
657 /* Enable interrupts */
662 /* PUBLIC FUNCTIONS ***********************************************************/
664 BOOLEAN
Bios32Initialize(VOID
)
667 * Initialize BIOS32 static data
671 RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE05B), PostCode
, sizeof(PostCode
));
672 RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF0), Bootstrap
, sizeof(Bootstrap
));
674 /* System BIOS Copyright */
675 RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE000), BiosCopyright
, sizeof(BiosCopyright
)-1);
677 /* System BIOS Version */
678 RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE080), BiosVersion
, sizeof(BiosVersion
)-1);
679 // FIXME: or E061, or E100 ??
681 /* System BIOS Date */
682 RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF5), BiosDate
, sizeof(BiosDate
)-1);
684 /* System BIOS Model (same as Bct->Model) */
685 *(PBYTE
)(SEG_OFF_TO_PTR(0xF000, 0xFFFE)) = BIOS_MODEL
;
687 /* Redefine our POST function */
688 RegisterBop(BOP_RESET
, Bios32ResetBop
);
694 VOID
Bios32Cleanup(VOID
)
696 MouseBios32Cleanup();