[NTVDM]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 27 Feb 2014 03:08:23 +0000 (03:08 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 27 Feb 2014 03:08:23 +0000 (03:08 +0000)
Be able to load an external DOS BIOS file (at 70:0000) and, in case it is the DOS BIOS file of the NT VDM, load the DOS kernel file ntdos.sys when the ntio.sys calls BOP DOS function 0x11 (and put the kernel at DI:0000).
Work in progress...

svn path=/branches/ntvdm/; revision=62343

subsystems/ntvdm/dos/dem.c

index b7f0179..df57840 100644 (file)
@@ -15,6 +15,7 @@
 #define NDEBUG
 
 #include "emulator.h"
+#include "utils.h"
 
 #include "dem.h"
 #include "bop.h"
@@ -40,7 +41,54 @@ static VOID WINAPI DosSystemBop(LPWORD Stack)
     BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
     setIP(getIP() + 1);
 
-    DPRINT1("Unknown DOS System BOP Function: 0x%02X\n", FuncNum);
+    switch (FuncNum)
+    {
+        case 0x11:  // Load the DOS kernel
+        {
+            BOOLEAN Success;
+            HANDLE  hDosKernel;
+            ULONG   ulDosKernelSize = 0;
+
+            DPRINT1("You are loading Windows NT DOS!\n");
+
+            /* Open the DOS kernel file */
+            hDosKernel = FileOpen("ntdos.sys", &ulDosKernelSize);
+
+            /* If we failed, bail out */
+            if (hDosKernel == NULL) goto Quit;
+
+            /*
+             * Attempt to load the DOS kernel into memory.
+             * The segment where to load the DOS kernel is defined
+             * by the DOS BIOS and is found in DI:0000 .
+             */
+            Success = FileLoadByHandle(hDosKernel,
+                                       REAL_TO_PHYS(TO_LINEAR(getDI(), 0x0000)),
+                                       ulDosKernelSize,
+                                       &ulDosKernelSize);
+            DPRINT1("DOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
+
+            /* Close the DOS kernel file */
+            FileClose(hDosKernel);
+
+Quit:
+            if (!Success)
+            {
+                /* We failed everything, stop the VDM */
+                VdmRunning = FALSE;
+            }
+
+            break;
+        }
+
+        default:
+        {
+
+            DPRINT1("Unknown DOS System BOP Function: 0x%02X\n", FuncNum);
+            // setCF(1); // Disable, otherwise we enter an infinite loop
+            break;
+        }
+    }
 }
 
 static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
@@ -51,7 +99,7 @@ static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
 
     switch (FuncNum)
     {
-        case 0x08: // Launch external command
+        case 0x08:  // Launch external command
         {
 #define CMDLINE_LENGTH  1024
 
@@ -132,16 +180,42 @@ static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
 
 /* PUBLIC FUNCTIONS ***********************************************************/
 
-BOOLEAN DosInitialize(IN LPCSTR DosKernelFileNames)
+BOOLEAN DosInitialize(IN LPCSTR DosKernelFileName)
 {
     /* Register the DOS BOPs */
     RegisterBop(BOP_DOS, DosSystemBop        );
     RegisterBop(BOP_CMD, DosCmdInterpreterBop);
 
-    if (DosKernelFileNames)
+    if (DosKernelFileName)
     {
-        DisplayMessage(L"NTVDM: Loading DOS kernel from external files is currently unsupported");
-        return FALSE;
+        BOOLEAN Success;
+        HANDLE  hDosBios;
+        ULONG   ulDosBiosSize = 0;
+
+        /* Open the DOS BIOS file */
+        hDosBios = FileOpen(DosKernelFileName, &ulDosBiosSize);
+
+        /* If we failed, bail out */
+        if (hDosBios == NULL) return FALSE;
+
+        /* Attempt to load the DOS BIOS into memory */
+        Success = FileLoadByHandle(hDosBios,
+                                   REAL_TO_PHYS(TO_LINEAR(0x0070, 0x0000)),
+                                   ulDosBiosSize,
+                                   &ulDosBiosSize);
+        DPRINT1("DOS BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
+
+        /* Close the DOS BIOS file */
+        FileClose(hDosBios);
+
+        if (Success)
+        {
+            /* Position execution pointers and return */
+            setCS(0x0070);
+            setIP(0x0000);
+        }
+
+        return Success;
     }
     else
     {