示例#1
0
int vboxscsiReadString(PPDMDEVINS pDevIns, PVBOXSCSI pVBoxSCSI, uint8_t iRegister,
                       RTGCPTR *pGCPtrDst, PRTGCUINTREG pcTransfer, unsigned cb)
{
    RTGCPTR  GCDst      = *pGCPtrDst;
    uint32_t cbTransfer = *pcTransfer * cb;

    LogFlowFunc(("pDevIns=%#p pVBoxSCSI=%#p iRegister=%d cTransfer=%u cb=%u\n",
                 pDevIns, pVBoxSCSI, iRegister, *pcTransfer, cb));

    /* Read string only valid for data in register. */
    AssertMsg(iRegister == 1, ("Hey only register 1 can be read from with string\n"));
    Assert(pVBoxSCSI->pBuf);

    int rc = PGMPhysSimpleDirtyWriteGCPtr(PDMDevHlpGetVMCPU(pDevIns), GCDst, pVBoxSCSI->pBuf, cbTransfer);
    AssertRC(rc);

    *pGCPtrDst = (RTGCPTR)((RTGCUINTPTR)GCDst + cbTransfer);
    *pcTransfer = 0;

    RTMemFree(pVBoxSCSI->pBuf);
    pVBoxSCSI->pBuf  = NULL;
    pVBoxSCSI->cbBuf = 0;
    pVBoxSCSI->cbCDB = 0;
    pVBoxSCSI->iCDB  = 0;
    pVBoxSCSI->iBuf  = 0;
    pVBoxSCSI->uTargetDevice = 0;
    pVBoxSCSI->enmState = VBOXSCSISTATE_NO_COMMAND;
    memset(pVBoxSCSI->aCDB, 0, sizeof(pVBoxSCSI->aCDB));

    return rc;
}
示例#2
0
/**
 * Check Windows XP sysenter heuristics and install patch
 *
 * @returns VBox status code.
 * @param   pVM         Pointer to the VM.
 * @param   pInstrGC    GC Instruction pointer for sysenter
 * @param   pPatchRec   Patch structure
 *
 */
int PATMPatchSysenterXP(PVM pVM, RTGCPTR32 pInstrGC, PPATMPATCHREC pPatchRec)
{
    PPATCHINFO  pPatch = &pPatchRec->patch;
    uint8_t     uTemp[16];
    RTGCPTR32   lpfnKiFastSystemCall, lpfnKiIntSystemCall = 0; /* (initializing it to shut up warning.) */
    int         rc, i;
    PVMCPU      pVCpu = VMMGetCpu0(pVM);

    Assert(sizeof(uTemp) > sizeof(uFnKiIntSystemCall));
    Assert(sizeof(uTemp) > sizeof(uFnKiFastSystemCall));

    /* Guest OS specific patch; check heuristics first */

    /* check the epilog of KiFastSystemCall */
    lpfnKiFastSystemCall = pInstrGC - 2;
    rc = PGMPhysSimpleReadGCPtr(pVCpu, uTemp, lpfnKiFastSystemCall, sizeof(uFnKiFastSystemCall));
    if (    RT_FAILURE(rc)
        ||  memcmp(uFnKiFastSystemCall, uTemp, sizeof(uFnKiFastSystemCall)))
    {
        return VERR_PATCHING_REFUSED;
    }

    /* Now search for KiIntSystemCall */
    for (i=0;i<64;i++)
    {
        rc = PGMPhysSimpleReadGCPtr(pVCpu, uTemp, pInstrGC + i, sizeof(uFnKiIntSystemCall));
        if(RT_FAILURE(rc))
        {
            break;
        }
        if(!memcmp(uFnKiIntSystemCall, uTemp, sizeof(uFnKiIntSystemCall)))
        {
            lpfnKiIntSystemCall = pInstrGC + i;
            /* Found it! */
            break;
        }
    }
    if (i == 64)
    {
        Log(("KiIntSystemCall not found!!\n"));
        return VERR_PATCHING_REFUSED;
    }

    if (PAGE_ADDRESS(lpfnKiFastSystemCall) != PAGE_ADDRESS(lpfnKiIntSystemCall))
    {
        Log(("KiFastSystemCall and KiIntSystemCall not in the same page!!\n"));
        return VERR_PATCHING_REFUSED;
    }

    // make a copy of the guest code bytes that will be overwritten
    rc = PGMPhysSimpleReadGCPtr(pVCpu, pPatch->aPrivInstr, pPatch->pPrivInstrGC, SIZEOF_NEARJUMP32);
    AssertRC(rc);

    /* Now we simply jump from the fast version to the 'old and slow' system call */
    uTemp[0] = 0xE9;
    *(RTGCPTR32 *)&uTemp[1] = lpfnKiIntSystemCall - (pInstrGC + SIZEOF_NEARJUMP32);
    rc = PGMPhysSimpleDirtyWriteGCPtr(pVCpu, pInstrGC, uTemp, SIZEOF_NEARJUMP32);
    if (RT_FAILURE(rc))
    {
        Log(("PGMPhysSimpleDirtyWriteGCPtr failed with rc=%Rrc!!\n", rc));
        return VERR_PATCHING_REFUSED;
    }

#ifdef LOG_ENABLED
    Log(("Sysenter Patch code ----------------------------------------------------------\n"));
    PATMP2GLOOKUPREC cacheRec;
    RT_ZERO(cacheRec);
    cacheRec.pPatch = pPatch;

    patmr3DisasmCodeStream(pVM, pInstrGC, pInstrGC, patmr3DisasmCallback, &cacheRec);
    /* Free leftover lock if any. */
    if (cacheRec.Lock.pvMap)
        PGMPhysReleasePageMappingLock(pVM, &cacheRec.Lock);
    Log(("Sysenter Patch code ends -----------------------------------------------------\n"));
#endif

    pPatch->uState = PATCH_ENABLED;
    return VINF_SUCCESS;
}