From 8d73d7c58ac03bcfb86000f27ea69512bd7ec229 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sat, 4 Oct 2014 13:36:17 +0000 Subject: [PATCH] [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 --- reactos/subsystems/ntvdm/bios/bios.c | 91 +----- reactos/subsystems/ntvdm/bios/bios.h | 10 + reactos/subsystems/ntvdm/bios/bios32/bios32.c | 135 ++++++--- reactos/subsystems/ntvdm/dos/dem.c | 273 ++++++++++++++++-- reactos/subsystems/ntvdm/dos/dem.h | 2 - reactos/subsystems/ntvdm/ntvdm.c | 156 ++-------- reactos/subsystems/ntvdm/ntvdm.h | 7 + 7 files changed, 407 insertions(+), 267 deletions(-) diff --git a/reactos/subsystems/ntvdm/bios/bios.c b/reactos/subsystems/ntvdm/bios/bios.c index ad04e48fbb2..7b6d038c309 100644 --- a/reactos/subsystems/ntvdm/bios/bios.c +++ b/reactos/subsystems/ntvdm/bios/bios.c @@ -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(); + + // /* Register the BIOS support BOPs */ + // RegisterBop(BOP_EQUIPLIST , BiosEquipmentService); + // RegisterBop(BOP_GETMEMSIZE, BiosGetMemorySize); - if (BiosFileName) + 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; } diff --git a/reactos/subsystems/ntvdm/bios/bios.h b/reactos/subsystems/ntvdm/bios/bios.h index 808e013d4cc..5799db56a3b 100644 --- a/reactos/subsystems/ntvdm/bios/bios.h +++ b/reactos/subsystems/ntvdm/bios/bios.h @@ -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 diff --git a/reactos/subsystems/ntvdm/bios/bios32/bios32.c b/reactos/subsystems/ntvdm/bios/bios32/bios32.c index 46d139f5f36..c6fbc845345 100644 --- a/reactos/subsystems/ntvdm/bios/bios32/bios32.c +++ b/reactos/subsystems/ntvdm/bios/bios32/bios32.c @@ -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; } diff --git a/reactos/subsystems/ntvdm/dos/dem.c b/reactos/subsystems/ntvdm/dos/dem.c index 13fde993e59..2e20a9c4003 100644 --- a/reactos/subsystems/ntvdm/dos/dem.c +++ b/reactos/subsystems/ntvdm/dos/dem.c @@ -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(); + + if (!Success) goto Quit32; + + /* 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); - Result = DosBIOSInitialize(); - DosMouseInitialize(); // FIXME: Should be done by the DOS BIOS - // Result &= DosKRNLInitialize(); + /* Close the thread handle */ + CloseHandle(CommandThread); - return Result; +#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 diff --git a/reactos/subsystems/ntvdm/dos/dem.h b/reactos/subsystems/ntvdm/dos/dem.h index 1e5f2de1b05..297ac26f002 100644 --- a/reactos/subsystems/ntvdm/dos/dem.h +++ b/reactos/subsystems/ntvdm/dos/dem.h @@ -20,8 +20,6 @@ /* FUNCTIONS ******************************************************************/ -BOOLEAN DosInitialize(IN LPCSTR DosKernelFileNames); - DWORD WINAPI demClientErrorEx diff --git a/reactos/subsystems/ntvdm/ntvdm.c b/reactos/subsystems/ntvdm/ntvdm.c index ecdaa7d2f5e..ab75aff6530 100644 --- a/reactos/subsystems/ntvdm/ntvdm.c +++ b/reactos/subsystems/ntvdm/ntvdm.c @@ -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 []\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(); diff --git a/reactos/subsystems/ntvdm/ntvdm.h b/reactos/subsystems/ntvdm/ntvdm.h index 68ca34cb0f0..1bfe64f6dc8 100644 --- a/reactos/subsystems/ntvdm/ntvdm.h +++ b/reactos/subsystems/ntvdm/ntvdm.h @@ -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 */ -- 2.17.1