Index: include/iprt/file.h
===================================================================
--- include/iprt/file.h	(revision 121)
+++ include/iprt/file.h	(working copy)
@@ -47,6 +47,27 @@
 # define RTFILE_LINEFEED    "\n"
 #endif
 
+#ifdef RT_OS_OS2
+/* internal file handle structure     */
+#pragma pack (1)
+struct RTFILEINT
+{
+    uint32_t hFile;   /* native file handle            */
+    uint8_t type;     /* file handle type (see below)  */
+    uint8_t rawfs;    /* use RAW FS (UNC pathnames)    */
+    uint64_t off;     /* seek offset                   */
+};
+#pragma pack ()
+/* normal file handle */
+# define FILE_TYPE_NORMAL 0
+/* volume open with flag OPEN_FLAGS_DASD   */
+# define FILE_TYPE_DASD   1
+/* cdrom file handle, cdrom ioctl          */
+# define FILE_TYPE_CD     2
+/* phys disk open using phys disk ioctl    */
+# define FILE_TYPE_RAW    3
+#endif
+
 /** Platform specific native standard input "handle". */
 #ifdef RT_OS_WINDOWS
 # define RTFILE_NATIVE_STDIN ((uint32_t)-10)
Index: src/VBox/Runtime/r3/posix/fileio-posix.cpp
===================================================================
--- src/VBox/Runtime/r3/posix/fileio-posix.cpp	(revision 121)
+++ src/VBox/Runtime/r3/posix/fileio-posix.cpp	(working copy)
@@ -45,8 +45,23 @@
 #ifdef RT_OS_LINUX
 # include <sys/file.h>
 #endif
-#if defined(RT_OS_OS2) && (!defined(__INNOTEK_LIBC__) || __INNOTEK_LIBC__ < 0x006)
-# include <io.h>
+
+#if defined(RT_OS_OS2)
+# define  OS2EMX_PLAIN_CHAR
+# define  INCL_BASE
+# define  INCL_DOSDEVIOCTL
+# include <os2.h>
+# include <stdio.h>
+# define  IOCTL_CDROMDISK2         0x82
+# define  CDROMDISK_READDATA       0x76
+# define  CDROMDISK_WRITEDATA      0x56
+# define  CDROMDISK2_FEATURES      0x63
+# define  CDROMDISK2_DRIVELETTERS  0x60
+# define  FEATURE_EXECMD_SUPPORT   0x00000004L
+# include <ctype.h> // for tolower
+# if (!defined(__INNOTEK_LIBC__) || __INNOTEK_LIBC__ < 0x006)
+#  include <io.h>
+# endif
 #endif
 #if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
 # include <sys/disk.h>
@@ -61,6 +76,7 @@
 #include <iprt/path.h>
 #include <iprt/assert.h>
 #include <iprt/string.h>
+#include <iprt/mem.h>
 #include <iprt/err.h>
 #include <iprt/log.h>
 #include "internal/file.h"
@@ -98,7 +114,808 @@
     return fRc;
 }
 
+#ifdef RT_OS_OS2
+// check if the driveletter is cdrom one
+static bool rtOs2IsCdRom(const char *pszFilename)
+{
+    typedef struct _CDROMDeviceMap
+    {
+        USHORT usDriveCount;
+        USHORT usFirstLetter;
+    } CDROMDeviceMap;
 
+    HFILE hf;
+    ULONG ulAction = 0;
+    CDROMDeviceMap CDMap;
+    ULONG ulParamSize = sizeof(ulAction);
+    ULONG ulDataSize = sizeof(CDROMDeviceMap);
+    char driveName[3] = { '?', ':', '\0' };
+
+    if (DosOpen("\\DEV\\CD-ROM2$", &hf, &ulAction, 0, FILE_NORMAL,
+                OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
+                OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, NULL))
+        return false;
+
+    DosDevIOCtl(hf, IOCTL_CDROMDISK2, CDROMDISK2_DRIVELETTERS,
+                NULL, 0, &ulParamSize,
+                (PVOID)&CDMap, sizeof(CDROMDeviceMap), &ulDataSize);
+    DosClose(hf);
+
+    for (int drv = CDMap.usFirstLetter; drv < CDMap.usFirstLetter + CDMap.usDriveCount; drv++)
+    {
+        driveName[0] = 'A' + drv;
+        if (!stricmp(driveName, pszFilename))
+            return true;
+    }
+
+    return false;
+}
+
+static int rtOs2ExtraFileOpen(PRTFILE pFile, const char *pszFilename, uint64_t fOpen, int fOpenMode, int fMode)
+{
+    int    fh;
+    APIRET rc;
+    ULONG  dummy;
+
+    errno = 0;
+    (*pFile)->rawfs = 0;
+
+    // in case someone appended the default
+    // path to a drive letter, truncate path
+    // (otherwise we'll get n:\dir\w: or n:/dir/w:)
+    // and it will trap trying to open it
+    int len = strlen(pszFilename);
+
+    // access via the raw filesystem
+    if ( !strncmp(pszFilename, "\\\\.\\", 4) )
+        //(*pFile)->type = FILE_TYPE_RAWFS;
+        (*pFile)->rawfs = 1;
+    // handle d:\path\to\w: or d:\path\to/w: case (truncate path)
+    else if (len >= 3 &&
+        pszFilename[len - 1] == ':' &&
+        (pszFilename[len - 3] == '\\' || pszFilename[len - 3] == '/'))
+        pszFilename += len - 2;
+
+     // a special case of opening the drive letter
+     // in OPEN_FLAGS_DASD mode (logical disk or CDROM or floppy)
+     // otherwise, opening "w:" causes VERR_IS_A_DIRECTORY error    if ( (tolower(pszFilename[0]) <= 'z' &&
+    if ( (*pFile)->rawfs || 
+         (tolower(pszFilename[0]) >= 'a' &&
+         tolower(pszFilename[0]) <= 'z' &&
+         pszFilename[1] == ':' &&
+         pszFilename[2] == '\0') )
+    {
+        // logical disk
+        ULONG  ulAction;
+        ULONG  sig;
+        ULONG  parmlen = sizeof(sig);
+        ULONG  datalen = sizeof(sig);
+        //HFILE  hDisk = NULLHANDLE;
+        ULONG  fsOpenMode = OPEN_SHARE_DENYNONE | OPEN_FLAGS_NOINHERIT | OPEN_FLAGS_FAIL_ON_ERROR;
+
+        if (! (*pFile)->rawfs)
+            fsOpenMode |= OPEN_FLAGS_DASD;
+
+        switch (fOpen & RTFILE_O_ACCESS_MASK)
+        {
+            case RTFILE_O_READ:
+                fsOpenMode |= OPEN_ACCESS_READONLY;
+                break;
+            case RTFILE_O_WRITE:
+                fsOpenMode |= OPEN_ACCESS_WRITEONLY;
+                break;
+            case RTFILE_O_READWRITE:
+                fsOpenMode |= OPEN_ACCESS_READWRITE;
+                break;
+            default:
+                AssertMsgFailed(("RTFileOpen received an invalid RW value, fOpen=%#llx\n", fOpen));
+                return VERR_INVALID_PARAMETER;
+        }
+
+        rc = DosOpenL(pszFilename, (PHFILE)&fh,
+                      &ulAction, 0, FILE_NORMAL,
+                      OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
+                      fsOpenMode, NULL);
+
+        if (rc == 0)
+        {
+            if (! fh)
+                return VERR_MEDIA_NOT_PRESENT;
+
+            if (rtOs2IsCdRom(pszFilename))
+            {
+                // identify CDROM driver
+                sig = ('C') | ('D' << 8) | ('9' << 16) | ('9' << 24);
+
+                if ( (rc = DosDevIOCtl(fh, IOCTL_CDROMDISK, CDROMDISK_GETDRIVER,
+                                       &sig, sizeof(sig), NULL,
+                                       &sig, sizeof(sig), NULL)) ||
+                      sig != (('C') | ('D' << 8) | ('0' << 16) | ('1' << 24)) )
+                    return VERR_MEDIA_NOT_PRESENT;
+
+                RTFileFromNative(pFile, fh);
+                (*pFile)->type = FILE_TYPE_CD;
+
+                // lock drive
+                if ( (rc = DosDevIOCtl(fh, IOCTL_DISK, DSK_LOCKDRIVE,
+                                       &dummy, sizeof(dummy), NULL,
+                                       &dummy, sizeof(dummy), NULL)) )
+                    return RTErrConvertFromOS2(rc);
+
+                return VINF_SUCCESS;
+            }
+
+            RTFileFromNative(pFile, fh);
+
+            if (! strncmp(pszFilename, "\\\\.\\Physical_Disk", 17))
+            {
+                (*pFile)->type = FILE_TYPE_RAW;
+
+                // lock drive
+                if ( (rc = DosDevIOCtl(fh, IOCTL_PHYSICALDISK, PDSK_LOCKPHYSDRIVE,
+                                       &dummy, sizeof(dummy), NULL,
+                                       &dummy, sizeof(dummy), NULL)) )
+                    return RTErrConvertFromOS2(rc);
+            }
+            else
+            {
+                (*pFile)->type = FILE_TYPE_DASD;
+
+                // lock drive
+                if ( (rc = DosDevIOCtl(fh, IOCTL_DISK, DSK_LOCKDRIVE,
+                                       &dummy, sizeof(dummy), NULL,
+                                       &dummy, sizeof(dummy), NULL)) )
+                    return RTErrConvertFromOS2(rc);
+            }
+
+            return VINF_SUCCESS;
+        }
+
+        return RTErrConvertFromOS2(rc);
+    }
+    else if (pszFilename[0] <= '9' &&
+             pszFilename[0] >= '0' &&
+             pszFilename[1] == ':' &&
+             pszFilename[2] == '\0')
+    {
+        // physical disk number
+        rc = DosPhysicalDisk(INFO_GETIOCTLHANDLE,
+                             (PHFILE)&fh,
+                             2L,
+                             (PSZ)pszFilename,
+                             strlen((PSZ)pszFilename) + 1);
+
+        if (! rc)
+        {
+            if (! fh)
+                return VERR_MEDIA_NOT_PRESENT;
+
+            RTFileFromNative(pFile, fh);
+            (*pFile)->type = FILE_TYPE_RAW;
+
+            // lock drive
+            if ( (rc = DosDevIOCtl(fh, IOCTL_PHYSICALDISK, PDSK_LOCKPHYSDRIVE,
+                                   &dummy, sizeof(dummy), NULL,
+                                   &dummy, sizeof(dummy), NULL)) )
+                return RTErrConvertFromOS2(rc);
+
+            return VINF_SUCCESS;
+        }
+
+        return RTErrConvertFromOS2(rc);
+    }
+    else
+    {
+        fh = open(pszFilename, fOpenMode, fMode);
+        RTFileFromNative(pFile, fh);
+        return -1;
+    }
+
+    return VINF_SUCCESS;
+}
+
+static int rtOs2ExtraFileSeek(RTFILE hFile, int64_t offSeek, unsigned uMethod, off_t *poffActual)
+{
+    static const unsigned aSeekRecode[] =
+    {
+        SEEK_SET,
+        SEEK_CUR,
+        SEEK_END,
+    };
+
+    #pragma pack(1)
+
+    /* parameter packet */
+    struct {
+        UCHAR command;
+        UCHAR drive;
+    } parm;
+
+    struct {
+        UCHAR command;
+    } parmphys;
+
+    #pragma pack()
+
+    /* data packet      */
+    BIOSPARAMETERBLOCK bpb;
+    DEVICEPARAMETERBLOCK dpb;
+    ULONG parm2 = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24);
+    ULONG parmlen2 = sizeof(parm2);
+    ULONG data2 = 0;
+    ULONG datalen2 = sizeof(data2);
+    int rc = NO_ERROR;
+
+    LONGLONG cb;
+    ULONG cbSectors;
+    ULONG parmlen;
+    ULONG datalen;
+
+    if (hFile->type == FILE_TYPE_NORMAL)
+    {
+        rc = lseek(RTFileToNative(hFile), (off_t)offSeek, aSeekRecode[uMethod]);
+
+        if (rc < 0)
+            rc = RTErrConvertFromErrno(errno);
+        else
+        {
+            hFile->off = rc;
+            rc = 0;
+        }
+    }
+    else
+    {
+        switch (uMethod)
+        {
+            case RTFILE_SEEK_BEGIN:
+                hFile->off = offSeek;
+                break;
+
+            case RTFILE_SEEK_CURRENT:
+                hFile->off += offSeek;
+                break;
+
+            case RTFILE_SEEK_END:
+                switch (hFile->type)
+                {
+                    case FILE_TYPE_CD:
+                        if ( (rc = DosDevIOCtl(RTFileToNative(hFile),
+                                               IOCTL_CDROMDISK, CDROMDISK_DEVICESTATUS,
+                                               &parm2, parmlen2, &parmlen2,
+                                               &data2, datalen2, &datalen2)) )
+                            break;
+
+                        if (data2 & (1 << 11))
+                        {
+                            // disk does not present
+                            rc = ERROR_UNCERTAIN_MEDIA;
+                            break;
+                        }
+
+                        parm2 = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24);
+
+                        if ( (rc = DosDevIOCtl(RTFileToNative(hFile),
+                                               IOCTL_CDROMDISK, CDROMDISK_GETVOLUMESIZE,
+                                               &parm2, parmlen2, &parmlen2,
+                                               &data2, datalen2, &datalen2)) )
+                            break;
+
+                        // return disk size in bytes
+                        hFile->off = data2 << 11; // multiply by sector size (2048)
+                        rc = NO_ERROR;
+                        break;
+
+                    case FILE_TYPE_DASD:
+                        parmlen = sizeof(parm);
+                        datalen = sizeof(bpb);
+
+                        memset(&bpb, 0, sizeof(bpb));
+
+                        parm.command = 1; // Return the BPB for the media currently in the drive
+                        parm.drive = 0;   // unused
+
+                        if ( (rc = DosDevIOCtl(RTFileToNative(hFile), IOCTL_DISK, DSK_GETDEVICEPARAMS,
+                                               &parm, parmlen, &parmlen,
+                                               &bpb, datalen, &datalen)) )
+                            break;
+
+                        hFile->off = bpb.cCylinders
+                                   * bpb.cHeads
+                                   * bpb.usSectorsPerTrack;
+                        hFile->off <<= 9; // multiply by sector size (512)
+                        break;
+
+                    case FILE_TYPE_RAW:
+                        parmlen = sizeof(parmphys);
+                        datalen = sizeof(dpb);
+
+                        memset(&dpb, 0, sizeof(dpb));
+
+                        parmphys.command = 1;
+
+                        if ( (rc = DosDevIOCtl(RTFileToNative(hFile), IOCTL_PHYSICALDISK, PDSK_GETPHYSDEVICEPARAMS,
+                                               &parmphys, parmlen, &parmlen,
+                                               &dpb, datalen, &datalen)) )
+                            break;
+
+                        hFile->off = dpb.cCylinders
+                                   * dpb.cHeads
+                                   * dpb.cSectorsPerTrack;
+                        hFile->off <<= 9; // multiply by sector size (512)
+                        break;
+
+                    default:
+                        AssertMsgFailed(("Incorrect handle type!\n"));
+                }
+                hFile->off -= offSeek;
+                break;
+
+            default:
+                AssertMsgFailed(("Incorrect seek type!\n"));
+        }
+    }
+    *poffActual = hFile->off;
+    rc = RTErrConvertFromOS2(rc);
+    return rc;
+}
+
+static int rtOs2ExtraFileRead(RTFILE hFile, void *pvBuf, size_t cbToRead, ssize_t *pcbRead)
+{
+    #pragma pack(1)
+
+    // parameter packet
+    struct ReadData_param {
+        ULONG       ID_code;                // 'CD01'
+        UCHAR       address_mode;           // Addressing format of start_sector:
+                                            //  00 - Logical Block format
+                                            //  01 - Minutes/Seconds/Frame format
+        USHORT      transfer_count;         // Numbers of sectors to read.
+                                            //  Must  be non zero
+        ULONG       start_sector;           // Starting sector number of the read operation
+        UCHAR       reserved;               // Reserved. Must be 0
+        UCHAR       interleave_size;        // Not used. Must be 0
+        UCHAR       interleave_skip_factor; // Not used. Must be 0
+    } parm;
+    ULONG parmlen = sizeof(parm);
+
+    #define SECTORSIZE      2048
+
+    struct ReadData_data {
+        UCHAR        data_area[SECTORSIZE];
+    } data;
+
+    ULONG datalen = sizeof(data);
+    uint32_t cbRead32;
+
+    /* parameter packet */
+    struct PARM {
+        unsigned char command;
+        unsigned char drive;
+    } parm2;
+
+    #pragma pack()
+
+    /* data packet      */
+    BIOSPARAMETERBLOCK bpb;
+    ULONG parmlen2 = sizeof(parm2);
+    ULONG datalen2 = sizeof(bpb);
+    int32_t rc = 0;
+
+    parm2.command = 1;
+    parm2.drive = 0;
+
+    struct {
+        unsigned char command;
+    } parmphys;
+    DEVICEPARAMETERBLOCK dpb;
+    ULONG parmphyslen = sizeof(parmphys);
+    ULONG dataphyslen = sizeof(dpb);
+
+    parmphys.command = 0;
+
+    if (hFile->type == FILE_TYPE_DASD || hFile->type == FILE_TYPE_CD)
+    {
+        if ( (rc = DosDevIOCtl(RTFileToNative(hFile), IOCTL_DISK, DSK_GETDEVICEPARAMS,
+                               &parm2, parmlen2, &parmlen2, &bpb, datalen2, &datalen2)) )
+            return RTErrConvertFromOS2(rc);
+    }
+    else if (hFile->type == FILE_TYPE_RAW)
+    {
+        if ( (rc = DosDevIOCtl(RTFileToNative(hFile), IOCTL_PHYSICALDISK, PDSK_GETPHYSDEVICEPARAMS,
+                               &parmphys, parmphyslen, &parmphyslen, &dpb, dataphyslen, &dataphyslen)) )
+            return RTErrConvertFromOS2(rc);
+    }
+
+    #define BUFSIZE 0x4000
+    #define SECSIZE 512
+    ULONG parmlen4 = sizeof(TRACKLAYOUT) + sizeof(USHORT) * 2 * (bpb.usSectorsPerTrack - 1);
+    char trkbuf[sizeof(TRACKLAYOUT) + sizeof(USHORT) * 2 * 255];
+    PTRACKLAYOUT ptrk = (PTRACKLAYOUT)trkbuf;
+    ULONG datalen4 = BUFSIZE;
+    USHORT cyl, head, sec, n;
+    ssize_t cbRead = 0;
+
+    if (hFile->rawfs)
+    {
+        rc = DosRead(RTFileToNative(hFile), pvBuf, cbToRead, (PULONG)&cbRead);
+        rc = RTErrConvertFromOS2(rc);
+    }
+    else
+    {
+        switch (hFile->type)
+        {
+            case FILE_TYPE_NORMAL:
+                cbRead = read(RTFileToNative(hFile), pvBuf, cbToRead);
+
+                if (cbRead < 0)
+                    rc = RTErrConvertFromErrno(errno);
+                else
+                    rc = VINF_SUCCESS;
+                break;
+
+            case FILE_TYPE_CD:
+                AssertReturn(!(hFile->off % SECTORSIZE), VERR_INVALID_PARAMETER);
+                cbRead32 = (cbToRead > SECTORSIZE) ? SECTORSIZE : (uint32_t)cbToRead;
+                AssertReturn(!(cbToRead % SECTORSIZE), VERR_INVALID_PARAMETER);
+
+                memset(&parm, 0, sizeof(parm));
+                parm.ID_code = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24);
+                parm.address_mode = 0; // lba
+
+                do
+                {
+                    parm.transfer_count = 1;
+                    parm.start_sector = (ULONG)(hFile->off / SECTORSIZE);
+
+                    rc = DosDevIOCtl(RTFileToNative(hFile), IOCTL_CDROMDISK, CDROMDISK_READDATA,
+                                     &parm, parmlen, &parmlen, &data, datalen, &datalen);
+
+                    rc = RTErrConvertFromOS2(rc);
+
+                    if (RT_SUCCESS(rc))
+                        memcpy((char *)pvBuf, &data, cbRead32);
+                    else
+                        break;
+
+                    hFile->off    += cbRead32;
+                    cbRead        += cbRead32;
+                    cbToRead      -= cbRead32;
+                    pvBuf         = (uint8_t *)pvBuf + cbRead32;
+
+                } while ((cbToRead > 0) && RT_SUCCESS(rc));
+                break;
+
+            case FILE_TYPE_DASD:
+                cbRead32 = (cbToRead > BUFSIZE) ? BUFSIZE : (uint32_t)cbToRead;
+
+                memset((char *)trkbuf, 0, sizeof(trkbuf));
+
+                for (int i = 0; i < bpb.usSectorsPerTrack; i++)
+                {
+                    ptrk->TrackTable[i].usSectorNumber = i + 1;
+                    ptrk->TrackTable[i].usSectorSize = SECSIZE;
+                }
+
+                do
+                {
+                    cyl = hFile->off / (SECSIZE * bpb.cHeads * bpb.usSectorsPerTrack);
+                    head = (hFile->off / SECSIZE - bpb.cHeads * bpb.usSectorsPerTrack * cyl) / bpb.usSectorsPerTrack;
+                    sec = hFile->off / SECSIZE - bpb.cHeads * bpb.usSectorsPerTrack * cyl - head * bpb.usSectorsPerTrack;
+
+                    if (sec + cbRead32 / SECSIZE > bpb.usSectorsPerTrack)
+                        n = bpb.usSectorsPerTrack - sec + 1;
+                    else
+                        n = cbRead32 / SECSIZE;
+
+                    ptrk->bCommand = 1;
+                    ptrk->usHead = head;
+                    ptrk->usCylinder = cyl;
+                    ptrk->usFirstSector = sec;
+                    ptrk->cSectors = n;
+
+                    rc = DosDevIOCtl(RTFileToNative(hFile), IOCTL_DISK, DSK_READTRACK,
+                                     trkbuf, parmlen4, &parmlen4, pvBuf, datalen4, &datalen4);
+
+                    rc = RTErrConvertFromOS2(rc);
+
+                    if (RT_FAILURE(rc))
+                        break;
+
+                    hFile->off    += cbRead32;
+                    cbToRead      -= cbRead32;
+                    cbRead        += cbRead32;
+                    pvBuf         = (uint8_t *)pvBuf + cbRead32;
+
+                } while ((cbToRead > 0) && RT_SUCCESS(rc));
+                break;
+
+            case FILE_TYPE_RAW:
+                cbRead32 = (cbToRead > BUFSIZE) ? BUFSIZE : (uint32_t)cbToRead;
+
+                memset((char *)trkbuf, 0, sizeof(trkbuf));
+
+                for (int i = 0; i < dpb.cSectorsPerTrack; i++)
+                {
+                    ptrk->TrackTable[i].usSectorNumber = i + 1;
+                    ptrk->TrackTable[i].usSectorSize = SECSIZE;
+                }
+
+                do
+                {
+                    cyl = hFile->off / (SECSIZE * dpb.cHeads * dpb.cSectorsPerTrack);
+                    head = (hFile->off / SECSIZE - dpb.cHeads * dpb.cSectorsPerTrack * cyl) / dpb.cSectorsPerTrack;
+                    sec = hFile->off / SECSIZE - dpb.cHeads * dpb.cSectorsPerTrack * cyl - head * dpb.cSectorsPerTrack;
+
+                    if (sec + cbRead32 / SECSIZE > dpb.cSectorsPerTrack)
+                        n = dpb.cSectorsPerTrack - sec + 1;
+                    else
+                        n = cbRead32 / SECSIZE;
+
+                    ptrk->bCommand = 1;
+                    ptrk->usHead = head;
+                    ptrk->usCylinder = cyl;
+                    ptrk->usFirstSector = sec;
+                    ptrk->cSectors = n;
+
+                    rc = DosDevIOCtl(RTFileToNative(hFile), IOCTL_PHYSICALDISK, PDSK_READPHYSTRACK,
+                                     trkbuf, parmlen4, &parmlen4, (void *)pvBuf, datalen4, &datalen4);
+
+                    rc = RTErrConvertFromOS2(rc);
+
+                    if (RT_FAILURE(rc))
+                        break;
+
+                    hFile->off += cbRead32;
+                    cbRead     += cbRead32;
+                    cbToRead   -= cbRead32;
+                    pvBuf      =  (uint8_t *)pvBuf + cbRead32;
+
+                } while ((cbToRead > 0) && RT_SUCCESS(rc));
+                break;
+
+            default:
+                rc = VERR_NOT_SUPPORTED;
+        }
+    }
+    *pcbRead = cbRead;
+    return rc;
+}
+
+static int rtOs2ExtraFileWrite(RTFILE hFile, const void *pvBuf, size_t cbToWrite, ssize_t *pcbWritten)
+{
+    #pragma pack(1)
+
+    // parameter packet
+    struct WriteData_param {
+        ULONG       ID_code;                // 'CD01'
+        UCHAR       address_mode;           // Addressing format of start_sector:
+                                            //  00 - Logical Block format
+                                            //  01 - Minutes/Seconds/Frame format
+        USHORT      transfer_count;         // Numbers of sectors to read.
+                                            //  Must  be non zero
+        ULONG       start_sector;           // Starting sector number of the read operation
+        UCHAR       reserved;               // Reserved. Must be 0
+        UCHAR       interleave_size;        // Not used. Must be 0
+        UCHAR       interleave_skip_factor; // Not used. Must be 0
+    } parm;
+    ULONG parmlen = sizeof(parm);
+
+    #define SECTORSIZE      2048
+
+    // data packet
+    struct WriteData_data {
+        UCHAR       sector_data[2048]; // Sector to be written to the disk
+    } data;
+
+    ULONG datalen, data_offset;
+    uint32_t cbWrite32;
+
+    datalen = sizeof(data);
+
+    /* parameter packet */
+    struct {
+        unsigned char command;
+        unsigned char drive;
+    } parm2;
+
+    #pragma pack()
+
+    /* data packet      */
+    BIOSPARAMETERBLOCK bpb;
+    ULONG parmlen2 = sizeof(parm2);
+    ULONG datalen2 = sizeof(bpb);
+    int32_t rc = 0;
+
+    parm2.command = 1;
+    parm2.drive = 0;
+
+    struct {
+        unsigned char command;
+    } parmphys;
+    DEVICEPARAMETERBLOCK dpb;
+    ULONG parmphyslen = sizeof(parmphys);
+    ULONG dataphyslen = sizeof(dpb);
+
+    parmphys.command = 0;
+
+    if (hFile->type == FILE_TYPE_DASD || hFile->type == FILE_TYPE_CD)
+    {
+        if ( (rc = DosDevIOCtl(RTFileToNative(hFile), IOCTL_DISK, DSK_GETDEVICEPARAMS,
+                               &parm2, parmlen2, &parmlen2, &bpb, datalen2, &datalen2)) )
+            return RTErrConvertFromOS2(rc);
+    }
+    else if (hFile->type == FILE_TYPE_RAW)
+    {
+        if ( (rc = DosDevIOCtl(RTFileToNative(hFile), IOCTL_PHYSICALDISK, PDSK_GETPHYSDEVICEPARAMS,
+                               &parmphys, parmphyslen, &parmphyslen, &dpb, dataphyslen, &dataphyslen)) )
+            return RTErrConvertFromOS2(rc);
+    }
+
+    #define BUFSIZE 0x4000
+    #define SECSIZE 512
+
+    ULONG parmlen4;
+
+    if (hFile->type == FILE_TYPE_DASD || hFile->type == FILE_TYPE_CD)
+        parmlen4 = sizeof(TRACKLAYOUT) + sizeof(USHORT) * 2 * (bpb.usSectorsPerTrack - 1);
+    else if (hFile->type == FILE_TYPE_RAW)
+        parmlen4 = sizeof(TRACKLAYOUT) + sizeof(USHORT) * 2 * (dpb.cSectorsPerTrack - 1);
+
+    char trkbuf[sizeof(TRACKLAYOUT) + sizeof(USHORT) * 2 * 255];
+    PTRACKLAYOUT ptrk = (PTRACKLAYOUT)trkbuf;
+    ULONG datalen4 = BUFSIZE;
+    USHORT cyl, head, sec, n;
+    ssize_t cbWritten = 0;
+
+    if (hFile->rawfs)
+    {
+        rc = DosWrite(RTFileToNative(hFile), pvBuf, cbToWrite, (PULONG)&cbWritten);
+        rc = RTErrConvertFromOS2(rc);
+    }
+    else
+    {
+        switch (hFile->type)
+        {
+            case FILE_TYPE_NORMAL:
+                cbWritten = write(RTFileToNative(hFile), pvBuf, cbToWrite);
+
+                if (cbWritten < 0)
+                    rc = RTErrConvertFromErrno(errno);
+                else
+                    rc = VINF_SUCCESS;
+                break;
+
+            case FILE_TYPE_CD:
+                AssertReturn(!(hFile->off % SECTORSIZE), VERR_INVALID_PARAMETER);
+                cbWrite32 = (cbToWrite > SECTORSIZE) ? SECTORSIZE : (uint32_t)cbToWrite;
+                AssertReturn(!(cbToWrite % SECTORSIZE), VERR_INVALID_PARAMETER);
+
+                memset(&parm, 0, sizeof(parm));
+                memset(&data, 0, sizeof(data));
+
+                parm.ID_code = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24);
+                parm.address_mode = 0; // lba
+
+                do
+                {
+                    parm.transfer_count = 1;
+                    parm.start_sector = (ULONG)(hFile->off / SECTORSIZE);
+
+                    memcpy(&data, (char *)pvBuf, cbWrite32);
+
+                    rc = DosDevIOCtl(RTFileToNative(hFile), IOCTL_CDROMDISK, CDROMDISK_WRITEDATA,
+                                     &parm, parmlen, &parmlen, &data, datalen, &datalen);
+
+                    rc = RTErrConvertFromOS2(rc);
+
+                    if (RT_FAILURE(rc))
+                        break;
+
+                    hFile->off += cbWrite32;
+                    cbWritten  += cbWrite32;
+                    cbToWrite  -= cbWrite32;
+                    pvBuf      =  (uint8_t *)pvBuf + cbWrite32;
+
+                } while ((cbToWrite > 0) && RT_SUCCESS(rc));
+                break;
+
+            case FILE_TYPE_DASD:
+                cbWrite32 = (cbToWrite > BUFSIZE) ? BUFSIZE : (uint32_t)cbToWrite;
+
+                memset((char *)trkbuf, 0, sizeof(trkbuf));
+
+                for (int i = 0; i < bpb.usSectorsPerTrack; i++)
+                {
+                    ptrk->TrackTable[i].usSectorNumber = i + 1;
+                    ptrk->TrackTable[i].usSectorSize = SECSIZE;
+                }
+
+                do
+                {
+                    cyl = hFile->off / (SECSIZE * bpb.cHeads * bpb.usSectorsPerTrack);
+                    head = (hFile->off / SECSIZE - bpb.cHeads * bpb.usSectorsPerTrack * cyl) / bpb.usSectorsPerTrack;
+                    sec = hFile->off / SECSIZE - bpb.cHeads * bpb.usSectorsPerTrack * cyl - head * bpb.usSectorsPerTrack;
+
+                    if (sec + cbWrite32 / SECSIZE > bpb.usSectorsPerTrack)
+                        n = bpb.usSectorsPerTrack - sec + 1;
+                    else
+                        n = cbWrite32 / SECSIZE;
+
+                    ptrk->bCommand = 1;
+                    ptrk->usHead = head;
+                    ptrk->usCylinder = cyl;
+                    ptrk->usFirstSector = sec;
+                    ptrk->cSectors = n;
+
+                    rc = DosDevIOCtl(RTFileToNative(hFile), IOCTL_DISK, DSK_WRITETRACK,
+                                     trkbuf, parmlen4, &parmlen4, (void *)pvBuf, datalen4, &datalen4);
+
+                    rc = RTErrConvertFromOS2(rc);
+
+                    if (RT_FAILURE(rc))
+                        break;
+
+                    hFile->off += cbWrite32;
+                    cbWritten  += cbWrite32;
+                    cbToWrite  -= cbWrite32;
+                    pvBuf      =  (uint8_t *)pvBuf + cbWrite32;
+
+                } while ((cbToWrite > 0) && RT_SUCCESS(rc));
+                break;
+
+            case FILE_TYPE_RAW:
+                cbWrite32 = (cbToWrite > BUFSIZE) ? BUFSIZE : (uint32_t)cbToWrite;
+
+                memset((char *)trkbuf, 0, sizeof(trkbuf));
+
+                for (int i = 0; i < dpb.cSectorsPerTrack; i++)
+                {
+                    ptrk->TrackTable[i].usSectorNumber = i + 1;
+                    ptrk->TrackTable[i].usSectorSize = SECSIZE;
+                }
+
+                do
+                {
+                    cyl = hFile->off / (SECSIZE * dpb.cHeads * dpb.cSectorsPerTrack);
+                    head = (hFile->off / SECSIZE - dpb.cHeads * dpb.cSectorsPerTrack * cyl) / dpb.cSectorsPerTrack;
+                    sec = hFile->off / SECSIZE - dpb.cHeads * dpb.cSectorsPerTrack * cyl - head * dpb.cSectorsPerTrack;
+
+                    if (sec + cbWrite32 / SECSIZE > dpb.cSectorsPerTrack)
+                        n = dpb.cSectorsPerTrack - sec + 1;
+                    else
+                        n = cbWrite32 / SECSIZE;
+
+                    ptrk->bCommand = 1;
+                    ptrk->usHead = head;
+                    ptrk->usCylinder = cyl;
+                    ptrk->usFirstSector = sec;
+                    ptrk->cSectors = n;
+
+                    rc = DosDevIOCtl(RTFileToNative(hFile), IOCTL_PHYSICALDISK, PDSK_WRITEPHYSTRACK,
+                                     trkbuf, parmlen4, &parmlen4, (void *)pvBuf, datalen4, &datalen4);
+
+                    rc = RTErrConvertFromOS2(rc);
+
+                    if (RT_FAILURE(rc))
+                        break;
+
+                    hFile->off += cbWrite32;
+                    cbWritten  += cbWrite32;
+                    cbToWrite  -= cbWrite32;
+                    pvBuf      =  (uint8_t *)pvBuf + cbWrite32;
+
+                } while ((cbToWrite > 0) && RT_SUCCESS(rc));
+                break;
+
+            default:
+                rc = VERR_NOT_SUPPORTED;
+        }
+    }
+    *pcbWritten = cbWritten;
+    return rc;
+}
+#endif
+
 RTR3DECL(int) RTFileOpen(PRTFILE pFile, const char *pszFilename, uint64_t fOpen)
 {
     /*
@@ -108,6 +925,13 @@
     *pFile = NIL_RTFILE;
     AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
 
+#ifdef RT_OS_OS2
+    *pFile = (RTFILE)RTMemAllocZ(sizeof(struct RTFILEINT));
+
+    (*pFile)->type = FILE_TYPE_NORMAL;
+    (*pFile)->off = 0;
+#endif
+
     /*
      * Merge forced open flags and validate them.
      */
@@ -202,9 +1026,21 @@
     if (RT_FAILURE(rc))
         return (rc);
 
-    int fh = open(pszNativeFilename, fOpenMode, fMode);
+    int fh = 0;
+#ifdef RT_OS_OS2
+    int ret = rtOs2ExtraFileOpen(pFile, pszNativeFilename,
+                                 fOpen, fOpenMode, fMode);
+
     int iErr = errno;
+    fh = RTFileToNative(*pFile);
 
+    if (RT_FAILURE(ret) && ret != -1)
+        return ret;
+#else
+    fh = open(pszNativeFilename, fOpenMode, fMode);
+    iErr = errno;
+#endif
+
 #ifdef O_CLOEXEC
     if (   (fOpenMode & O_CLOEXEC)
         && s_fHave_O_CLOEXEC == 0)
@@ -216,7 +1052,9 @@
             iErr = errno;
         }
         else if (fh >= 0)
+        {
             s_fHave_O_CLOEXEC = fcntl(fh, F_GETFD, 0) > 0 ? 1 : -1;
+        }
     }
 #endif
 
@@ -328,8 +1166,7 @@
          */
         if (iErr == 0)
         {
-            *pFile = (RTFILE)(uintptr_t)fh;
-            Assert((intptr_t)*pFile == fh);
+            RTFileFromNative(pFile, fh);
             LogFlow(("RTFileOpen(%p:{%RTfile}, %p:{%s}, %#llx): returns %Rrc\n",
                      pFile, *pFile, pszFilename, pszFilename, fOpen, rc));
             return VINF_SUCCESS;
@@ -337,6 +1174,11 @@
 
         close(fh);
     }
+#ifdef RT_OS_OS2
+    // it traps in some cases if we free it at this point
+    // (in an unsuccessful open case)
+    //RTMemFree(*pFile);
+#endif
     return RTErrConvertFromErrno(iErr);
 }
 
@@ -355,22 +1197,67 @@
 {
     if (hFile == NIL_RTFILE)
         return VINF_SUCCESS;
+#ifdef RT_OS_OS2
+    // lock drive
+    ULONG  dummy;
+    APIRET rc;
+
+    if (hFile->type == FILE_TYPE_DASD || hFile->type == FILE_TYPE_CD)
+    {
+        if ( (rc = DosDevIOCtl(RTFileToNative(hFile),
+                               IOCTL_DISK, DSK_UNLOCKDRIVE,
+                               &dummy, sizeof(dummy), NULL,
+                               &dummy, sizeof(dummy), NULL)) )
+            return RTErrConvertFromOS2(rc);
+    }
+    else if (hFile->type == FILE_TYPE_RAW)
+    {
+        if ( (rc = DosDevIOCtl(RTFileToNative(hFile),
+                               IOCTL_PHYSICALDISK, PDSK_UNLOCKPHYSDRIVE,
+                               &dummy, sizeof(dummy), NULL,
+                               &dummy, sizeof(dummy), NULL)) )
+            return RTErrConvertFromOS2(rc);
+    }
+
+    if (! hFile->rawfs && hFile->type == FILE_TYPE_RAW)
+    {
+        // physical disk handle
+        HFILE fh = RTFileToNative(hFile);
+        DosPhysicalDisk(INFO_FREEIOCTLHANDLE, 
+                        NULL, 
+                        0L, 
+                        &fh,
+                        2L);
+    }
+    else
+#endif
     if (close(RTFileToNative(hFile)) == 0)
+    {
+#ifdef RT_OS_OS2
+        RTMemFree(hFile);
+#endif
         return VINF_SUCCESS;
+    }
     return RTErrConvertFromErrno(errno);
 }
 
 
 RTR3DECL(int) RTFileFromNative(PRTFILE pFile, RTHCINTPTR uNative)
 {
+#ifndef RT_OS_OS2
     AssertCompile(sizeof(uNative) == sizeof(*pFile));
+#endif
     if (uNative < 0)
     {
         AssertMsgFailed(("%p\n", uNative));
         *pFile = NIL_RTFILE;
         return VERR_INVALID_HANDLE;
     }
+#ifdef RT_OS_OS2
+    (*pFile)->hFile = uNative;
+#else
     *pFile = (RTFILE)uNative;
+#endif
     return VINF_SUCCESS;
 }
 
@@ -378,7 +1265,11 @@
 RTR3DECL(RTHCINTPTR) RTFileToNative(RTFILE hFile)
 {
     AssertReturn(hFile != NIL_RTFILE, -1);
+#ifdef RT_OS_OS2
+    return (intptr_t)hFile->hFile;
+#else
     return (intptr_t)hFile;
+#endif
 }
 
 
@@ -415,7 +1306,6 @@
     return rc;
 }
 
-
 RTR3DECL(int)  RTFileSeek(RTFILE hFile, int64_t offSeek, unsigned uMethod, uint64_t *poffActual)
 {
     static const unsigned aSeekRecode[] =
@@ -443,17 +1333,25 @@
         return VERR_NOT_SUPPORTED;
     }
 
-    off_t offCurrent = lseek(RTFileToNative(hFile), (off_t)offSeek, aSeekRecode[uMethod]);
+    off_t offCurrent;
+#ifdef RT_OS_OS2
+    int ret = rtOs2ExtraFileSeek(hFile, offSeek, uMethod, &offCurrent);
+#else
+    offCurrent = lseek(RTFileToNative(hFile), (off_t)offSeek, aSeekRecode[uMethod]);
+    int ret = VINF_SUCCESS;
+
+    if (ret < 0)
+        ret = RTErrConvertFromErrno(errno);
+#endif
     if (offCurrent != ~0)
     {
         if (poffActual)
             *poffActual = (uint64_t)offCurrent;
         return VINF_SUCCESS;
     }
-    return RTErrConvertFromErrno(errno);
+    return ret;
 }
 
-
 RTR3DECL(int)  RTFileRead(RTFILE hFile, void *pvBuf, size_t cbToRead, size_t *pcbRead)
 {
     if (cbToRead <= 0)
@@ -462,8 +1360,13 @@
     /*
      * Attempt read.
      */
-    ssize_t cbRead = read(RTFileToNative(hFile), pvBuf, cbToRead);
+    ssize_t cbRead;
+#ifdef RT_OS_OS2
+    if ((rtOs2ExtraFileRead(hFile, pvBuf, cbToRead, &cbRead) == VINF_SUCCESS) && (cbRead >= 0))
+#else
+    cbRead = read(RTFileToNative(hFile), pvBuf, cbToRead);
     if (cbRead >= 0)
+#endif
     {
         if (pcbRead)
             /* caller can handle partial read. */
@@ -473,13 +1376,25 @@
             /* Caller expects all to be read. */
             while ((ssize_t)cbToRead > cbRead)
             {
-                ssize_t cbReadPart = read(RTFileToNative(hFile), (char*)pvBuf + cbRead, cbToRead - cbRead);
+                ssize_t cbReadPart;
+                int rc;
+#ifdef RT_OS_OS2
+                if (((rc = rtOs2ExtraFileRead(hFile, (char *)pvBuf + cbRead, cbToRead - cbRead,
+                                           &cbReadPart)) != VINF_SUCCESS) || (cbReadPart <= 0))
+                {
+                    if (cbReadPart == 0)
+                        return VERR_EOF;
+                    return rc;
+                }
+#else
+                cbReadPart = read(RTFileToNative(hFile), (char*)pvBuf + cbRead, cbToRead - cbRead);
                 if (cbReadPart <= 0)
                 {
                     if (cbReadPart == 0)
                         return VERR_EOF;
                     return RTErrConvertFromErrno(errno);
                 }
+#endif
                 cbRead += cbReadPart;
             }
         }
@@ -498,8 +1413,13 @@
     /*
      * Attempt write.
      */
-    ssize_t cbWritten = write(RTFileToNative(hFile), pvBuf, cbToWrite);
+    ssize_t cbWritten;
+#ifdef RT_OS_OS2
+    if ((rtOs2ExtraFileWrite(hFile, pvBuf, cbToWrite, &cbWritten) == VINF_SUCCESS) && (cbWritten >= 0))
+#else
+    cbWritten = write(RTFileToNative(hFile), pvBuf, cbToWrite);
     if (cbWritten >= 0)
+#endif
     {
         if (pcbWritten)
             /* caller can handle partial write. */
@@ -509,9 +1429,17 @@
             /* Caller expects all to be write. */
             while ((ssize_t)cbToWrite > cbWritten)
             {
-                ssize_t cbWrittenPart = write(RTFileToNative(hFile), (const char *)pvBuf + cbWritten, cbToWrite - cbWritten);
+                ssize_t cbWrittenPart;
+                int rc;
+#ifdef RT_OS_OS2
+                if (((rc = rtOs2ExtraFileWrite(hFile, (char *)pvBuf + cbWritten, cbToWrite - cbWritten,
+                                            &cbWrittenPart)) != VINF_SUCCESS) || (cbWrittenPart <= 0))
+                    return rc;
+#else
+                cbWrittenPart = write(RTFileToNative(hFile), (const char *)pvBuf + cbWritten, cbToWrite - cbWritten);
                 if (cbWrittenPart <= 0)
                     return RTErrConvertFromErrno(errno);
+#endif
                 cbWritten += cbWrittenPart;
             }
         }
@@ -675,6 +1603,11 @@
 
 RTR3DECL(int)  RTFileFlush(RTFILE hFile)
 {
+#ifdef RT_OS_OS2
+    // Access to a physical disk is not mediated by
+    // a filesystem cache, so it is synchronous
+    if (hFile->type != FILE_TYPE_RAW)
+#endif
     if (fsync(RTFileToNative(hFile)))
         return RTErrConvertFromErrno(errno);
     return VINF_SUCCESS;
Index: src/VBox/Devices/Storage/DrvHostBase.cpp
===================================================================
--- src/VBox/Devices/Storage/DrvHostBase.cpp	(revision 121)
+++ src/VBox/Devices/Storage/DrvHostBase.cpp	(working copy)
@@ -96,6 +96,11 @@
         /*IN*/ ULONG                Length,
         /*IN*/ FS_INFORMATION_CLASS FileSystemInformationClass );
 
+#elif defined(RT_OS_OS2)
+# define  OS2EMX_PLAIN_CHAR
+# define  INCL_BASE
+# define  INCL_DOSDEVIOCTL
+# include <os2.h>
 #elif defined(RT_OS_FREEBSD)
 # include <sys/cdefs.h>
 # include <sys/param.h>
@@ -1128,6 +1133,13 @@
     }
     RTFILE hFileRawDevice;
     int rc = drvHostBaseOpen(pThis, &hFileDevice, &hFileRawDevice, pThis->fReadOnlyConfig);
+#elif defined(RT_OS_OS2)
+    if (pThis->hFileDevice != NIL_RTFILE)
+    {
+        RTFileClose(pThis->hFileDevice);
+        pThis->hFileDevice = NIL_RTFILE;
+    }
+    int rc = drvHostBaseOpen(pThis, &hFileDevice, pThis->fReadOnlyConfig);
 #else
     int rc = drvHostBaseOpen(pThis, &hFileDevice, pThis->fReadOnlyConfig);
 #endif
@@ -2041,7 +2053,7 @@
     pThis->fAttachFailError = fAttachFailError;
 
     /* name to open & watch for */
-#ifdef RT_OS_WINDOWS
+#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
     int iBit = RT_C_TO_UPPER(pThis->pszDevice[0]) - 'A';
     if (    iBit > 'Z' - 'A'
         ||  pThis->pszDevice[1] != ':'
@@ -2051,7 +2063,11 @@
         return VERR_INVALID_PARAMETER;
     }
     pThis->fUnitMask = 1 << iBit;
+#if defined(RT_OS_WINDOWS)
     RTStrAPrintf(&pThis->pszDeviceOpen, "\\\\.\\%s", pThis->pszDevice);
+#else
+    RTStrAPrintf(&pThis->pszDeviceOpen, "%s", pThis->pszDevice);
+#endif
 
 #elif defined(RT_OS_SOLARIS)
     char *pszBlockDevName = getfullblkname(pThis->pszDevice);
@@ -2199,7 +2215,7 @@
             }
         }
     }
-#ifdef RT_OS_WINDOWS
+#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
     if (RT_SUCCESS(src))
         DRVHostBaseMediaPresent(pThis);
 #endif
Index: src/VBox/Devices/Storage/DrvHostDVD.cpp
===================================================================
--- src/VBox/Devices/Storage/DrvHostDVD.cpp	(revision 121)
+++ src/VBox/Devices/Storage/DrvHostDVD.cpp	(working copy)
@@ -86,6 +86,13 @@
 # undef _interlockedbittestandreset64
 # undef USE_MEDIA_POLLING
 
+#elif defined(RT_OS_OS2)
+# define  INCL_BASE
+# define  INCL_DOSDEVICES
+# define  INCL_DOSDEVIOCTL
+# include <os2.h>
+# include <stdio.h> // printf
+
 #elif defined(RT_OS_FREEBSD)
 # include <sys/cdefs.h>
 # include <sys/param.h>
@@ -106,6 +113,7 @@
 #include <iprt/string.h>
 #include <iprt/thread.h>
 #include <iprt/critsect.h>
+#include <iprt/mem.h>
 #include <VBox/scsi.h>
 
 #include "VBoxDD.h"
@@ -202,6 +210,17 @@
                 AssertMsgFailed(("Failed to open '%s' for ejecting this tray.\n",  rc));
 
 
+#elif defined(RT_OS_OS2)
+            ULONG parm = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24);
+            ULONG parmlen = sizeof(parm);
+
+            if (! (rc = DosDevIOCtl((HFILE)RTFileToNative(pThis->hFileDevice),
+                               IOCTL_CDROMDISK, CDROMDISK_EJECTDISK,
+                               &parm, parmlen, &parmlen,
+                               NULL, 0, NULL)))
+                rc = VINF_SUCCESS;
+            else
+                rc = RTErrConvertFromOS2(rc);
 #else
             AssertMsgFailed(("Eject is not implemented!\n"));
             rc = VINF_SUCCESS;
@@ -280,6 +299,28 @@
         /** @todo figure out the return codes for already locked. */
         rc = RTErrConvertFromWin32(GetLastError());
 
+#elif defined(RT_OS_OS2)
+    #pragma pack(1)
+    typedef struct _PARM
+    {
+        ULONG sig;
+        char flag;
+    } PARM;
+    #pragma pack()
+
+    ULONG  parmlen, datalen = 0;
+    PARM   parm;
+    APIRET rc;
+
+    parm.sig = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24);
+    parm.flag = fLock ? 1 : 0;
+
+    if (! (rc = DosDevIOCtl((HFILE)RTFileToNative(pThis->hFileDevice), IOCTL_CDROMDISK, CDROMDISK_LOCKUNLOCKDOOR,
+                            &parm, sizeof(PARM), &parmlen,
+                            0, datalen, &datalen)))
+        rc = VINF_SUCCESS;
+    else
+        rc = RTErrConvertFromOS2(rc);
 #else
     AssertMsgFailed(("Lock/Unlock is not implemented!\n"));
     int rc = VINF_SUCCESS;
@@ -631,6 +672,150 @@
         rc = RTErrConvertFromWin32(GetLastError());
     Log2(("%s: scsistatus=%d bytes returned=%d tlength=%d\n", __FUNCTION__, Req.spt.ScsiStatus, cbReturned, Req.spt.DataTransferLength));
 
+#elif defined(RT_OS_OS2)
+    #define CDROMDISK_EXECMD 0x7A
+    uint16_t flags;
+
+    #pragma pack(1)
+
+    struct ExecCMD {
+        ULONG        ID_code;          // 'CD01'
+        USHORT       data_length;      // length of the Data Packet
+        USHORT       cmd_length;       // length of the Command Buffer
+        USHORT       flags;            // flags
+        UCHAR        cmd_buffer[16];   // Command Buffer for SCSI command
+        ULONG        cmd_timeout;      // Timeout for executing command (0 - default)
+    } cmd;
+
+    // flags:
+    #define EX_DIRECTION_IN  0x0001
+    #define EX_PLAYING_CHK   0x0002
+    #define EX_RETURN_STATUS 0x0004
+    #define EX_SET_TIMEOUT   0x0008
+
+    #define DATA_TRANSFER_SIZE 2048
+
+    struct RetStatus {
+        UCHAR       sense_key;    // Sense Key
+        UCHAR       asc_code;     // Additional Sense Code (ASC)
+        UCHAR       ascq_code;    // Additional Sense Code Qualifier (ASCQ)
+    };
+
+    #pragma pack()
+
+    ULONG cmdlen = sizeof(cmd);
+    ULONG datalen;
+    char  *data;
+
+    switch (enmTxDir)
+    {
+        case PDMBLOCKTXDIR_NONE:
+            Assert(*pcbBuf == 0);
+            flags = EX_DIRECTION_IN;
+            break;
+        case PDMBLOCKTXDIR_FROM_DEVICE:
+            Assert(*pcbBuf != 0);
+            /* Make sure that the buffer is clear for commands reading
+             * data. The actually received data may be shorter than what
+             * we expect, and due to the unreliable feedback about how much
+             * data the ioctl actually transferred, it's impossible to
+             * prevent that. Returning previous buffer contents may cause
+             * security problems inside the guest OS, if users can issue
+             * commands to the CDROM device. */
+            memset(pvBuf, 0, *pcbBuf);
+            flags = EX_DIRECTION_IN;
+            break;
+        case PDMBLOCKTXDIR_TO_DEVICE:
+            Assert(*pcbBuf != 0);
+            flags = 0;
+            break;
+        default:
+            AssertMsgFailed(("enmTxDir invalid!\n"));
+            flags = 0;
+    }
+
+    flags |= EX_SET_TIMEOUT | EX_RETURN_STATUS;
+
+    uint32_t cbTransferred = 0;
+    int32_t  cbSize   = (int32_t)*pcbBuf;
+    uint16_t cbSize32 = (cbSize >= DATA_TRANSFER_SIZE) ? DATA_TRANSFER_SIZE : cbSize;
+    char     *pBuf    = (char *)pvBuf;
+
+    if (! cbSize32)
+        cbSize32 = 4;
+
+    data = (char *)RTMemAllocZ(cbSize32 + cbSense);
+
+    do
+    {
+        memset(&cmd, 0, sizeof(cmd));
+        memset(data, 0, cbSize32 + cbSense);
+
+        cmd.ID_code = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24);
+        cmd.cmd_length = sizeof(cmd.cmd_buffer);
+        memcpy((char *)cmd.cmd_buffer, (char *)pbCmd, 12);
+        cmd.flags = flags;
+        cmd.cmd_timeout = (cTimeoutMillies + 999) / 1000; // convert to seconds
+        datalen = cmd.data_length = cbSize32;
+
+        printf("cmd=%02x, cbSize=%u, cbSize32=%u", *(char *)cmd.cmd_buffer & 0xff, cbSize, cbSize32);
+
+        switch (enmTxDir)
+        {
+            case PDMBLOCKTXDIR_NONE:
+                printf(", direction: none");
+                break;
+
+            case PDMBLOCKTXDIR_FROM_DEVICE:
+                printf(", direction: from");
+                break;
+
+            case PDMBLOCKTXDIR_TO_DEVICE:
+                printf(", direction: to");
+                break;
+
+            default:
+                printf(", direction: illegal");
+                AssertMsgFailed(("enmTxDir invalid!\n"));
+        }
+
+        // copy data to ioctl data buffer
+        if (enmTxDir == PDMBLOCKTXDIR_TO_DEVICE)
+            memcpy(data, pBuf, cbSize32);
+
+        if (! (rc = DosDevIOCtl((HFILE)RTFileToNative(pThis->hFileDevice),
+                                IOCTL_CDROMDISK, CDROMDISK_EXECMD, 
+                                &cmd, cmdlen, &cmdlen, data, datalen, &datalen)) )
+        {
+            printf(", success, datalen=%lu", datalen);
+            // copy sense info
+            memcpy(pabSense, (char *)data + cbSize32, cbSense);
+
+            // copy data we got from CDROM driver
+            if ((enmTxDir == PDMBLOCKTXDIR_FROM_DEVICE) && datalen)
+            {
+                printf(", direction: from\n");
+                memcpy(pBuf, data, datalen);
+            }
+            else
+                printf(", direction: to\n");
+
+            pBuf          += datalen;
+            cbSize        -= datalen;
+            cbTransferred += datalen;
+        }
+        else
+            printf(", rc=%u\n", rc);
+
+        rc = RTErrConvertFromOS2(rc);
+
+    } while ((cbSize > 0) && RT_SUCCESS(rc));
+
+    RTMemFree(data);
+
+    printf("%s: bytes returned=%u\n", __FUNCTION__, cbTransferred);
+    Log2(("%s: bytes returned=%u\n", __FUNCTION__, cbTransferred));
+    
 #else
 # error "Unsupported platform."
 #endif
Index: src/VBox/Devices/Storage/DrvHostFloppy.cpp
===================================================================
--- src/VBox/Devices/Storage/DrvHostFloppy.cpp	(revision 121)
+++ src/VBox/Devices/Storage/DrvHostFloppy.cpp	(working copy)
@@ -28,10 +28,14 @@
 # include <sys/fcntl.h>
 # include <errno.h>
 
-# elif defined(RT_OS_WINDOWS)
+#elif defined(RT_OS_WINDOWS)
 # include <windows.h>
 # include <dbt.h>
 
+#elif defined(RT_OS_OS2)
+# define  INCL_BASE
+# define  INCL_DOSDEVIOCTL
+# include <os2.h>
 #elif defined(RT_OS_L4)
 
 #else /* !RT_OS_WINDOWS nor RT_OS_LINUX nor RT_OS_L4 */
@@ -101,6 +105,56 @@
 }
 #endif /* RT_OS_WINDOWS */
 
+#ifdef RT_OS_OS2
+
+/* parameter packet */
+#pragma pack(1)
+struct PARM {
+    unsigned char command;
+    unsigned char drive;
+};
+#pragma pack()
+
+/**
+ * Get media size - needs a special IOCTL.
+ *
+ * @param   pThis   The instance data.
+ */
+static DECLCALLBACK(int) drvHostFloppyGetMediaSize(PDRVHOSTBASE pThis, uint64_t *pcb)
+{
+    struct PARM parm;
+    BIOSPARAMETERBLOCK bpb;
+    ULONG cbSectors;
+    ULONG parmlen = sizeof(parm);
+    ULONG datalen = sizeof(bpb);
+    APIRET rc;
+
+    parm.command = 1; // Return the BPB for the media currently in the drive
+    parm.drive = 0;   // unused
+
+    memset(&bpb, 0, sizeof(bpb));
+
+    rc = DosDevIOCtl((HFILE)RTFileToNative(pThis->hFileDevice), IOCTL_DISK, DSK_GETDEVICEPARAMS,
+                     &parm, parmlen, &parmlen,
+                     &bpb, datalen, &datalen);
+
+    if (! rc) {
+        cbSectors = bpb.cCylinders * bpb.cHeads * bpb.usSectorsPerTrack;
+        *pcb = cbSectors * bpb.usBytesPerSector;
+        rc = VINF_SUCCESS;
+    }
+    else
+    {
+        rc = RTErrConvertFromOS2(rc);
+        Log(("DrvHostFloppy: ioctl DSK_GETDEVICEPARAMS(%s) failed, rc=%Rrc\n",
+             pThis->pszDevice, rc));
+        return rc;
+    }
+
+    return rc;
+}
+#endif /* RT_OS_OS2 */
+
 #ifdef RT_OS_LINUX
 /**
  * Get media size and do change processing.
@@ -198,7 +252,7 @@
             /*
              * Override stuff.
              */
-#ifdef RT_OS_WINDOWS
+#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
             pThis->Base.pfnGetMediaSize = drvHostFloppyGetMediaSize;
 #endif
 #ifdef RT_OS_LINUX
Index: src/VBox/Devices/Storage/DrvHostBase.h
===================================================================
--- src/VBox/Devices/Storage/DrvHostBase.h	(revision 121)
+++ src/VBox/Devices/Storage/DrvHostBase.h	(working copy)
@@ -129,6 +129,10 @@
     /** The unit mask. */
     DWORD                   fUnitMask;
 #endif
+#ifdef RT_OS_OS2
+    /** The unit mask. */
+    ULONG                   fUnitMask;
+#endif
 
 #ifdef RT_OS_LINUX
     /** Double buffer required for ioctl with the Linux kernel as long as we use
Index: src/VBox/Devices/Makefile.kmk
===================================================================
--- src/VBox/Devices/Makefile.kmk	(revision 121)
+++ src/VBox/Devices/Makefile.kmk	(working copy)
@@ -179,13 +179,13 @@
  	Storage/ATAPIPassthrough.cpp \
  	Network/DrvNetSniffer.cpp \
  	Network/Pcap.cpp
- ifn1of ($(KBUILD_TARGET), os2)
+ #ifn1of ($(KBUILD_TARGET), )
   VBoxDD_SOURCES += Storage/DrvHostBase.cpp
- endif
- ifn1of ($(KBUILD_TARGET), os2)
+ #endif
+ #ifn1of ($(KBUILD_TARGET), )
   VBoxDD_SOURCES += Storage/DrvHostDVD.cpp
- endif
- ifn1of ($(KBUILD_TARGET), darwin freebsd os2 solaris)
+ #endif
+ ifn1of ($(KBUILD_TARGET), darwin freebsd solaris)
   VBoxDD_SOURCES += Storage/DrvHostFloppy.cpp
  endif
 
@@ -545,6 +545,8 @@
    Audio/DrvHostDSound.cpp
  endif
 
+# VBoxDD_LIBS.os2 += poll
+
  ifeq ($(KBUILD_TARGET),linux)
   VBoxDD_SOURCES += \
    	Audio/DrvHostOSSAudio.cpp
@@ -707,8 +709,10 @@
  	Serial/DrvHostSerial.cpp
 
  ifeq ($(KBUILD_TARGET),os2)
+  # VBoxDD_SOURCES += Serial/DrvHostSerial.cpp
+  # VBoxDD_SOURCES += Parallel/DrvHostParallel.cpp
   VBoxDD_SOURCES.os2 += Network/DrvTAPOs2.cpp
- endif
+ endif # freebsd
 
  ifeq ($(KBUILD_TARGET),solaris)
   VBoxDD_SOURCES.solaris += Serial/DrvHostSerial.cpp
Index: src/VBox/Devices/build/VBoxDD.cpp
===================================================================
--- src/VBox/Devices/build/VBoxDD.cpp	(revision 121)
+++ src/VBox/Devices/build/VBoxDD.cpp	(working copy)
@@ -222,12 +222,12 @@
     rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvVD);
     if (RT_FAILURE(rc))
         return rc;
-#if defined(RT_OS_DARWIN) || defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS) || defined(RT_OS_FREEBSD)
+#if defined(RT_OS_DARWIN) || defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) || defined(RT_OS_FREEBSD)
     rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvHostDVD);
     if (RT_FAILURE(rc))
         return rc;
 #endif
-#if defined(RT_OS_LINUX) || defined(RT_OS_WINDOWS)
+#if defined(RT_OS_LINUX) || defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
     rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvHostFloppy);
     if (RT_FAILURE(rc))
         return rc;
Index: src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp
===================================================================
--- src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp	(revision 121)
+++ src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp	(working copy)
@@ -59,6 +59,12 @@
 # include <fcntl.h>
 # include <unistd.h>
 #endif
+#ifdef RT_OS_OS2
+# define  INCL_BASE
+# define  INCL_DOSDEVIOCTL
+# include <os2.h>
+# include <stdio.h> // SEEK_END
+#endif
 #ifdef RT_OS_LINUX
 # include <sys/utsname.h>
 # include <linux/hdreg.h>
@@ -1192,7 +1198,7 @@
             i++;
             pszPartitions = argv[i];
         }
-#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(RT_OS_WINDOWS)
+#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
         else if (strcmp(argv[i], "-relative") == 0)
         {
             fRelative = true;
@@ -1290,6 +1296,112 @@
             vrc = VINF_SUCCESS;
         }
     }
+#elif defined(RT_OS_OS2)
+    /* parameter packet */
+    #pragma pack(1)
+    struct {
+        unsigned char command;
+        unsigned char drive;
+    } parm;
+    struct {
+        unsigned char command;
+    } parmphys;
+    #pragma pack()
+    /* data packet      */
+    BIOSPARAMETERBLOCK bpb;
+    DEVICEPARAMETERBLOCK dpb;
+    ULONG cbSectors;
+    ULONG parmlen;
+    ULONG datalen;
+    LONGLONG xrc;
+    APIRET ret;
+
+    if (hRawFile->type == FILE_TYPE_RAW)
+    {
+        parmlen = sizeof(parmphys);
+        datalen = sizeof(dpb);
+
+        memset(&dpb, 0, sizeof(dpb));
+
+        parmphys.command = 1;
+
+        ret = DosDevIOCtl((HFILE)RTFileToNative(hRawFile), IOCTL_PHYSICALDISK, PDSK_GETPHYSDEVICEPARAMS,
+                          &parmphys, parmlen, &parmlen,
+                          &dpb, datalen, &datalen);
+    }
+    else if (hRawFile->type == FILE_TYPE_DASD ||
+             hRawFile->type == FILE_TYPE_CD)
+    {
+        parmlen = sizeof(parm);
+        datalen = sizeof(bpb);
+
+        memset(&bpb, 0, sizeof(bpb));
+
+        parm.command = 1; // Return the BPB for the media currently in the drive
+        parm.drive = 0;   // unused
+
+        ret = DosDevIOCtl((HFILE)RTFileToNative(hRawFile), IOCTL_DISK, DSK_GETDEVICEPARAMS,
+                          &parm, parmlen, &parmlen,
+                          &bpb, datalen, &datalen);
+    }
+    //else if (hRawFile->type == FILE_TYPE_RAWFS)
+    //    ret = DosSetFilePtrL(RTFileToNative(hRawFile), 0, FILE_END, &xrc);
+
+    if (! ret)
+    {
+        if (hRawFile->type == FILE_TYPE_RAW)
+        {
+            cbSize = dpb.cCylinders
+                   * dpb.cHeads
+                   * dpb.cSectorsPerTrack;
+            cbSize <<= 9; // multiply by sector size
+        }
+        else if (bpb.bDeviceType == 5) // fixed disk
+        {
+            cbSize = bpb.cCylinders
+                   * bpb.cHeads
+                   * bpb.usSectorsPerTrack;
+            cbSize <<= 9; // multiply by sector size
+        }
+        //else if (hRawFile->type == FILE_TYPE_RAWFS)
+        //    cbSize = xrc;
+        else
+        {
+            RTMsgError("File '%s' is no fixed/removable medium device", rawdisk.c_str());
+            vrc = VERR_INVALID_PARAMETER;
+            goto out;
+        }
+
+        if (fRelative)
+        {
+            RTMsgError("The -relative parameter is invalid for raw disk %s", rawdisk.c_str());
+            vrc = VERR_INVALID_PARAMETER;
+            goto out;
+        }
+    }
+    else
+    {
+        /*
+         * Could be raw image, remember error code and try to get the size first
+         * before failing.
+         */
+        vrc = RTErrConvertFromOS2(ret);
+        if (RT_FAILURE(RTFileGetSize(hRawFile, &cbSize)))
+        {
+            RTMsgError("Cannot get the geometry of the raw disk '%s': %Rrc", rawdisk.c_str(), vrc);
+            goto out;
+        }
+        else
+        {
+            if (fRelative)
+            {
+                RTMsgError("The -relative parameter is invalid for raw images");
+                vrc = VERR_INVALID_PARAMETER;
+                goto out;
+            }
+            vrc = VINF_SUCCESS;
+        }
+    }
 #elif defined(RT_OS_LINUX)
     struct stat DevStat;
     if (!fstat(RTFileToNative(hRawFile), &DevStat))
