- BIOS32: As a demonstration, load a BIOS expansion ROM (the one I've tested is the "OS in PCI expansion ROM" from: https://sites.google.com/site/pinczakko/building-a-kernel-in-pci-expansion-rom ; we don't support PCI thingies at all, but the bootstrap code works correctly).
- Initialize the BIOS32 stack for the callbacks.
- In the common BIOS functions, if we try to load the Windows NTVDM (SoftPC) BIOS (file: bios4.rom), we immediately hit a BOP 0x00 followed by INT 0x19 (bootstrap to run an OS). The BOP 0x00 is the function used by the BIOS to ask NTVDM to initialize the hardware, the IVT with data and so on. Also we finish to load the low part of the NTVDM BIOS in it (file: bios1.rom).
It's work-in-progress, nothing is done, there are lots of debugging code...

Have fun!

(to load a custom bios you need to put its filename as the first parameter of the BiosInitialize call, in the main() function in ntvdm.c).

svn path=/branches/ntvdm/; revision=62333
This commit is contained in:
Hermès Bélusca-Maïto 2014-02-26 01:16:56 +00:00
parent e03a6d7ebb
commit ae22dab753
4 changed files with 102 additions and 80 deletions

View file

@ -11,92 +11,96 @@
#define NDEBUG
#include "emulator.h"
#include "callback.h"
#include "bios.h"
#include "bop.h"
#include "rom.h"
/* PRIVATE VARIABLES **********************************************************/
static BOOLEAN Bios32Loaded = FALSE;
static CALLBACK16 __BiosContext;
/* BOP Identifiers */
#define BOP_BIOSINIT 0x00 // Windows NTVDM (SoftPC) BIOS calls BOP 0x00
// to let the virtual machine initialize itself
// the IVT and its hardware.
/* PRIVATE FUNCTIONS **********************************************************/
static VOID WINAPI BiosInitBop(LPWORD Stack)
{
/* Load the second part of the Windows NTVDM BIOS image */
LPCWSTR BiosFileName = L"bios1.rom";
PVOID BiosLocation = (PVOID)TO_LINEAR(BIOS_SEGMENT, 0x0000);
DWORD BiosSize = 0;
BOOLEAN Success;
DPRINT1("You are loading Windows NTVDM BIOS!");
/* Initialize a private callback context */
InitializeContext(&__BiosContext, BIOS_SEGMENT, 0x0000);
Success = LoadRom(BiosFileName, BiosLocation, &BiosSize);
DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
if (Success == FALSE) return;
// DisplayMessage(L"First bytes at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n"
// L"3 last bytes at 0x%p: 0x%02x 0x%02x 0x%02x",
// BiosLocation,
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 0),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 1),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 2),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 3),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 4),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 5),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 6),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 7),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 8),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 9),
// (PVOID)((ULONG_PTR)BiosLocation + BiosSize - 2),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 2),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 1),
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 0));
/* Initialize IVT and hardware */
/* Load VGA BIOS */
// Success = LoadRom(L"v7vga.rom", (PVOID)0xC0000, &BiosSize);
// DPRINT1("VGA BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
/* Load some ROMs */
Success = LoadRom(L"boot.bin", (PVOID)0xE0000, &BiosSize);
DPRINT1("Test ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
SearchAndInitRoms(&__BiosContext);
}
/* PUBLIC FUNCTIONS ***********************************************************/
BOOLEAN BiosInitialize(IN LPCWSTR BiosFileName,
IN HANDLE ConsoleInput,
IN HANDLE ConsoleOutput)
{
/* Register the BIOS support BOPs */
RegisterBop(BOP_BIOSINIT, BiosInitBop);
if (BiosFileName)
{
BOOL Success;
HANDLE hBiosFile;
DWORD BiosSize;
PVOID BiosLocation;
PVOID BiosLocation = NULL;
DWORD BiosSize = 0;
BOOLEAN Success = LoadBios(BiosFileName, &BiosLocation, &BiosSize);
/* Open the BIOS file */
SetLastError(0); // For debugging purposes
hBiosFile = CreateFileW(BiosFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
DPRINT1("BIOS opening %s ; GetLastError() = %u\n", hBiosFile != INVALID_HANDLE_VALUE ? "succeeded" : "failed", GetLastError());
/* If we failed, bail out */
if (hBiosFile == INVALID_HANDLE_VALUE) return FALSE;
/* OK, we have a handle to the BIOS file */
/*
* Retrieve the size of the file. Since the size of the BIOS file
* should be at most 64kB, we just use GetFileSize.
*/
BiosSize = GetFileSize(hBiosFile, NULL);
if (BiosSize == INVALID_FILE_SIZE && GetLastError() != ERROR_SUCCESS)
{
/* We failed, return failure */
/* Close the BIOS file */
CloseHandle(hBiosFile);
return FALSE;
}
/* BIOS location needs to be aligned on 32-bit boundary */
/* (PVOID)((ULONG_PTR)BaseAddress + ROM_AREA_END + 1 - BiosSize) */
BiosLocation = (PVOID)MEM_ALIGN_DOWN((ULONG_PTR)TO_LINEAR(0xF000, 0xFFFF) + 1 - BiosSize, sizeof(ULONG));
DisplayMessage(L"First bytes at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n"
L"3 last bytes at 0x%p: 0x%02x 0x%02x 0x%02x",
BiosLocation,
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 0),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 1),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 2),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 3),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 4),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 5),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 6),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 7),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 8),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 9),
(PVOID)((ULONG_PTR)TO_LINEAR(0xF000, 0xFFFF) - 2),
*(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(0xF000, 0xFFFF) - 2),
*(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(0xF000, 0xFFFF) - 1),
*(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(0xF000, 0xFFFF) - 0));
/* Attempt to load the BIOS file into memory */
SetLastError(0); // For debugging purposes
Success = ReadFile(hBiosFile,
REAL_TO_PHYS(BiosLocation),
BiosSize,
&BiosSize,
NULL);
DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
/* Close the BIOS file */
CloseHandle(hBiosFile);
if (Success == FALSE) return FALSE;
DisplayMessage(L"First bytes at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n"
L"3 last bytes at 0x%p: 0x%02x 0x%02x 0x%02x",
@ -112,10 +116,10 @@ BOOLEAN BiosInitialize(IN LPCWSTR BiosFileName,
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 8),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 9),
(PVOID)((ULONG_PTR)TO_LINEAR(0xF000, 0xFFFF) - 2),
*(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(0xF000, 0xFFFF) - 2),
*(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(0xF000, 0xFFFF) - 1),
*(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(0xF000, 0xFFFF) - 0));
(PVOID)((ULONG_PTR)BiosLocation + BiosSize - 2),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 2),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 1),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 0));
DisplayMessage(L"POST at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
TO_LINEAR(getCS(), getIP()),

View file

@ -16,14 +16,11 @@
/* DEFINES ********************************************************************/
#define ROM_AREA_START 0xE0000
#define ROM_AREA_END 0xFFFFF
// #define BDA_SEGMENT 0x40
#define BIOS_SEGMENT 0xF000
#if 0
#define BDA_SEGMENT 0x40
#define BIOS_SEGMENT 0xF000
/*
* BIOS Data Area at 0040:XXXX
*

View file

@ -13,6 +13,8 @@
#include "emulator.h"
#include "callback.h"
#include "../rom.h"
#include "../bios.h"
#include "bios32.h"
#include "io.h"
@ -355,8 +357,22 @@ static VOID InitializeBiosInt32(VOID)
BOOLEAN Bios32Initialize(IN HANDLE ConsoleInput,
IN HANDLE ConsoleOutput)
{
BOOLEAN Success;
UCHAR Low, High;
/* Disable interrupts */
setIF(0);
/* Initialize the stack */
// That's what says IBM... (stack at 30:00FF going downwards)
// setSS(0x0000);
// setSP(0x0400);
setSS(0x0050); // Stack at 50:0400, going downwards
setSP(0x0400);
/* Set data segment */
setDS(BDA_SEGMENT);
/* Initialize the BDA */
Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0);
Bda->EquipmentList = BIOS_EQUIPMENT_LIST;
@ -389,6 +405,14 @@ BOOLEAN Bios32Initialize(IN HANDLE ConsoleInput,
/* Enable interrupts */
setIF(1);
///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
/* Load some ROMs */
Success = LoadRom(L"boot.bin", (PVOID)0xE0000, NULL);
DPRINT1("Test ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
SearchAndInitRoms(&BiosContext);
/* We are done */
return TRUE;
}

View file

@ -31,11 +31,8 @@
#define BIOS_EQUIPMENT_LIST 0x2C // HACK: Disable FPU for now
#define ROM_AREA_START 0xE0000
#define ROM_AREA_END 0xFFFFF
#define BDA_SEGMENT 0x40
#define BIOS_SEGMENT 0xF000
// #define BIOS_SEGMENT 0xF000
/*
* BIOS Data Area at 0040:XXXX