mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[NTVDM]
- Move almost all the DOS command launch thread into dem.c, - Rework the code so that now, when we want to either load our BIOS32 or a custom one, we start their execution at F000:FFF0 as it should be, - For modularity purposes (ie. to be able one day to load real OSes in our ntvdm), implement INT 19h (bootstrap loader) so that it calls a (temporary) dos bootsector loader that writes some bootstrap code at 0000:7c00, then the INT 19h runs this code, that has as an effect to load our DOS32 (for a real OS, the MBR code goes to 0000:7c00 and is then run). svn path=/trunk/; revision=64521
This commit is contained in:
parent
38258d656e
commit
8d73d7c58a
7 changed files with 407 additions and 267 deletions
|
@ -25,7 +25,7 @@
|
|||
/* DEFINES ********************************************************************/
|
||||
|
||||
/* BOP Identifiers */
|
||||
#define BOP_BIOSINIT 0x00 // Windows NTVDM (SoftPC) BIOS calls BOP 0x00
|
||||
#define BOP_RESET 0x00 // Windows NTVDM (SoftPC) BIOS calls BOP 0x00
|
||||
// to let the virtual machine initialize itself
|
||||
// the IVT and its hardware.
|
||||
#define BOP_EQUIPLIST 0x11
|
||||
|
@ -35,84 +35,11 @@
|
|||
|
||||
static BOOLEAN Bios32Loaded = FALSE;
|
||||
|
||||
static CALLBACK16 __BiosContext;
|
||||
PBIOS_DATA_AREA Bda;
|
||||
PBIOS_CONFIG_TABLE Bct;
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
static VOID WINAPI BiosInitBop(LPWORD Stack)
|
||||
{
|
||||
BOOLEAN Success;
|
||||
|
||||
/* Load the second part of the Windows NTVDM BIOS image */
|
||||
LPCSTR BiosFileName = "bios1.rom";
|
||||
PVOID BiosLocation = (PVOID)TO_LINEAR(BIOS_SEGMENT, 0x0000);
|
||||
DWORD BiosSize = 0;
|
||||
|
||||
/* Disable interrupts */
|
||||
setIF(0);
|
||||
|
||||
DisplayMessage(L"You are loading Windows NTVDM BIOS!\n");
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/* Stop the VDM */
|
||||
EmulatorTerminate();
|
||||
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 */
|
||||
|
||||
/* Initialize the Keyboard and Video BIOS */
|
||||
if (!KbdBiosInitialize() || !VidBiosInitialize())
|
||||
{
|
||||
/* Stop the VDM */
|
||||
EmulatorTerminate();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Load VGA BIOS */
|
||||
// Success = LoadRom("v7vga.rom", (PVOID)0xC0000, &BiosSize);
|
||||
// DPRINT1("VGA BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
|
||||
|
||||
/* Enable interrupts */
|
||||
setIF(1);
|
||||
|
||||
///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
|
||||
|
||||
/* Load some ROMs */
|
||||
// Success = LoadRom("boot.bin", (PVOID)0xE0000, &BiosSize);
|
||||
// DPRINT1("Test ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
|
||||
|
||||
SearchAndInitRoms(&__BiosContext);
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
||||
VOID WINAPI BiosEquipmentService(LPWORD Stack)
|
||||
|
@ -140,12 +67,14 @@ BiosInitialize(IN LPCSTR BiosFileName)
|
|||
// The BCT is found at F000:E6F5 for 100% compatible BIOSes.
|
||||
Bct = (PBIOS_CONFIG_TABLE)SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xE6F5);
|
||||
|
||||
/* Register the BIOS support BOPs */
|
||||
RegisterBop(BOP_BIOSINIT , BiosInitBop);
|
||||
RegisterBop(BOP_EQUIPLIST , BiosEquipmentService);
|
||||
RegisterBop(BOP_GETMEMSIZE, BiosGetMemorySize);
|
||||
/**** HACK! HACK! for Windows NTVDM BIOS ****/
|
||||
// WinNtVdmBiosSupportInitialize();
|
||||
|
||||
if (BiosFileName)
|
||||
// /* Register the BIOS support BOPs */
|
||||
// RegisterBop(BOP_EQUIPLIST , BiosEquipmentService);
|
||||
// RegisterBop(BOP_GETMEMSIZE, BiosGetMemorySize);
|
||||
|
||||
if (BiosFileName && BiosFileName[0] != '\0')
|
||||
{
|
||||
PVOID BiosLocation = NULL;
|
||||
DWORD BiosSize = 0;
|
||||
|
@ -199,8 +128,8 @@ BiosInitialize(IN LPCSTR BiosFileName)
|
|||
Success = Bios32Loaded = Bios32Initialize();
|
||||
}
|
||||
|
||||
/* Enable interrupts */
|
||||
setIF(1);
|
||||
// /* Enable interrupts */
|
||||
// setIF(1);
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,16 @@
|
|||
|
||||
/* DEFINES ********************************************************************/
|
||||
|
||||
/* BOP Identifiers */
|
||||
#define BOP_RESET 0x00 // Windows NTVDM (SoftPC) BIOS calls BOP 0x00
|
||||
// to let the virtual machine initialize itself
|
||||
// the IVT and its hardware.
|
||||
#define BOP_EQUIPLIST 0x11
|
||||
#define BOP_GETMEMSIZE 0x12
|
||||
|
||||
|
||||
|
||||
|
||||
#define BDA_SEGMENT 0x40
|
||||
#define BIOS_SEGMENT 0xF000
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
|
||||
#include "emulator.h"
|
||||
#include "cpu/cpu.h" // for EMULATOR_FLAG_CF
|
||||
#include "cpu/bop.h"
|
||||
#include "int32.h"
|
||||
// #include "bop.h"
|
||||
|
||||
#include "../bios.h"
|
||||
#include "../rom.h"
|
||||
|
@ -129,7 +129,8 @@ static BYTE Bootstrap[] =
|
|||
*/
|
||||
static BYTE PostCode[] =
|
||||
{
|
||||
0xCD, 0x19, // int 0x19, the bootstrap loader interrupt
|
||||
LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_RESET, // Call BIOS POST
|
||||
0xCD, 0x19, // INT 0x19, the bootstrap loader interrupt
|
||||
// LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_UNSIMULATE
|
||||
};
|
||||
|
||||
|
@ -278,17 +279,26 @@ static VOID WINAPI BiosRomBasic(LPWORD Stack)
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
VOID DosBootsectorInitialize(VOID);
|
||||
|
||||
static VOID WINAPI BiosBootstrapLoader(LPWORD Stack)
|
||||
{
|
||||
/*
|
||||
* In real bioses one loads the bootsector read from a diskette
|
||||
* or from a disk, to 0000:7C00 and then one runs it.
|
||||
* In real BIOSes one loads the bootsector read from a diskette
|
||||
* or from a disk, copy it to 0000:7C00 and then boot it.
|
||||
* Since we are 32-bit VM and we hardcode our DOS at the moment,
|
||||
* just call the DOS 32-bit initialization code.
|
||||
*/
|
||||
|
||||
DPRINT1("BiosBootstrapLoader -->\n");
|
||||
|
||||
/* Load DOS */
|
||||
DosBootsectorInitialize();
|
||||
/* Position CPU to 0000:7C00 to boot the OS */
|
||||
setCS(0x0000);
|
||||
setIP(0x7C00);
|
||||
|
||||
DPRINT1("<-- BiosBootstrapLoader\n");
|
||||
}
|
||||
|
||||
|
@ -510,37 +520,10 @@ static VOID InitializeBiosInt32(VOID)
|
|||
((PULONG)BaseAddress)[0x49] = (ULONG)NULL;
|
||||
}
|
||||
|
||||
static VOID InitializeBiosInfo(VOID)
|
||||
{
|
||||
RtlZeroMemory(Bct, sizeof(*Bct));
|
||||
|
||||
Bct->Length = sizeof(*Bct);
|
||||
Bct->Model = BIOS_MODEL;
|
||||
Bct->SubModel = BIOS_SUBMODEL;
|
||||
Bct->Revision = BIOS_REVISION;
|
||||
Bct->Feature[0] = 0x70; // At the moment we don't support "wait for external event (INT 15/AH=41h)", we also don't have any "extended BIOS area allocated (usually at top of RAM)"; see http://www.ctyme.com/intr/rb-1594.htm#Table510
|
||||
Bct->Feature[1] = 0x00; // We don't support anything from here; see http://www.ctyme.com/intr/rb-1594.htm#Table511
|
||||
Bct->Feature[2] = 0x00;
|
||||
Bct->Feature[3] = 0x00;
|
||||
Bct->Feature[4] = 0x00;
|
||||
}
|
||||
|
||||
static VOID InitializeBiosData(VOID)
|
||||
{
|
||||
UCHAR Low, High;
|
||||
|
||||
/* System BIOS Copyright */
|
||||
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE000), BiosCopyright, sizeof(BiosCopyright)-1);
|
||||
|
||||
/* System BIOS Version */
|
||||
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE080), BiosVersion, sizeof(BiosVersion)-1); // FIXME: or E061, or E100 ??
|
||||
|
||||
/* System BIOS Date */
|
||||
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF5), BiosDate, sizeof(BiosDate)-1);
|
||||
|
||||
/* System BIOS Model (same as Bct->Model) */
|
||||
*(PBYTE)(SEG_OFF_TO_PTR(0xF000, 0xFFFE)) = BIOS_MODEL;
|
||||
|
||||
/* Initialize the BDA contents */
|
||||
RtlZeroMemory(Bda, sizeof(*Bda));
|
||||
Bda->EquipmentList = BIOS_EQUIPMENT_LIST;
|
||||
|
@ -556,15 +539,33 @@ static VOID InitializeBiosData(VOID)
|
|||
Bda->MemorySize = MAKEWORD(Low, High);
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
static VOID InitializeBiosInfo(VOID)
|
||||
{
|
||||
RtlZeroMemory(Bct, sizeof(*Bct));
|
||||
|
||||
Bct->Length = sizeof(*Bct);
|
||||
Bct->Model = BIOS_MODEL;
|
||||
Bct->SubModel = BIOS_SUBMODEL;
|
||||
Bct->Revision = BIOS_REVISION;
|
||||
Bct->Feature[0] = 0x70; // At the moment we don't support "wait for external event (INT 15/AH=41h)", we also don't have any "extended BIOS area allocated (usually at top of RAM)"; see http://www.ctyme.com/intr/rb-1594.htm#Table510
|
||||
Bct->Feature[1] = 0x00; // We don't support anything from here; see http://www.ctyme.com/intr/rb-1594.htm#Table511
|
||||
Bct->Feature[2] = 0x00;
|
||||
Bct->Feature[3] = 0x00;
|
||||
Bct->Feature[4] = 0x00;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The BIOS POST (Power On-Self Test)
|
||||
*/
|
||||
BOOLEAN Bios32Initialize(VOID)
|
||||
VOID
|
||||
Bios32Post(VOID)
|
||||
{
|
||||
BOOLEAN Success;
|
||||
|
||||
DPRINT1("Bios32Post\n");
|
||||
|
||||
/* Initialize the stack */
|
||||
// That's what says IBM... (stack at 30:00FF going downwards)
|
||||
// setSS(0x0000);
|
||||
|
@ -587,7 +588,13 @@ BOOLEAN Bios32Initialize(VOID)
|
|||
|
||||
/* Initialize the Keyboard, Video and Mouse BIOS */
|
||||
if (!KbdBios32Initialize() || !VidBios32Initialize() || !MouseBios32Initialize())
|
||||
return FALSE;
|
||||
{
|
||||
// return FALSE;
|
||||
|
||||
/* Stop the VDM */
|
||||
EmulatorTerminate();
|
||||
return;
|
||||
}
|
||||
|
||||
///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
|
||||
|
||||
|
@ -597,10 +604,70 @@ BOOLEAN Bios32Initialize(VOID)
|
|||
|
||||
SearchAndInitRoms(&BiosContext);
|
||||
|
||||
/*
|
||||
* End of the 32-bit POST portion. We then fall back into 16-bit where
|
||||
* the rest of the POST code is executed, typically calling INT 19h
|
||||
* to boot up the OS.
|
||||
*/
|
||||
}
|
||||
|
||||
static VOID WINAPI Bios32ResetBop(LPWORD Stack)
|
||||
{
|
||||
DPRINT1("Bios32ResetBop\n");
|
||||
|
||||
/* Disable interrupts */
|
||||
setIF(0);
|
||||
|
||||
// FIXME: Check the word at 0040h:0072h and do one of the following actions:
|
||||
// - if the word is 1234h, perform a warm reboot (aka. Ctrl-Alt-Del);
|
||||
// - if the word is 0000h, perform a cold reboot (aka. Reset).
|
||||
|
||||
/* Initialize IVT and hardware */
|
||||
|
||||
/* Initialize the Keyboard and Video BIOS */
|
||||
if (!KbdBiosInitialize() || !VidBiosInitialize())
|
||||
{
|
||||
/* Stop the VDM */
|
||||
EmulatorTerminate();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do the POST */
|
||||
Bios32Post();
|
||||
|
||||
/* Enable interrupts */
|
||||
setIF(1);
|
||||
}
|
||||
|
||||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
||||
BOOLEAN Bios32Initialize(VOID)
|
||||
{
|
||||
/*
|
||||
* Initialize BIOS32 static data
|
||||
*/
|
||||
|
||||
/* Bootstrap code */
|
||||
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE05B), PostCode , sizeof(PostCode ));
|
||||
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF0), Bootstrap, sizeof(Bootstrap));
|
||||
|
||||
/* System BIOS Copyright */
|
||||
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE000), BiosCopyright, sizeof(BiosCopyright)-1);
|
||||
|
||||
/* System BIOS Version */
|
||||
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE080), BiosVersion, sizeof(BiosVersion)-1);
|
||||
// FIXME: or E061, or E100 ??
|
||||
|
||||
/* System BIOS Date */
|
||||
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF5), BiosDate, sizeof(BiosDate)-1);
|
||||
|
||||
/* System BIOS Model (same as Bct->Model) */
|
||||
*(PBYTE)(SEG_OFF_TO_PTR(0xF000, 0xFFFE)) = BIOS_MODEL;
|
||||
|
||||
/* Redefine our POST function */
|
||||
RegisterBop(BOP_RESET, Bios32ResetBop);
|
||||
|
||||
/* We are done */
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -33,8 +33,10 @@
|
|||
/* DEFINES ********************************************************************/
|
||||
|
||||
/* BOP Identifiers */
|
||||
#define BOP_DOS 0x50 // DOS System BOP (for NTIO.SYS and NTDOS.SYS)
|
||||
#define BOP_CMD 0x54 // DOS Command Interpreter BOP (for COMMAND.COM)
|
||||
#define BOP_LOAD_DOS 0x2B // DOS Loading and Initializing BOP. In parameter (following bytes) we take a NULL-terminated string indicating the name of the DOS kernel file.
|
||||
#define BOP_START_DOS 0x2C // DOS Starting BOP. In parameter (following bytes) we take a NULL-terminated string indicating the name of the DOS kernel file.
|
||||
#define BOP_DOS 0x50 // DOS System BOP (for NTIO.SYS and NTDOS.SYS)
|
||||
#define BOP_CMD 0x54 // DOS Command Interpreter BOP (for COMMAND.COM)
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
|
@ -185,17 +187,157 @@ static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef STANDALONE
|
||||
static DWORD
|
||||
WINAPI
|
||||
CommandThreadProc(LPVOID Parameter)
|
||||
{
|
||||
BOOLEAN First = TRUE;
|
||||
DWORD Result;
|
||||
VDM_COMMAND_INFO CommandInfo;
|
||||
CHAR CmdLine[MAX_PATH];
|
||||
CHAR AppName[MAX_PATH];
|
||||
CHAR PifFile[MAX_PATH];
|
||||
CHAR Desktop[MAX_PATH];
|
||||
CHAR Title[MAX_PATH];
|
||||
ULONG EnvSize = 256;
|
||||
PVOID Env = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, EnvSize);
|
||||
|
||||
UNREFERENCED_PARAMETER(Parameter);
|
||||
ASSERT(Env != NULL);
|
||||
|
||||
do
|
||||
{
|
||||
/* Clear the structure */
|
||||
ZeroMemory(&CommandInfo, sizeof(CommandInfo));
|
||||
|
||||
/* Initialize the structure members */
|
||||
CommandInfo.TaskId = SessionId;
|
||||
CommandInfo.VDMState = VDM_FLAG_DOS;
|
||||
CommandInfo.CmdLine = CmdLine;
|
||||
CommandInfo.CmdLen = sizeof(CmdLine);
|
||||
CommandInfo.AppName = AppName;
|
||||
CommandInfo.AppLen = sizeof(AppName);
|
||||
CommandInfo.PifFile = PifFile;
|
||||
CommandInfo.PifLen = sizeof(PifFile);
|
||||
CommandInfo.Desktop = Desktop;
|
||||
CommandInfo.DesktopLen = sizeof(Desktop);
|
||||
CommandInfo.Title = Title;
|
||||
CommandInfo.TitleLen = sizeof(Title);
|
||||
CommandInfo.Env = Env;
|
||||
CommandInfo.EnvLen = EnvSize;
|
||||
|
||||
if (First) CommandInfo.VDMState |= VDM_FLAG_FIRST_TASK;
|
||||
|
||||
Command:
|
||||
if (!GetNextVDMCommand(&CommandInfo))
|
||||
{
|
||||
if (CommandInfo.EnvLen > EnvSize)
|
||||
{
|
||||
/* Expand the environment size */
|
||||
EnvSize = CommandInfo.EnvLen;
|
||||
Env = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Env, EnvSize);
|
||||
|
||||
/* Repeat the request */
|
||||
goto Command;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Start the process from the command line */
|
||||
DPRINT1("Starting '%s' ('%s')...\n", AppName, CmdLine);
|
||||
Result = DosStartProcess(AppName, CmdLine, Env);
|
||||
if (Result != ERROR_SUCCESS)
|
||||
{
|
||||
DisplayMessage(L"Could not start '%S'. Error: %u", AppName, Result);
|
||||
// break;
|
||||
continue;
|
||||
}
|
||||
|
||||
First = FALSE;
|
||||
}
|
||||
while (AcceptCommands);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, Env);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
||||
BOOLEAN DosInitialize(IN LPCSTR DosKernelFileName)
|
||||
//
|
||||
// This function (equivalent of the DOS bootsector) is called by the bootstrap
|
||||
// loader *BEFORE* jumping at 0000:7C00. What we should do is to write at 0000:7C00
|
||||
// a BOP call that calls DosInitialize back. Then the bootstrap loader jumps at
|
||||
// 0000:7C00, our BOP gets called and then we can initialize the 32-bit part of the DOS.
|
||||
//
|
||||
|
||||
/* 16-bit bootstrap code at 0000:7C00 */
|
||||
/* Of course, this is not in real bootsector format, because we don't care */
|
||||
static BYTE Bootsector1[] =
|
||||
{
|
||||
LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_LOAD_DOS, // Call DOS Loading
|
||||
};
|
||||
/* This portion of code is run if we failed to load the DOS */
|
||||
static BYTE Bootsector2[] =
|
||||
{
|
||||
0xEA, // jmp far ptr
|
||||
0x5B, 0xE0, 0x00, 0xF0, // F000:E05B /** HACK! What to do instead?? **/
|
||||
};
|
||||
|
||||
static VOID WINAPI DosInitialize(LPWORD Stack);
|
||||
|
||||
VOID DosBootsectorInitialize(VOID)
|
||||
{
|
||||
/* We write the bootsector at 0000:7C00 */
|
||||
ULONG_PTR Address = (ULONG_PTR)SEG_OFF_TO_PTR(0x0000, 0x7C00);
|
||||
CHAR DosKernelFileName[] = ""; // No DOS file name, therefore we'll load DOS32
|
||||
|
||||
DPRINT1("DosBootsectorInitialize\n");
|
||||
|
||||
/* Write the "bootsector" */
|
||||
RtlCopyMemory((PVOID)Address, Bootsector1, sizeof(Bootsector1));
|
||||
Address += sizeof(Bootsector1);
|
||||
RtlCopyMemory((PVOID)Address, DosKernelFileName, sizeof(DosKernelFileName));
|
||||
Address += sizeof(DosKernelFileName);
|
||||
RtlCopyMemory((PVOID)Address, Bootsector2, sizeof(Bootsector2));
|
||||
|
||||
/* Register the DOS Loading BOP */
|
||||
RegisterBop(BOP_LOAD_DOS, DosInitialize);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// This function is called by the DOS bootsector. We finish to load
|
||||
// the DOS, then we jump to 0070:0000.
|
||||
//
|
||||
|
||||
/* 16-bit startup code at 0070:0000 */
|
||||
static BYTE Startup[] =
|
||||
{
|
||||
LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_START_DOS, // Call DOS Start
|
||||
};
|
||||
|
||||
static VOID WINAPI DosStart(LPWORD Stack);
|
||||
|
||||
static VOID WINAPI DosInitialize(LPWORD Stack)
|
||||
{
|
||||
BOOLEAN Success = FALSE;
|
||||
|
||||
/* Get the DOS kernel file name (NULL-terminated) */
|
||||
// FIXME: Isn't it possible to use some DS:SI instead??
|
||||
LPCSTR DosKernelFileName = (LPCSTR)SEG_OFF_TO_PTR(getCS(), getIP());
|
||||
setIP(getIP() + strlen(DosKernelFileName) + 1); // Skip it
|
||||
|
||||
DPRINT1("DosInitialize('%s')\n", DosKernelFileName);
|
||||
|
||||
/* Register the DOS BOPs */
|
||||
RegisterBop(BOP_DOS, DosSystemBop );
|
||||
RegisterBop(BOP_CMD, DosCmdInterpreterBop);
|
||||
|
||||
if (DosKernelFileName)
|
||||
if (DosKernelFileName && DosKernelFileName[0] != '\0')
|
||||
{
|
||||
BOOLEAN Success;
|
||||
HANDLE hDosBios;
|
||||
ULONG ulDosBiosSize = 0;
|
||||
|
||||
|
@ -203,7 +345,7 @@ BOOLEAN DosInitialize(IN LPCSTR DosKernelFileName)
|
|||
hDosBios = FileOpen(DosKernelFileName, &ulDosBiosSize);
|
||||
|
||||
/* If we failed, bail out */
|
||||
if (hDosBios == NULL) return FALSE;
|
||||
if (hDosBios == NULL) goto QuitCustom;
|
||||
|
||||
/* Attempt to load the DOS BIOS into memory */
|
||||
Success = FileLoadByHandle(hDosBios,
|
||||
|
@ -220,27 +362,122 @@ BOOLEAN DosInitialize(IN LPCSTR DosKernelFileName)
|
|||
/* Close the DOS BIOS file */
|
||||
FileClose(hDosBios);
|
||||
|
||||
if (Success)
|
||||
{
|
||||
/* Position execution pointers and return */
|
||||
setCS(0x0070);
|
||||
setIP(0x0000);
|
||||
}
|
||||
if (!Success) goto QuitCustom;
|
||||
|
||||
return Success;
|
||||
/* Position execution pointers and return */
|
||||
setCS(0x0070);
|
||||
setIP(0x0000);
|
||||
|
||||
/* Return control */
|
||||
QuitCustom:
|
||||
if (!Success)
|
||||
DisplayMessage(L"Custom DOS '%S' loading failed, what to do??", DosKernelFileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOLEAN Result;
|
||||
Success = DosBIOSInitialize();
|
||||
// Success &= DosKRNLInitialize();
|
||||
|
||||
Result = DosBIOSInitialize();
|
||||
DosMouseInitialize(); // FIXME: Should be done by the DOS BIOS
|
||||
// Result &= DosKRNLInitialize();
|
||||
if (!Success) goto Quit32;
|
||||
|
||||
return Result;
|
||||
/* Write the "bootsector" */
|
||||
RtlCopyMemory(SEG_OFF_TO_PTR(0x0070, 0x0000), Startup, sizeof(Startup));
|
||||
|
||||
/* Register the DOS Starting BOP */
|
||||
RegisterBop(BOP_START_DOS, DosStart);
|
||||
|
||||
/* Position execution pointers and return */
|
||||
setCS(0x0070);
|
||||
setIP(0x0000);
|
||||
|
||||
/* Return control */
|
||||
Quit32:
|
||||
if (!Success)
|
||||
DisplayMessage(L"DOS32 loading failed, what to do??");
|
||||
}
|
||||
|
||||
if (Success)
|
||||
{
|
||||
/*
|
||||
* We succeeded, deregister the DOS Loading BOP
|
||||
* so that no app will be able to call us back.
|
||||
*/
|
||||
RegisterBop(BOP_LOAD_DOS, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static VOID WINAPI DosStart(LPWORD Stack)
|
||||
{
|
||||
#ifdef STANDALONE
|
||||
DWORD Result;
|
||||
CHAR ApplicationName[MAX_PATH];
|
||||
CHAR CommandLine[DOS_CMDLINE_LENGTH];
|
||||
#endif
|
||||
|
||||
DPRINT1("DosStart\n");
|
||||
|
||||
/*
|
||||
* We succeeded, deregister the DOS Starting BOP
|
||||
* so that no app will be able to call us back.
|
||||
*/
|
||||
RegisterBop(BOP_START_DOS, NULL);
|
||||
|
||||
/* Load the mouse driver */
|
||||
DosMouseInitialize();
|
||||
|
||||
#ifndef STANDALONE
|
||||
|
||||
/* Create the GetNextVDMCommand thread */
|
||||
CommandThread = CreateThread(NULL, 0, &CommandThreadProc, NULL, 0, NULL);
|
||||
if (CommandThread == NULL)
|
||||
{
|
||||
wprintf(L"FATAL: Failed to create the command processing thread: %d\n", GetLastError());
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/* Wait for the command thread to exit */
|
||||
WaitForSingleObject(CommandThread, INFINITE);
|
||||
|
||||
/* Close the thread handle */
|
||||
CloseHandle(CommandThread);
|
||||
|
||||
#else
|
||||
|
||||
if (NtVdmArgc >= 2)
|
||||
{
|
||||
WideCharToMultiByte(CP_ACP, 0, NtVdmArgv[1], -1, ApplicationName, sizeof(ApplicationName), NULL, NULL);
|
||||
|
||||
if (NtVdmArgc >= 3)
|
||||
WideCharToMultiByte(CP_ACP, 0, NtVdmArgv[2], -1, CommandLine, sizeof(CommandLine), NULL, NULL);
|
||||
else
|
||||
strcpy(CommandLine, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
DisplayMessage(L"Invalid DOS command line\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/* Start the process from the command line */
|
||||
DPRINT1("Starting '%s' ('%s')...\n", ApplicationName, CommandLine);
|
||||
Result = DosStartProcess(ApplicationName,
|
||||
CommandLine,
|
||||
GetEnvironmentStrings());
|
||||
if (Result != ERROR_SUCCESS)
|
||||
{
|
||||
DisplayMessage(L"Could not start '%S'. Error: %u", ApplicationName, Result);
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Quit:
|
||||
/* Stop the VDM */
|
||||
EmulatorTerminate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* PUBLIC EXPORTED APIS *******************************************************/
|
||||
|
||||
// demLFNCleanup
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
BOOLEAN DosInitialize(IN LPCSTR DosKernelFileNames);
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
demClientErrorEx
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "ntvdm.h"
|
||||
#include "emulator.h"
|
||||
#include "cpu/cpu.h"
|
||||
|
||||
#include "clock.h"
|
||||
#include "hardware/ps2.h"
|
||||
|
@ -26,19 +27,25 @@
|
|||
static HANDLE ConsoleInput = INVALID_HANDLE_VALUE;
|
||||
static HANDLE ConsoleOutput = INVALID_HANDLE_VALUE;
|
||||
static DWORD OrgConsoleInputMode, OrgConsoleOutputMode;
|
||||
static BOOLEAN AcceptCommands = TRUE;
|
||||
static HANDLE CommandThread = NULL;
|
||||
|
||||
static HMENU hConsoleMenu = NULL;
|
||||
static INT VdmMenuPos = -1;
|
||||
static BOOLEAN ShowPointer = FALSE;
|
||||
|
||||
// For DOS
|
||||
#ifndef STANDALONE
|
||||
BOOLEAN AcceptCommands = TRUE;
|
||||
HANDLE CommandThread = NULL;
|
||||
ULONG SessionId = 0;
|
||||
#endif
|
||||
|
||||
HANDLE VdmTaskEvent = NULL;
|
||||
|
||||
// Command line of NTVDM
|
||||
INT NtVdmArgc;
|
||||
WCHAR** NtVdmArgv;
|
||||
|
||||
|
||||
static HMENU hConsoleMenu = NULL;
|
||||
static INT VdmMenuPos = -1;
|
||||
static BOOLEAN ShowPointer = FALSE;
|
||||
|
||||
/*
|
||||
* Those menu helpers were taken from the GUI frontend in winsrv.dll
|
||||
*/
|
||||
|
@ -198,6 +205,7 @@ ConsoleCtrlHandler(DWORD ControlType)
|
|||
case CTRL_BREAK_EVENT:
|
||||
{
|
||||
/* Call INT 23h */
|
||||
DPRINT1("Ctrl-C/Break: Call INT 23h\n");
|
||||
EmulatorInterrupt(0x23);
|
||||
break;
|
||||
}
|
||||
|
@ -206,14 +214,18 @@ ConsoleCtrlHandler(DWORD ControlType)
|
|||
if (WaitForSingleObject(VdmTaskEvent, 0) == WAIT_TIMEOUT)
|
||||
{
|
||||
/* Exit immediately */
|
||||
#ifndef STANDALONE
|
||||
if (CommandThread) TerminateThread(CommandThread, 0);
|
||||
#endif
|
||||
EmulatorTerminate();
|
||||
}
|
||||
#ifndef STANDALONE
|
||||
else
|
||||
{
|
||||
/* Stop accepting new commands */
|
||||
AcceptCommands = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -361,100 +373,12 @@ VOID FocusEventHandler(PFOCUS_EVENT_RECORD FocusEvent)
|
|||
DPRINT1("Focus events not handled\n");
|
||||
}
|
||||
|
||||
#ifndef STANDALONE
|
||||
static DWORD
|
||||
WINAPI
|
||||
CommandThreadProc(LPVOID Parameter)
|
||||
{
|
||||
BOOLEAN First = TRUE;
|
||||
DWORD Result;
|
||||
VDM_COMMAND_INFO CommandInfo;
|
||||
CHAR CmdLine[MAX_PATH];
|
||||
CHAR AppName[MAX_PATH];
|
||||
CHAR PifFile[MAX_PATH];
|
||||
CHAR Desktop[MAX_PATH];
|
||||
CHAR Title[MAX_PATH];
|
||||
ULONG EnvSize = 256;
|
||||
PVOID Env = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, EnvSize);
|
||||
|
||||
UNREFERENCED_PARAMETER(Parameter);
|
||||
ASSERT(Env != NULL);
|
||||
|
||||
do
|
||||
{
|
||||
/* Clear the structure */
|
||||
ZeroMemory(&CommandInfo, sizeof(CommandInfo));
|
||||
|
||||
/* Initialize the structure members */
|
||||
CommandInfo.TaskId = SessionId;
|
||||
CommandInfo.VDMState = VDM_FLAG_DOS;
|
||||
CommandInfo.CmdLine = CmdLine;
|
||||
CommandInfo.CmdLen = sizeof(CmdLine);
|
||||
CommandInfo.AppName = AppName;
|
||||
CommandInfo.AppLen = sizeof(AppName);
|
||||
CommandInfo.PifFile = PifFile;
|
||||
CommandInfo.PifLen = sizeof(PifFile);
|
||||
CommandInfo.Desktop = Desktop;
|
||||
CommandInfo.DesktopLen = sizeof(Desktop);
|
||||
CommandInfo.Title = Title;
|
||||
CommandInfo.TitleLen = sizeof(Title);
|
||||
CommandInfo.Env = Env;
|
||||
CommandInfo.EnvLen = EnvSize;
|
||||
|
||||
if (First) CommandInfo.VDMState |= VDM_FLAG_FIRST_TASK;
|
||||
|
||||
Command:
|
||||
if (!GetNextVDMCommand(&CommandInfo))
|
||||
{
|
||||
if (CommandInfo.EnvLen > EnvSize)
|
||||
{
|
||||
/* Expand the environment size */
|
||||
EnvSize = CommandInfo.EnvLen;
|
||||
Env = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Env, EnvSize);
|
||||
|
||||
/* Repeat the request */
|
||||
goto Command;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Start the process from the command line */
|
||||
DPRINT1("Starting '%s' ('%s')...\n", AppName, CmdLine);
|
||||
Result = DosStartProcess(AppName, CmdLine, Env);
|
||||
if (Result != ERROR_SUCCESS)
|
||||
{
|
||||
DisplayMessage(L"Could not start '%S'. Error: %u", AppName, Result);
|
||||
// break;
|
||||
continue;
|
||||
}
|
||||
|
||||
First = FALSE;
|
||||
}
|
||||
while (AcceptCommands);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, Env);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
INT
|
||||
wmain(INT argc, WCHAR *argv[])
|
||||
{
|
||||
#ifdef STANDALONE
|
||||
|
||||
DWORD Result;
|
||||
CHAR ApplicationName[MAX_PATH];
|
||||
CHAR CommandLine[DOS_CMDLINE_LENGTH];
|
||||
|
||||
if (argc >= 2)
|
||||
{
|
||||
WideCharToMultiByte(CP_ACP, 0, argv[1], -1, ApplicationName, sizeof(ApplicationName), NULL, NULL);
|
||||
|
||||
if (argc >= 3) WideCharToMultiByte(CP_ACP, 0, argv[2], -1, CommandLine, sizeof(CommandLine), NULL, NULL);
|
||||
else strcpy(CommandLine, "");
|
||||
}
|
||||
else
|
||||
if (argc < 2)
|
||||
{
|
||||
wprintf(L"\nReactOS Virtual DOS Machine\n\n"
|
||||
L"Usage: NTVDM <executable> [<parameters>]\n");
|
||||
|
@ -481,6 +405,9 @@ wmain(INT argc, WCHAR *argv[])
|
|||
|
||||
#endif
|
||||
|
||||
NtVdmArgc = argc;
|
||||
NtVdmArgv = argv;
|
||||
|
||||
DPRINT1("\n\n\nNTVDM - Starting...\n\n\n");
|
||||
|
||||
/* Create the task event */
|
||||
|
@ -508,43 +435,8 @@ wmain(INT argc, WCHAR *argv[])
|
|||
goto Cleanup;
|
||||
}
|
||||
|
||||
/* Initialize the VDM DOS kernel */
|
||||
if (!DosInitialize(NULL))
|
||||
{
|
||||
wprintf(L"FATAL: Failed to initialize the VDM DOS kernel.\n");
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
#ifndef STANDALONE
|
||||
|
||||
/* Create the GetNextVDMCommand thread */
|
||||
CommandThread = CreateThread(NULL, 0, &CommandThreadProc, NULL, 0, NULL);
|
||||
if (CommandThread == NULL)
|
||||
{
|
||||
wprintf(L"FATAL: Failed to create the command processing thread: %d\n", GetLastError());
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
/* Wait for the command thread to exit */
|
||||
WaitForSingleObject(CommandThread, INFINITE);
|
||||
|
||||
/* Close the thread handle */
|
||||
CloseHandle(CommandThread);
|
||||
|
||||
#else
|
||||
|
||||
/* Start the process from the command line */
|
||||
DPRINT1("Starting '%s' ('%s')...\n", ApplicationName, CommandLine);
|
||||
Result = DosStartProcess(ApplicationName,
|
||||
CommandLine,
|
||||
GetEnvironmentStrings());
|
||||
if (Result != ERROR_SUCCESS)
|
||||
{
|
||||
DisplayMessage(L"Could not start '%S'. Error: %u", ApplicationName, Result);
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* Let's go! Start simulation */
|
||||
CpuSimulate();
|
||||
|
||||
Cleanup:
|
||||
BiosCleanup();
|
||||
|
|
|
@ -41,11 +41,18 @@ DWORD WINAPI SetLastConsoleEventActive(VOID);
|
|||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
#ifndef STANDALONE
|
||||
extern BOOLEAN AcceptCommands;
|
||||
extern HANDLE CommandThread;
|
||||
extern ULONG SessionId;
|
||||
#endif
|
||||
|
||||
extern HANDLE VdmTaskEvent;
|
||||
|
||||
// Command line of NTVDM
|
||||
extern INT NtVdmArgc;
|
||||
extern WCHAR** NtVdmArgv;
|
||||
|
||||
|
||||
/*
|
||||
* Interface functions
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue