[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 "cpu/bop.h"
19 #include "int32.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 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
135 };
136
137
138 /* PRIVATE FUNCTIONS **********************************************************/
139
140 static VOID WINAPI BiosException(LPWORD Stack)
141 {
142 /* Get the exception number and call the emulator API */
143 BYTE ExceptionNumber = LOBYTE(Stack[STACK_INT_NUM]);
144 EmulatorException(ExceptionNumber, Stack);
145 }
146
147 static VOID WINAPI BiosMiscService(LPWORD Stack)
148 {
149 switch (getAH())
150 {
151 /* Keyboard intercept */
152 case 0x4F:
153 {
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 */
156 // setCF(1);
157 Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
158 break;
159 }
160
161 /* Wait */
162 case 0x86:
163 {
164 /*
165 * Interval in microseconds in CX:DX
166 * See Ralf Brown: http://www.ctyme.com/intr/rb-1525.htm
167 * for more information.
168 */
169
170 // HACK: For now, use the Win32 API (that takes time in milliseconds).
171 Sleep(MAKELONG(getDX(), getCX()) / 1000);
172
173 /* Clear CF */
174 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
175
176 break;
177 }
178
179 /* Copy Extended Memory */
180 case 0x87:
181 {
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);
188
189 /* Check for flags */
190 if (Gdt[2].Granularity) SourceLimit = (SourceLimit << 12) | 0xFFF;
191 if (Gdt[3].Granularity) DestLimit = (DestLimit << 12) | 0xFFF;
192
193 if ((Count > SourceLimit) || (Count > DestLimit))
194 {
195 setAX(0x80);
196 Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
197
198 break;
199 }
200
201 /* Copy */
202 RtlMoveMemory((PVOID)((ULONG_PTR)BaseAddress + DestBase),
203 (PVOID)((ULONG_PTR)BaseAddress + SourceBase),
204 Count);
205
206 setAX(ERROR_SUCCESS);
207 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
208 break;
209 }
210
211 /* Get Extended Memory Size */
212 case 0x88:
213 {
214 UCHAR Low, High;
215
216 /*
217 * Return the (usable) extended memory (after 1 MB)
218 * size in kB from CMOS.
219 */
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));
225
226 /* Clear CF */
227 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
228
229 break;
230 }
231
232 /* Get Configuration */
233 case 0xC0:
234 {
235 /* Return the BIOS ROM Configuration Table address in ES:BX */
236 // The BCT is found at F000:E6F5 for 100% compatible BIOSes.
237 setES(BIOS_SEGMENT);
238 setBX(0xE6F5);
239
240 /* Call successful; clear CF */
241 setAH(0x00);
242 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
243
244 break;
245 }
246
247 /* Return Extended-Bios Data-Area Segment Address (PS) */
248 case 0xC1:
249 {
250 // Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
251 // setES(???);
252
253 /* We do not support EBDA yet */
254 Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
255
256 break;
257 }
258
259 /* Pointing Device BIOS Interface (PS) */
260 case 0xC2:
261 {
262 DPRINT1("INT 15h, AH = C2h must be implemented in order to support vendor mouse drivers\n");
263 break;
264 }
265
266 default:
267 {
268 DPRINT1("BIOS Function INT 15h, AH = 0x%02X NOT IMPLEMENTED\n",
269 getAH());
270 }
271 }
272 }
273
274 static VOID WINAPI BiosRomBasic(LPWORD Stack)
275 {
276 /* ROM Basic is unsupported, display a message to the user */
277 DisplayMessage(L"NTVDM doesn't support ROM Basic. The VDM is closing.");
278
279 /* Stop the VDM */
280 EmulatorTerminate();
281 return;
282 }
283
284
285 VOID DosBootsectorInitialize(VOID);
286
287 static VOID WINAPI BiosBootstrapLoader(LPWORD Stack)
288 {
289 /*
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.
294 */
295
296 DPRINT1("BiosBootstrapLoader -->\n");
297
298 /* Load DOS */
299 DosBootsectorInitialize();
300
301 /*
302 * Position CPU to 0000:7C00 to boot the OS.
303 *
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.
309 */
310 Stack[STACK_CS] = 0x0000;
311 Stack[STACK_IP] = 0x7C00;
312
313 DPRINT1("<-- BiosBootstrapLoader\n");
314 }
315
316 static VOID WINAPI BiosTimeService(LPWORD Stack)
317 {
318 switch (getAH())
319 {
320 case 0x00:
321 {
322 /* Set AL to 1 if midnight had passed, 0 otherwise */
323 setAL(Bda->MidnightPassed ? 0x01 : 0x00);
324
325 /* Return the tick count in CX:DX */
326 setCX(HIWORD(Bda->TickCounter));
327 setDX(LOWORD(Bda->TickCounter));
328
329 /* Reset the midnight flag */
330 Bda->MidnightPassed = FALSE;
331
332 break;
333 }
334
335 case 0x01:
336 {
337 /* Set the tick count to CX:DX */
338 Bda->TickCounter = MAKELONG(getDX(), getCX());
339
340 /* Reset the midnight flag */
341 Bda->MidnightPassed = FALSE;
342
343 break;
344 }
345
346 default:
347 {
348 DPRINT1("BIOS Function INT 1Ah, AH = 0x%02X NOT IMPLEMENTED\n",
349 getAH());
350 }
351 }
352 }
353
354 static VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack)
355 {
356 /* Increase the system tick count */
357 Bda->TickCounter++;
358 }
359
360
361 // From SeaBIOS
362 static VOID PicSetIRQMask(USHORT off, USHORT on)
363 {
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);
367 }
368
369 // From SeaBIOS
370 VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func)
371 {
372 UCHAR vector;
373
374 PicSetIRQMask(1 << hwirq, 0);
375 if (hwirq < 8)
376 vector = BIOS_PIC_MASTER_INT + hwirq;
377 else
378 vector = BIOS_PIC_SLAVE_INT + hwirq - 8;
379
380 RegisterBiosInt32(vector, func);
381 }
382
383
384 VOID PicIRQComplete(LPWORD Stack)
385 {
386 /* Get the interrupt number */
387 BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]);
388
389 /*
390 * If this was a PIC IRQ, send an End-of-Interrupt to the PIC.
391 */
392
393 if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8)
394 {
395 /* It was an IRQ from the master PIC */
396 IOWriteB(PIC_MASTER_CMD, PIC_OCW2_EOI);
397 }
398 else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8)
399 {
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);
403 }
404 }
405
406 static VOID WINAPI BiosHandleMasterPicIRQ(LPWORD Stack)
407 {
408 BYTE IrqNumber;
409
410 IOWriteB(PIC_MASTER_CMD, PIC_OCW3_READ_ISR /* == 0x0B */);
411 IrqNumber = IOReadB(PIC_MASTER_CMD);
412
413 DPRINT("Master - IrqNumber = 0x%02X\n", IrqNumber);
414
415 PicIRQComplete(Stack);
416 }
417
418 static VOID WINAPI BiosHandleSlavePicIRQ(LPWORD Stack)
419 {
420 BYTE IrqNumber;
421
422 IOWriteB(PIC_SLAVE_CMD, PIC_OCW3_READ_ISR /* == 0x0B */);
423 IrqNumber = IOReadB(PIC_SLAVE_CMD);
424
425 DPRINT("Slave - IrqNumber = 0x%02X\n", IrqNumber);
426
427 PicIRQComplete(Stack);
428 }
429
430 // Timer IRQ 0
431 static VOID WINAPI BiosTimerIrq(LPWORD Stack)
432 {
433 /*
434 * Perform the system timer interrupt.
435 *
436 * Do not call directly BiosSystemTimerInterrupt(Stack);
437 * because some programs may hook only BIOS_SYS_TIMER_INTERRUPT
438 * for their purpose...
439 */
440 /** EmulatorInterrupt(BIOS_SYS_TIMER_INTERRUPT); **/
441 Int32Call(&BiosContext, BIOS_SYS_TIMER_INTERRUPT);
442 PicIRQComplete(Stack);
443 }
444
445
446 static VOID BiosHwSetup(VOID)
447 {
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);
451
452 /*
453 * Set the interrupt vector offsets for each PIC
454 * (base IRQs: 0x08-0x0F for IRQ 0-7, 0x70-0x77 for IRQ 8-15)
455 */
456 IOWriteB(PIC_MASTER_DATA, BIOS_PIC_MASTER_INT);
457 IOWriteB(PIC_SLAVE_DATA , BIOS_PIC_SLAVE_INT );
458
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);
463
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);
467
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);
474
475
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);
482
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);
487
488 /* Initialize PIT Counter 2 - Mode 3, 16bit binary count */
489 IOWriteB(PIT_COMMAND_PORT, 0xB6);
490 // Count for 440Hz
491 IOWriteB(PIT_DATA_PORT(2), 0x97);
492 IOWriteB(PIT_DATA_PORT(2), 0x0A);
493
494 EnableHwIRQ(0, BiosTimerIrq);
495 }
496
497 static VOID InitializeBiosInt32(VOID)
498 {
499 USHORT i;
500
501 /* Initialize the callback context */
502 InitializeContext(&BiosContext, BIOS_SEGMENT, 0x0000);
503
504 /* Register the default BIOS 32-bit Interrupts */
505 for (i = 0x00; i <= 0xFF; i++)
506 {
507 RegisterBiosInt32(i, NULL);
508 }
509
510 /* Initialize the exception vector interrupts to a default Exception handler */
511 for (i = 0; i < 8; i++)
512 RegisterBiosInt32(i, BiosException);
513
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);
519
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);
528
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;
535 }
536
537 static VOID InitializeBiosData(VOID)
538 {
539 UCHAR Low, High;
540
541 /* Initialize the BDA contents */
542 RtlZeroMemory(Bda, sizeof(*Bda));
543 Bda->EquipmentList = BIOS_EQUIPMENT_LIST;
544
545 /*
546 * Retrieve the conventional memory size
547 * in kB from CMOS, typically 640 kB.
548 */
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);
554 }
555
556 static VOID InitializeBiosInfo(VOID)
557 {
558 RtlZeroMemory(Bct, sizeof(*Bct));
559
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;
569 }
570
571
572
573 /*
574 * The BIOS POST (Power On-Self Test)
575 */
576 VOID
577 Bios32Post(VOID)
578 {
579 BOOLEAN Success;
580
581 DPRINT1("Bios32Post\n");
582
583 /* Initialize the stack */
584 // That's what says IBM... (stack at 30:00FF going downwards)
585 // setSS(0x0000);
586 // setSP(0x0400);
587 setSS(0x0050); // Stack at 50:0400, going downwards
588 setSP(0x0400);
589
590 /* Set data segment */
591 setDS(BDA_SEGMENT);
592
593 /* Initialize the BDA and the BIOS ROM Information */
594 InitializeBiosData();
595 InitializeBiosInfo();
596
597 /*
598 * Initialize IVT and hardware
599 */
600
601 /* Register the BIOS 32-bit Interrupts */
602 InitializeBiosInt32();
603
604 /* Initialize platform hardware (PIC/PIT chips, ...) */
605 BiosHwSetup();
606
607 /* Initialize the Keyboard, Video and Mouse BIOS */
608 if (!KbdBios32Initialize() || !VidBios32Initialize() || !MouseBios32Initialize())
609 {
610 // return FALSE;
611
612 /* Stop the VDM */
613 EmulatorTerminate();
614 return;
615 }
616
617 #if 0
618 /* Initialize the Keyboard and Video BIOS */
619 if (!KbdBiosInitialize() || !VidBiosInitialize())
620 {
621 /* Stop the VDM */
622 EmulatorTerminate();
623 return;
624 }
625 #endif
626
627 ///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
628
629 /* Load some ROMs */
630 Success = LoadRom("boot.bin", (PVOID)0xE0000, NULL);
631 DPRINT1("Test ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
632
633 SearchAndInitRoms(&BiosContext);
634
635 /*
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
638 * to boot up the OS.
639 */
640 }
641
642 static VOID WINAPI Bios32ResetBop(LPWORD Stack)
643 {
644 DPRINT1("Bios32ResetBop\n");
645
646 /* Disable interrupts */
647 setIF(0);
648
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).
653
654 /* Do the POST */
655 Bios32Post();
656
657 /* Enable interrupts */
658 setIF(1);
659 }
660
661
662 /* PUBLIC FUNCTIONS ***********************************************************/
663
664 BOOLEAN Bios32Initialize(VOID)
665 {
666 /*
667 * Initialize BIOS32 static data
668 */
669
670 /* Bootstrap code */
671 RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE05B), PostCode , sizeof(PostCode ));
672 RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF0), Bootstrap, sizeof(Bootstrap));
673
674 /* System BIOS Copyright */
675 RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE000), BiosCopyright, sizeof(BiosCopyright)-1);
676
677 /* System BIOS Version */
678 RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE080), BiosVersion, sizeof(BiosVersion)-1);
679 // FIXME: or E061, or E100 ??
680
681 /* System BIOS Date */
682 RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF5), BiosDate, sizeof(BiosDate)-1);
683
684 /* System BIOS Model (same as Bct->Model) */
685 *(PBYTE)(SEG_OFF_TO_PTR(0xF000, 0xFFFE)) = BIOS_MODEL;
686
687 /* Redefine our POST function */
688 RegisterBop(BOP_RESET, Bios32ResetBop);
689
690 /* We are done */
691 return TRUE;
692 }
693
694 VOID Bios32Cleanup(VOID)
695 {
696 MouseBios32Cleanup();
697 VidBios32Cleanup();
698 KbdBios32Cleanup();
699 }
700
701 /* EOF */