Create the AHCI branch for Aman's work
[reactos.git] / subsystems / mvdm / ntvdm / bios / rom.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: subsystems/mvdm/ntvdm/bios/rom.c
5 * PURPOSE: ROM Support Functions
6 * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "ntvdm.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16 #include "emulator.h"
17 #include "memory.h"
18 #include "cpu/callback.h"
19 #include "rom.h"
20
21 #include "utils.h"
22
23 /* PRIVATE FUNCTIONS **********************************************************/
24
25 static BOOLEAN FASTCALL ShadowRomWrite(ULONG Address, PVOID Buffer, ULONG Size)
26 {
27 /* Prevent writing to ROM */
28 return FALSE;
29 }
30
31 static HANDLE
32 OpenRomFile(IN PCSTR RomFileName,
33 OUT PULONG RomSize OPTIONAL)
34 {
35 HANDLE hRomFile;
36 ULONG ulRomSize = 0;
37
38 /* Open the ROM image file */
39 hRomFile = FileOpen(RomFileName, &ulRomSize);
40
41 /* If we failed, bail out */
42 if (hRomFile == NULL) return NULL;
43
44 /*
45 * The size of the ROM image file is at most 256kB. For instance,
46 * the SeaBIOS image, which includes also expansion ROMs inside it,
47 * covers the range C000:0000 to F000:FFFF .
48 */
49 if (ulRomSize > 0x40000)
50 {
51 /* We failed, bail out */
52 DPRINT1("ROM image size 0x%lx too large, expected at most 0x40000 (256kB)", ulRomSize);
53 FileClose(hRomFile);
54 return NULL;
55 }
56
57 /* Success, return file handle and size if needed */
58 if (RomSize) *RomSize = ulRomSize;
59 return hRomFile;
60 }
61
62 static BOOLEAN
63 LoadRomFileByHandle(IN HANDLE RomFileHandle,
64 IN PVOID RomLocation,
65 IN ULONG RomSize,
66 OUT PULONG BytesRead)
67 {
68 /*
69 * The size of the ROM image file is at most 256kB. For instance,
70 * the SeaBIOS image, which includes also expansion ROMs inside it,
71 * covers the range C000:0000 to F000:FFFF .
72 */
73 if (RomSize > 0x40000)
74 {
75 DPRINT1("ROM image size 0x%lx too large, expected at most 0x40000 (256kB)", RomSize);
76 return FALSE;
77 }
78
79 /* Attempt to load the ROM image file into memory */
80 return FileLoadByHandle(RomFileHandle,
81 REAL_TO_PHYS(RomLocation),
82 RomSize,
83 BytesRead);
84 }
85
86 static VOID
87 InitRomRange(IN PCALLBACK16 Context,
88 IN ULONG Start,
89 IN ULONG End,
90 IN ULONG Increment)
91 {
92 ULONG Address, EntryPoint;
93 ULONG RomSize;
94 UCHAR Checksum;
95
96 for (Address = Start; Address < End; Address += Increment)
97 {
98 /* Does the ROM have a valid signature? */
99 if (*(PUSHORT)REAL_TO_PHYS(Address) == OPTION_ROM_SIGNATURE)
100 {
101 /* Check the control sum of the ROM */
102
103 /*
104 * If this is an adapter ROM (Start: C8000, End: E0000),
105 * its reported size is stored in byte 2 of the ROM.
106 *
107 * If this is an expansion ROM (Start: E0000, End: F0000),
108 * its real length is 64kB.
109 */
110 RomSize = *(PUCHAR)REAL_TO_PHYS(Address + 2) * 512; // Size in blocks of 512 bytes
111 if (Address >= 0xE0000) RomSize = 0x10000;
112
113 Checksum = CalcRomChecksum(Address, RomSize);
114 if (Checksum == 0x00)
115 {
116 EntryPoint = Address + 3;
117 DPRINT1("Going to run @ address 0x%p\n", EntryPoint);
118
119 EntryPoint = MAKELONG((EntryPoint & 0xFFFF), (EntryPoint & 0xF0000) >> 4);
120 // setDS((Address & 0xF0000) >> 4);
121 setDS((Address & 0xFF000) >> 4);
122 RunCallback16(Context, EntryPoint);
123 // Call16((EntryPoint & 0xF0000) >> 4, (EntryPoint & 0xFFFF));
124
125 DPRINT1("ROM @ address 0x%p initialized\n", Address);
126 }
127 else
128 {
129 DPRINT1("ROM @ address 0x%p has invalid checksum of 0x%02x\n", Address, Checksum);
130 }
131 }
132 }
133 }
134
135 /* PUBLIC FUNCTIONS ***********************************************************/
136
137 BOOLEAN
138 WriteProtectRom(IN PVOID RomLocation,
139 IN ULONG RomSize)
140 {
141 return MemInstallFastMemoryHook(RomLocation, RomSize,
142 NULL, ShadowRomWrite);
143 }
144
145 BOOLEAN
146 WriteUnProtectRom(IN PVOID RomLocation,
147 IN ULONG RomSize)
148 {
149 return MemRemoveFastMemoryHook(RomLocation, RomSize);
150 }
151
152 UCHAR
153 CalcRomChecksum(IN ULONG RomLocation,
154 IN ULONG RomSize)
155 {
156 ULONG RomLastAddress = RomLocation + RomSize;
157 UCHAR Sum = 0x00; // Using a UCHAR guarantees that we wrap at 0xFF i.e. we do a sum modulo 0x100.
158
159 while (RomLocation < RomLastAddress)
160 {
161 Sum += *(PUCHAR)REAL_TO_PHYS(RomLocation);
162 ++RomLocation;
163 }
164
165 return Sum;
166 }
167
168 BOOLEAN
169 LoadBios(IN PCSTR BiosFileName,
170 OUT PVOID* BiosLocation OPTIONAL,
171 OUT PULONG BiosSize OPTIONAL)
172 {
173 BOOLEAN Success;
174 HANDLE hBiosFile;
175 ULONG ulBiosSize = 0;
176 PVOID pBiosLocation;
177
178 /* Open the BIOS image file */
179 hBiosFile = OpenRomFile(BiosFileName, &ulBiosSize);
180
181 /* If we failed, bail out */
182 if (hBiosFile == NULL) return FALSE;
183
184 /* BIOS location needs to be aligned on 32-bit boundary */
185 // (PVOID)((ULONG_PTR)BaseAddress + ROM_AREA_END + 1 - ulBiosSize)
186 pBiosLocation = MEM_ALIGN_DOWN(TO_LINEAR(0xF000, 0xFFFF) + 1 - ulBiosSize, sizeof(ULONG));
187
188 /* Attempt to load the BIOS image file into memory */
189 Success = LoadRomFileByHandle(hBiosFile,
190 pBiosLocation,
191 ulBiosSize,
192 &ulBiosSize);
193 DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
194
195 /* Close the BIOS image file */
196 FileClose(hBiosFile);
197
198 /*
199 * In case of success, write-protect the BIOS location
200 * and return the BIOS location and its size if needed.
201 */
202 if (Success)
203 {
204 WriteProtectRom(pBiosLocation, ulBiosSize);
205
206 if (BiosLocation) *BiosLocation = pBiosLocation;
207 if (BiosSize) *BiosSize = ulBiosSize;
208 }
209
210 return Success;
211 }
212
213 BOOLEAN
214 LoadRom(IN PCSTR RomFileName,
215 IN PVOID RomLocation,
216 OUT PULONG RomSize OPTIONAL)
217 {
218 BOOLEAN Success;
219 HANDLE hRomFile;
220 ULONG ulRomSize = 0;
221
222 /* Open the ROM image file */
223 hRomFile = OpenRomFile(RomFileName, &ulRomSize);
224
225 /* If we failed, bail out */
226 if (hRomFile == NULL) return FALSE;
227
228 /* Attempt to load the ROM image file into memory */
229 Success = LoadRomFileByHandle(hRomFile,
230 RomLocation,
231 ulRomSize,
232 &ulRomSize);
233 DPRINT1("ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
234
235 /* Close the ROM image file and return */
236 FileClose(hRomFile);
237
238 /*
239 * In case of success, write-protect the ROM location
240 * and return the ROM size if needed.
241 */
242 if (Success)
243 {
244 WriteProtectRom(RomLocation, ulRomSize);
245 if (RomSize) *RomSize = ulRomSize;
246 }
247
248 return Success;
249 }
250
251 VOID
252 SearchAndInitRoms(IN PCALLBACK16 Context)
253 {
254 /* Video ROMs -- Start: C0000, End: C8000, 2kB blocks */
255 InitRomRange(Context, 0xC0000, 0xC8000, 0x0800);
256
257 /* Adapters ROMs -- Start: C8000, End: E0000, 2kB blocks */
258 InitRomRange(Context, 0xC8000, 0xE0000, 0x0800);
259
260 /* Expansion ROM -- Start: E0000, End: F0000, 64kB block */
261 InitRomRange(Context, 0xE0000, 0xEFFFF, 0x10000);
262 }
263
264 /* EOF */