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)
9 /* INCLUDES *******************************************************************/
18 #include "cpu/callback.h"
23 /* PRIVATE FUNCTIONS **********************************************************/
25 static BOOLEAN FASTCALL
ShadowRomWrite(ULONG Address
, PVOID Buffer
, ULONG Size
)
27 /* Prevent writing to ROM */
32 OpenRomFile(IN PCSTR RomFileName
,
33 OUT PULONG RomSize OPTIONAL
)
38 /* Open the ROM image file */
39 hRomFile
= FileOpen(RomFileName
, &ulRomSize
);
41 /* If we failed, bail out */
42 if (hRomFile
== NULL
) return NULL
;
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 .
49 if (ulRomSize
> 0x40000)
51 /* We failed, bail out */
52 DPRINT1("ROM image size 0x%lx too large, expected at most 0x40000 (256kB)", ulRomSize
);
57 /* Success, return file handle and size if needed */
58 if (RomSize
) *RomSize
= ulRomSize
;
63 LoadRomFileByHandle(IN HANDLE RomFileHandle
,
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 .
73 if (RomSize
> 0x40000)
75 DPRINT1("ROM image size 0x%lx too large, expected at most 0x40000 (256kB)", RomSize
);
79 /* Attempt to load the ROM image file into memory */
80 return FileLoadByHandle(RomFileHandle
,
81 REAL_TO_PHYS(RomLocation
),
87 InitRomRange(IN PCALLBACK16 Context
,
92 ULONG Address
, EntryPoint
;
96 for (Address
= Start
; Address
< End
; Address
+= Increment
)
98 /* Does the ROM have a valid signature? */
99 if (*(PUSHORT
)REAL_TO_PHYS(Address
) == OPTION_ROM_SIGNATURE
)
101 /* Check the control sum of the ROM */
104 * If this is an adapter ROM (Start: C8000, End: E0000),
105 * its reported size is stored in byte 2 of the ROM.
107 * If this is an expansion ROM (Start: E0000, End: F0000),
108 * its real length is 64kB.
110 RomSize
= *(PUCHAR
)REAL_TO_PHYS(Address
+ 2) * 512; // Size in blocks of 512 bytes
111 if (Address
>= 0xE0000) RomSize
= 0x10000;
113 Checksum
= CalcRomChecksum(Address
, RomSize
);
114 if (Checksum
== 0x00)
116 EntryPoint
= Address
+ 3;
117 DPRINT1("Going to run @ address 0x%p\n", EntryPoint
);
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));
125 DPRINT1("ROM @ address 0x%p initialized\n", Address
);
129 DPRINT1("ROM @ address 0x%p has invalid checksum of 0x%02x\n", Address
, Checksum
);
135 /* PUBLIC FUNCTIONS ***********************************************************/
138 WriteProtectRom(IN PVOID RomLocation
,
141 return MemInstallFastMemoryHook(RomLocation
, RomSize
,
142 NULL
, ShadowRomWrite
);
146 WriteUnProtectRom(IN PVOID RomLocation
,
149 return MemRemoveFastMemoryHook(RomLocation
, RomSize
);
153 CalcRomChecksum(IN ULONG RomLocation
,
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.
159 while (RomLocation
< RomLastAddress
)
161 Sum
+= *(PUCHAR
)REAL_TO_PHYS(RomLocation
);
169 LoadBios(IN PCSTR BiosFileName
,
170 OUT PVOID
* BiosLocation OPTIONAL
,
171 OUT PULONG BiosSize OPTIONAL
)
175 ULONG ulBiosSize
= 0;
178 /* Open the BIOS image file */
179 hBiosFile
= OpenRomFile(BiosFileName
, &ulBiosSize
);
181 /* If we failed, bail out */
182 if (hBiosFile
== NULL
) return FALSE
;
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
));
188 /* Attempt to load the BIOS image file into memory */
189 Success
= LoadRomFileByHandle(hBiosFile
,
193 DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success
? "succeeded" : "failed", GetLastError());
195 /* Close the BIOS image file */
196 FileClose(hBiosFile
);
199 * In case of success, write-protect the BIOS location
200 * and return the BIOS location and its size if needed.
204 WriteProtectRom(pBiosLocation
, ulBiosSize
);
206 if (BiosLocation
) *BiosLocation
= pBiosLocation
;
207 if (BiosSize
) *BiosSize
= ulBiosSize
;
214 LoadRom(IN PCSTR RomFileName
,
215 IN PVOID RomLocation
,
216 OUT PULONG RomSize OPTIONAL
)
222 /* Open the ROM image file */
223 hRomFile
= OpenRomFile(RomFileName
, &ulRomSize
);
225 /* If we failed, bail out */
226 if (hRomFile
== NULL
) return FALSE
;
228 /* Attempt to load the ROM image file into memory */
229 Success
= LoadRomFileByHandle(hRomFile
,
233 DPRINT1("ROM loading %s ; GetLastError() = %u\n", Success
? "succeeded" : "failed", GetLastError());
235 /* Close the ROM image file and return */
239 * In case of success, write-protect the ROM location
240 * and return the ROM size if needed.
244 WriteProtectRom(RomLocation
, ulRomSize
);
245 if (RomSize
) *RomSize
= ulRomSize
;
252 SearchAndInitRoms(IN PCALLBACK16 Context
)
254 /* Video ROMs -- Start: C0000, End: C8000, 2kB blocks */
255 InitRomRange(Context
, 0xC0000, 0xC8000, 0x0800);
257 /* Adapters ROMs -- Start: C8000, End: E0000, 2kB blocks */
258 InitRomRange(Context
, 0xC8000, 0xE0000, 0x0800);
260 /* Expansion ROM -- Start: E0000, End: F0000, 64kB block */
261 InitRomRange(Context
, 0xE0000, 0xEFFFF, 0x10000);