[NTVDM]
[reactos.git] / reactos / subsystems / ntvdm / bios / bios.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: bios.c
5 * PURPOSE: VDM BIOS Support Library
6 * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #define NDEBUG
12
13 #include "emulator.h"
14 #include "cpu/callback.h"
15 #include "cpu/bop.h"
16
17 #include "bios.h"
18 #include "bios32/bios32.h"
19
20 #include "rom.h"
21
22 #include "io.h"
23 #include "hardware/cmos.h"
24
25 /* DEFINES ********************************************************************/
26
27 /* BOP Identifiers */
28 #define BOP_BIOSINIT 0x00 // Windows NTVDM (SoftPC) BIOS calls BOP 0x00
29 // to let the virtual machine initialize itself
30 // the IVT and its hardware.
31 #define BOP_EQUIPLIST 0x11
32 #define BOP_GETMEMSIZE 0x12
33
34 /* PRIVATE VARIABLES **********************************************************/
35
36 static BOOLEAN Bios32Loaded = FALSE;
37
38 static CALLBACK16 __BiosContext;
39 PBIOS_DATA_AREA Bda;
40 PBIOS_CONFIG_TABLE Bct;
41
42 /* PRIVATE FUNCTIONS **********************************************************/
43
44 static VOID WINAPI BiosInitBop(LPWORD Stack)
45 {
46 BOOLEAN Success;
47
48 /* Load the second part of the Windows NTVDM BIOS image */
49 LPCSTR BiosFileName = "bios1.rom";
50 PVOID BiosLocation = (PVOID)TO_LINEAR(BIOS_SEGMENT, 0x0000);
51 DWORD BiosSize = 0;
52
53 /* Disable interrupts */
54 setIF(0);
55
56 DisplayMessage(L"You are loading Windows NTVDM BIOS!\n");
57
58 /* Initialize a private callback context */
59 InitializeContext(&__BiosContext, BIOS_SEGMENT, 0x0000);
60
61 Success = LoadRom(BiosFileName, BiosLocation, &BiosSize);
62 DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
63
64 if (Success == FALSE)
65 {
66 /* Stop the VDM */
67 EmulatorTerminate();
68 return;
69 }
70
71 // DisplayMessage(L"First bytes at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n"
72 // L"3 last bytes at 0x%p: 0x%02x 0x%02x 0x%02x",
73 // BiosLocation,
74 // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 0),
75 // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 1),
76 // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 2),
77 // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 3),
78 // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 4),
79 // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 5),
80 // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 6),
81 // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 7),
82 // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 8),
83 // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 9),
84
85 // (PVOID)((ULONG_PTR)BiosLocation + BiosSize - 2),
86 // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 2),
87 // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 1),
88 // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 0));
89
90 /* Initialize IVT and hardware */
91
92 /* Initialize the Keyboard and Video BIOS */
93 if (!KbdBiosInitialize() || !VidBiosInitialize())
94 {
95 /* Stop the VDM */
96 EmulatorTerminate();
97 return;
98 }
99
100 /* Load VGA BIOS */
101 // Success = LoadRom("v7vga.rom", (PVOID)0xC0000, &BiosSize);
102 // DPRINT1("VGA BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
103
104 /* Enable interrupts */
105 setIF(1);
106
107 ///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
108
109 /* Load some ROMs */
110 // Success = LoadRom("boot.bin", (PVOID)0xE0000, &BiosSize);
111 // DPRINT1("Test ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
112
113 SearchAndInitRoms(&__BiosContext);
114 }
115
116 /* PUBLIC FUNCTIONS ***********************************************************/
117
118 VOID WINAPI BiosEquipmentService(LPWORD Stack)
119 {
120 /* Return the equipment list */
121 setAX(Bda->EquipmentList);
122 }
123
124 VOID WINAPI BiosGetMemorySize(LPWORD Stack)
125 {
126 /* Return the conventional memory size in kB, typically 640 kB */
127 setAX(Bda->MemorySize);
128 }
129
130 BOOLEAN
131 BiosInitialize(IN LPCSTR BiosFileName)
132 {
133 BOOLEAN Success = FALSE;
134
135 /* Disable interrupts */
136 setIF(0);
137
138 /* Initialize the BDA and the BCT pointers */
139 Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0x0000);
140 // The BCT is found at F000:E6F5 for 100% compatible BIOSes.
141 Bct = (PBIOS_CONFIG_TABLE)SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xE6F5);
142
143 /* Register the BIOS support BOPs */
144 RegisterBop(BOP_BIOSINIT , BiosInitBop);
145 RegisterBop(BOP_EQUIPLIST , BiosEquipmentService);
146 RegisterBop(BOP_GETMEMSIZE, BiosGetMemorySize);
147
148 if (BiosFileName)
149 {
150 PVOID BiosLocation = NULL;
151 DWORD BiosSize = 0;
152
153 Success = LoadBios(BiosFileName, &BiosLocation, &BiosSize);
154 DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
155
156 if (!Success) return FALSE;
157
158 DisplayMessage(L"First bytes at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n"
159 L"3 last bytes at 0x%p: 0x%02x 0x%02x 0x%02x",
160 BiosLocation,
161 *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 0),
162 *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 1),
163 *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 2),
164 *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 3),
165 *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 4),
166 *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 5),
167 *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 6),
168 *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 7),
169 *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 8),
170 *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 9),
171
172 (PVOID)((ULONG_PTR)BiosLocation + BiosSize - 2),
173 *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 2),
174 *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 1),
175 *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 0));
176
177 DisplayMessage(L"POST at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
178 TO_LINEAR(getCS(), getIP()),
179 *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 0),
180 *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 1),
181 *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 2),
182 *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 3),
183 *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 4));
184
185 /* Boot it up */
186
187 /*
188 * The CPU is already in reset-mode so that
189 * CS:IP points to F000:FFF0 as required.
190 */
191 DisplayMessage(L"CS=0x%p ; IP=0x%p", getCS(), getIP());
192 // setCS(0xF000);
193 // setIP(0xFFF0);
194
195 Success = TRUE;
196 }
197 else
198 {
199 Success = Bios32Loaded = Bios32Initialize();
200 }
201
202 /* Enable interrupts */
203 setIF(1);
204
205 return Success;
206 }
207
208 VOID
209 BiosCleanup(VOID)
210 {
211 if (Bios32Loaded) Bios32Cleanup();
212 }
213
214 /* EOF */