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 */ 265