Index: trunk/src/VBox/ValidationKit/testdriver/vbox.py
===================================================================
--- trunk/src/VBox/ValidationKit/testdriver/vbox.py	(revision 70710)
+++ trunk/src/VBox/ValidationKit/testdriver/vbox.py	(revision 70718)
@@ -2115,4 +2115,21 @@
                 reporter.log("    traceFile:      %s" % (oNic.traceFile));
             self.processPendingEvents();
+
+        reporter.log("  Serial ports:");
+        for iSlot in range(0, 8):
+            try:    oPort = oVM.getSerialPort(iSlot)
+            except: break;
+            if oPort is not None and oPort.enabled:
+                enmHostMode = oPort.hostMode;
+                if   enmHostMode == vboxcon.PortMode_Disconnected:      sType = "Disconnected";
+                elif enmHostMode == vboxcon.PortMode_HostPipe:          sType = "HostPipe";
+                elif enmHostMode == vboxcon.PortMode_HostDevice:        sType = "HostDevice";
+                elif enmHostMode == vboxcon.PortMode_RawFile:           sType = "RawFile";
+                elif enmHostMode == vboxcon.PortMode_TCP:               sType = "TCP";
+                else: sType = "unknown %s" % (enmHostMode);
+                reporter.log("    slot #%d: hostMode: %s (%s)  I/O port: %s  IRQ: %s  server: %s  path: %s" %
+                             (iSlot, sType, enmHostMode, oPort.IOBase, oPort.IRQ, oPort.server, oPort.path,) );
+                self.processPendingEvents();
+
         return True;
 
@@ -2179,10 +2196,30 @@
 
     # pylint: disable=R0913,R0914,R0915
-    def createTestVM(self, sName, iGroup, sHd = None, cMbRam = None, cCpus = 1, fVirtEx = None, fNestedPaging = None, \
-                     sDvdImage = None, sKind = "Other", fIoApic = None, fPae = None, fFastBootLogo = True, \
-                     eNic0Type = None, eNic0AttachType = None, sNic0NetName = 'default', sNic0MacAddr = 'grouped', \
-                     sFloppy = None, fNatForwardingForTxs = None, sHddControllerType = 'IDE Controller', \
-                     fVmmDevTestingPart = None, fVmmDevTestingMmio = False, sFirmwareType = 'bios', sChipsetType = 'piix3', \
-                     sDvdControllerType = 'IDE Controller',):
+    def createTestVM(self,
+                     sName,
+                     iGroup,
+                     sHd = None,
+                     cMbRam = None,
+                     cCpus = 1,
+                     fVirtEx = None,
+                     fNestedPaging = None,
+                     sDvdImage = None,
+                     sKind = "Other",
+                     fIoApic = None,
+                     fPae = None,
+                     fFastBootLogo = True,
+                     eNic0Type = None,
+                     eNic0AttachType = None,
+                     sNic0NetName = 'default',
+                     sNic0MacAddr = 'grouped',
+                     sFloppy = None,
+                     fNatForwardingForTxs = None,
+                     sHddControllerType = 'IDE Controller',
+                     fVmmDevTestingPart = None,
+                     fVmmDevTestingMmio = False,
+                     sFirmwareType = 'bios',
+                     sChipsetType = 'piix3',
+                     sDvdControllerType = 'IDE Controller',
+                     sCom1RawFile = None):
         """
         Creates a test VM with a immutable HD from the test resources.
@@ -2276,4 +2313,6 @@
             elif sChipsetType == 'ich9':
                 fRc = oSession.setChipsetType(vboxcon.ChipsetType_ICH9);
+            if fRc and sCom1RawFile:
+                fRc = oSession.setupSerialToRawFile(0, sCom1RawFile);
 
             if fRc: fRc = oSession.saveSettings();
Index: trunk/src/VBox/ValidationKit/testdriver/vboxtestvms.py
===================================================================
--- trunk/src/VBox/ValidationKit/testdriver/vboxtestvms.py	(revision 70710)
+++ trunk/src/VBox/ValidationKit/testdriver/vboxtestvms.py	(revision 70718)
@@ -35,4 +35,5 @@
 import random;
 import socket;
+import string;
 
 # Validation Kit imports.
@@ -40,4 +41,5 @@
 from testdriver import reporter;
 from testdriver import vboxcon;
+from common import utils;
 
 
@@ -53,4 +55,16 @@
     'hwvirt-np' : 'NestedPaging'
 };
+
+## @name VM grouping flags
+## @{
+g_kfGrpSmoke     = 0x0001;                          ##< Smoke test VM.
+g_kfGrpStandard  = 0x0002;                          ##< Standard test VM.
+g_kfGrpStdSmoke  = g_kfGrpSmoke | g_kfGrpStandard;  ##< shorthand.
+g_kfGrpWithGAs   = 0x0004;                          ##< The VM has guest additions installed.
+g_kfGrpNoTxs     = 0x0008;                          ##< The VM lacks test execution service.
+g_kfGrpAncient   = 0x1000;                          ##< Ancient OS.
+g_kfGrpExotic    = 0x2000;                          ##< Exotic OS.
+## @}
+
 
 ## @name Flags.
@@ -107,5 +121,6 @@
     [ 'Solaris_64',     'Solaris_64',            g_k64,    1, 256, ['sol10-64', 'sol10u-64[0-9]']],
     [ 'Solaris_64',     'Solaris11_64',          g_k64,    1, 256, ['sol11u1']],
-    [ 'BSD',            'FreeBSD_64',            g_k32_64, 1, 1, ['bs-.*']], # boot sectors, wanted 64-bit type.
+    [ 'BSD',            'FreeBSD_64',            g_k32_64, 1, 1,   ['bs-.*']], # boot sectors, wanted 64-bit type.
+    [ 'DOS',            'DOS',                   g_k32,    1, 1,   ['bs-.*']],
 ];
 
@@ -114,4 +129,5 @@
 ## @{
 g_ksGuestOsTypeDarwin  = 'darwin';
+g_ksGuestOsTypeDOS     = 'dos';
 g_ksGuestOsTypeFreeBSD = 'freebsd';
 g_ksGuestOsTypeLinux   = 'linux';
@@ -150,4 +166,5 @@
 g_kdaParavirtProvidersSupported = {
     g_ksGuestOsTypeDarwin  : ( g_ksParavirtProviderMinimal, ),
+    g_ksGuestOsTypeDOS     : ( g_ksParavirtProviderNone, ),
     g_ksGuestOsTypeFreeBSD : ( g_ksParavirtProviderNone, ),
     g_ksGuestOsTypeLinux   : ( g_ksParavirtProviderNone, g_ksParavirtProviderHyperV, g_ksParavirtProviderKVM),
@@ -222,8 +239,10 @@
         self.sFirmwareType           = sFirmwareType;
         self.sChipsetType            = sChipsetType;
+        self.fCom1RawFile            = False;
 
         self.fSnapshotRestoreCurrent = False;        # Whether to restore execution on the current snapshot.
         self.fSkip                   = False;        # All VMs are included in the configured set by default.
         self.aInfo                   = None;
+        self.sCom1RawFile            = None;         # Set by createVmInner and getReconfiguredVm if fCom1RawFile is set.
         self._guessStuff(fRandomPvPMode);
 
@@ -237,4 +256,6 @@
         if sType.lower().startswith('bsd'):
             return g_ksGuestOsTypeFreeBSD
+        if sType.lower().startswith('dos'):
+            return g_ksGuestOsTypeDOS
         if sType.lower().startswith('linux'):
             return g_ksGuestOsTypeLinux
@@ -288,4 +309,6 @@
             elif self.sKind.find("Solaris") >= 0:
                 self.sGuestOsType = g_ksGuestOsTypeSolaris;
+            elif self.sKind.find("DOS") >= 0:
+                self.sGuestOsType = g_ksGuestOsTypeDOS;
             else:
                 reporter.fatal('The OS of test VM "%s", sKind="%s" cannot be guessed' % (self.sVmName, self.sKind));
@@ -362,4 +385,10 @@
         return self.createVmInner(oTestDrv, eMyNic0AttachType, sMyDvdImage);
 
+    def _generateRawPortFilename(self, oTestDrv, sInfix, sSuffix):
+        """ Generates a raw port filename. """
+        random.seed();
+        sRandom = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(10));
+        return os.path.join(oTestDrv.sScratchPath, self.sVmName + sInfix + sRandom + sSuffix);
+
     def createVmInner(self, oTestDrv, eNic0AttachType, sDvdImage):
         """
@@ -370,4 +399,6 @@
         reporter.log2('');
         reporter.log2('Calling createTestVM on %s...' % (self.sVmName,))
+        if self.fCom1RawFile:
+            self.sCom1RawFile = self._generateRawPortFilename(oTestDrv, '-com1-', '.out');
         return oTestDrv.createTestVM(self.sVmName,
                                      1,                 # iGroup
@@ -384,5 +415,7 @@
                                      fVmmDevTestingMmio = self.fVmmDevTestingPart,
                                      sFirmwareType      = self.sFirmwareType,
-                                     sChipsetType       = self.sChipsetType);
+                                     sChipsetType       = self.sChipsetType,
+                                     sCom1RawFile       = self.sCom1RawFile if self.fCom1RawFile else None
+                                     );
 
     def getReconfiguredVm(self, oTestDrv, cCpus, sVirtMode, sParavirtMode = None):
@@ -438,4 +471,14 @@
                                     fRc = fRc and oSession.setOsType(oOsType.id + '_64');
 
+                        # New serial raw file.
+                        if fRc and self.fCom1RawFile:
+                            self.sCom1RawFile = self._generateRawPortFilename(oTestDrv, '-com1-', '.out');
+                            utils.noxcptDeleteFile(self.sCom1RawFile);
+                            fRc = oSession.setupSerialToRawFile(0, self.sCom1RawFile);
+
+                        # Make life simpler for child classes.
+                        if fRc:
+                            fRc = self._childVmReconfig(oTestDrv, oVM, oSession);
+
                         fRc = fRc and oSession.saveSettings();
                         if not oSession.close():
@@ -445,4 +488,8 @@
         return (fRc, None);
 
+    def _childVmReconfig(self, oTestDrv, oVM, oSession):
+        """ Hook into getReconfiguredVm() for children. """
+        _ = oTestDrv; _ = oVM; _ = oSession;
+        return True;
 
     def isWindows(self):
@@ -545,17 +592,60 @@
 
 
-
-#class AncientTestVm(object):
-#    """
-#    A ancient Test VM, using the serial port for communicating results.
-#
-#    We're looking for 'PASSED' and 'FAILED' lines in the COM1 output.
-#    """
-#
-#    def __init__(self, oSet, sVmName, fGrouping = , sHd = None, sKind = None, acCpusSup = None, asVirtModesSup = None, # pylint: disable=R0913
-#                 fIoApic = None, fPae = None, sNic0AttachType = None, sFloppy = None, sFirmwareType = 'bios',
-#                 sChipsetType = 'piix3', sHddControllerType = 'IDE Controller', sDvdControllerType = 'IDE Controller'):
-#        TestVm.__init__(self, oSet, sVmName,
-#
+class AncientTestVm(TestVm):
+    """
+    A ancient Test VM, using the serial port for communicating results.
+
+    We're looking for 'PASSED' and 'FAILED' lines in the COM1 output.
+    """
+
+
+    def __init__(self, # pylint: disable=R0913
+                 sVmName,                                   # type: str
+                 fGrouping = g_kfGrpAncient | g_kfGrpNoTxs, # type: int
+                 sHd = None,                                # type: str
+                 sKind = None,                              # type: str
+                 acCpusSup = None,                          # type: List[int]
+                 asVirtModesSup = None,                     # type: List[str]
+                 sNic0AttachType = None,                    # type: str
+                 sFloppy = None,                            # type: str
+                 sFirmwareType = 'bios',                    # type: str
+                 sChipsetType = 'piix3',                    # type: str
+                 sHddControllerName = 'IDE Controller',     # type: str
+                 sDvdControllerName = 'IDE Controller',     # type: str
+                 cMBRamMax = None,                          # type: int
+                 ):
+        TestVm.__init__(self,
+                        sVmName,
+                        fGrouping = fGrouping,
+                        sHd = sHd,
+                        sKind = sKind,
+                        acCpusSup = [1] if acCpusSup is None else acCpusSup,
+                        asVirtModesSup = asVirtModesSup,
+                        sNic0AttachType = sNic0AttachType,
+                        sFloppy = sFloppy,
+                        sFirmwareType = sFirmwareType,
+                        sChipsetType = sChipsetType,
+                        sHddControllerType = sHddControllerName,
+                        sDvdControllerType = sDvdControllerName,
+                        asParavirtModesSup = (g_ksParavirtProviderNone,)
+                        );
+        self.fCom1RawFile = True;
+        self.cMBRamMax= cMBRamMax;
+
+
+    def _childVmReconfig(self, oTestDrv, oVM, oSession):
+        _ = oVM; _ = oTestDrv;
+        fRc = True;
+
+        # DOS 4.01 doesn't like the default 32MB of memory.
+        if fRc and self.cMBRamMax is not None:
+            try:
+                cMBRam = oSession.o.machine.memorySize;
+            except:
+                cMBRam = self.cMBRamMax + 4;
+            if self.cMBRamMax < cMBRam:
+                fRc = oSession.setRamSize(self.cMBRamMax);
+
+        return fRc;
 
 
@@ -926,11 +1016,11 @@
     ## @name VM grouping flags
     ## @{
-    kfGrpSmoke     = 0x0001;               ##< Smoke test VM.
-    kfGrpStandard  = 0x0002;               ##< Standard test VM.
-    kfGrpStdSmoke  = kfGrpSmoke | kfGrpStandard;  ##< shorthand.
-    kfGrpWithGAs   = 0x0004;               ##< The VM has guest additions installed.
-    kfGrpNoTxs     = 0x0008;               ##< The VM lacks test execution service.
-    kfGrpAncient   = 0x1000;               ##< Ancient OS.
-    kfGrpExotic    = 0x2000;               ##< Exotic OS.
+    kfGrpSmoke     = g_kfGrpSmoke;
+    kfGrpStandard  = g_kfGrpStandard;
+    kfGrpStdSmoke  = g_kfGrpStdSmoke;
+    kfGrpWithGAs   = g_kfGrpWithGAs;
+    kfGrpNoTxs     = g_kfGrpNoTxs;
+    kfGrpAncient   = g_kfGrpAncient;
+    kfGrpExotic    = g_kfGrpExotic;
     ## @}
 
@@ -962,5 +1052,5 @@
                sKind = 'WindowsNT3x', acCpusSup = [1], sHddControllerType = 'BusLogic SCSI Controller',
                sDvdControllerType = 'BusLogic SCSI Controller'),
-        TestVm('tst-nt351',                 kfGrpAncient,               sHd = '5.2/great-old-ones/t-nt350/t-nt350.vdi',
+        TestVm('tst-nt351',                 kfGrpAncient,               sHd = '5.2/great-old-ones/t-nt350/t-nt351.vdi',
                sKind = 'WindowsNT3x', acCpusSup = [1], sHddControllerType = 'BusLogic SCSI Controller',
                sDvdControllerType = 'BusLogic SCSI Controller'),
@@ -1016,5 +1106,11 @@
 
         # DOS and Old Windows.
-        # todo ...
+        AncientTestVm('tst-dos20',              sKind = 'DOS',  sHd = '5.2/great-old-ones/t-dos20/t-dos20.vdi'),
+        AncientTestVm('tst-dos71',              sKind = 'DOS',  sHd = '5.2/great-old-ones/t-dos71/t-dos71.vdi'),
+        AncientTestVm('tst-dos401-win30me',     sKind = 'DOS',  sHd = '5.2/great-old-ones/t-dos401-win30me/t-dos401-win30me.vdi',
+                      cMBRamMax = 4),
+        AncientTestVm('tst-dos5-win311a',       sKind = 'DOS',  sHd = '5.2/great-old-ones/t-dos5-win311a/t-dos5-win311a.vdi'),
+        AncientTestVm('tst-dos622',             sKind = 'DOS',  sHd = '5.2/great-old-ones/t-dos622/t-dos622.vdi'),
+        AncientTestVm('tst-dos622-emm386',      sKind = 'DOS',  sHd = '5.2/great-old-ones/t-dos622-emm386/t-dos622-emm386.vdi'),
     );
 
Index: trunk/src/VBox/ValidationKit/testdriver/vboxwrappers.py
===================================================================
--- trunk/src/VBox/ValidationKit/testdriver/vboxwrappers.py	(revision 70710)
+++ trunk/src/VBox/ValidationKit/testdriver/vboxwrappers.py	(revision 70718)
@@ -2365,4 +2365,37 @@
 
 
+    def setupSerialToRawFile(self, iSerialPort, sRawFile):
+        """
+        Enables the given serial port (zero based) and redirects it to sRawFile.
+        Returns the True on success, False on failure (logged).
+        """
+        try:
+            oPort = self.o.machine.GetSerialPort(iSerialPort);
+        except:
+            fRc = reporter.errorXcpt('failed to get serial port #%u' % (iSerialPort,));
+        else:
+            try:
+                oPort.path = sRawFile;
+            except:
+                fRc = reporter.errorXcpt('failed to set the "path" property on serial port #%u to "%s"'
+                                          % (iSerialPort, sRawFile));
+            else:
+                try:
+                    oPort.hostMode = vboxcon.PortMode_RawFile;
+                except:
+                    fRc = reporter.errorXcpt('failed to set the "hostMode" property on serial port #%u to PortMode_RawFile'
+                                             % (iSerialPort,));
+                else:
+                    try:
+                        oPort.enabled = True;
+                    except:
+                        fRc = reporter.errorXcpt('failed to set the "enable" property on serial port #%u to True'
+                                                 % (iSerialPort,));
+                    else:
+                        reporter.log('set SerialPort[%s].enabled/hostMode/path=True/RawFile/%s' % (iSerialPort, sRawFile,));
+                        fRc = True;
+        self.oTstDrv.processPendingEvents();
+        return fRc;
+
 
     #
