reactos/subsystems/mvdm/ntvdm/bios/rom.c

265 lines
7.5 KiB
C
Raw Normal View History

/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: subsystems/mvdm/ntvdm/bios/rom.c
* PURPOSE: ROM Support Functions
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/* INCLUDES *******************************************************************/
#include "ntvdm.h"
#define NDEBUG
#include <debug.h>
#include "emulator.h"
#include "memory.h"
#include "cpu/callback.h"
#include "rom.h"
#include "utils.h"
/* PRIVATE FUNCTIONS **********************************************************/
static BOOLEAN FASTCALL ShadowRomWrite(ULONG Address, PVOID Buffer, ULONG Size)
{
/* Prevent writing to ROM */
return FALSE;
}
static HANDLE
OpenRomFile(IN PCSTR RomFileName,
OUT PULONG RomSize OPTIONAL)
{
HANDLE hRomFile;
ULONG ulRomSize = 0;
/* Open the ROM image file */
hRomFile = FileOpen(RomFileName, &ulRomSize);
/* If we failed, bail out */
if (hRomFile == NULL) return NULL;
/*
* The size of the ROM image file is at most 256kB. For instance,
* the SeaBIOS image, which includes also expansion ROMs inside it,
* covers the range C000:0000 to F000:FFFF .
*/
if (ulRomSize > 0x40000)
{
/* We failed, bail out */
DPRINT1("ROM image size 0x%lx too large, expected at most 0x40000 (256kB)\n", ulRomSize);
FileClose(hRomFile);
return NULL;
}
/* Success, return file handle and size if needed */
if (RomSize) *RomSize = ulRomSize;
return hRomFile;
}
static BOOLEAN
LoadRomFileByHandle(IN HANDLE RomFileHandle,
IN PVOID RomLocation,
IN ULONG RomSize,
OUT PULONG BytesRead)
{
/*
* The size of the ROM image file is at most 256kB. For instance,
* the SeaBIOS image, which includes also expansion ROMs inside it,
* covers the range C000:0000 to F000:FFFF .
*/
if (RomSize > 0x40000)
{
DPRINT1("ROM image size 0x%lx too large, expected at most 0x40000 (256kB)\n", RomSize);
return FALSE;
}
/* Attempt to load the ROM image file into memory */
return FileLoadByHandle(RomFileHandle,
REAL_TO_PHYS(RomLocation),
RomSize,
BytesRead);
}
static VOID
InitRomRange(IN PCALLBACK16 Context,
IN ULONG Start,
IN ULONG End,
IN ULONG Increment)
{
ULONG Address, EntryPoint;
ULONG RomSize;
UCHAR Checksum;
for (Address = Start; Address < End; Address += Increment)
{
/* Does the ROM have a valid signature? */
if (*(PUSHORT)REAL_TO_PHYS(Address) == OPTION_ROM_SIGNATURE)
{
/* Check the control sum of the ROM */
/*
[NTVDM] - Add some level of "Advanced debugging" (see ntvdm.h) which one can adjust to enable/disable debugging features inside NTVDM (this can be useful as long as NTVDM is under heavy bugfixing. When it will be more perfect, this stuff will be removed). - Add the possibility to load option ROMs at a given segment. Currently their list should be specified from inside ntvdm.c (in the BiosInitialize call), but I plan to make it available from a registry option (or via command-line for NTVDM-standalone mode). - Start to separate the initialization of "static" BIOS data (stuff that lives in ROM space) and initialization of "dynamic" BIOS data (eg. initializing the interrupt vector table, the BIOS data area at segment 40h, ...) so that we may be able to reuse part of our code to be able to more-or-less run external (16-bit) BIOSes, or the Windows NTVDM BIOS that uses BOPs to run some of its stuff in ntvdm in 32-bit (as we do for our 32-bit BIOS, except that *all* of our bios is 32-bit, not just some parts). Also, some file reorganization will be in order there soon... - Add video BIOS version information in memory so that tools such as Microsoft Diagnostics can correctly recognize our video BIOS (btw, we try to emulate the functionality of Cirrus' CL-GD5434). - Correctly put video BIOS ROM header (+ checksum) in memory so that it is recognized as such by diagnostics tools. - During BIOS POST, scan for ROMs starting segment 0xC000 (where video ROMs reside). - Store statically the BIOS configuration table. - Fix INT 16h, AH=12h "Get extended shift states" so that it correctly returns the state of right Ctrl and Alt keys. - Fix bit-setting state; report that our keyboard is 101/102 enhanced keyboard. - Correctly set the error return values (AH=86h and CF set) when a function of INT 15h is unsupported. - Implement INT 15h, AH=C9h "Get CPU Type and Mask Revision"; INT 1Ah, AH=02h "Get Real-Time Clock Time" and Ah=04h "Get Real-Time Clock Date" by reading the CMOS. - Implement CMOS century register support. svn path=/trunk/; revision=68598
2015-08-04 20:17:05 +00:00
* If this is an adapter ROM (Start: C8000, End: E0000),
* its reported size is stored in byte 2 of the ROM.
*
* If this is an expansion ROM (Start: E0000, End: F0000),
* its real length is 64kB.
*/
[NTVDM] - Add some level of "Advanced debugging" (see ntvdm.h) which one can adjust to enable/disable debugging features inside NTVDM (this can be useful as long as NTVDM is under heavy bugfixing. When it will be more perfect, this stuff will be removed). - Add the possibility to load option ROMs at a given segment. Currently their list should be specified from inside ntvdm.c (in the BiosInitialize call), but I plan to make it available from a registry option (or via command-line for NTVDM-standalone mode). - Start to separate the initialization of "static" BIOS data (stuff that lives in ROM space) and initialization of "dynamic" BIOS data (eg. initializing the interrupt vector table, the BIOS data area at segment 40h, ...) so that we may be able to reuse part of our code to be able to more-or-less run external (16-bit) BIOSes, or the Windows NTVDM BIOS that uses BOPs to run some of its stuff in ntvdm in 32-bit (as we do for our 32-bit BIOS, except that *all* of our bios is 32-bit, not just some parts). Also, some file reorganization will be in order there soon... - Add video BIOS version information in memory so that tools such as Microsoft Diagnostics can correctly recognize our video BIOS (btw, we try to emulate the functionality of Cirrus' CL-GD5434). - Correctly put video BIOS ROM header (+ checksum) in memory so that it is recognized as such by diagnostics tools. - During BIOS POST, scan for ROMs starting segment 0xC000 (where video ROMs reside). - Store statically the BIOS configuration table. - Fix INT 16h, AH=12h "Get extended shift states" so that it correctly returns the state of right Ctrl and Alt keys. - Fix bit-setting state; report that our keyboard is 101/102 enhanced keyboard. - Correctly set the error return values (AH=86h and CF set) when a function of INT 15h is unsupported. - Implement INT 15h, AH=C9h "Get CPU Type and Mask Revision"; INT 1Ah, AH=02h "Get Real-Time Clock Time" and Ah=04h "Get Real-Time Clock Date" by reading the CMOS. - Implement CMOS century register support. svn path=/trunk/; revision=68598
2015-08-04 20:17:05 +00:00
RomSize = *(PUCHAR)REAL_TO_PHYS(Address + 2) * 512; // Size in blocks of 512 bytes
if (Address >= 0xE0000) RomSize = 0x10000;
[NTVDM] - Add some level of "Advanced debugging" (see ntvdm.h) which one can adjust to enable/disable debugging features inside NTVDM (this can be useful as long as NTVDM is under heavy bugfixing. When it will be more perfect, this stuff will be removed). - Add the possibility to load option ROMs at a given segment. Currently their list should be specified from inside ntvdm.c (in the BiosInitialize call), but I plan to make it available from a registry option (or via command-line for NTVDM-standalone mode). - Start to separate the initialization of "static" BIOS data (stuff that lives in ROM space) and initialization of "dynamic" BIOS data (eg. initializing the interrupt vector table, the BIOS data area at segment 40h, ...) so that we may be able to reuse part of our code to be able to more-or-less run external (16-bit) BIOSes, or the Windows NTVDM BIOS that uses BOPs to run some of its stuff in ntvdm in 32-bit (as we do for our 32-bit BIOS, except that *all* of our bios is 32-bit, not just some parts). Also, some file reorganization will be in order there soon... - Add video BIOS version information in memory so that tools such as Microsoft Diagnostics can correctly recognize our video BIOS (btw, we try to emulate the functionality of Cirrus' CL-GD5434). - Correctly put video BIOS ROM header (+ checksum) in memory so that it is recognized as such by diagnostics tools. - During BIOS POST, scan for ROMs starting segment 0xC000 (where video ROMs reside). - Store statically the BIOS configuration table. - Fix INT 16h, AH=12h "Get extended shift states" so that it correctly returns the state of right Ctrl and Alt keys. - Fix bit-setting state; report that our keyboard is 101/102 enhanced keyboard. - Correctly set the error return values (AH=86h and CF set) when a function of INT 15h is unsupported. - Implement INT 15h, AH=C9h "Get CPU Type and Mask Revision"; INT 1Ah, AH=02h "Get Real-Time Clock Time" and Ah=04h "Get Real-Time Clock Date" by reading the CMOS. - Implement CMOS century register support. svn path=/trunk/; revision=68598
2015-08-04 20:17:05 +00:00
Checksum = CalcRomChecksum(Address, RomSize);
if (Checksum == 0x00)
{
EntryPoint = Address + 3;
DPRINT1("Going to run @ address 0x%p\n", EntryPoint);
EntryPoint = MAKELONG((EntryPoint & 0xFFFF), (EntryPoint & 0xF0000) >> 4);
// setDS((Address & 0xF0000) >> 4);
setDS((Address & 0xFF000) >> 4);
RunCallback16(Context, EntryPoint);
// Call16((EntryPoint & 0xF0000) >> 4, (EntryPoint & 0xFFFF));
DPRINT1("ROM @ address 0x%p initialized\n", Address);
}
else
{
DPRINT1("ROM @ address 0x%p has invalid checksum of 0x%02x\n", Address, Checksum);
}
}
}
}
/* PUBLIC FUNCTIONS ***********************************************************/
BOOLEAN
WriteProtectRom(IN PVOID RomLocation,
IN ULONG RomSize)
{
return MemInstallFastMemoryHook(RomLocation, RomSize,
NULL, ShadowRomWrite);
}
[NTVDM] - Add some level of "Advanced debugging" (see ntvdm.h) which one can adjust to enable/disable debugging features inside NTVDM (this can be useful as long as NTVDM is under heavy bugfixing. When it will be more perfect, this stuff will be removed). - Add the possibility to load option ROMs at a given segment. Currently their list should be specified from inside ntvdm.c (in the BiosInitialize call), but I plan to make it available from a registry option (or via command-line for NTVDM-standalone mode). - Start to separate the initialization of "static" BIOS data (stuff that lives in ROM space) and initialization of "dynamic" BIOS data (eg. initializing the interrupt vector table, the BIOS data area at segment 40h, ...) so that we may be able to reuse part of our code to be able to more-or-less run external (16-bit) BIOSes, or the Windows NTVDM BIOS that uses BOPs to run some of its stuff in ntvdm in 32-bit (as we do for our 32-bit BIOS, except that *all* of our bios is 32-bit, not just some parts). Also, some file reorganization will be in order there soon... - Add video BIOS version information in memory so that tools such as Microsoft Diagnostics can correctly recognize our video BIOS (btw, we try to emulate the functionality of Cirrus' CL-GD5434). - Correctly put video BIOS ROM header (+ checksum) in memory so that it is recognized as such by diagnostics tools. - During BIOS POST, scan for ROMs starting segment 0xC000 (where video ROMs reside). - Store statically the BIOS configuration table. - Fix INT 16h, AH=12h "Get extended shift states" so that it correctly returns the state of right Ctrl and Alt keys. - Fix bit-setting state; report that our keyboard is 101/102 enhanced keyboard. - Correctly set the error return values (AH=86h and CF set) when a function of INT 15h is unsupported. - Implement INT 15h, AH=C9h "Get CPU Type and Mask Revision"; INT 1Ah, AH=02h "Get Real-Time Clock Time" and Ah=04h "Get Real-Time Clock Date" by reading the CMOS. - Implement CMOS century register support. svn path=/trunk/; revision=68598
2015-08-04 20:17:05 +00:00
BOOLEAN
WriteUnProtectRom(IN PVOID RomLocation,
IN ULONG RomSize)
{
return MemRemoveFastMemoryHook(RomLocation, RomSize);
}
UCHAR
CalcRomChecksum(IN ULONG RomLocation,
IN ULONG RomSize)
{
ULONG RomLastAddress = RomLocation + RomSize;
UCHAR Sum = 0x00; // Using a UCHAR guarantees that we wrap at 0xFF i.e. we do a sum modulo 0x100.
while (RomLocation < RomLastAddress)
{
Sum += *(PUCHAR)REAL_TO_PHYS(RomLocation);
++RomLocation;
}
return Sum;
}
BOOLEAN
LoadBios(IN PCSTR BiosFileName,
OUT PVOID* BiosLocation OPTIONAL,
OUT PULONG BiosSize OPTIONAL)
{
BOOLEAN Success;
HANDLE hBiosFile;
ULONG ulBiosSize = 0;
PVOID pBiosLocation;
/* Open the BIOS image file */
hBiosFile = OpenRomFile(BiosFileName, &ulBiosSize);
/* If we failed, bail out */
if (hBiosFile == NULL) return FALSE;
/* BIOS location needs to be aligned on 32-bit boundary */
// (PVOID)((ULONG_PTR)BaseAddress + ROM_AREA_END + 1 - ulBiosSize)
pBiosLocation = MEM_ALIGN_DOWN(TO_LINEAR(0xF000, 0xFFFF) + 1 - ulBiosSize, sizeof(ULONG));
/* Attempt to load the BIOS image file into memory */
Success = LoadRomFileByHandle(hBiosFile,
pBiosLocation,
ulBiosSize,
&ulBiosSize);
DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
/* Close the BIOS image file */
FileClose(hBiosFile);
/*
* In case of success, write-protect the BIOS location
* and return the BIOS location and its size if needed.
*/
if (Success)
{
WriteProtectRom(pBiosLocation, ulBiosSize);
if (BiosLocation) *BiosLocation = pBiosLocation;
if (BiosSize) *BiosSize = ulBiosSize;
}
return Success;
}
BOOLEAN
LoadRom(IN PCSTR RomFileName,
IN PVOID RomLocation,
OUT PULONG RomSize OPTIONAL)
{
BOOLEAN Success;
HANDLE hRomFile;
ULONG ulRomSize = 0;
/* Open the ROM image file */
hRomFile = OpenRomFile(RomFileName, &ulRomSize);
/* If we failed, bail out */
if (hRomFile == NULL) return FALSE;
/* Attempt to load the ROM image file into memory */
Success = LoadRomFileByHandle(hRomFile,
RomLocation,
ulRomSize,
&ulRomSize);
DPRINT1("ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
/* Close the ROM image file and return */
FileClose(hRomFile);
/*
* In case of success, write-protect the ROM location
* and return the ROM size if needed.
*/
if (Success)
{
WriteProtectRom(RomLocation, ulRomSize);
if (RomSize) *RomSize = ulRomSize;
}
return Success;
}
VOID
SearchAndInitRoms(IN PCALLBACK16 Context)
{
[NTVDM] - Add some level of "Advanced debugging" (see ntvdm.h) which one can adjust to enable/disable debugging features inside NTVDM (this can be useful as long as NTVDM is under heavy bugfixing. When it will be more perfect, this stuff will be removed). - Add the possibility to load option ROMs at a given segment. Currently their list should be specified from inside ntvdm.c (in the BiosInitialize call), but I plan to make it available from a registry option (or via command-line for NTVDM-standalone mode). - Start to separate the initialization of "static" BIOS data (stuff that lives in ROM space) and initialization of "dynamic" BIOS data (eg. initializing the interrupt vector table, the BIOS data area at segment 40h, ...) so that we may be able to reuse part of our code to be able to more-or-less run external (16-bit) BIOSes, or the Windows NTVDM BIOS that uses BOPs to run some of its stuff in ntvdm in 32-bit (as we do for our 32-bit BIOS, except that *all* of our bios is 32-bit, not just some parts). Also, some file reorganization will be in order there soon... - Add video BIOS version information in memory so that tools such as Microsoft Diagnostics can correctly recognize our video BIOS (btw, we try to emulate the functionality of Cirrus' CL-GD5434). - Correctly put video BIOS ROM header (+ checksum) in memory so that it is recognized as such by diagnostics tools. - During BIOS POST, scan for ROMs starting segment 0xC000 (where video ROMs reside). - Store statically the BIOS configuration table. - Fix INT 16h, AH=12h "Get extended shift states" so that it correctly returns the state of right Ctrl and Alt keys. - Fix bit-setting state; report that our keyboard is 101/102 enhanced keyboard. - Correctly set the error return values (AH=86h and CF set) when a function of INT 15h is unsupported. - Implement INT 15h, AH=C9h "Get CPU Type and Mask Revision"; INT 1Ah, AH=02h "Get Real-Time Clock Time" and Ah=04h "Get Real-Time Clock Date" by reading the CMOS. - Implement CMOS century register support. svn path=/trunk/; revision=68598
2015-08-04 20:17:05 +00:00
/* Video ROMs -- Start: C0000, End: C8000, 2kB blocks */
InitRomRange(Context, 0xC0000, 0xC8000, 0x0800);
/* Adapters ROMs -- Start: C8000, End: E0000, 2kB blocks */
InitRomRange(Context, 0xC8000, 0xE0000, 0x0800);
/* Expansion ROM -- Start: E0000, End: F0000, 64kB block */
InitRomRange(Context, 0xE0000, 0xEFFFF, 0x10000);
}
/* EOF */