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 *******************************************************************/
16 #include "cpu/callback.h"
21 /* PRIVATE FUNCTIONS **********************************************************/
23 static BOOLEAN FASTCALL
ShadowRomWrite(ULONG Address
, PVOID Buffer
, ULONG Size
)
25 /* Prevent writing to ROM */
30 OpenRomFile(IN PCSTR RomFileName
,
31 OUT PULONG RomSize OPTIONAL
)
36 /* Open the ROM image file */
37 hRomFile
= FileOpen(RomFileName
, &ulRomSize
);
39 /* If we failed, bail out */
40 if (hRomFile
== NULL
) return NULL
;
43 * The size of the ROM image file is at most 256kB. For instance,
44 * the SeaBIOS image, which includes also expansion ROMs inside it,
45 * covers the range C000:0000 to F000:FFFF .
47 if (ulRomSize
> 0x40000)
49 /* We failed, bail out */
50 DPRINT1("ROM image size 0x%lx too large, expected at most 0x40000 (256kB)", ulRomSize
);
55 /* Success, return file handle and size if needed */
56 if (RomSize
) *RomSize
= ulRomSize
;
61 LoadRomFileByHandle(IN HANDLE RomFileHandle
,
67 * The size of the ROM image file is at most 256kB. For instance,
68 * the SeaBIOS image, which includes also expansion ROMs inside it,
69 * covers the range C000:0000 to F000:FFFF .
71 if (RomSize
> 0x40000)
73 DPRINT1("ROM image size 0x%lx too large, expected at most 0x40000 (256kB)", RomSize
);
77 /* Attempt to load the ROM image file into memory */
78 return FileLoadByHandle(RomFileHandle
,
79 REAL_TO_PHYS(RomLocation
),
85 InitRomRange(IN PCALLBACK16 Context
,
90 ULONG Address
, EntryPoint
;
94 for (Address
= Start
; Address
< End
; Address
+= Increment
)
96 /* Does the ROM have a valid signature? */
97 if (*(PUSHORT
)REAL_TO_PHYS(Address
) == OPTION_ROM_SIGNATURE
)
99 /* Check the control sum of the ROM */
102 * If this is an adapter ROM (Start: C8000, End: E0000),
103 * its reported size is stored in byte 2 of the ROM.
105 * If this is an expansion ROM (Start: E0000, End: F0000),
106 * its real length is 64kB.
108 RomSize
= *(PUCHAR
)REAL_TO_PHYS(Address
+ 2) * 512; // Size in blocks of 512 bytes
109 if (Address
>= 0xE0000) RomSize
= 0x10000;
111 Checksum
= CalcRomChecksum(Address
, RomSize
);
112 if (Checksum
== 0x00)
114 EntryPoint
= Address
+ 3;
115 DPRINT1("Going to run @ address 0x%p\n", EntryPoint
);
117 EntryPoint
= MAKELONG((EntryPoint
& 0xFFFF), (EntryPoint
& 0xF0000) >> 4);
118 // setDS((Address & 0xF0000) >> 4);
119 setDS((Address
& 0xFF000) >> 4);
120 RunCallback16(Context
, EntryPoint
);
121 // Call16((EntryPoint & 0xF0000) >> 4, (EntryPoint & 0xFFFF));
123 DPRINT1("ROM @ address 0x%p initialized\n", Address
);
127 DPRINT1("ROM @ address 0x%p has invalid checksum of 0x%02x\n", Address
, Checksum
);
133 /* PUBLIC FUNCTIONS ***********************************************************/
136 WriteProtectRom(IN PVOID RomLocation
,
139 return MemInstallFastMemoryHook(RomLocation
, RomSize
,
140 NULL
, ShadowRomWrite
);
144 WriteUnProtectRom(IN PVOID RomLocation
,
147 return MemRemoveFastMemoryHook(RomLocation
, RomSize
);
151 CalcRomChecksum(IN ULONG RomLocation
,
154 ULONG RomLastAddress
= RomLocation
+ RomSize
;
155 UCHAR Sum
= 0x00; // Using a UCHAR guarantees that we wrap at 0xFF i.e. we do a sum modulo 0x100.
157 while (RomLocation
< RomLastAddress
)
159 Sum
+= *(PUCHAR
)REAL_TO_PHYS(RomLocation
);
167 LoadBios(IN PCSTR BiosFileName
,
168 OUT PVOID
* BiosLocation OPTIONAL
,
169 OUT PULONG BiosSize OPTIONAL
)
173 ULONG ulBiosSize
= 0;
176 /* Open the BIOS image file */
177 hBiosFile
= OpenRomFile(BiosFileName
, &ulBiosSize
);
179 /* If we failed, bail out */
180 if (hBiosFile
== NULL
) return FALSE
;
182 /* BIOS location needs to be aligned on 32-bit boundary */
183 // (PVOID)((ULONG_PTR)BaseAddress + ROM_AREA_END + 1 - ulBiosSize)
184 pBiosLocation
= MEM_ALIGN_DOWN(TO_LINEAR(0xF000, 0xFFFF) + 1 - ulBiosSize
, sizeof(ULONG
));
186 /* Attempt to load the BIOS image file into memory */
187 Success
= LoadRomFileByHandle(hBiosFile
,
191 DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success
? "succeeded" : "failed", GetLastError());
193 /* Close the BIOS image file */
194 FileClose(hBiosFile
);
197 * In case of success, write-protect the BIOS location
198 * and return the BIOS location and its size if needed.
202 WriteProtectRom(pBiosLocation
, ulBiosSize
);
204 if (BiosLocation
) *BiosLocation
= pBiosLocation
;
205 if (BiosSize
) *BiosSize
= ulBiosSize
;
212 LoadRom(IN PCSTR RomFileName
,
213 IN PVOID RomLocation
,
214 OUT PULONG RomSize OPTIONAL
)
220 /* Open the ROM image file */
221 hRomFile
= OpenRomFile(RomFileName
, &ulRomSize
);
223 /* If we failed, bail out */
224 if (hRomFile
== NULL
) return FALSE
;
226 /* Attempt to load the ROM image file into memory */
227 Success
= LoadRomFileByHandle(hRomFile
,
231 DPRINT1("ROM loading %s ; GetLastError() = %u\n", Success
? "succeeded" : "failed", GetLastError());
233 /* Close the ROM image file and return */
237 * In case of success, write-protect the ROM location
238 * and return the ROM size if needed.
242 WriteProtectRom(RomLocation
, ulRomSize
);
243 if (RomSize
) *RomSize
= ulRomSize
;
250 SearchAndInitRoms(IN PCALLBACK16 Context
)
252 /* Video ROMs -- Start: C0000, End: C8000, 2kB blocks */
253 InitRomRange(Context
, 0xC0000, 0xC8000, 0x0800);
255 /* Adapters ROMs -- Start: C8000, End: E0000, 2kB blocks */
256 InitRomRange(Context
, 0xC8000, 0xE0000, 0x0800);
258 /* Expansion ROM -- Start: E0000, End: F0000, 64kB block */
259 InitRomRange(Context
, 0xE0000, 0xEFFFF, 0x10000);