diff options
Diffstat (limited to 'src/VBox/HostDrivers/Support/os2')
-rw-r--r-- | src/VBox/HostDrivers/Support/os2/Makefile.kup | 0 | ||||
-rw-r--r-- | src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp | 547 | ||||
-rw-r--r-- | src/VBox/HostDrivers/Support/os2/SUPDrv-os2.def | 45 | ||||
-rw-r--r-- | src/VBox/HostDrivers/Support/os2/SUPDrvA-os2.asm | 973 | ||||
-rw-r--r-- | src/VBox/HostDrivers/Support/os2/SUPLib-os2.cpp | 193 | ||||
-rw-r--r-- | src/VBox/HostDrivers/Support/os2/SUPR0IdcClient-os2.c | 51 |
6 files changed, 1809 insertions, 0 deletions
diff --git a/src/VBox/HostDrivers/Support/os2/Makefile.kup b/src/VBox/HostDrivers/Support/os2/Makefile.kup new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/VBox/HostDrivers/Support/os2/Makefile.kup diff --git a/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp b/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp new file mode 100644 index 00000000..7cfd9c47 --- /dev/null +++ b/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp @@ -0,0 +1,547 @@ +/* $Id: SUPDrv-os2.cpp $ */ +/** @file + * VBoxDrv - The VirtualBox Support Driver - OS/2 specifics. + */ + +/* + * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_SUP_DRV +#define __STDC_CONSTANT_MACROS +#define __STDC_LIMIT_MACROS + +#include <os2ddk/bsekee.h> +#undef RT_MAX + +#include "SUPDrvInternal.h" +#include <VBox/version.h> +#include <iprt/initterm.h> +#include <iprt/string.h> +#include <iprt/spinlock.h> +#include <iprt/process.h> +#include <iprt/assert.h> +#include <VBox/log.h> +#include <iprt/param.h> + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +/** + * Device extention & session data association structure. + */ +static SUPDRVDEVEXT g_DevExt; +/** Spinlock protecting g_apSessionHashTab. */ +static RTSPINLOCK g_Spinlock = NIL_RTSPINLOCK; +/** Hash table */ +static PSUPDRVSESSION g_apSessionHashTab[19]; +/** Calculates the index into g_apSessionHashTab.*/ +#define SESSION_HASH(sfn) ((sfn) % RT_ELEMENTS(g_apSessionHashTab)) + +RT_C_DECLS_BEGIN +/* Defined in SUPDrvA-os2.asm */ +extern uint16_t g_offLogHead; +extern uint16_t volatile g_offLogTail; +extern uint16_t const g_cchLogMax; +extern char g_szLog[]; +/* (init only:) */ +extern char g_szInitText[]; +extern uint16_t g_cchInitText; +extern uint16_t g_cchInitTextMax; +RT_C_DECLS_END + + +/********************************************************************************************************************************* +* Internal Functions * +*********************************************************************************************************************************/ + + + +/** + * 32-bit Ring-0 initialization. + * + * @returns 0 on success, non-zero on failure. + * @param pszArgs Pointer to the device arguments. + */ +DECLASM(int) VBoxDrvInit(const char *pszArgs) +{ + /* + * Initialize the runtime. + */ + int rc = RTR0Init(0); + if (RT_SUCCESS(rc)) + { + Log(("VBoxDrvInit: pszArgs=%s\n", pszArgs)); + + /* + * Initialize the device extension. + */ + rc = supdrvInitDevExt(&g_DevExt, sizeof(SUPDRVSESSION)); + if (RT_SUCCESS(rc)) + { + /* + * Initialize the session hash table. + */ + rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxDrvOS2"); + if (RT_SUCCESS(rc)) + { + /* + * Process the commandline. Later. + */ + bool fVerbose = true; + + /* + * Success + */ + if (fVerbose) + { + strcpy(&g_szInitText[0], + "\r\n" + "VirtualBox.org Support Driver for OS/2 version " VBOX_VERSION_STRING "\r\n" + "Copyright (C) 2007 Knut St. Osmundsen\r\n" + "Copyright (C) 2007-2016 Oracle Corporation\r\n"); + g_cchInitText = strlen(&g_szInitText[0]); + } + return VINF_SUCCESS; + } + g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxDrv.sys: RTSpinlockCreate failed, rc=%Rrc\n", rc); + supdrvDeleteDevExt(&g_DevExt); + } + else + g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxDrv.sys: supdrvInitDevExt failed, rc=%Rrc\n", rc); + RTR0Term(); + } + else + g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxDrv.sys: RTR0Init failed, rc=%Rrc\n", rc); + return rc; +} + + +DECLASM(int) VBoxDrvOpen(uint16_t sfn) +{ + int rc; + PSUPDRVSESSION pSession; + + /* + * Create a new session. + */ + rc = supdrvCreateSession(&g_DevExt, true /* fUser */, true /*fUnrestricted*/, &pSession); + if (RT_SUCCESS(rc)) + { + pSession->sfn = sfn; + + /* + * Insert it into the hash table. + */ + unsigned iHash = SESSION_HASH(sfn); + RTSpinlockAcquire(g_Spinlock); + pSession->pNextHash = g_apSessionHashTab[iHash]; + g_apSessionHashTab[iHash] = pSession; + RTSpinlockRelease(g_Spinlock); + } + + Log(("VBoxDrvOpen: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, (int)RTProcSelf())); + return rc; +} + + +DECLASM(int) VBoxDrvClose(uint16_t sfn) +{ + Log(("VBoxDrvClose: pid=%d sfn=%d\n", (int)RTProcSelf(), sfn)); + + /* + * Remove from the hash table. + */ + PSUPDRVSESSION pSession; + const RTPROCESS Process = RTProcSelf(); + const unsigned iHash = SESSION_HASH(sfn); + RTSpinlockAcquire(g_Spinlock); + + pSession = g_apSessionHashTab[iHash]; + if (pSession) + { + if ( pSession->sfn == sfn + && pSession->Process == Process) + { + g_apSessionHashTab[iHash] = pSession->pNextHash; + pSession->pNextHash = NULL; + } + else + { + PSUPDRVSESSION pPrev = pSession; + pSession = pSession->pNextHash; + while (pSession) + { + if ( pSession->sfn == sfn + && pSession->Process == Process) + { + pPrev->pNextHash = pSession->pNextHash; + pSession->pNextHash = NULL; + break; + } + + /* next */ + pPrev = pSession; + pSession = pSession->pNextHash; + } + } + } + RTSpinlockRelease(g_Spinlock); + if (!pSession) + { + OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d sfn=%d\n", (int)Process, sfn)); + return VERR_INVALID_PARAMETER; + } + + /* + * Close the session. + */ + supdrvSessionRelease(pSession); + return 0; +} + + +DECLASM(int) VBoxDrvIOCtlFast(uint16_t sfn, uint8_t iFunction) +{ + /* + * Find the session. + */ + const RTPROCESS Process = RTProcSelf(); + const unsigned iHash = SESSION_HASH(sfn); + PSUPDRVSESSION pSession; + + RTSpinlockAcquire(g_Spinlock); + pSession = g_apSessionHashTab[iHash]; + if (pSession && pSession->Process != Process) + { + do pSession = pSession->pNextHash; + while ( pSession + && ( pSession->sfn != sfn + || pSession->Process != Process)); + + if (RT_LIKELY(pSession)) + supdrvSessionRetain(pSession); + } + RTSpinlockRelease(g_Spinlock); + if (RT_UNLIKELY(!pSession)) + { + OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process)); + return VERR_INVALID_PARAMETER; + } + + /* + * Dispatch the fast IOCtl. + */ + int rc; + if ((unsigned)(iFunction - SUP_IOCTL_FAST_DO_FIRST) < (unsigned)32) + rc = supdrvIOCtlFast(iFunction, 0, &g_DevExt, pSession); + else + rc = VERR_INVALID_FUNCTION; + supdrvSessionRelease(pSession); + return rc; +} + + +DECLASM(int) VBoxDrvIOCtl(uint16_t sfn, uint8_t iCat, uint8_t iFunction, void *pvParm, void *pvData, uint16_t *pcbParm, uint16_t *pcbData) +{ + /* + * Find the session. + */ + const RTPROCESS Process = RTProcSelf(); + const unsigned iHash = SESSION_HASH(sfn); + PSUPDRVSESSION pSession; + + RTSpinlockAcquire(g_Spinlock); + pSession = g_apSessionHashTab[iHash]; + if (pSession && pSession->Process != Process) + { + do pSession = pSession->pNextHash; + while ( pSession + && ( pSession->sfn != sfn + || pSession->Process != Process)); + + if (RT_LIKELY(pSession)) + supdrvSessionRetain(pSession); + } + RTSpinlockRelease(g_Spinlock); + if (!pSession) + { + OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process)); + return VERR_INVALID_PARAMETER; + } + + /* + * Verify the category and dispatch the IOCtl. + */ + if (RT_LIKELY(iCat == SUP_CTL_CATEGORY)) + { + Log(("VBoxDrvIOCtl: pSession=%p iFunction=%#x pvParm=%p pvData=%p *pcbParm=%d *pcbData=%d\n", pSession, iFunction, pvParm, pvData, *pcbParm, *pcbData)); + Assert(pvParm); + Assert(!pvData); + + /* + * Lock the header. + */ + PSUPREQHDR pHdr = (PSUPREQHDR)pvParm; + AssertReturn(*pcbParm == sizeof(*pHdr), VERR_INVALID_PARAMETER); + KernVMLock_t Lock; + int rc = KernVMLock(VMDHL_WRITE, pHdr, *pcbParm, &Lock, (KernPageList_t *)-1, NULL); + AssertMsgReturn(!rc, ("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pHdr, *pcbParm, &Lock, rc), VERR_LOCK_FAILED); + + /* + * Validate the header. + */ + if (RT_LIKELY((pHdr->fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) == SUPREQHDR_FLAGS_MAGIC)) + { + uint32_t cbReq = RT_MAX(pHdr->cbIn, pHdr->cbOut); + if (RT_LIKELY( pHdr->cbIn >= sizeof(*pHdr) + && pHdr->cbOut >= sizeof(*pHdr) + && cbReq <= _1M*16)) + { + /* + * Lock the rest of the buffer if necessary. + */ + if (((uintptr_t)pHdr & PAGE_OFFSET_MASK) + cbReq > PAGE_SIZE) + { + rc = KernVMUnlock(&Lock); + AssertMsgReturn(!rc, ("KernVMUnlock(Lock) -> %#x\n", rc), VERR_LOCK_FAILED); + + rc = KernVMLock(VMDHL_WRITE, pHdr, cbReq, &Lock, (KernPageList_t *)-1, NULL); + AssertMsgReturn(!rc, ("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pHdr, cbReq, &Lock, rc), VERR_LOCK_FAILED); + } + + /* + * Process the IOCtl. + */ + rc = supdrvIOCtl(iFunction, &g_DevExt, pSession, pHdr, cbReq); + } + else + { + OSDBGPRINT(("VBoxDrvIOCtl: max(%#x,%#x); iCmd=%#x\n", pHdr->cbIn, pHdr->cbOut, iFunction)); + rc = VERR_INVALID_PARAMETER; + } + } + else + { + OSDBGPRINT(("VBoxDrvIOCtl: bad magic fFlags=%#x; iCmd=%#x\n", pHdr->fFlags, iFunction)); + rc = VERR_INVALID_PARAMETER; + } + + /* + * Unlock and return. + */ + int rc2 = KernVMUnlock(&Lock); + AssertMsg(!rc2, ("rc2=%d\n", rc2)); NOREF(rc2);s + } + else + rc = VERR_NOT_SUPPORTED; + + supdrvSessionRelease(pSession); + Log2(("VBoxDrvIOCtl: returns %d\n", rc)); + return rc; +} + + +void VBOXCALL supdrvOSCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession) +{ + NOREF(pDevExt); + NOREF(pSession); +} + + +void VBOXCALL supdrvOSSessionHashTabInserted(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser) +{ + NOREF(pDevExt); NOREF(pSession); NOREF(pvUser); +} + + +void VBOXCALL supdrvOSSessionHashTabRemoved(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser) +{ + NOREF(pDevExt); NOREF(pSession); NOREF(pvUser); +} + + +void VBOXCALL supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession) +{ + NOREF(pObj); + NOREF(pSession); +} + + +bool VBOXCALL supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc) +{ + NOREF(pObj); + NOREF(pSession); + NOREF(pszObjName); + NOREF(prc); + return false; +} + + +bool VBOXCALL supdrvOSGetForcedAsyncTscMode(PSUPDRVDEVEXT pDevExt) +{ + NOREF(pDevExt); + return false; +} + + +bool VBOXCALL supdrvOSAreCpusOfflinedOnSuspend(void) +{ + return false; +} + + +bool VBOXCALL supdrvOSAreTscDeltasInSync(void) +{ + NOREF(pDevExt); + return false; +} + + +int VBOXCALL supdrvOSLdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename) +{ + NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename); + return VERR_NOT_SUPPORTED; +} + + +int VBOXCALL supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv, + const uint8_t *pbImageBits, const char *pszSymbol) +{ + NOREF(pDevExt); NOREF(pImage); NOREF(pv); NOREF(pbImageBits); NOREF(pszSymbol); + return VERR_NOT_SUPPORTED; +} + + +int VBOXCALL supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, PSUPLDRLOAD pReq) +{ + NOREF(pDevExt); NOREF(pImage); NOREF(pbImageBits); NOREF(pReq); + return VERR_NOT_SUPPORTED; +} + + +void VBOXCALL supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage) +{ + NOREF(pDevExt); NOREF(pImage); +} + + +void VBOXCALL supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename) +{ + NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename); +} + + +void VBOXCALL supdrvOSLdrNotifyUnloaded(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage) +{ + NOREF(pDevExt); NOREF(pImage); +} + + +int VBOXCALL supdrvOSLdrQuerySymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, + const char *pszSymbol, size_t cchSymbol, void **ppvSymbol) +{ + RT_NOREF(pDevExt, pImage, pszSymbol, cchSymbol, ppvSymbol); + return VERR_WRONG_ORDER; +} + + +#ifdef SUPDRV_WITH_MSR_PROBER + +int VBOXCALL supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue) +{ + NOREF(uMsr); NOREF(idCpu); NOREF(puValue); + return VERR_NOT_SUPPORTED; +} + + +int VBOXCALL supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue) +{ + NOREF(uMsr); NOREF(idCpu); NOREF(uValue); + return VERR_NOT_SUPPORTED; +} + + +int VBOXCALL supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq) +{ + NOREF(idCpu); NOREF(pReq); + return VERR_NOT_SUPPORTED; +} + +#endif /* SUPDRV_WITH_MSR_PROBER */ + + +/** + * Callback for writing to the log buffer. + * + * @returns number of bytes written. + * @param pvArg Unused. + * @param pachChars Pointer to an array of utf-8 characters. + * @param cbChars Number of bytes in the character array pointed to by pachChars. + */ +static DECLCALLBACK(size_t) VBoxDrvLogOutput(void *pvArg, const char *pachChars, size_t cbChars) +{ + size_t cchWritten = 0; + while (cbChars-- > 0) + { + const uint16_t offLogHead = g_offLogHead; + const uint16_t offLogHeadNext = (offLogHead + 1) & (g_cchLogMax - 1); + if (offLogHeadNext == g_offLogTail) + break; /* no */ + g_szLog[offLogHead] = *pachChars++; + g_offLogHead = offLogHeadNext; + cchWritten++; + } + return cchWritten; +} + + +SUPR0DECL(int) SUPR0Printf(const char *pszFormat, ...) +{ + va_list va; + +#if 0 //def DEBUG_bird + va_start(va, pszFormat); + RTLogComPrintfV(pszFormat, va); + va_end(va); +#endif + + va_start(va, pszFormat); + int cch = RTLogFormatV(VBoxDrvLogOutput, NULL, pszFormat, va); + va_end(va); + + return cch; +} + + +SUPR0DECL(uint32_t) SUPR0GetKernelFeatures(void) +{ + return 0; +} + diff --git a/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.def b/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.def new file mode 100644 index 00000000..366f4395 --- /dev/null +++ b/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.def @@ -0,0 +1,45 @@ +; $Id: SUPDrv-os2.def $ +;; @file +; VBoxDrv - OS/2 definition file. +; + +; +; Copyright (C) 2007-2019 Oracle Corporation +; +; This file is part of VirtualBox Open Source Edition (OSE), as +; available from http://www.virtualbox.org. This file is free software; +; you can redistribute it and/or modify it under the terms of the GNU +; General Public License (GPL) as published by the Free Software +; Foundation, in version 2 as it comes in the "COPYING" file of the +; VirtualBox OSE distribution. VirtualBox OSE is distributed in the +; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL) only, as it comes in the "COPYING.CDDL" file of the +; VirtualBox OSE distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; + + +PHYSICAL DEVICE VBoxDrv +DESCRIPTION 'VirtualBox.org Support Driver for OS/2.' +CODE PRELOAD EXECUTEREAD +DATA PRELOAD +; We're using wlink.exe, so this doesn't work. +;SEGMENTS +; DATA16 class 'FAR_DATA' +; DATA16_INIT class 'FAR_DATA' +; +; CODE16 class 'CODE' +; CODE16_INIT class 'CODE' +; +; CODE32 class 'CODE' +; TEXT32 class 'CODE' +; +; DATA32 class 'DATA' +; BSS32 class 'BSS' + diff --git a/src/VBox/HostDrivers/Support/os2/SUPDrvA-os2.asm b/src/VBox/HostDrivers/Support/os2/SUPDrvA-os2.asm new file mode 100644 index 00000000..b27fcd0f --- /dev/null +++ b/src/VBox/HostDrivers/Support/os2/SUPDrvA-os2.asm @@ -0,0 +1,973 @@ +; $Id: SUPDrvA-os2.asm $ +;; @file +; VBoxDrv - OS/2 assembly file, the first file in the link. +; + +; +; Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net> +; +; Permission is hereby granted, free of charge, to any person +; obtaining a copy of this software and associated documentation +; files (the "Software"), to deal in the Software without +; restriction, including without limitation the rights to use, +; copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the +; Software is furnished to do so, subject to the following +; conditions: +; +; The above copyright notice and this permission notice shall be +; included in all copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +; OTHER DEALINGS IN THE SOFTWARE. +; + + +;******************************************************************************* +;* Header Files * +;******************************************************************************* +%define RT_INCL_16BIT_SEGMENTS +%include "iprt/asmdefs.mac" + + +;******************************************************************************* +;* Structures and Typedefs * +;******************************************************************************* +;; +; Request packet header. +struc PKTHDR + .cb resb 1 + .unit resb 1 + .cmd resb 1 + .status resw 1 + .res1 resd 1 + .link resd 1 +endstruc + + +;; +; Init request packet - input. +struc PKTINITIN + .cb resb 1 + .unit resb 1 + .cmd resb 1 + .status resw 1 + .res1 resd 1 + .link resd 1 + + .data_1 resb 1 + .fpfnDevHlp resd 1 + .fpszArgs resd 1 + .data_2 resb 1 +endstruc + +;; +; Init request packet - output. +struc PKTINITOUT + .cb resb 1 + .unit resb 1 + .cmd resb 1 + .status resw 1 + .res1 resd 1 + .link resd 1 + + .cUnits resb 1 ; block devs only. + .cbCode16 resw 1 + .cbData16 resw 1 + .fpaBPBs resd 1 ; block devs only. + .data_2 resb 1 +endstruc + +;; +; Open request packet. +struc PKTOPEN + .cb resb 1 + .unit resb 1 + .cmd resb 1 + .status resw 1 + .res1 resd 1 + .link resd 1 + .sfn resw 1 +endstruc + +;; +; Close request packet. +struc PKTCLOSE + .cb resb 1 + .unit resb 1 + .cmd resb 1 + .status resw 1 + .res1 resd 1 + .link resd 1 + .sfn resw 1 +endstruc + +;; +; IOCtl request packet. +struc PKTIOCTL + .cb resb 1 + .unit resb 1 + .cmd resb 1 + .status resw 1 + .res1 resd 1 + .link resd 1 + + .cat resb 1 + .fun resb 1 + .pParm resd 1 + .pData resd 1 + .sfn resw 1 + .cbParm resw 1 + .cbData resw 1 +endstruc + +;; +; Read/Write request packet +struc PKTRW + .cb resb 1 + .unit resb 1 + .cmd resb 1 + .status resw 1 + .res1 resd 1 + .link resd 1 + + .media resb 1 + .PhysTrans resd 1 + .cbTrans resw 1 + .start resd 1 + .sfn resw 1 +endstruc + + + +;; +; The two device headers. +segment DATA16 + +; Some devhdr.inc stuff. +%define DEVLEV_3 0180h +%define DEV_30 0800h +%define DEV_CHAR_DEV 8000h +%define DEV_16MB 0002h +%define DEV_IOCTL2 0001h + +; Some dhcalls.h stuff. +%define DevHlp_VirtToLin 05bh +%define DevHlp_SAVE_MESSAGE 03dh +%define DevHlp_PhysToVirt 015h + +; Fast IOCtl category, also defined in SUPDrvIOC.h +%define SUP_CTL_CATEGORY_FAST 0c1h + + +;******************************************************************************* +;* External Symbols * +;******************************************************************************* +extern KernThunkStackTo32 +extern KernThunkStackTo16 +extern DOS16OPEN +extern DOS16CLOSE +extern DOS16WRITE +extern NAME(VBoxDrvInit) +extern NAME(VBoxDrvOpen) +extern NAME(VBoxDrvClose) +extern NAME(VBoxDrvIOCtl) +extern NAME(VBoxDrvIOCtlFast) + + +;; +; Device headers. The first one is the one we'll be opening and the +; latter is only used for 32-bit initialization. +GLOBALNAME g_VBoxDrvHdr1 + dw NAME(g_VBoxDrvHdr2) wrt DATA16 ; NextHeader.off + dw DATA16 ; NextHeader.sel + dw DEVLEV_3 | DEV_30 | DEV_CHAR_DEV; SDevAtt + dw NAME(VBoxDrvEP) wrt CODE16 ; StrategyEP + dw 0 ; InterruptEP + db 'vboxdrv$' ; DevName + dw 0 ; SDevProtCS + dw 0 ; SDevProtDS + dw 0 ; SDevRealCS + dw 0 ; SDevRealDS + dd DEV_16MB | DEV_IOCTL2 ; SDevCaps + +align 4 +GLOBALNAME g_VBoxDrvHdr2 + dd 0ffffffffh ; NextHeader (NIL) + dw DEVLEV_3 | DEV_30 | DEV_CHAR_DEV; SDevAtt + dw NAME(VBoxDrvInitEP) wrt CODE16 ; StrategyEP + dw 0 ; InterruptEP + db 'vboxdr1$' ; DevName + dw 0 ; SDevProtCS + dw 0 ; SDevProtDS + dw 0 ; SDevRealCS + dw 0 ; SDevRealDS + dd DEV_16MB | DEV_IOCTL2 ; SDevCaps + + +;; Tristate 32-bit initialization indicator [0 = need init, -1 = init failed, 1 init succeeded]. +; Check in the open path of the primary driver. The secondary driver will +; open the primary one during it's init and thereby trigger the 32-bit init. +GLOBALNAME g_fInitialized + db 0 + +align 4 +;; Pointer to the device helper service routine +; This is set during the initialization of the 2nd device driver. +GLOBALNAME g_fpfnDevHlp + dd 0 + + +;; Where we write to the log. +GLOBALNAME g_offLogHead + dw 0 +;; Where we read from the log. +GLOBALNAME g_offLogTail + dw 0 +;; The size of the log. (power of two!) +%define LOG_SIZE 16384 +GLOBALNAME g_cchLogMax + dw LOG_SIZE +;; The log buffer. +GLOBALNAME g_szLog + times LOG_SIZE db 0 + + +; +; The init data. +; +segment DATA16_INIT +GLOBALNAME g_InitDataStart + +;; Far pointer to the device argument. +g_fpszArgs: + dd 0 + +%if 0 +;; Message table for the Save_Message device helper. +GLOBALNAME g_MsgTab + dw 1178 ; MsgId - 'MSG_REPLACEMENT_STRING'. + dw 1 ; cMsgStrings + dw NAME(g_szInitText) ; MsgStrings[0] + dw seg NAME(g_szInitText) +%else +;; Far pointer to DOS16WRITE (corrected set before called). +; Just a temporary hack to work around a wlink issue. +GLOBALNAME g_fpfnDos16Write + dw DOS16WRITE + dw seg DOS16WRITE +%endif + +;; Size of the text currently in the g_szInitText buffer. +GLOBALNAME g_cchInitText + dw 0 +;; The max size of text that can fit into the g_szInitText buffer. +GLOBALNAME g_cchInitTextMax + dw 512 +;; The init text buffer. +GLOBALNAME g_szInitText + times 512 db 0 + +; +; The 16-bit code segment. +; +segment CODE16 + + +;; +; The strategy entry point (vboxdrv$). +; +; ss:bx -> request packet +; ds:si -> device header +; +; Can clobber any registers it likes except SP. +; +BEGINPROC VBoxDrvEP + push ebp + mov ebp, esp + push es ; bp - 2 + push bx ; bp - 4 + and sp, 0fffch + + ; + ; Check for the most frequent first. + ; + cmp byte [es:bx + PKTHDR.cmd], 10h ; Generic IOCtl + jne near VBoxDrvEP_NotGenIOCtl + + + ; + ; Generic I/O Control Request. + ; +VBoxDrvEP_GenIOCtl: + + ; Fast IOCtl? + cmp byte [es:bx + PKTIOCTL.cat], SUP_CTL_CATEGORY_FAST + jne VBoxDrvEP_GenIOCtl_Other + + ; + ; Fast IOCtl. + ; DECLASM(int) VBoxDrvIOCtlFast(uint16_t sfn, uint8_t iFunction) + ; +VBoxDrvEP_GenIOCtl_Fast: + ; function. + movzx edx, byte [es:bx + PKTIOCTL.fun] + push edx ; 04h + + ; system file number. + movzx eax, word [es:bx + PKTIOCTL.sfn] + push eax ; 00h + + ; go to the 32-bit code + ;jmp far dword NAME(VBoxDrvEP_GenIOCtl_Fast_32) wrt FLAT + db 066h + db 0eah + dd NAME(VBoxDrvEP_GenIOCtl_Fast_32) ;wrt FLAT + dw TEXT32 wrt FLAT +segment TEXT32 +GLOBALNAME VBoxDrvEP_GenIOCtl_Fast_32 + + ; switch stack to 32-bit. + mov ax, DATA32 wrt FLAT + mov ds, ax + mov es, ax + call KernThunkStackTo32 + + ; call the C code (don't cleanup the stack). + call NAME(VBoxDrvIOCtlFast) + + ; switch back the stack. + push eax + call KernThunkStackTo16 + pop eax + + ; jump back to the 16-bit code. + ;jmp far dword NAME(VBoxDrvEP_GenIOCtl_Fast_16) wrt CODE16 + db 066h + db 0eah + dw NAME(VBoxDrvEP_GenIOCtl_Fast_16) wrt CODE16 + dw CODE16 +segment CODE16 +GLOBALNAME VBoxDrvEP_GenIOCtl_Fast_16 + les bx, [bp - 4] ; Reload the packet pointer. + or eax, eax + jnz near VBoxDrvEP_GeneralFailure + + ; setup output stuff. + xor eax, eax + mov [es:bx + PKTIOCTL.cbParm], eax ; update cbParm and cbData. + mov word [es:bx + PKTHDR.status], 00100h ; done, ok. + + mov sp, bp + pop ebp + retf + + ; + ; Other IOCtl (slow) + ; +VBoxDrvEP_GenIOCtl_Other: + mov eax, [es:bx + PKTIOCTL.cbParm] ; Load cbParm and cbData + push eax ; 1eh - in/out data size. + ; 1ch - in/out parameter size. + push edx ; 18h - pointer to data size (filled in later). + push ecx ; 14h - pointer to param size (filled in later). + + ; pData (convert to flat 32-bit) + mov ax, word [es:bx + PKTIOCTL.pData + 2] ; selector + cmp ax, 3 ; <= 3 -> nil selector... + jbe .no_data + movzx esi, word [es:bx + PKTIOCTL.pData] ; offset + mov dl, DevHlp_VirtToLin + call far [NAME(g_fpfnDevHlp)] + jc near VBoxDrvEP_GeneralFailure + jmp .finish_data +.no_data: + xor eax, eax +.finish_data: + push eax ; 10h + + ; pParm (convert to flat 32-bit) + mov ax, word [es:bx + PKTIOCTL.pParm + 2] ; selector + cmp ax, 3 ; <= 3 -> nil selector... + jbe .no_parm + movzx esi, word [es:bx + PKTIOCTL.pParm] ; offset + mov dl, DevHlp_VirtToLin + call far [NAME(g_fpfnDevHlp)] + jc near VBoxDrvEP_GeneralFailure + jmp .finish_parm +.no_parm: + xor eax, eax +.finish_parm: + push eax ; 0ch + + ; function. + movzx edx, byte [es:bx + PKTIOCTL.fun] + push edx ; 08h + + ; category. + movzx ecx, byte [es:bx + PKTIOCTL.cat] + push ecx ; 04h + + ; system file number. + movzx eax, word [es:bx + PKTIOCTL.sfn] + push eax ; 00h + + ; go to the 32-bit code + ;jmp far dword NAME(VBoxDrvEP_GenIOCtl_Other_32) wrt FLAT + db 066h + db 0eah + dd NAME(VBoxDrvEP_GenIOCtl_Other_32) ;wrt FLAT + dw TEXT32 wrt FLAT +segment TEXT32 +GLOBALNAME VBoxDrvEP_GenIOCtl_Other_32 + + ; switch stack to 32-bit. + mov ax, DATA32 wrt FLAT + mov ds, ax + mov es, ax + call KernThunkStackTo32 + + ; update in/out parameter pointers + lea eax, [esp + 1ch] + mov [esp + 14h], eax + lea edx, [esp + 1eh] + mov [esp + 18h], edx + + ; call the C code (don't cleanup the stack). + call NAME(VBoxDrvIOCtl) + + ; switch back the stack. + push eax + call KernThunkStackTo16 + pop eax + + ; jump back to the 16-bit code. + ;jmp far dword NAME(VBoxDrvEP_GenIOCtl_Other_16) wrt CODE16 + db 066h + db 0eah + dw NAME(VBoxDrvEP_GenIOCtl_Other_16) wrt CODE16 + dw CODE16 +segment CODE16 +GLOBALNAME VBoxDrvEP_GenIOCtl_Other_16 + les bx, [bp - 4] ; Reload the packet pointer. + or eax, eax + jnz near VBoxDrvEP_GeneralFailure + + ; setup output stuff. + mov edx, esp + mov eax, [ss:edx + 1ch] ; output sizes. + mov [es:bx + PKTIOCTL.cbParm], eax ; update cbParm and cbData. + mov word [es:bx + PKTHDR.status], 00100h ; done, ok. + + mov sp, bp + pop ebp + retf + + + ; + ; Less Performance Critical Requests. + ; +VBoxDrvEP_NotGenIOCtl: + cmp byte [es:bx + PKTHDR.cmd], 0dh ; Open + je VBoxDrvEP_Open + cmp byte [es:bx + PKTHDR.cmd], 0eh ; Close + je VBoxDrvEP_Close + cmp byte [es:bx + PKTHDR.cmd], 00h ; Init + je VBoxDrvEP_Init + cmp byte [es:bx + PKTHDR.cmd], 04h ; Read + je near VBoxDrvEP_Read + jmp near VBoxDrvEP_NotSupported + + + ; + ; Open Request. w/ ring-0 init. + ; +VBoxDrvEP_Open: + cmp byte [NAME(g_fInitialized)], 1 + jne VBoxDrvEP_OpenOther + + ; First argument, the system file number. + movzx eax, word [es:bx + PKTOPEN.sfn] + push eax + + ; go to the 32-bit code + ;jmp far dword NAME(VBoxDrvEP_Open_32) wrt FLAT + db 066h + db 0eah + dd NAME(VBoxDrvEP_Open_32) ;wrt FLAT + dw TEXT32 wrt FLAT +segment TEXT32 +GLOBALNAME VBoxDrvEP_Open_32 + + ; switch stack to 32-bit. + mov ax, DATA32 wrt FLAT + mov ds, ax + mov es, ax + call KernThunkStackTo32 + + ; call the C code. + call NAME(VBoxDrvOpen) + + ; switch back the stack. + push eax + call KernThunkStackTo16 + pop eax + + ; jump back to the 16-bit code. + ;jmp far dword NAME(VBoxDrvEP_Open_32) wrt CODE16 + db 066h + db 0eah + dw NAME(VBoxDrvEP_Open_16) wrt CODE16 + dw CODE16 +segment CODE16 +GLOBALNAME VBoxDrvEP_Open_16 + les bx, [bp - 4] ; Reload the packet pointer. + or eax, eax + jnz near VBoxDrvEP_GeneralFailure + mov word [es:bx + PKTHDR.status], 00100h ; done, ok. + jmp near VBoxDrvEP_Done + + ; Initializing or failed init? +VBoxDrvEP_OpenOther: + cmp byte [NAME(g_fInitialized)], 0 + jne VBoxDrvEP_OpenFailed + + mov byte [NAME(g_fInitialized)], -1 + call NAME(VBoxDrvRing0Init) + cmp byte [NAME(g_fInitialized)], 1 + je VBoxDrvEP_Open + +VBoxDrvEP_OpenFailed: + mov word [es:bx + PKTHDR.status], 0810fh ; error, done, init failed. + jmp near VBoxDrvEP_Done + + + ; + ; Close Request. + ; +VBoxDrvEP_Close: + ; First argument, the system file number. + movzx eax, word [es:bx + PKTOPEN.sfn] + push eax + + ; go to the 32-bit code + ;jmp far dword NAME(VBoxDrvEP_Close_32) wrt FLAT + db 066h + db 0eah + dd NAME(VBoxDrvEP_Close_32) ;wrt FLAT + dw TEXT32 wrt FLAT +segment TEXT32 +GLOBALNAME VBoxDrvEP_Close_32 + + ; switch stack to 32-bit. + mov ax, DATA32 wrt FLAT + mov ds, ax + mov es, ax + call KernThunkStackTo32 + + ; call the C code. + call NAME(VBoxDrvClose) + + ; switch back the stack. + push eax + call KernThunkStackTo16 + pop eax + + ; jump back to the 16-bit code. + ;jmp far dword NAME(VBoxDrvEP_Close_32) wrt CODE16 + db 066h + db 0eah + dw NAME(VBoxDrvEP_Close_16) wrt CODE16 + dw CODE16 +segment CODE16 +GLOBALNAME VBoxDrvEP_Close_16 + les bx, [bp - 4] ; Reload the packet pointer. + or eax, eax + jnz near VBoxDrvEP_GeneralFailure + mov word [es:bx + PKTHDR.status], 00100h ; done, ok. + jmp near VBoxDrvEP_Done + + + ; + ; Init Request. + ; The other driver header will do this. + ; +VBoxDrvEP_Init: + mov word [es:bx + PKTHDR.status], 00100h ; done, ok. + mov byte [es:bx + PKTINITOUT.cUnits], 0 + mov word [es:bx + PKTINITOUT.cbCode16], NAME(g_InitCodeStart) wrt CODE16 + mov word [es:bx + PKTINITOUT.cbData16], NAME(g_InitDataStart) wrt DATA16 + mov dword [es:bx + PKTINITOUT.fpaBPBs], 0 + jmp near VBoxDrvEP_Done + + + ; + ; Read Request. + ; Return log data. + ; +VBoxDrvEP_Read: + ; Any log data available? + xor dx, dx + mov ax, [NAME(g_offLogTail)] + cmp ax, [NAME(g_offLogHead)] + jz near .log_done + + ; create a temporary mapping of the physical buffer. Docs claims it trashes nearly everything... + push ebp + mov cx, [es:bx + PKTRW.cbTrans] + push cx + mov ax, [es:bx + PKTRW.PhysTrans + 2] + mov bx, [es:bx + PKTRW.PhysTrans] + mov dh, 1 + mov dl, DevHlp_PhysToVirt + call far [NAME(g_fpfnDevHlp)] + pop bx ; bx = cbTrans + pop ebp + jc near .log_phystovirt_failed + ; es:di -> the output buffer. + + ; setup the copy operation. + mov ax, [NAME(g_offLogTail)] + xor dx, dx ; dx tracks the number of bytes copied. +.log_loop: + mov cx, [NAME(g_offLogHead)] + cmp ax, cx + je .log_done + jb .log_loop_before + mov cx, LOG_SIZE +.log_loop_before: ; cx = end offset + sub cx, ax ; cx = sequential bytes to copy. + cmp cx, bx + jbe .log_loop_min + mov cx, bx ; output buffer is smaller than available data. +.log_loop_min: + mov si, NAME(g_szLog) + add si, ax ; ds:si -> the log buffer. + add dx, cx ; update output counter + add ax, cx ; calc new offLogTail + and ax, LOG_SIZE - 1 + rep movsb ; do the copy + mov [NAME(g_offLogTail)], ax ; commit the read. + jmp .log_loop + +.log_done: + les bx, [bp - 4] ; Reload the packet pointer. + mov word [es:bx + PKTRW.cbTrans], dx + mov word [es:bx + PKTHDR.status], 00100h ; done, ok. + jmp near VBoxDrvEP_Done + +.log_phystovirt_failed: + les bx, [bp - 4] ; Reload the packet pointer. + jmp VBoxDrvEP_GeneralFailure + + + ; + ; Return 'unknown command' error. + ; +VBoxDrvEP_NotSupported: + mov word [es:bx + PKTHDR.status], 08103h ; error, done, unknown command. + jmp VBoxDrvEP_Done + + ; + ; Return 'general failure' error. + ; +VBoxDrvEP_GeneralFailure: + mov word [es:bx + PKTHDR.status], 0810ch ; error, done, general failure. + jmp VBoxDrvEP_Done + + ; + ; Non-optimized return path. + ; +VBoxDrvEP_Done: + mov sp, bp + pop ebp + retf +ENDPROC VBoxDrvEP + + +;; +; The helper device entry point. +; +; This is only used to do the DosOpen on the main driver so we can +; do ring-3 init and report failures. +; +GLOBALNAME VBoxDrvInitEP + ; The only request we're servicing is the 'init' one. + cmp word [es:bx + PKTHDR.cmd], 0 + je near NAME(VBoxDrvInitEPServiceInitReq) + + ; Ok, it's not the init request, just fail it. + mov word [es:bx + PKTHDR.status], 08103h ; error, done, unknown command. + retf + + +; +; The 16-bit init code. +; +segment CODE16_INIT +GLOBALNAME g_InitCodeStart + +;; The device name for DosOpen. +g_szDeviceName: + db '\DEV\vboxdrv$', 0 + +; icsdebug can't see where stuff starts otherwise. (kDevTest) +int3 +int3 +int3 +int3 +int3 +int3 + +;; +; The Ring-3 init code. +; +BEGINPROC VBoxDrvInitEPServiceInitReq + push ebp + mov ebp, esp + push es ; bp - 2 + push sp ; bp - 4 + push -1 ; bp - 6: hfOpen + push 0 ; bp - 8: usAction + and sp, 0fffch + + ; check for the init package. + cmp word [es:bx + PKTHDR.cmd], 0 + jne near .not_init + + ; + ; Copy the data out of the init packet. + ; + mov eax, [es:bx + PKTINITIN.fpfnDevHlp] + mov [NAME(g_fpfnDevHlp)], eax + mov edx, [es:bx + PKTINITIN.fpszArgs] + mov [g_fpszArgs], edx + + ; + ; Open the first driver, close it, and check status. + ; + + ; APIRET _Pascal DosOpen(PSZ pszFname, PHFILE phfOpen, PUSHORT pusAction, + ; ULONG ulFSize, USHORT usAttr, USHORT fsOpenFlags, + ; USHORT fsOpenMode, ULONG ulReserved); + push seg g_szDeviceName ; pszFname + push g_szDeviceName + push ss ; phfOpen + lea dx, [bp - 6] + push dx + push ss ; pusAction + lea dx, [bp - 8] + push dx + push dword 0 ; ulFSize + push 0 ; usAttr = FILE_NORMAL + push 1 ; fsOpenFlags = FILE_OPEN + push 00040h ; fsOpenMode = OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY + push dword 0 ; ulReserved + call far DOS16OPEN + + push ax ; Quickly flush any text. + call NAME(VBoxDrvInitFlushText) + pop ax + + or ax, ax + jnz .done_err + + ; APIRET APIENTRY DosClose(HFILE hf); + mov cx, [bp - 6] + push cx + call far DOS16CLOSE + or ax, ax + jnz .done_err ; This can't happen (I hope). + + ; + ; Ok, we're good. + ; + mov word [es:bx + PKTHDR.status], 00100h ; done, ok. + mov byte [es:bx + PKTINITOUT.cUnits], 0 + mov word [es:bx + PKTINITOUT.cbCode16], NAME(g_InitCodeStart) wrt CODE16 + mov word [es:bx + PKTINITOUT.cbData16], NAME(g_InitDataStart) wrt DATA16 + mov dword [es:bx + PKTINITOUT.fpaBPBs], 0 + jmp .done + + ; + ; Init failure. + ; +.done_err: + mov word [es:bx + PKTHDR.status], 0810fh ; error, done, init failed. + mov byte [es:bx + PKTINITOUT.cUnits], 0 + mov word [es:bx + PKTINITOUT.cbCode16], 0 + mov word [es:bx + PKTINITOUT.cbData16], 0 + mov dword [es:bx + PKTINITOUT.fpaBPBs], 0 + jmp .done + + ; + ; Not init, return 'unknown command'. + ; +.not_init: + mov word [es:bx + PKTHDR.status], 08103h ; error, done, unknown command. + jmp .done + + ; + ; Request done. + ; +.done: + mov sp, bp + pop ebp + retf +ENDPROC VBoxDrvInitEPServiceInitReq + + +;; +; The Ring-0 init code. +; +BEGINPROC VBoxDrvRing0Init + push es + push esi + push ebp + mov ebp, esp + and sp, 0fffch + + ; + ; Thunk the argument string pointer first. + ; + movzx esi, word [g_fpszArgs] ; offset + mov ax, [g_fpszArgs + 2] ; selector + mov dl, DevHlp_VirtToLin + call far [NAME(g_fpfnDevHlp)] + jc near VBoxDrvRing0Init_done ; eax is non-zero on failure (can't happen) + push eax ; 00h - pszArgs (for VBoxDrvInit). + + ; + ; Do 16-bit init? + ; + + + ; + ; Do 32-bit init + ; + ;jmp far dword NAME(VBoxDrvRing0Init_32) wrt FLAT + db 066h + db 0eah + dd NAME(VBoxDrvRing0Init_32) ;wrt FLAT + dw TEXT32 wrt FLAT +segment TEXT32 +GLOBALNAME VBoxDrvRing0Init_32 + + ; switch stack to 32-bit. + mov ax, DATA32 wrt FLAT + mov ds, ax + mov es, ax + call KernThunkStackTo32 + + ; call the C code. + call NAME(VBoxDrvInit) + + ; switch back the stack and reload ds. + push eax + call KernThunkStackTo16 + pop eax + + mov dx, seg NAME(g_fInitialized) + mov ds, dx + + ; jump back to the 16-bit code. + ;jmp far dword NAME(VBoxDrvRing0Init_16) wrt CODE16 + db 066h + db 0eah + dw NAME(VBoxDrvRing0Init_16) wrt CODE16 + dw CODE16_INIT +segment CODE16_INIT +GLOBALNAME VBoxDrvRing0Init_16 + + ; check the result and set g_fInitialized on success. + or eax, eax + jnz VBoxDrvRing0Init_done + mov byte [NAME(g_fInitialized)], 1 + +VBoxDrvRing0Init_done: + mov sp, bp + pop ebp + pop esi + pop es + ret +ENDPROC VBoxDrvRing0Init + + +;; +; Flush any text in the text buffer. +; +BEGINPROC VBoxDrvInitFlushText + push bp + mov bp, sp + + ; Anything in the buffer? + mov ax, [NAME(g_cchInitText)] + or ax, ax + jz .done + +%if 1 + ; Write it to STDOUT. + ; APIRET _Pascal DosWrite(HFILE hf, PVOID pvBuf, USHORT cbBuf, PUSHORT pcbBytesWritten); + push ax ; bp - 2 : cbBytesWritten + mov cx, sp + push 1 ; STDOUT + push seg NAME(g_szInitText) ; pvBuf + push NAME(g_szInitText) + push ax ; cbBuf + push ss ; pcbBytesWritten + push cx +%if 0 ; wlink generates a non-aliased fixup here which results in 16-bit offset with the flat 32-bit selector. + call far DOS16WRITE +%else + ; convert flat pointer to a far pointer using the tiled algorithm. + push ds + mov ax, DATA32 wrt FLAT + mov ds, ax + mov eax, g_pfnDos16Write wrt FLAT + movzx eax, word [eax + 2] ; High word of the flat address (in DATA32). + shl ax, 3 + or ax, 0007h + pop ds + mov [NAME(g_fpfnDos16Write) + 2], ax ; Update the selector (in DATA16_INIT). + ; do the call + call far [NAME(g_fpfnDos16Write)] +%endif + +%else ; alternative workaround for the wlink issue. + ; Use the save message devhlp. + push esi + push ebx + xor bx, bx + mov si, NAME(g_MsgTab) + mov dx, seg NAME(g_MsgTab) + mov ds, dx + mov dl, DevHlp_SAVE_MESSAGE + call far [NAME(g_fpfnDevHlp)] + pop ebx + pop esi +%endif + + ; Empty the buffer. + mov word [NAME(g_cchInitText)], 0 + mov byte [NAME(g_szInitText)], 0 + +.done: + mov sp, bp + pop bp + ret +ENDPROC VBoxDrvInitFlushText + + + +;; +; This must be present +segment DATA32 +g_pfnDos16Write: + dd DOS16WRITE ; flat + diff --git a/src/VBox/HostDrivers/Support/os2/SUPLib-os2.cpp b/src/VBox/HostDrivers/Support/os2/SUPLib-os2.cpp new file mode 100644 index 00000000..5da2fb81 --- /dev/null +++ b/src/VBox/HostDrivers/Support/os2/SUPLib-os2.cpp @@ -0,0 +1,193 @@ +/* $Id: SUPLib-os2.cpp $ */ +/** @file + * VirtualBox Support Library - OS/2 specific parts. + */ + +/* + * Copyright (C) 2006-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define INCL_BASE +#define INCL_ERRORS +#include <os2.h> +#undef RT_MAX + +#ifdef IN_SUP_HARDENED_R3 +# undef DEBUG /* Warning: disables RT_STRICT */ +# define LOG_DISABLED +# define RTLOG_REL_DISABLED +# include <iprt/log.h> +#endif + +#include <VBox/types.h> +#include <VBox/sup.h> +#include <VBox/param.h> +#include <VBox/err.h> +#include <VBox/log.h> +#include <iprt/path.h> +#include <iprt/assert.h> +#include <iprt/err.h> +#include "../SUPLibInternal.h" +#include "../SUPDrvIOC.h" + +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +/** OS/2 Device name. */ +#define DEVICE_NAME "/dev/vboxdrv$" + + + +int suplibOsInit(PSUPLIBDATA pThis, bool fPreInited, bool fUnrestricted, SUPINITOP *penmWhat, PRTERRINFO pErrInfo) +{ + /* + * Nothing to do if pre-inited. + */ + if (fPreInited) + return VINF_SUCCESS; + + /* + * Try open the device. + */ + ULONG ulAction = 0; + HFILE hDevice = (HFILE)-1; + APIRET rc = DosOpen((PCSZ)DEVICE_NAME, + &hDevice, + &ulAction, + 0, + FILE_NORMAL, + OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS, + OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, + NULL); + if (rc) + { + int vrc; + switch (rc) + { + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: vrc = VERR_VM_DRIVER_NOT_INSTALLED; break; + default: vrc = VERR_VM_DRIVER_OPEN_ERROR; break; + } + LogRel(("Failed to open \"%s\", rc=%d, vrc=%Rrc\n", DEVICE_NAME, rc, vrc)); + return vrc; + } + + pThis->hDevice = hDevice; + pThis->fUnrestricted = true; + return VINF_SUCCESS; +} + + +int suplibOsTerm(PSUPLIBDATA pThis) +{ + /* + * Check if we're inited at all. + */ + if (pThis->hDevice != (intptr_t)NIL_RTFILE) + { + APIRET rc = DosClose((HFILE)pThis->hDevice); + AssertMsg(rc == NO_ERROR, ("%d\n", rc)); NOREF(rc); + pThis->hDevice = (intptr_t)NIL_RTFILE; + } + + return 0; +} + + +#ifndef IN_SUP_HARDENED_R3 + +int suplibOsInstall(void) +{ + /** @remark OS/2: Not supported */ + return VERR_NOT_SUPPORTED; +} + + +int suplibOsUninstall(void) +{ + /** @remark OS/2: Not supported */ + return VERR_NOT_SUPPORTED; +} + + +int suplibOsIOCtl(PSUPLIBDATA pThis, uintptr_t uFunction, void *pvReq, size_t cbReq) +{ + ULONG cbReturned = sizeof(SUPREQHDR); + int rc = DosDevIOCtl((HFILE)pThis->hDevice, SUP_CTL_CATEGORY, uFunction, + pvReq, cbReturned, &cbReturned, + NULL, 0, NULL); + if (RT_LIKELY(rc == NO_ERROR)) + return VINF_SUCCESS; + return RTErrConvertFromOS2(rc); +} + + +int suplibOsIOCtlFast(PSUPLIBDATA pThis, uintptr_t uFunction, uintptr_t idCpu) +{ + NOREF(idCpu); + int32_t rcRet = VERR_INTERNAL_ERROR; + int rc = DosDevIOCtl((HFILE)pThis->hDevice, SUP_CTL_CATEGORY_FAST, uFunction, + NULL, 0, NULL, + NULL, 0, NULL); + if (RT_LIKELY(rc == NO_ERROR)) + rc = rcRet; + else + rc = RTErrConvertFromOS2(rc); + return rc; +} + + +int suplibOsPageAlloc(PSUPLIBDATA pThis, size_t cPages, void **ppvPages) +{ + NOREF(pThis); + *ppvPages = NULL; + int rc = DosAllocMem(ppvPages, cPages << PAGE_SHIFT, PAG_READ | PAG_WRITE | PAG_EXECUTE | PAG_COMMIT | OBJ_ANY); + if (rc == ERROR_INVALID_PARAMETER) + rc = DosAllocMem(ppvPages, cPages << PAGE_SHIFT, PAG_READ | PAG_WRITE | PAG_EXECUTE | PAG_COMMIT | OBJ_ANY); + if (!rc) + rc = VINF_SUCCESS; + else + rc = RTErrConvertFromOS2(rc); + return rc; +} + + +int suplibOsPageFree(PSUPLIBDATA pThis, void *pvPages, size_t /* cPages */) +{ + NOREF(pThis); + if (pvPages) + { + int rc = DosFreeMem(pvPages); + Assert(!rc); NOREF(rc); + } + return VINF_SUCCESS; +} + +#endif /* !IN_SUP_HARDENED_R3 */ + diff --git a/src/VBox/HostDrivers/Support/os2/SUPR0IdcClient-os2.c b/src/VBox/HostDrivers/Support/os2/SUPR0IdcClient-os2.c new file mode 100644 index 00000000..f9e7c35e --- /dev/null +++ b/src/VBox/HostDrivers/Support/os2/SUPR0IdcClient-os2.c @@ -0,0 +1,51 @@ +/* $Id: SUPR0IdcClient-os2.c $ */ +/** @file + * VirtualBox Support Driver - IDC Client Lib, OS/2 Specific Code. + */ + +/* + * Copyright (C) 2008-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "../SUPR0IdcClientInternal.h" +#include <iprt/errcore.h> + + +int VBOXCALL supR0IdcNativeOpen(PSUPDRVIDCHANDLE pHandle, PSUPDRVIDCREQCONNECT pReq) +{ + return VERR_NOT_SUPPORTED; +} + + +int VBOXCALL supR0IdcNativeClose(PSUPDRVIDCHANDLE pHandle, PSUPDRVIDCREQHDR pReq) +{ + return VERR_NOT_SUPPORTED; +} + + +int VBOXCALL supR0IdcNativeCall(PSUPDRVIDCHANDLE pHandle, uint32_t iReq, PSUPDRVIDCREQHDR pReq) +{ + return VERR_NOT_SUPPORTED; +} + |