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; }
/** * 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; }