/** * Mouse event handler. * * @returns VBox status code. * @param pThis The PS/2 auxiliary device instance data. * @param dx X direction movement delta. * @param dy Y direction movement delta. * @param dz Z (vertical scroll) movement delta. * @param dw W (horizontal scroll) movement delta. * @param fButtons Depressed button mask. */ static int ps2mPutEventWorker(PPS2M pThis, int32_t dx, int32_t dy, int32_t dz, int32_t dw, uint32_t fButtons) { RT_NOREF1(dw); int rc = VINF_SUCCESS; /* Update internal accumulators and button state. */ pThis->iAccumX += dx; pThis->iAccumY += dy; pThis->iAccumZ += dz; pThis->fAccumB |= fButtons; /// @todo accumulate based on current protocol? pThis->fCurrB = fButtons; #if 1 /* Report the event and start the throttle timer unless it's already running. */ if (!pThis->fThrottleActive) { ps2mReportAccumulatedEvents(pThis, (GeneriQ *)&pThis->evtQ, true); KBCUpdateInterrupts(pThis->pParent); pThis->fThrottleActive = true; TMTimerSetMillies(pThis->CTX_SUFF(pThrottleTimer), pThis->uThrottleDelay); } #else /* Clamp the delta values to the allowed range. */ dx = RT_MIN(RT_MAX(dx, -256), 255); dy = RT_MIN(RT_MAX(dy, -256), 255); /* Start with the sync bit. */ val = RT_BIT(3); /* Add buttons 1-3. */ val |= fButtons & PS2M_STD_BTN_MASK; /* Set the X/Y sign bits. */ if (dx < 0) val |= RT_BIT(4); if (dy < 0) val |= RT_BIT(5); ps2kInsertQueue((GeneriQ *)&pThis->evtQ, val); ps2kInsertQueue((GeneriQ *)&pThis->evtQ, (uint8_t)dx); ps2kInsertQueue((GeneriQ *)&pThis->evtQ, (uint8_t)dy); if (pThis->enmProtocol > PS2M_PROTO_PS2STD) { ps2kInsertQueue((GeneriQ *)&pThis->evtQ, (uint8_t)dz); } #endif return rc; }
/* Report accumulated movement and button presses, then clear the accumulators. */ static void ps2mReportAccumulatedEvents(PPS2M pThis, GeneriQ *pQueue, bool fAccumBtns) { uint32_t fBtnState = fAccumBtns ? pThis->fAccumB : pThis->fCurrB; uint8_t val; int dX, dY, dZ; /* Clamp the accumulated delta values to the allowed range. */ dX = RT_MIN(RT_MAX(pThis->iAccumX, -255), 255); dY = RT_MIN(RT_MAX(pThis->iAccumY, -255), 255); dZ = RT_MIN(RT_MAX(pThis->iAccumZ, -8), 7); /* Start with the sync bit and buttons 1-3. */ val = RT_BIT(3) | (fBtnState & PS2M_STD_BTN_MASK); /* Set the X/Y sign bits. */ if (dX < 0) val |= RT_BIT(4); if (dY < 0) val |= RT_BIT(5); /* Send the standard 3-byte packet (always the same). */ ps2kInsertQueue(pQueue, val); ps2kInsertQueue(pQueue, dX); ps2kInsertQueue(pQueue, dY); /* Add fourth byte if extended protocol is in use. */ if (pThis->enmProtocol > PS2M_PROTO_PS2STD) { if (pThis->enmProtocol == PS2M_PROTO_IMPS2) ps2kInsertQueue(pQueue, dZ); else { Assert(pThis->enmProtocol == PS2M_PROTO_IMEX); /* Z value uses 4 bits; buttons 4/5 in bits 4 and 5. */ val = dZ & 0x0f; val |= (fBtnState << 1) & (RT_BIT(4) | RT_BIT(5)); ps2kInsertQueue(pQueue, val); } } /* Clear the movement accumulators, but not necessarily button state. */ pThis->iAccumX = pThis->iAccumY = pThis->iAccumZ = 0; /* Clear accumulated button state only when it's being used. */ if (fAccumBtns) { pThis->fReportedB = pThis->fAccumB; pThis->fAccumB = 0; } }
/** Print the 'true' if nested paging is supported, 'false' if not and * 'dunno' if we cannot tell. */ static RTEXITCODE handlerCpuNestedPaging(int argc, char **argv) { NOREF(argc); NOREF(argv); HWVIRTTYPE enmHwVirt = isHwVirtSupported(); int fSupported = -1; #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) if (enmHwVirt == HWVIRTTYPE_AMDV) { uint32_t uEax, uEbx, uEcx, uEdx; ASMCpuId(0x80000000, &uEax, &uEbx, &uEcx, &uEdx); if (ASMIsValidExtRange(uEax) && uEax >= 0x8000000a) { ASMCpuId(0x8000000a, &uEax, &uEbx, &uEcx, &uEdx); if (uEdx & RT_BIT(0) /* AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING */) fSupported = 1; else fSupported = 0; } } #endif int cch = RTPrintf(fSupported == 1 ? "true\n" : fSupported == 0 ? "false\n" : "dunno\n"); return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; }
/* Report accumulated movement and button presses, then clear the accumulators. */ static void ps2mReportAccumulatedEvents(PPS2M pThis) { uint8_t val; int8_t dX, dY, dZ; /* Clamp the accumulated delta values to the allowed range. */ dX = RT_MIN(RT_MAX(pThis->iAccumX, -256), 255); dY = RT_MIN(RT_MAX(pThis->iAccumY, -256), 255); dZ = RT_MIN(RT_MAX(pThis->iAccumZ, -8), 7); /* Start with the sync bit and buttons 1-3. */ val = RT_BIT(3) | (pThis->fAccumB & PS2M_STD_BTN_MASK); /* Set the X/Y sign bits. */ if (dX < 0) val |= RT_BIT(4); if (dY < 0) val |= RT_BIT(5); /* Send the standard 3-byte packet (always the same). */ ps2kInsertQueue((GeneriQ *)&pThis->evtQ, val); ps2kInsertQueue((GeneriQ *)&pThis->evtQ, dX); ps2kInsertQueue((GeneriQ *)&pThis->evtQ, dY); /* Add fourth byte if extended protocol is in use. */ if (pThis->enmProtocol > PS2M_PROTO_PS2STD) { if (pThis->enmProtocol == PS2M_PROTO_IMPS2) ps2kInsertQueue((GeneriQ *)&pThis->evtQ, dZ); else { Assert(pThis->enmProtocol == PS2M_PROTO_IMEX); /* Z value uses 4 bits; buttons 4/5 in bits 4 and 5. */ val = dZ & 0x0f; val |= (pThis->fAccumB << 1) & (RT_BIT(4) | RT_BIT(5)); ps2kInsertQueue((GeneriQ *)&pThis->evtQ, dZ); } } /* Clear the accumulators. */ pThis->iAccumX = pThis->iAccumY = pThis->iAccumZ = pThis->fAccumB = 0; /* Poke the KBC to update its state. */ KBCUpdateInterrupts(pThis->pParent); }
int vscsiReqSenseErrorInfoSet(PVSCSISENSE pVScsiSense, PVSCSIREQINT pVScsiReq, uint8_t uSCSISenseKey, uint8_t uSCSIASC, uint8_t uSCSIASCQ, uint32_t uInfo) { memset(pVScsiSense->abSenseBuf, 0, sizeof(pVScsiSense->abSenseBuf)); pVScsiSense->abSenseBuf[0] = RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED; /* Fixed format */ pVScsiSense->abSenseBuf[2] = uSCSISenseKey; vscsiH2BEU32(&pVScsiSense->abSenseBuf[3], uInfo); pVScsiSense->abSenseBuf[7] = 10; pVScsiSense->abSenseBuf[12] = uSCSIASC; pVScsiSense->abSenseBuf[13] = uSCSIASCQ; if (pVScsiReq->pbSense && pVScsiReq->cbSense) memcpy(pVScsiReq->pbSense, pVScsiSense->abSenseBuf, RT_MIN(sizeof(pVScsiSense->abSenseBuf), pVScsiReq->cbSense)); return SCSI_STATUS_CHECK_CONDITION; }
static bool rtFsExtIsBlockRangeInUse(PRTFILESYSTEMEXTBLKGRP pBlkGrpDesc, uint32_t offBlockStart, size_t cBlocks) { bool fUsed = false; while (cBlocks) { uint32_t idxByte = offBlockStart / 8; uint32_t iBit = offBlockStart % 8; if (pBlkGrpDesc->abBlockBitmap[idxByte] & RT_BIT(iBit)) { fUsed = true; break; } cBlocks--; offBlockStart++; } return fUsed; }
int main() { /* * Init the runtime and stuff. */ RTTEST hTest; int rc = RTTestInitAndCreate("tstRTBitOperations", &hTest); if (rc) return rc; RTTestBanner(hTest); int i; int j; int k; /* * Tests */ struct TestMap { uint32_t au32[4]; }; #if 0 struct TestMap sTest; struct TestMap *p = &sTest; #else struct TestMap *p = (struct TestMap *)RTTestGuardedAllocTail(hTest, sizeof(*p)); #endif #define DUMP() RTTestPrintf(hTest, RTTESTLVL_INFO, "au32={%08x,%08x,%08x,%08x}", p->au32[0], p->au32[1], p->au32[2], p->au32[3]) #define CHECK(expr) do { if (!(expr)) { RTTestFailed(hTest, "line %d: %s", __LINE__, #expr); DUMP(); } CHECK_GUARD(s); } while (0) #define CHECK_BIT(expr, b1) do { if (!(expr)) { RTTestFailed(hTest, "line %d, b1=%d: %s", __LINE__, b1, #expr); } CHECK_GUARD(s); } while (0) #define CHECK_BIT2(expr, b1, b2) do { if (!(expr)) { RTTestFailed(hTest, "line %d, b1=%d b2=%d: %s", __LINE__, b1, b2, #expr); } CHECK_GUARD(s); } while (0) #define CHECK_BIT3(expr, b1, b2, b3) do { if (!(expr)) { RTTestFailed(hTest, "line %d, b1=%d b2=%d b3=%d: %s", __LINE__, b1, b2, b3, #expr); } CHECK_GUARD(s); } while (0) #define GUARD_MAP(p) do { } while (0) #define CHECK_GUARD(p) do { } while (0) #define MAP_CLEAR(p) do { RT_ZERO(*(p)); GUARD_MAP(p); } while (0) #define MAP_SET(p) do { memset(p, 0xff, sizeof(*(p))); GUARD_MAP(p); } while (0) /* self check. */ MAP_CLEAR(p); CHECK_GUARD(p); /* bit set */ MAP_CLEAR(p); ASMBitSet(&p->au32[0], 0); ASMBitSet(&p->au32[0], 31); ASMBitSet(&p->au32[0], 65); CHECK(p->au32[0] == 0x80000001U); CHECK(p->au32[2] == 0x00000002U); CHECK(ASMBitTestAndSet(&p->au32[0], 0) && p->au32[0] == 0x80000001U); CHECK(!ASMBitTestAndSet(&p->au32[0], 16) && p->au32[0] == 0x80010001U); CHECK(ASMBitTestAndSet(&p->au32[0], 16) && p->au32[0] == 0x80010001U); CHECK(!ASMBitTestAndSet(&p->au32[0], 80) && p->au32[2] == 0x00010002U); MAP_CLEAR(p); ASMAtomicBitSet(&p->au32[0], 0); ASMAtomicBitSet(&p->au32[0], 30); ASMAtomicBitSet(&p->au32[0], 64); CHECK(p->au32[0] == 0x40000001U); CHECK(p->au32[2] == 0x00000001U); CHECK(ASMAtomicBitTestAndSet(&p->au32[0], 0) && p->au32[0] == 0x40000001U); CHECK(!ASMAtomicBitTestAndSet(&p->au32[0], 16) && p->au32[0] == 0x40010001U); CHECK(ASMAtomicBitTestAndSet(&p->au32[0], 16) && p->au32[0] == 0x40010001U); CHECK(!ASMAtomicBitTestAndSet(&p->au32[0], 80) && p->au32[2] == 0x00010001U); /* bit clear */ MAP_SET(p); ASMBitClear(&p->au32[0], 0); ASMBitClear(&p->au32[0], 31); ASMBitClear(&p->au32[0], 65); CHECK(p->au32[0] == ~0x80000001U); CHECK(p->au32[2] == ~0x00000002U); CHECK(!ASMBitTestAndClear(&p->au32[0], 0) && p->au32[0] == ~0x80000001U); CHECK(ASMBitTestAndClear(&p->au32[0], 16) && p->au32[0] == ~0x80010001U); CHECK(!ASMBitTestAndClear(&p->au32[0], 16) && p->au32[0] == ~0x80010001U); CHECK(ASMBitTestAndClear(&p->au32[0], 80) && p->au32[2] == ~0x00010002U); MAP_SET(p); ASMAtomicBitClear(&p->au32[0], 0); ASMAtomicBitClear(&p->au32[0], 30); ASMAtomicBitClear(&p->au32[0], 64); CHECK(p->au32[0] == ~0x40000001U); CHECK(p->au32[2] == ~0x00000001U); CHECK(!ASMAtomicBitTestAndClear(&p->au32[0], 0) && p->au32[0] == ~0x40000001U); CHECK(ASMAtomicBitTestAndClear(&p->au32[0], 16) && p->au32[0] == ~0x40010001U); CHECK(!ASMAtomicBitTestAndClear(&p->au32[0], 16) && p->au32[0] == ~0x40010001U); CHECK(ASMAtomicBitTestAndClear(&p->au32[0], 80) && p->au32[2] == ~0x00010001U); /* toggle */ MAP_SET(p); ASMBitToggle(&p->au32[0], 0); ASMBitToggle(&p->au32[0], 31); ASMBitToggle(&p->au32[0], 65); ASMBitToggle(&p->au32[0], 47); ASMBitToggle(&p->au32[0], 47); CHECK(p->au32[0] == ~0x80000001U); CHECK(p->au32[2] == ~0x00000002U); CHECK(!ASMBitTestAndToggle(&p->au32[0], 0) && p->au32[0] == ~0x80000000U); CHECK(ASMBitTestAndToggle(&p->au32[0], 0) && p->au32[0] == ~0x80000001U); CHECK(ASMBitTestAndToggle(&p->au32[0], 16) && p->au32[0] == ~0x80010001U); CHECK(!ASMBitTestAndToggle(&p->au32[0], 16) && p->au32[0] == ~0x80000001U); CHECK(ASMBitTestAndToggle(&p->au32[0], 80) && p->au32[2] == ~0x00010002U); MAP_SET(p); ASMAtomicBitToggle(&p->au32[0], 0); ASMAtomicBitToggle(&p->au32[0], 30); ASMAtomicBitToggle(&p->au32[0], 64); ASMAtomicBitToggle(&p->au32[0], 47); ASMAtomicBitToggle(&p->au32[0], 47); CHECK(p->au32[0] == ~0x40000001U); CHECK(p->au32[2] == ~0x00000001U); CHECK(!ASMAtomicBitTestAndToggle(&p->au32[0], 0) && p->au32[0] == ~0x40000000U); CHECK(ASMAtomicBitTestAndToggle(&p->au32[0], 0) && p->au32[0] == ~0x40000001U); CHECK(ASMAtomicBitTestAndToggle(&p->au32[0], 16) && p->au32[0] == ~0x40010001U); CHECK(!ASMAtomicBitTestAndToggle(&p->au32[0], 16) && p->au32[0] == ~0x40000001U); CHECK(ASMAtomicBitTestAndToggle(&p->au32[0], 80) && p->au32[2] == ~0x00010001U); /* test bit. */ for (i = 0; i < 128; i++) { MAP_SET(p); CHECK_BIT(ASMBitTest(&p->au32[0], i), i); ASMBitToggle(&p->au32[0], i); CHECK_BIT(!ASMBitTest(&p->au32[0], i), i); CHECK_BIT(!ASMBitTestAndToggle(&p->au32[0], i), i); CHECK_BIT(ASMBitTest(&p->au32[0], i), i); CHECK_BIT(ASMBitTestAndToggle(&p->au32[0], i), i); CHECK_BIT(!ASMBitTest(&p->au32[0], i), i); MAP_SET(p); CHECK_BIT(ASMBitTest(&p->au32[0], i), i); ASMAtomicBitToggle(&p->au32[0], i); CHECK_BIT(!ASMBitTest(&p->au32[0], i), i); CHECK_BIT(!ASMAtomicBitTestAndToggle(&p->au32[0], i), i); CHECK_BIT(ASMBitTest(&p->au32[0], i), i); CHECK_BIT(ASMAtomicBitTestAndToggle(&p->au32[0], i), i); CHECK_BIT(!ASMBitTest(&p->au32[0], i), i); } /* bit searching */ MAP_SET(p); CHECK(ASMBitFirstClear(&p->au32[0], sizeof(p->au32) * 8) == -1); CHECK(ASMBitFirstSet(&p->au32[0], sizeof(p->au32) * 8) == 0); ASMBitClear(&p->au32[0], 1); CHECK(ASMBitFirstClear(&p->au32[0], sizeof(p->au32) * 8) == 1); CHECK(ASMBitFirstSet(&p->au32[0], sizeof(p->au32) * 8) == 0); MAP_SET(p); ASMBitClear(&p->au32[0], 95); CHECK(ASMBitFirstClear(&p->au32[0], sizeof(p->au32) * 8) == 95); CHECK(ASMBitFirstSet(&p->au32[0], sizeof(p->au32) * 8) == 0); MAP_SET(p); ASMBitClear(&p->au32[0], 127); CHECK(ASMBitFirstClear(&p->au32[0], sizeof(p->au32) * 8) == 127); CHECK(ASMBitFirstSet(&p->au32[0], sizeof(p->au32) * 8) == 0); CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, 0) == 1); CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, 1) == 2); CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, 2) == 3); MAP_SET(p); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 0) == -1); ASMBitClear(&p->au32[0], 32); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 32) == -1); ASMBitClear(&p->au32[0], 88); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 57) == 88); MAP_SET(p); ASMBitClear(&p->au32[0], 31); ASMBitClear(&p->au32[0], 57); ASMBitClear(&p->au32[0], 88); ASMBitClear(&p->au32[0], 101); ASMBitClear(&p->au32[0], 126); ASMBitClear(&p->au32[0], 127); CHECK(ASMBitFirstClear(&p->au32[0], sizeof(p->au32) * 8) == 31); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 31) == 57); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 57) == 88); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 88) == 101); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 101) == 126); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 126) == 127); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 127) == -1); CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, 29) == 30); CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, 30) == 32); MAP_CLEAR(p); for (i = 1; i < 128; i++) CHECK_BIT(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, i - 1) == i, i); for (i = 0; i < 128; i++) { MAP_SET(p); ASMBitClear(&p->au32[0], i); CHECK_BIT(ASMBitFirstClear(&p->au32[0], sizeof(p->au32) * 8) == i, i); for (j = 0; j < i; j++) CHECK_BIT(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, j) == i, i); for (j = i; j < 128; j++) CHECK_BIT(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, j) == -1, i); } /* clear range. */ MAP_SET(p); ASMBitClearRange(&p->au32, 0, 128); CHECK(!p->au32[0] && !p->au32[1] && !p->au32[2] && !p->au32[3]); for (i = 0; i < 128; i++) { for (j = i + 1; j <= 128; j++) { MAP_SET(p); ASMBitClearRange(&p->au32, i, j); for (k = 0; k < i; k++) CHECK_BIT3(ASMBitTest(&p->au32[0], k), i, j, k); for (k = i; k < j; k++) CHECK_BIT3(!ASMBitTest(&p->au32[0], k), i, j, k); for (k = j; k < 128; k++) CHECK_BIT3(ASMBitTest(&p->au32[0], k), i, j, k); } } /* set range. */ MAP_CLEAR(p); ASMBitSetRange(&p->au32[0], 0, 5); ASMBitSetRange(&p->au32[0], 6, 44); ASMBitSetRange(&p->au32[0], 64, 65); CHECK(p->au32[0] == UINT32_C(0xFFFFFFDF)); CHECK(p->au32[1] == UINT32_C(0x00000FFF)); CHECK(p->au32[2] == UINT32_C(0x00000001)); MAP_CLEAR(p); ASMBitSetRange(&p->au32[0], 0, 1); ASMBitSetRange(&p->au32[0], 62, 63); ASMBitSetRange(&p->au32[0], 63, 64); ASMBitSetRange(&p->au32[0], 127, 128); CHECK(p->au32[0] == UINT32_C(0x00000001) && p->au32[1] == UINT32_C(0xC0000000)); CHECK(p->au32[2] == UINT32_C(0x00000000) && p->au32[3] == UINT32_C(0x80000000)); MAP_CLEAR(p); ASMBitSetRange(&p->au32, 0, 128); CHECK(!~p->au32[0] && !~p->au32[1] && !~p->au32[2] && !~p->au32[3]); for (i = 0; i < 128; i++) { for (j = i + 1; j <= 128; j++) { MAP_CLEAR(p); ASMBitSetRange(&p->au32, i, j); for (k = 0; k < i; k++) CHECK_BIT3(!ASMBitTest(&p->au32[0], k), i, j, k); for (k = i; k < j; k++) CHECK_BIT3(ASMBitTest(&p->au32[0], k), i, j, k); for (k = j; k < 128; k++) CHECK_BIT3(!ASMBitTest(&p->au32[0], k), i, j, k); } } /* searching for set bits. */ MAP_CLEAR(p); CHECK(ASMBitFirstSet(&p->au32[0], sizeof(p->au32) * 8) == -1); ASMBitSet(&p->au32[0], 65); CHECK(ASMBitFirstSet(&p->au32[0], sizeof(p->au32) * 8) == 65); CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, 65) == -1); for (i = 0; i < 65; i++) CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, i) == 65); for (i = 65; i < 128; i++) CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, i) == -1); ASMBitSet(&p->au32[0], 17); CHECK(ASMBitFirstSet(&p->au32[0], sizeof(p->au32) * 8) == 17); CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, 17) == 65); for (i = 0; i < 16; i++) CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, i) == 17); for (i = 17; i < 65; i++) CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, i) == 65); MAP_SET(p); for (i = 1; i < 128; i++) CHECK_BIT(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, i - 1) == i, i); for (i = 0; i < 128; i++) { MAP_CLEAR(p); ASMBitSet(&p->au32[0], i); CHECK_BIT(ASMBitFirstSet(&p->au32[0], sizeof(p->au32) * 8) == i, i); for (j = 0; j < i; j++) CHECK_BIT(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, j) == i, i); for (j = i; j < 128; j++) CHECK_BIT(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, j) == -1, i); } CHECK(ASMBitLastSetU32(0) == 0); CHECK(ASMBitLastSetU32(1) == 1); CHECK(ASMBitLastSetU32(0x80000000) == 32); CHECK(ASMBitLastSetU32(0xffffffff) == 32); CHECK(ASMBitLastSetU32(RT_BIT(23) | RT_BIT(11)) == 24); for (i = 0; i < 32; i++) CHECK(ASMBitLastSetU32(1 << i) == (unsigned)i + 1); CHECK(ASMBitFirstSetU32(0) == 0); CHECK(ASMBitFirstSetU32(1) == 1); CHECK(ASMBitFirstSetU32(0x80000000) == 32); CHECK(ASMBitFirstSetU32(0xffffffff) == 1); CHECK(ASMBitFirstSetU32(RT_BIT(23) | RT_BIT(11)) == 12); for (i = 0; i < 32; i++) CHECK(ASMBitFirstSetU32(1 << i) == (unsigned)i + 1); /* * Special tests. */ test2(hTest); /* * Summary */ return RTTestSummaryAndDestroy(hTest); }
int main(int argc, char **argv) { RTTEST hTest; int rc = RTTestInitAndCreate("tstRTUuid", &hTest); if (rc) return rc; RTTestBanner(hTest); #define CHECK_RC() \ do { if (RT_FAILURE(rc)) { RTTestFailed(hTest, "line %d: rc=%Rrc", __LINE__, rc); } } while (0) RTTestSub(hTest, "RTUuidClear & RTUuisIsNull"); RTUUID UuidNull; rc = RTUuidClear(&UuidNull); CHECK_RC(); RTTEST_CHECK(hTest, RTUuidIsNull(&UuidNull)); RTTEST_CHECK(hTest, RTUuidCompare(&UuidNull, &UuidNull) == 0); RTTestSub(hTest, "RTUuidCreate"); RTUUID Uuid; rc = RTUuidCreate(&Uuid); CHECK_RC(); RTTEST_CHECK(hTest, !RTUuidIsNull(&Uuid)); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid) == 0); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &UuidNull) > 0); RTTEST_CHECK(hTest, RTUuidCompare(&UuidNull, &Uuid) < 0); RTTestSub(hTest, "RTUuidToStr"); char sz[RTUUID_STR_LENGTH]; rc = RTUuidToStr(&Uuid, sz, sizeof(sz)); CHECK_RC(); RTTEST_CHECK(hTest, strlen(sz) == RTUUID_STR_LENGTH - 1); RTTestPrintf(hTest, RTTESTLVL_INFO, "UUID=%s\n", sz); RTTestSub(hTest, "RTUuidFromStr"); RTUUID Uuid2; rc = RTUuidFromStr(&Uuid2, sz); CHECK_RC(); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); char *psz = (char *)RTTestGuardedAllocTail(hTest, RTUUID_STR_LENGTH); if (psz) { RTStrPrintf(psz, RTUUID_STR_LENGTH, "%s", sz); RTTESTI_CHECK_RC(RTUuidFromStr(&Uuid2, psz), VINF_SUCCESS); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); for (unsigned off = 1; off < RTUUID_STR_LENGTH; off++) { char *psz2 = psz + off; RTStrPrintf(psz2, RTUUID_STR_LENGTH - off, "%s", sz); RTTESTI_CHECK_RC(RTUuidFromStr(&Uuid2, psz2), VERR_INVALID_UUID_FORMAT); } RTTestGuardedFree(hTest, psz); } RTUuidClear(&Uuid2); char sz2[RTUUID_STR_LENGTH + 2]; RTStrPrintf(sz2, sizeof(sz2), "{%s}", sz); rc = RTUuidFromStr(&Uuid2, sz2); CHECK_RC(); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); psz = (char *)RTTestGuardedAllocTail(hTest, RTUUID_STR_LENGTH + 2); if (psz) { RTStrPrintf(psz, RTUUID_STR_LENGTH + 2, "{%s}", sz); RTTESTI_CHECK_RC(RTUuidFromStr(&Uuid2, psz), VINF_SUCCESS); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); for (unsigned off = 1; off < RTUUID_STR_LENGTH + 2; off++) { char *psz2 = psz + off; RTStrPrintf(psz2, RTUUID_STR_LENGTH + 2 - off, "{%s}", sz); RTTESTI_CHECK_RC(RTUuidFromStr(&Uuid2, psz2), VERR_INVALID_UUID_FORMAT); } RTTestGuardedFree(hTest, psz); } RTTestSub(hTest, "RTUuidToUtf16"); RTUTF16 wsz[RTUUID_STR_LENGTH]; rc = RTUuidToUtf16(&Uuid, wsz, sizeof(wsz)); CHECK_RC(); RTTEST_CHECK(hTest, RTUtf16Len(wsz) == RTUUID_STR_LENGTH - 1); RTTestSub(hTest, "RTUuidFromUtf16"); rc = RTUuidFromUtf16(&Uuid2, wsz); CHECK_RC(); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); RTUTF16 *pwsz; rc = RTStrToUtf16(sz2, &pwsz); RTTEST_CHECK(hTest, rc == VINF_SUCCESS); if (RT_SUCCESS(rc)) { RTTESTI_CHECK_RC(RTUuidFromUtf16(&Uuid2, pwsz), VINF_SUCCESS); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); RTUTF16 *pwsz2 = (RTUTF16*)RTTestGuardedAllocTail(hTest, 2 * (RTUUID_STR_LENGTH + 2)); if (pwsz2) { memcpy(pwsz2, pwsz, 2 * (RTUUID_STR_LENGTH + 2)); RTTESTI_CHECK_RC(RTUuidFromUtf16(&Uuid2, pwsz2), VINF_SUCCESS); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); for (unsigned off = 1; off < RTUUID_STR_LENGTH + 2; off++) { RTUTF16 *pwsz3 = pwsz2 + off; memcpy(pwsz3, pwsz, 2 * (RTUUID_STR_LENGTH + 1 - off)); pwsz3[RTUUID_STR_LENGTH + 1 - off] = 0; RTTESTI_CHECK_RC(RTUuidFromUtf16(&Uuid2, pwsz3), VERR_INVALID_UUID_FORMAT); } RTTestGuardedFree(hTest, pwsz2); } RTUtf16Free(pwsz); } RTTestSub(hTest, "RTUuidCompareStr"); RTTEST_CHECK(hTest, RTUuidCompareStr(&Uuid, sz) == 0); RTTEST_CHECK(hTest, RTUuidCompareStr(&Uuid, "00000000-0000-0000-0000-000000000000") > 0); RTTEST_CHECK(hTest, RTUuidCompareStr(&UuidNull, "00000000-0000-0000-0000-000000000000") == 0); RTTestSub(hTest, "RTUuidCompare2Strs"); RTTEST_CHECK(hTest, RTUuidCompare2Strs(sz, sz) == 0); RTTEST_CHECK(hTest, RTUuidCompare2Strs(sz, "00000000-0000-0000-0000-000000000000") > 0); RTTEST_CHECK(hTest, RTUuidCompare2Strs("00000000-0000-0000-0000-000000000000", sz) < 0); RTTEST_CHECK(hTest, RTUuidCompare2Strs("00000000-0000-0000-0000-000000000000", "00000000-0000-0000-0000-000000000000") == 0); RTTEST_CHECK(hTest, RTUuidCompare2Strs("d95d883b-f91d-4ce5-a5c5-d08bb6a85dec", "a56193c7-3e0b-4c03-9d66-56efb45082f7") > 0); RTTEST_CHECK(hTest, RTUuidCompare2Strs("a56193c7-3e0b-4c03-9d66-56efb45082f7", "d95d883b-f91d-4ce5-a5c5-d08bb6a85dec") < 0); /* * Check the binary representation. */ RTTestSub(hTest, "Binary representation"); RTUUID Uuid3; Uuid3.au8[0] = 0x01; Uuid3.au8[1] = 0x23; Uuid3.au8[2] = 0x45; Uuid3.au8[3] = 0x67; Uuid3.au8[4] = 0x89; Uuid3.au8[5] = 0xab; Uuid3.au8[6] = 0xcd; Uuid3.au8[7] = 0x4f; Uuid3.au8[8] = 0x10; Uuid3.au8[9] = 0xb2; Uuid3.au8[10] = 0x54; Uuid3.au8[11] = 0x76; Uuid3.au8[12] = 0x98; Uuid3.au8[13] = 0xba; Uuid3.au8[14] = 0xdc; Uuid3.au8[15] = 0xfe; Uuid3.Gen.u8ClockSeqHiAndReserved = (Uuid3.Gen.u8ClockSeqHiAndReserved & 0x3f) | 0x80; Uuid3.Gen.u16TimeHiAndVersion = (Uuid3.Gen.u16TimeHiAndVersion & 0x0fff) | 0x4000; const char *pszUuid3 = "67452301-ab89-4fcd-90b2-547698badcfe"; rc = RTUuidToStr(&Uuid3, sz, sizeof(sz)); CHECK_RC(); RTTEST_CHECK(hTest, strcmp(sz, pszUuid3) == 0); rc = RTUuidFromStr(&Uuid, pszUuid3); CHECK_RC(); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid3) == 0); RTTEST_CHECK(hTest, memcmp(&Uuid3, &Uuid, sizeof(Uuid)) == 0); /* * checking the clock seq and time hi and version bits... */ RTTestSub(hTest, "Clock seq, time hi, version bits"); RTUUID Uuid4Changes; Uuid4Changes.au64[0] = 0; Uuid4Changes.au64[1] = 0; RTUUID Uuid4Prev; RTUuidCreate(&Uuid4Prev); for (unsigned i = 0; i < 1024; i++) { RTUUID Uuid4; RTUuidCreate(&Uuid4); Uuid4Changes.au64[0] |= Uuid4.au64[0] ^ Uuid4Prev.au64[0]; Uuid4Changes.au64[1] |= Uuid4.au64[1] ^ Uuid4Prev.au64[1]; #if 0 /** @todo make a bit string/dumper similar to %Rhxs/d. */ RTPrintf("tstUuid: %d %d %d %d-%d %d %d %d %d %d %d %d-%d %d %d %d ; %d %d %d %d-%d %d %d %d %d %d %d %d-%d %d %d %d\n", !!(Uuid4.Gen.u16ClockSeq & RT_BIT(0)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(1)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(2)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(3)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(4)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(5)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(6)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(7)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(8)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(9)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(10)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(11)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(12)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(13)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(14)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(15)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(0)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(1)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(2)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(3)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(4)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(5)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(6)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(7)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(8)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(9)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(10)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(11)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(12)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(13)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(14)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(15)) ); #endif Uuid4Prev = Uuid4; } RTUUID Uuid4Fixed; Uuid4Fixed.au64[0] = ~Uuid4Changes.au64[0]; Uuid4Fixed.au64[1] = ~Uuid4Changes.au64[1]; RTTestPrintf(hTest, RTTESTLVL_INFO, "fixed bits: %RTuuid (mask)\n", &Uuid4Fixed); RTTestPrintf(hTest, RTTESTLVL_INFO, "tstUuid: raw: %.*Rhxs\n", sizeof(Uuid4Fixed), &Uuid4Fixed); Uuid4Prev.au64[0] &= Uuid4Fixed.au64[0]; Uuid4Prev.au64[1] &= Uuid4Fixed.au64[1]; RTTestPrintf(hTest, RTTESTLVL_INFO, "tstUuid: fixed bits: %RTuuid (value)\n", &Uuid4Prev); RTTestPrintf(hTest, RTTESTLVL_INFO, "tstUuid: raw: %.*Rhxs\n", sizeof(Uuid4Prev), &Uuid4Prev); /* * Summary. */ return RTTestSummaryAndDestroy(hTest); }
DEF_PS2Q_TYPE(AuxEvtQ, AUX_EVT_QUEUE_SIZE); DEF_PS2Q_TYPE(AuxCmdQ, AUX_CMD_QUEUE_SIZE); #ifndef VBOX_DEVICE_STRUCT_TESTCASE //@todo: hack DEF_PS2Q_TYPE(GeneriQ, 1); #endif /* Auxiliary device special modes of operation. */ typedef enum { AUX_MODE_STD, /* Standard operation. */ AUX_MODE_RESET, /* Currently in reset. */ AUX_MODE_WRAP /* Wrap mode (echoing input). */ } PS2M_MODE; /* Auxiliary device operational state. */ typedef enum { AUX_STATE_SCALING = RT_BIT(4), /* 2:1 scaling in effect. */ AUX_STATE_ENABLED = RT_BIT(5), /* Reporting enabled in stream mode. */ AUX_STATE_REMOTE = RT_BIT(6) /* Remote mode (reports on request). */ } PS2M_STATE; /* Protocols supported by the PS/2 mouse. */ typedef enum { PS2M_PROTO_PS2STD = 0, /* Standard PS/2 mouse protocol. */ PS2M_PROTO_IMPS2 = 3, /* IntelliMouse PS/2 protocol. */ PS2M_PROTO_IMEX = 4 /* IntelliMouse Explorer protocol. */ } PS2M_PROTO; /* Protocol selection 'knock' states. */ typedef enum { PS2M_KNOCK_INITIAL, PS2M_KNOCK_IMPS2_1ST,
DEF_PS2Q_TYPE(AuxEvtQ, AUX_EVT_QUEUE_SIZE); DEF_PS2Q_TYPE(AuxCmdQ, AUX_CMD_QUEUE_SIZE); #ifndef VBOX_DEVICE_STRUCT_TESTCASE /// @todo hack DEF_PS2Q_TYPE(GeneriQ, 1); #endif /* Auxiliary device special modes of operation. */ typedef enum { AUX_MODE_STD, /* Standard operation. */ AUX_MODE_RESET, /* Currently in reset. */ AUX_MODE_WRAP /* Wrap mode (echoing input). */ } PS2M_MODE; /* Auxiliary device operational state. */ typedef enum { AUX_STATE_RATE_ERR = RT_BIT(0), /* Invalid rate received. */ AUX_STATE_RES_ERR = RT_BIT(1), /* Invalid resolution received. */ AUX_STATE_SCALING = RT_BIT(4), /* 2:1 scaling in effect. */ AUX_STATE_ENABLED = RT_BIT(5), /* Reporting enabled in stream mode. */ AUX_STATE_REMOTE = RT_BIT(6) /* Remote mode (reports on request). */ } PS2M_STATE; /* Externally visible state bits. */ #define AUX_STATE_EXTERNAL (AUX_STATE_SCALING | AUX_STATE_ENABLED | AUX_STATE_REMOTE) /* Protocols supported by the PS/2 mouse. */ typedef enum { PS2M_PROTO_PS2STD = 0, /* Standard PS/2 mouse protocol. */ PS2M_PROTO_IMPS2 = 3, /* IntelliMouse PS/2 protocol. */ PS2M_PROTO_IMEX = 4 /* IntelliMouse Explorer protocol. */ } PS2M_PROTO;
/** * Construct the DMI table. * * @returns VBox status code. * @param pDevIns The device instance. * @param pTable Where to create the DMI table. * @param cbMax The maximum size of the DMI table. * @param pUuid Pointer to the UUID to use if the DmiUuid * configuration string isn't present. * @param pCfg The handle to our config node. * @param cCpus Number of VCPUs. * @param pcbDmiTables Size of DMI data in bytes. * @param pcNumDmiTables Number of DMI tables. */ int FwCommonPlantDMITable(PPDMDEVINS pDevIns, uint8_t *pTable, unsigned cbMax, PCRTUUID pUuid, PCFGMNODE pCfg, uint16_t cCpus, uint16_t *pcbDmiTables, uint16_t *pcNumDmiTables) { #define CHECKSIZE(cbWant) \ { \ size_t cbNeed = (size_t)(pszStr + cbWant - (char *)pTable) + 5; /* +1 for strtab terminator +4 for end-of-table entry */ \ if (cbNeed > cbMax) \ { \ if (fHideErrors) \ { \ LogRel(("One of the DMI strings is too long -- using default DMI data!\n")); \ continue; \ } \ return PDMDevHlpVMSetError(pDevIns, VERR_TOO_MUCH_DATA, RT_SRC_POS, \ N_("One of the DMI strings is too long. Check all bios/Dmi* configuration entries. At least %zu bytes are needed but there is no space for more than %d bytes"), cbNeed, cbMax); \ } \ } #define READCFGSTRDEF(variable, name, default_value) \ { \ if (fForceDefault) \ pszTmp = default_value; \ else \ { \ rc = CFGMR3QueryStringDef(pCfg, name, szBuf, sizeof(szBuf), default_value); \ if (RT_FAILURE(rc)) \ { \ if (fHideErrors) \ { \ LogRel(("Configuration error: Querying \"" name "\" as a string failed -- using default DMI data!\n")); \ continue; \ } \ return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, \ N_("Configuration error: Querying \"" name "\" as a string failed")); \ } \ else if (!strcmp(szBuf, "<EMPTY>")) \ pszTmp = ""; \ else \ pszTmp = szBuf; \ } \ if (!pszTmp[0]) \ variable = 0; /* empty string */ \ else \ { \ variable = iStrNr++; \ size_t cStr = strlen(pszTmp) + 1; \ CHECKSIZE(cStr); \ memcpy(pszStr, pszTmp, cStr); \ pszStr += cStr ; \ } \ } #define READCFGSTR(variable, name) \ READCFGSTRDEF(variable, # name, s_szDef ## name) #define READCFGINT(variable, name) \ { \ if (fForceDefault) \ variable = s_iDef ## name; \ else \ { \ rc = CFGMR3QueryS32Def(pCfg, # name, & variable, s_iDef ## name); \ if (RT_FAILURE(rc)) \ { \ if (fHideErrors) \ { \ LogRel(("Configuration error: Querying \"" # name "\" as an int failed -- using default DMI data!\n")); \ continue; \ } \ return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, \ N_("Configuration error: Querying \"" # name "\" as an int failed")); \ } \ } \ } #define START_STRUCT(tbl) \ pszStr = (char *)(tbl + 1); \ iStrNr = 1; #define TERM_STRUCT \ { \ *pszStr++ = '\0'; /* terminate set of text strings */ \ if (iStrNr == 1) \ *pszStr++ = '\0'; /* terminate a structure without strings */ \ } bool fForceDefault = false; #ifdef VBOX_BIOS_DMI_FALLBACK /* * There will be two passes. If an error occurs during the first pass, a * message will be written to the release log and we fall back to default * DMI data and start a second pass. */ bool fHideErrors = true; #else /* * There will be one pass, every error is fatal and will prevent the VM * from starting. */ bool fHideErrors = false; #endif uint8_t fDmiUseHostInfo; int rc = CFGMR3QueryU8Def(pCfg, "DmiUseHostInfo", &fDmiUseHostInfo, 0); if (RT_FAILURE (rc)) return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"DmiUseHostInfo\"")); /* Sync up with host default DMI values */ if (fDmiUseHostInfo) fwCommonUseHostDMIStrings(); uint8_t fDmiExposeMemoryTable; rc = CFGMR3QueryU8Def(pCfg, "DmiExposeMemoryTable", &fDmiExposeMemoryTable, 0); if (RT_FAILURE (rc)) return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"DmiExposeMemoryTable\"")); uint8_t fDmiExposeProcessorInf; rc = CFGMR3QueryU8Def(pCfg, "DmiExposeProcInf", &fDmiExposeProcessorInf, 0); if (RT_FAILURE (rc)) return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"DmiExposeProcInf\"")); for (;; fForceDefault = true, fHideErrors = false) { int iStrNr; char szBuf[256]; char *pszStr = (char *)pTable; char szDmiSystemUuid[64]; char *pszDmiSystemUuid; const char *pszTmp; if (fForceDefault) pszDmiSystemUuid = NULL; else { rc = CFGMR3QueryString(pCfg, "DmiSystemUuid", szDmiSystemUuid, sizeof(szDmiSystemUuid)); if (rc == VERR_CFGM_VALUE_NOT_FOUND) pszDmiSystemUuid = NULL; else if (RT_FAILURE(rc)) { if (fHideErrors) { LogRel(("Configuration error: Querying \"DmiSystemUuid\" as a string failed, using default DMI data\n")); continue; } return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("Configuration error: Querying \"DmiSystemUuid\" as a string failed")); } else pszDmiSystemUuid = szDmiSystemUuid; } /********************************* * DMI BIOS information (Type 0) * *********************************/ PDMIBIOSINF pBIOSInf = (PDMIBIOSINF)pszStr; CHECKSIZE(sizeof(*pBIOSInf)); pszStr = (char *)&pBIOSInf->u8ReleaseMajor; pBIOSInf->header.u8Length = RT_OFFSETOF(DMIBIOSINF, u8ReleaseMajor); /* don't set these fields by default for legacy compatibility */ int iDmiBIOSReleaseMajor, iDmiBIOSReleaseMinor; READCFGINT(iDmiBIOSReleaseMajor, DmiBIOSReleaseMajor); READCFGINT(iDmiBIOSReleaseMinor, DmiBIOSReleaseMinor); if (iDmiBIOSReleaseMajor != 0 || iDmiBIOSReleaseMinor != 0) { pszStr = (char *)&pBIOSInf->u8FirmwareMajor; pBIOSInf->header.u8Length = RT_OFFSETOF(DMIBIOSINF, u8FirmwareMajor); pBIOSInf->u8ReleaseMajor = iDmiBIOSReleaseMajor; pBIOSInf->u8ReleaseMinor = iDmiBIOSReleaseMinor; int iDmiBIOSFirmwareMajor, iDmiBIOSFirmwareMinor; READCFGINT(iDmiBIOSFirmwareMajor, DmiBIOSFirmwareMajor); READCFGINT(iDmiBIOSFirmwareMinor, DmiBIOSFirmwareMinor); if (iDmiBIOSFirmwareMajor != 0 || iDmiBIOSFirmwareMinor != 0) { pszStr = (char *)(pBIOSInf + 1); pBIOSInf->header.u8Length = sizeof(DMIBIOSINF); pBIOSInf->u8FirmwareMajor = iDmiBIOSFirmwareMajor; pBIOSInf->u8FirmwareMinor = iDmiBIOSFirmwareMinor; } } iStrNr = 1; pBIOSInf->header.u8Type = 0; /* BIOS Information */ pBIOSInf->header.u16Handle = 0x0000; READCFGSTR(pBIOSInf->u8Vendor, DmiBIOSVendor); READCFGSTR(pBIOSInf->u8Version, DmiBIOSVersion); pBIOSInf->u16Start = 0xE000; READCFGSTR(pBIOSInf->u8Release, DmiBIOSReleaseDate); pBIOSInf->u8ROMSize = 1; /* 128K */ pBIOSInf->u64Characteristics = RT_BIT(4) /* ISA is supported */ | RT_BIT(7) /* PCI is supported */ | RT_BIT(15) /* Boot from CD is supported */ | RT_BIT(16) /* Selectable Boot is supported */ | RT_BIT(27) /* Int 9h, 8042 Keyboard services supported */ | RT_BIT(30) /* Int 10h, CGA/Mono Video Services supported */ /* any more?? */ ; pBIOSInf->u8CharacteristicsByte1 = RT_BIT(0) /* ACPI is supported */ /* any more?? */ ; pBIOSInf->u8CharacteristicsByte2 = 0 /* any more?? */ ; TERM_STRUCT; /*********************************** * DMI system information (Type 1) * ***********************************/ PDMISYSTEMINF pSystemInf = (PDMISYSTEMINF)pszStr; CHECKSIZE(sizeof(*pSystemInf)); START_STRUCT(pSystemInf); pSystemInf->header.u8Type = 1; /* System Information */ pSystemInf->header.u8Length = sizeof(*pSystemInf); pSystemInf->header.u16Handle = 0x0001; READCFGSTR(pSystemInf->u8Manufacturer, DmiSystemVendor); READCFGSTR(pSystemInf->u8ProductName, DmiSystemProduct); READCFGSTR(pSystemInf->u8Version, DmiSystemVersion); READCFGSTR(pSystemInf->u8SerialNumber, DmiSystemSerial); RTUUID uuid; if (pszDmiSystemUuid) { rc = RTUuidFromStr(&uuid, pszDmiSystemUuid); if (RT_FAILURE(rc)) { if (fHideErrors) { LogRel(("Configuration error: Invalid UUID for DMI tables specified, using default DMI data\n")); continue; } return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("Configuration error: Invalid UUID for DMI tables specified")); } uuid.Gen.u32TimeLow = RT_H2BE_U32(uuid.Gen.u32TimeLow); uuid.Gen.u16TimeMid = RT_H2BE_U16(uuid.Gen.u16TimeMid); uuid.Gen.u16TimeHiAndVersion = RT_H2BE_U16(uuid.Gen.u16TimeHiAndVersion); pUuid = &uuid; } memcpy(pSystemInf->au8Uuid, pUuid, sizeof(RTUUID)); pSystemInf->u8WakeupType = 6; /* Power Switch */ READCFGSTR(pSystemInf->u8SKUNumber, DmiSystemSKU); READCFGSTR(pSystemInf->u8Family, DmiSystemFamily); TERM_STRUCT; /********************************** * DMI board information (Type 2) * **********************************/ PDMIBOARDINF pBoardInf = (PDMIBOARDINF)pszStr; CHECKSIZE(sizeof(*pBoardInf)); START_STRUCT(pBoardInf); int iDmiBoardBoardType; pBoardInf->header.u8Type = 2; /* Board Information */ pBoardInf->header.u8Length = sizeof(*pBoardInf); pBoardInf->header.u16Handle = 0x0008; READCFGSTR(pBoardInf->u8Manufacturer, DmiBoardVendor); READCFGSTR(pBoardInf->u8Product, DmiBoardProduct); READCFGSTR(pBoardInf->u8Version, DmiBoardVersion); READCFGSTR(pBoardInf->u8SerialNumber, DmiBoardSerial); READCFGSTR(pBoardInf->u8AssetTag, DmiBoardAssetTag); pBoardInf->u8FeatureFlags = RT_BIT(0) /* hosting board, e.g. motherboard */ ; READCFGSTR(pBoardInf->u8LocationInChass, DmiBoardLocInChass); pBoardInf->u16ChassisHandle = 0x0003; /* see type 3 */ READCFGINT(iDmiBoardBoardType, DmiBoardBoardType); pBoardInf->u8BoardType = iDmiBoardBoardType; pBoardInf->u8cObjectHandles = 0; TERM_STRUCT; /******************************************** * DMI System Enclosure or Chassis (Type 3) * ********************************************/ PDMICHASSIS pChassis = (PDMICHASSIS)pszStr; CHECKSIZE(sizeof(*pChassis)); pszStr = (char*)&pChassis->u32OEMdefined; iStrNr = 1; #ifdef VBOX_WITH_DMI_CHASSIS pChassis->header.u8Type = 3; /* System Enclosure or Chassis */ #else pChassis->header.u8Type = 0x7e; /* inactive */ #endif pChassis->header.u8Length = RT_OFFSETOF(DMICHASSIS, u32OEMdefined); pChassis->header.u16Handle = 0x0003; READCFGSTR(pChassis->u8Manufacturer, DmiChassisVendor); int iDmiChassisType; READCFGINT(iDmiChassisType, DmiChassisType); pChassis->u8Type = iDmiChassisType; READCFGSTR(pChassis->u8Version, DmiChassisVersion); READCFGSTR(pChassis->u8SerialNumber, DmiChassisSerial); READCFGSTR(pChassis->u8AssetTag, DmiChassisAssetTag); pChassis->u8BootupState = 0x03; /* safe */ pChassis->u8PowerSupplyState = 0x03; /* safe */ pChassis->u8ThermalState = 0x03; /* safe */ pChassis->u8SecurityStatus = 0x03; /* none XXX */ # if 0 /* v2.3+, currently not supported */ pChassis->u32OEMdefined = 0; pChassis->u8Height = 0; /* unspecified */ pChassis->u8NumPowerChords = 0; /* unspecified */ pChassis->u8ContElems = 0; /* no contained elements */ pChassis->u8ContElemRecLen = 0; /* no contained elements */ # endif TERM_STRUCT; /************************************** * DMI Processor Information (Type 4) * **************************************/ /* * This is just a dummy processor. Should we expose the real guest CPU features * here? Accessing this information at this point is difficult. */ char szSocket[32]; PDMIPROCESSORINF pProcessorInf = (PDMIPROCESSORINF)pszStr; CHECKSIZE(sizeof(*pProcessorInf)); START_STRUCT(pProcessorInf); if (fDmiExposeProcessorInf) pProcessorInf->header.u8Type = 4; /* Processor Information */ else pProcessorInf->header.u8Type = 126; /* inactive structure */ pProcessorInf->header.u8Length = sizeof(*pProcessorInf); pProcessorInf->header.u16Handle = 0x0007; RTStrPrintf(szSocket, sizeof(szSocket), "Socket #%u", 0); pProcessorInf->u8SocketDesignation = iStrNr++; { size_t cStr = strlen(szSocket) + 1; CHECKSIZE(cStr); memcpy(pszStr, szSocket, cStr); pszStr += cStr; } pProcessorInf->u8ProcessorType = 0x03; /* Central Processor */ pProcessorInf->u8ProcessorFamily = 0xB1; /* Pentium III with Intel SpeedStep(TM) */ READCFGSTR(pProcessorInf->u8ProcessorManufacturer, DmiProcManufacturer); pProcessorInf->u64ProcessorID = UINT64_C(0x0FEBFBFF00010676); /* Ext Family ID = 0 * Ext Model ID = 2 * Processor Type = 0 * Family ID = 6 * Model = 7 * Stepping = 6 * Features: FPU, VME, DE, PSE, TSC, MSR, PAE, MCE, CX8, * APIC, SEP, MTRR, PGE, MCA, CMOV, PAT, PSE-36, * CFLSH, DS, ACPI, MMX, FXSR, SSE, SSE2, SS */ READCFGSTR(pProcessorInf->u8ProcessorVersion, DmiProcVersion); pProcessorInf->u8Voltage = 0x02; /* 3.3V */ pProcessorInf->u16ExternalClock = 0x00; /* unknown */ pProcessorInf->u16MaxSpeed = 3000; /* 3GHz */ pProcessorInf->u16CurrentSpeed = 3000; /* 3GHz */ pProcessorInf->u8Status = RT_BIT(6) /* CPU socket populated */ | RT_BIT(0) /* CPU enabled */ ; pProcessorInf->u8ProcessorUpgrade = 0x04; /* ZIF Socket */ pProcessorInf->u16L1CacheHandle = 0xFFFF; /* not specified */ pProcessorInf->u16L2CacheHandle = 0xFFFF; /* not specified */ pProcessorInf->u16L3CacheHandle = 0xFFFF; /* not specified */ pProcessorInf->u8SerialNumber = 0; /* not specified */ pProcessorInf->u8AssetTag = 0; /* not specified */ pProcessorInf->u8PartNumber = 0; /* not specified */ pProcessorInf->u8CoreCount = cCpus; /* */ pProcessorInf->u8CoreEnabled = cCpus; pProcessorInf->u8ThreadCount = 1; pProcessorInf->u16ProcessorCharacteristics = RT_BIT(2); /* 64-bit capable */ pProcessorInf->u16ProcessorFamily2 = 0; TERM_STRUCT; /*************************************** * DMI Physical Memory Array (Type 16) * ***************************************/ uint64_t u64RamSize; rc = CFGMR3QueryU64(pCfg, "RamSize", &u64RamSize); if (RT_FAILURE (rc)) return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"RamSize\"")); PDMIRAMARRAY pMemArray = (PDMIRAMARRAY)pszStr; CHECKSIZE(sizeof(*pMemArray)); START_STRUCT(pMemArray); if (fDmiExposeMemoryTable) pMemArray->header.u8Type = 16; /* Physical Memory Array */ else pMemArray->header.u8Type = 126; /* inactive structure */ pMemArray->header.u8Length = sizeof(*pMemArray); pMemArray->header.u16Handle = 0x0005; pMemArray->u8Location = 0x03; /* Motherboard */ pMemArray->u8Use = 0x03; /* System memory */ pMemArray->u8MemErrorCorrection = 0x01; /* Other */ pMemArray->u32MaxCapacity = (uint32_t)(u64RamSize / _1K); /* RAM size in K */ pMemArray->u16MemErrorHandle = 0xfffe; /* No error info structure */ pMemArray->u16NumberOfMemDevices = 1; TERM_STRUCT; /*************************************** * DMI Memory Device (Type 17) * ***************************************/ PDMIMEMORYDEV pMemDev = (PDMIMEMORYDEV)pszStr; CHECKSIZE(sizeof(*pMemDev)); START_STRUCT(pMemDev); if (fDmiExposeMemoryTable) pMemDev->header.u8Type = 17; /* Memory Device */ else pMemDev->header.u8Type = 126; /* inactive structure */ pMemDev->header.u8Length = sizeof(*pMemDev); pMemDev->header.u16Handle = 0x0006; pMemDev->u16PhysMemArrayHandle = 0x0005; /* handle of array we belong to */ pMemDev->u16MemErrHandle = 0xfffe; /* system doesn't provide this information */ pMemDev->u16TotalWidth = 0xffff; /* Unknown */ pMemDev->u16DataWidth = 0xffff; /* Unknown */ int16_t u16RamSizeM = (uint16_t)(u64RamSize / _1M); if (u16RamSizeM == 0) u16RamSizeM = 0x400; /* 1G */ pMemDev->u16Size = u16RamSizeM; /* RAM size */ pMemDev->u8FormFactor = 0x09; /* DIMM */ pMemDev->u8DeviceSet = 0x00; /* Not part of a device set */ READCFGSTRDEF(pMemDev->u8DeviceLocator, " ", "DIMM 0"); READCFGSTRDEF(pMemDev->u8BankLocator, " ", "Bank 0"); pMemDev->u8MemoryType = 0x03; /* DRAM */ pMemDev->u16TypeDetail = 0; /* Nothing special */ pMemDev->u16Speed = 1600; /* Unknown, shall be speed in MHz */ READCFGSTR(pMemDev->u8Manufacturer, DmiSystemVendor); READCFGSTRDEF(pMemDev->u8SerialNumber, " ", "00000000"); READCFGSTRDEF(pMemDev->u8AssetTag, " ", "00000000"); READCFGSTRDEF(pMemDev->u8PartNumber, " ", "00000000"); pMemDev->u8Attributes = 0; /* Unknown */ TERM_STRUCT; /***************************** * DMI OEM strings (Type 11) * *****************************/ PDMIOEMSTRINGS pOEMStrings = (PDMIOEMSTRINGS)pszStr; CHECKSIZE(sizeof(*pOEMStrings)); START_STRUCT(pOEMStrings); #ifdef VBOX_WITH_DMI_OEMSTRINGS pOEMStrings->header.u8Type = 0xb; /* OEM Strings */ #else pOEMStrings->header.u8Type = 126; /* inactive structure */ #endif pOEMStrings->header.u8Length = sizeof(*pOEMStrings); pOEMStrings->header.u16Handle = 0x0002; pOEMStrings->u8Count = 2; char szTmp[64]; RTStrPrintf(szTmp, sizeof(szTmp), "vboxVer_%u.%u.%u", RTBldCfgVersionMajor(), RTBldCfgVersionMinor(), RTBldCfgVersionBuild()); READCFGSTRDEF(pOEMStrings->u8VBoxVersion, "DmiOEMVBoxVer", szTmp); RTStrPrintf(szTmp, sizeof(szTmp), "vboxRev_%u", RTBldCfgRevision()); READCFGSTRDEF(pOEMStrings->u8VBoxRevision, "DmiOEMVBoxRev", szTmp); TERM_STRUCT; /************************************* * DMI OEM specific table (Type 128) * ************************************/ PDMIOEMSPECIFIC pOEMSpecific = (PDMIOEMSPECIFIC)pszStr; CHECKSIZE(sizeof(*pOEMSpecific)); START_STRUCT(pOEMSpecific); pOEMSpecific->header.u8Type = 0x80; /* OEM specific */ pOEMSpecific->header.u8Length = sizeof(*pOEMSpecific); pOEMSpecific->header.u16Handle = 0x0008; /* Just next free handle */ pOEMSpecific->u32CpuFreqKHz = RT_H2LE_U32((uint32_t)((uint64_t)TMCpuTicksPerSecond(PDMDevHlpGetVM(pDevIns)) / 1000)); TERM_STRUCT; /* End-of-table marker - includes padding to account for fixed table size. */ PDMIHDR pEndOfTable = (PDMIHDR)pszStr; pszStr = (char *)(pEndOfTable + 1); pEndOfTable->u8Type = 0x7f; pEndOfTable->u8Length = sizeof(*pEndOfTable); pEndOfTable->u16Handle = 0xFEFF; *pcbDmiTables = ((uintptr_t)pszStr - (uintptr_t)pTable) + 2; /* We currently plant 10 DMI tables. Update this if tables number changed. */ *pcNumDmiTables = 10; /* If more fields are added here, fix the size check in READCFGSTR */ /* Success! */ break; } #undef READCFGSTR #undef READCFGINT #undef CHECKSIZE return VINF_SUCCESS; }
static int vscsiLunMmcReqProcess(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq) { PVSCSILUNMMC pVScsiLunMmc = (PVSCSILUNMMC)pVScsiLun; VSCSIIOREQTXDIR enmTxDir = VSCSIIOREQTXDIR_INVALID; uint64_t uLbaStart = 0; uint32_t cSectorTransfer = 0; int rc = VINF_SUCCESS; int rcReq = SCSI_STATUS_OK; switch(pVScsiReq->pbCDB[0]) { case SCSI_INQUIRY: { SCSIINQUIRYDATA ScsiInquiryReply; memset(&ScsiInquiryReply, 0, sizeof(ScsiInquiryReply)); ScsiInquiryReply.cbAdditional = 31; ScsiInquiryReply.fRMB = 1; /* Removable. */ ScsiInquiryReply.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_CD_DVD; ScsiInquiryReply.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED; ScsiInquiryReply.u3AnsiVersion = 0x05; /* MMC-?? compliant */ ScsiInquiryReply.fCmdQue = 1; /* Command queuing supported. */ ScsiInquiryReply.fWBus16 = 1; vscsiPadStr(ScsiInquiryReply.achVendorId, "VBOX", 8); vscsiPadStr(ScsiInquiryReply.achProductId, "CD-ROM", 16); vscsiPadStr(ScsiInquiryReply.achProductLevel, "1.0", 4); RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, (uint8_t *)&ScsiInquiryReply, sizeof(SCSIINQUIRYDATA)); rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); break; } case SCSI_READ_CAPACITY: { uint8_t aReply[8]; memset(aReply, 0, sizeof(aReply)); /* * If sector size exceeds the maximum value that is * able to be stored in 4 bytes return 0xffffffff in this field */ if (pVScsiLunMmc->cSectors > UINT32_C(0xffffffff)) vscsiH2BEU32(aReply, UINT32_C(0xffffffff)); else vscsiH2BEU32(aReply, pVScsiLunMmc->cSectors - 1); vscsiH2BEU32(&aReply[4], pVScsiLunMmc->cbSector); RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply)); rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); break; } case SCSI_MODE_SENSE_6: { uint8_t uModePage = pVScsiReq->pbCDB[2] & 0x3f; uint8_t aReply[24]; uint8_t *pu8ReplyPos; memset(aReply, 0, sizeof(aReply)); aReply[0] = 4; /* Reply length 4. */ aReply[1] = 0; /* Default media type. */ aReply[2] = RT_BIT(4); /* Caching supported. */ aReply[3] = 0; /* Block descriptor length. */ pu8ReplyPos = aReply + 4; if ((uModePage == 0x08) || (uModePage == 0x3f)) { memset(pu8ReplyPos, 0, 20); *pu8ReplyPos++ = 0x08; /* Page code. */ *pu8ReplyPos++ = 0x12; /* Size of the page. */ *pu8ReplyPos++ = 0x4; /* Write cache enabled. */ } RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply)); rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); break; } case SCSI_MODE_SELECT_6: { /* @todo: implement!! */ rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); break; } case SCSI_READ_6: { enmTxDir = VSCSIIOREQTXDIR_READ; uLbaStart = ((uint64_t) pVScsiReq->pbCDB[3] | (pVScsiReq->pbCDB[2] << 8) | ((pVScsiReq->pbCDB[1] & 0x1f) << 16)); cSectorTransfer = pVScsiReq->pbCDB[4]; break; } case SCSI_READ_10: { enmTxDir = VSCSIIOREQTXDIR_READ; uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]); cSectorTransfer = vscsiBE2HU16(&pVScsiReq->pbCDB[7]); break; } case SCSI_READ_12: { enmTxDir = VSCSIIOREQTXDIR_READ; uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]); cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[6]); break; } case SCSI_READ_16: { enmTxDir = VSCSIIOREQTXDIR_READ; uLbaStart = vscsiBE2HU64(&pVScsiReq->pbCDB[2]); cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[10]); break; } case SCSI_READ_BUFFER: { uint8_t uDataMode = pVScsiReq->pbCDB[1] & 0x1f; switch (uDataMode) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x0a: break; case 0x0b: { uint8_t aReply[4]; /* We do not implement an echo buffer. */ memset(aReply, 0, sizeof(aReply)); RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply)); rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); break; } case 0x1a: case 0x1c: break; default: AssertMsgFailed(("Invalid data mode\n")); } break; } case SCSI_VERIFY_10: case SCSI_START_STOP_UNIT: { rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); break; } case SCSI_LOG_SENSE: { uint16_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]); uint8_t uPageCode = pVScsiReq->pbCDB[2] & 0x3f; uint8_t uSubPageCode = pVScsiReq->pbCDB[3]; switch (uPageCode) { case 0x00: { if (uSubPageCode == 0) { uint8_t aReply[4]; aReply[0] = 0; aReply[1] = 0; aReply[2] = 0; aReply[3] = 0; RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply)); rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); break; } } default: rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); } break; } case SCSI_SERVICE_ACTION_IN_16: { switch (pVScsiReq->pbCDB[1] & 0x1f) { case SCSI_SVC_ACTION_IN_READ_CAPACITY_16: { uint8_t aReply[32]; memset(aReply, 0, sizeof(aReply)); vscsiH2BEU64(aReply, pVScsiLunMmc->cSectors - 1); vscsiH2BEU32(&aReply[8], pVScsiLunMmc->cbSector); /* Leave the rest 0 */ RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply)); rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); break; } default: rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); /* Don't know if this is correct */ } break; } case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL: { pVScsiLunMmc->fLocked = pVScsiReq->pbCDB[4] & 1; rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); break; } default: //AssertMsgFailed(("Command %#x [%s] not implemented\n", pRequest->pbCDB[0], SCSICmdText(pRequest->pbCDB[0]))); rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE, 0x00); } if (enmTxDir != VSCSIIOREQTXDIR_INVALID) { LogFlow(("%s: uLbaStart=%llu cSectorTransfer=%u\n", __FUNCTION__, uLbaStart, cSectorTransfer)); if (RT_UNLIKELY(uLbaStart + cSectorTransfer > pVScsiLunMmc->cSectors)) { rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR, 0x00); vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS); } else if (!cSectorTransfer) { /* A 0 transfer length is not an error. */ rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS); } else { /* Enqueue new I/O request */ rc = vscsiIoReqTransferEnqueue(pVScsiLun, pVScsiReq, enmTxDir, uLbaStart * pVScsiLunMmc->cbSector, cSectorTransfer * pVScsiLunMmc->cbSector); } } else /* Request completed */ vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS); return rc; }
/** Print the 'true' if nested paging is supported, 'false' if not and * 'dunno' if we cannot tell. */ static RTEXITCODE handlerCpuNestedPaging(int argc, char **argv) { NOREF(argc); NOREF(argv); HWVIRTTYPE enmHwVirt = isHwVirtSupported(); int fSupported = -1; #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) if (enmHwVirt == HWVIRTTYPE_AMDV) { uint32_t uEax, uEbx, uEcx, uEdx; ASMCpuId(0x80000000, &uEax, &uEbx, &uEcx, &uEdx); if (ASMIsValidExtRange(uEax) && uEax >= 0x8000000a) { ASMCpuId(0x8000000a, &uEax, &uEbx, &uEcx, &uEdx); if (uEdx & RT_BIT(0) /* AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING */) fSupported = 1; else fSupported = 0; } } # if defined(RT_OS_LINUX) else if (enmHwVirt == HWVIRTTYPE_VTX) { /* * For Intel there is no generic way to query EPT support but on * Linux we can resort to checking for the EPT flag in /proc/cpuinfo */ RTFILE hFileCpu; int rc = RTFileOpen(&hFileCpu, "/proc/cpuinfo", RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE); if (RT_SUCCESS(rc)) { /* * Read enough to fit the first CPU entry in, we only check the first * CPU as all the others should have the same features. */ char szBuf[_4K]; size_t cbRead = 0; RT_ZERO(szBuf); /* Ensure proper termination. */ rc = RTFileRead(hFileCpu, &szBuf[0], sizeof(szBuf) - 1, &cbRead); if (RT_SUCCESS(rc)) { /* Look for the start of the flags section. */ char *pszStrFlags = RTStrStr(&szBuf[0], "flags"); if (pszStrFlags) { /* Look for the end as indicated by new line. */ char *pszEnd = pszStrFlags; while ( *pszEnd != '\0' && *pszEnd != '\n') pszEnd++; *pszEnd = '\0'; /* Cut off everything after the flags section. */ /* * Search for the ept flag indicating support and the absence meaning * not supported. */ if (RTStrStr(pszStrFlags, "ept")) fSupported = 1; else fSupported = 0; } } RTFileClose(hFileCpu); } } # endif #endif int cch = RTPrintf(fSupported == 1 ? "true\n" : fSupported == 0 ? "false\n" : "dunno\n"); return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; }
RTDECL(int) RTZipGzipDecompressIoStream(RTVFSIOSTREAM hVfsIosIn, uint32_t fFlags, PRTVFSIOSTREAM phVfsIosOut) { AssertPtrReturn(hVfsIosIn, VERR_INVALID_HANDLE); AssertReturn(!(fFlags & ~RTZIPGZIPDECOMP_F_ALLOW_ZLIB_HDR), VERR_INVALID_PARAMETER); AssertPtrReturn(phVfsIosOut, VERR_INVALID_POINTER); uint32_t cRefs = RTVfsIoStrmRetain(hVfsIosIn); AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE); /* * Create the decompression I/O stream. */ RTVFSIOSTREAM hVfsIos; PRTZIPGZIPSTREAM pThis; int rc = RTVfsNewIoStream(&g_rtZipGzipOps, sizeof(RTZIPGZIPSTREAM), RTFILE_O_READ, NIL_RTVFS, NIL_RTVFSLOCK, &hVfsIos, (void **)&pThis); if (RT_SUCCESS(rc)) { pThis->hVfsIos = hVfsIosIn; pThis->offStream = 0; pThis->fDecompress = true; pThis->SgSeg.pvSeg = &pThis->abBuffer[0]; pThis->SgSeg.cbSeg = sizeof(pThis->abBuffer); RTSgBufInit(&pThis->SgBuf, &pThis->SgSeg, 1); memset(&pThis->Zlib, 0, sizeof(pThis->Zlib)); pThis->Zlib.opaque = pThis; rc = inflateInit2(&pThis->Zlib, MAX_WBITS | RT_BIT(5) /* autodetect gzip header */); if (rc >= 0) { /* * Read the gzip header from the input stream to check that it's * a gzip stream as specified by the user. * * Note! Since we've told zlib to check for the gzip header, we * prebuffer what we read in the input buffer so it can * be handed on to zlib later on. */ rc = RTVfsIoStrmRead(pThis->hVfsIos, pThis->abBuffer, sizeof(RTZIPGZIPHDR), true /*fBlocking*/, NULL /*pcbRead*/); if (RT_SUCCESS(rc)) { /* Validate the header and make a copy of it. */ PCRTZIPGZIPHDR pHdr = (PCRTZIPGZIPHDR)pThis->abBuffer; if ( pHdr->bId1 == RTZIPGZIPHDR_ID1 && pHdr->bId2 == RTZIPGZIPHDR_ID2 && !(pHdr->fFlags & ~RTZIPGZIPHDR_FLG_VALID_MASK)) { if (pHdr->bCompressionMethod == RTZIPGZIPHDR_CM_DEFLATE) rc = VINF_SUCCESS; else rc = VERR_ZIP_UNSUPPORTED_METHOD; } else if ( (fFlags & RTZIPGZIPDECOMP_F_ALLOW_ZLIB_HDR) && (RT_MAKE_U16(pHdr->bId2, pHdr->bId1) % 31) == 0 && (pHdr->bId1 & 0xf) == RTZIPGZIPHDR_CM_DEFLATE ) { pHdr = NULL; rc = VINF_SUCCESS; } else rc = VERR_ZIP_BAD_HEADER; if (RT_SUCCESS(rc)) { pThis->Zlib.avail_in = sizeof(RTZIPGZIPHDR); pThis->Zlib.next_in = &pThis->abBuffer[0]; if (pHdr) { pThis->Hdr = *pHdr; /* Parse on if there are names or comments. */ if (pHdr->fFlags & (RTZIPGZIPHDR_FLG_NAME | RTZIPGZIPHDR_FLG_COMMENT)) { /** @todo Can implement this when someone needs the * name or comment for something useful. */ } } if (RT_SUCCESS(rc)) { *phVfsIosOut = hVfsIos; return VINF_SUCCESS; } } } } else rc = rtZipGzipConvertErrFromZlib(pThis, rc); /** @todo cleaning up in this situation is going to go wrong. */ RTVfsIoStrmRelease(hVfsIos); } else RTVfsIoStrmRelease(hVfsIosIn); return rc; }
/** * Construct the DMI table. * * @returns VBox status code. * @param pDevIns The device instance. * @param pTable Where to create the DMI table. * @param cbMax The maximum size of the DMI table. * @param pUuid Pointer to the UUID to use if the DmiUuid * configuration string isn't present. * @param pCfg The handle to our config node. */ int FwCommonPlantDMITable(PPDMDEVINS pDevIns, uint8_t *pTable, unsigned cbMax, PCRTUUID pUuid, PCFGMNODE pCfg) { #define CHECKSIZE(cbWant) \ { \ size_t cbNeed = (size_t)(pszStr + cbWant - (char *)pTable) + 5; /* +1 for strtab terminator +4 for end-of-table entry */ \ if (cbNeed > cbMax) \ { \ if (fHideErrors) \ { \ LogRel(("One of the DMI strings is too long -- using default DMI data!\n")); \ continue; \ } \ return PDMDevHlpVMSetError(pDevIns, VERR_TOO_MUCH_DATA, RT_SRC_POS, \ N_("One of the DMI strings is too long. Check all bios/Dmi* configuration entries. At least %zu bytes are needed but there is no space for more than %d bytes"), cbNeed, cbMax); \ } \ } #define READCFGSTRDEF(variable, name, default_value) \ { \ if (fForceDefault) \ pszTmp = default_value; \ else \ { \ rc = CFGMR3QueryStringDef(pCfg, name, szBuf, sizeof(szBuf), default_value); \ if (RT_FAILURE(rc)) \ { \ if (fHideErrors) \ { \ LogRel(("Configuration error: Querying \"" name "\" as a string failed -- using default DMI data!\n")); \ continue; \ } \ return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, \ N_("Configuration error: Querying \"" name "\" as a string failed")); \ } \ else if (!strcmp(szBuf, "<EMPTY>")) \ pszTmp = ""; \ else \ pszTmp = szBuf; \ } \ if (!pszTmp[0]) \ variable = 0; /* empty string */ \ else \ { \ variable = iStrNr++; \ size_t cStr = strlen(pszTmp) + 1; \ CHECKSIZE(cStr); \ memcpy(pszStr, pszTmp, cStr); \ pszStr += cStr ; \ } \ } #define READCFGSTR(variable, name) \ READCFGSTRDEF(variable, # name, s_szDef ## name) #define READCFGINT(variable, name) \ { \ if (fForceDefault) \ variable = s_iDef ## name; \ else \ { \ rc = CFGMR3QueryS32Def(pCfg, # name, & variable, s_iDef ## name); \ if (RT_FAILURE(rc)) \ { \ if (fHideErrors) \ { \ LogRel(("Configuration error: Querying \"" # name "\" as an int failed -- using default DMI data!\n")); \ continue; \ } \ return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, \ N_("Configuration error: Querying \"" # name "\" as an int failed")); \ } \ } \ } #define START_STRUCT(tbl) \ pszStr = (char *)(tbl + 1); \ iStrNr = 1; #define TERM_STRUCT \ { \ *pszStr++ = '\0'; /* terminate set of text strings */ \ if (iStrNr == 1) \ *pszStr++ = '\0'; /* terminate a structure without strings */ \ } bool fForceDefault = false; #ifdef VBOX_BIOS_DMI_FALLBACK /* * There will be two passes. If an error occurs during the first pass, a * message will be written to the release log and we fall back to default * DMI data and start a second pass. */ bool fHideErrors = true; #else /* * There will be one pass, every error is fatal and will prevent the VM * from starting. */ bool fHideErrors = false; #endif uint8_t fDmiUseHostInfo; int rc = CFGMR3QueryU8Def(pCfg, "DmiUseHostInfo", &fDmiUseHostInfo, 0); if (RT_FAILURE (rc)) return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"DmiUseHostInfo\"")); /* Sync up with host default DMI values */ if (fDmiUseHostInfo) fwCommonUseHostDMIStrings(); uint8_t fDmiExposeMemoryTable; rc = CFGMR3QueryU8Def(pCfg, "DmiExposeMemoryTable", &fDmiExposeMemoryTable, 0); if (RT_FAILURE (rc)) return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"DmiExposeMemoryTable\"")); for (;; fForceDefault = true, fHideErrors = false) { int iStrNr; char szBuf[256]; char *pszStr = (char *)pTable; char szDmiSystemUuid[64]; char *pszDmiSystemUuid; const char *pszTmp; if (fForceDefault) pszDmiSystemUuid = NULL; else { rc = CFGMR3QueryString(pCfg, "DmiSystemUuid", szDmiSystemUuid, sizeof(szDmiSystemUuid)); if (rc == VERR_CFGM_VALUE_NOT_FOUND) pszDmiSystemUuid = NULL; else if (RT_FAILURE(rc)) { if (fHideErrors) { LogRel(("Configuration error: Querying \"DmiSystemUuid\" as a string failed, using default DMI data\n")); continue; } return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("Configuration error: Querying \"DmiSystemUuid\" as a string failed")); } else pszDmiSystemUuid = szDmiSystemUuid; } /********************************* * DMI BIOS information (Type 0) * *********************************/ PDMIBIOSINF pBIOSInf = (PDMIBIOSINF)pszStr; CHECKSIZE(sizeof(*pBIOSInf)); pszStr = (char *)&pBIOSInf->u8ReleaseMajor; pBIOSInf->header.u8Length = RT_OFFSETOF(DMIBIOSINF, u8ReleaseMajor); /* don't set these fields by default for legacy compatibility */ int iDmiBIOSReleaseMajor, iDmiBIOSReleaseMinor; READCFGINT(iDmiBIOSReleaseMajor, DmiBIOSReleaseMajor); READCFGINT(iDmiBIOSReleaseMinor, DmiBIOSReleaseMinor); if (iDmiBIOSReleaseMajor != 0 || iDmiBIOSReleaseMinor != 0) { pszStr = (char *)&pBIOSInf->u8FirmwareMajor; pBIOSInf->header.u8Length = RT_OFFSETOF(DMIBIOSINF, u8FirmwareMajor); pBIOSInf->u8ReleaseMajor = iDmiBIOSReleaseMajor; pBIOSInf->u8ReleaseMinor = iDmiBIOSReleaseMinor; int iDmiBIOSFirmwareMajor, iDmiBIOSFirmwareMinor; READCFGINT(iDmiBIOSFirmwareMajor, DmiBIOSFirmwareMajor); READCFGINT(iDmiBIOSFirmwareMinor, DmiBIOSFirmwareMinor); if (iDmiBIOSFirmwareMajor != 0 || iDmiBIOSFirmwareMinor != 0) { pszStr = (char *)(pBIOSInf + 1); pBIOSInf->header.u8Length = sizeof(DMIBIOSINF); pBIOSInf->u8FirmwareMajor = iDmiBIOSFirmwareMajor; pBIOSInf->u8FirmwareMinor = iDmiBIOSFirmwareMinor; } } iStrNr = 1; pBIOSInf->header.u8Type = 0; /* BIOS Information */ pBIOSInf->header.u16Handle = 0x0000; READCFGSTR(pBIOSInf->u8Vendor, DmiBIOSVendor); READCFGSTR(pBIOSInf->u8Version, DmiBIOSVersion); pBIOSInf->u16Start = 0xE000; READCFGSTR(pBIOSInf->u8Release, DmiBIOSReleaseDate); pBIOSInf->u8ROMSize = 1; /* 128K */ pBIOSInf->u64Characteristics = RT_BIT(4) /* ISA is supported */ | RT_BIT(7) /* PCI is supported */ | RT_BIT(15) /* Boot from CD is supported */ | RT_BIT(16) /* Selectable Boot is supported */ | RT_BIT(27) /* Int 9h, 8042 Keyboard services supported */ | RT_BIT(30) /* Int 10h, CGA/Mono Video Services supported */ /* any more?? */ ; pBIOSInf->u8CharacteristicsByte1 = RT_BIT(0) /* ACPI is supported */ /* any more?? */ ; pBIOSInf->u8CharacteristicsByte2 = 0 /* any more?? */ ; TERM_STRUCT; /*********************************** * DMI system information (Type 1) * ***********************************/ PDMISYSTEMINF pSystemInf = (PDMISYSTEMINF)pszStr; CHECKSIZE(sizeof(*pSystemInf)); pszStr = (char *)(pSystemInf + 1); iStrNr = 1; pSystemInf->header.u8Type = 1; /* System Information */ pSystemInf->header.u8Length = sizeof(*pSystemInf); pSystemInf->header.u16Handle = 0x0001; READCFGSTR(pSystemInf->u8Manufacturer, DmiSystemVendor); READCFGSTR(pSystemInf->u8ProductName, DmiSystemProduct); READCFGSTR(pSystemInf->u8Version, DmiSystemVersion); READCFGSTR(pSystemInf->u8SerialNumber, DmiSystemSerial); RTUUID uuid; if (pszDmiSystemUuid) { rc = RTUuidFromStr(&uuid, pszDmiSystemUuid); if (RT_FAILURE(rc)) { if (fHideErrors) { LogRel(("Configuration error: Invalid UUID for DMI tables specified, using default DMI data\n")); continue; } return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("Configuration error: Invalid UUID for DMI tables specified")); } uuid.Gen.u32TimeLow = RT_H2BE_U32(uuid.Gen.u32TimeLow); uuid.Gen.u16TimeMid = RT_H2BE_U16(uuid.Gen.u16TimeMid); uuid.Gen.u16TimeHiAndVersion = RT_H2BE_U16(uuid.Gen.u16TimeHiAndVersion); pUuid = &uuid; } memcpy(pSystemInf->au8Uuid, pUuid, sizeof(RTUUID)); pSystemInf->u8WakeupType = 6; /* Power Switch */ READCFGSTR(pSystemInf->u8SKUNumber, DmiSystemSKU); READCFGSTR(pSystemInf->u8Family, DmiSystemFamily); TERM_STRUCT; /******************************************** * DMI System Enclosure or Chassis (Type 3) * ********************************************/ PDMICHASSIS pChassis = (PDMICHASSIS)pszStr; CHECKSIZE(sizeof(*pChassis)); pszStr = (char*)&pChassis->u32OEMdefined; iStrNr = 1; #ifdef VBOX_WITH_DMI_CHASSIS pChassis->header.u8Type = 3; /* System Enclosure or Chassis */ #else pChassis->header.u8Type = 0x7e; /* inactive */ #endif pChassis->header.u8Length = RT_OFFSETOF(DMICHASSIS, u32OEMdefined); pChassis->header.u16Handle = 0x0003; READCFGSTR(pChassis->u8Manufacturer, DmiChassisVendor); pChassis->u8Type = 0x01; /* ''other'', no chassis lock present */ READCFGSTR(pChassis->u8Version, DmiChassisVersion); READCFGSTR(pChassis->u8SerialNumber, DmiChassisSerial); READCFGSTR(pChassis->u8AssetTag, DmiChassisAssetTag); pChassis->u8BootupState = 0x03; /* safe */ pChassis->u8PowerSupplyState = 0x03; /* safe */ pChassis->u8ThermalState = 0x03; /* safe */ pChassis->u8SecurityStatus = 0x03; /* none XXX */ # if 0 /* v2.3+, currently not supported */ pChassis->u32OEMdefined = 0; pChassis->u8Height = 0; /* unspecified */ pChassis->u8NumPowerChords = 0; /* unspecified */ pChassis->u8ContElems = 0; /* no contained elements */ pChassis->u8ContElemRecLen = 0; /* no contained elements */ # endif TERM_STRUCT; if (fDmiExposeMemoryTable) { /*************************************** * DMI Physical Memory Array (Type 16) * ***************************************/ uint64_t u64RamSize; rc = CFGMR3QueryU64(pCfg, "RamSize", &u64RamSize); if (RT_FAILURE (rc)) return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"RamSize\"")); PDMIRAMARRAY pMemArray = (PDMIRAMARRAY)pszStr; CHECKSIZE(sizeof(*pMemArray)); START_STRUCT(pMemArray); pMemArray->header.u8Type = 16; /* Physical Memory Array */ pMemArray->header.u8Length = sizeof(*pMemArray); pMemArray->header.u16Handle = 0x0005; pMemArray->u8Location = 0x03; /* Motherboard */ pMemArray->u8Use = 0x03; /* System memory */ pMemArray->u8MemErrorCorrection = 0x01; /* Other */ uint32_t u32RamSizeK = (uint32_t)(u64RamSize / _1K); pMemArray->u32MaxCapacity = u32RamSizeK; /* RAM size in K */ pMemArray->u16MemErrorHandle = 0xfffe; /* No error info structure */ pMemArray->u16NumberOfMemDevices = 1; TERM_STRUCT; /*************************************** * DMI Memory Device (Type 17) * ***************************************/ PDMIMEMORYDEV pMemDev = (PDMIMEMORYDEV)pszStr; CHECKSIZE(sizeof(*pMemDev)); START_STRUCT(pMemDev); pMemDev->header.u8Type = 17; /* Memory Device */ pMemDev->header.u8Length = sizeof(*pMemDev); pMemDev->header.u16Handle = 0x0006; pMemDev->u16PhysMemArrayHandle = 0x0005; /* handle of array we belong to */ pMemDev->u16MemErrHandle = 0xfffe; /* system doesn't provide this information */ pMemDev->u16TotalWidth = 0xffff; /* Unknown */ pMemDev->u16DataWidth = 0xffff; /* Unknown */ int16_t u16RamSizeM = (uint16_t)(u64RamSize / _1M); if (u16RamSizeM == 0) u16RamSizeM = 0x400; /* 1G */ pMemDev->u16Size = u16RamSizeM; /* RAM size */ pMemDev->u8FormFactor = 0x09; /* DIMM */ pMemDev->u8DeviceSet = 0x00; /* Not part of a device set */ READCFGSTRDEF(pMemDev->u8DeviceLocator, " ", "DIMM 0"); READCFGSTRDEF(pMemDev->u8BankLocator, " ", "Bank 0"); pMemDev->u8MemoryType = 0x03; /* DRAM */ pMemDev->u16TypeDetail = 0; /* Nothing special */ pMemDev->u16Speed = 1600; /* Unknown, shall be speed in MHz */ READCFGSTR(pMemDev->u8Manufacturer, DmiSystemVendor); READCFGSTRDEF(pMemDev->u8SerialNumber, " ", "00000000"); READCFGSTRDEF(pMemDev->u8AssetTag, " ", "00000000"); READCFGSTRDEF(pMemDev->u8PartNumber, " ", "00000000"); pMemDev->u8Attributes = 0; /* Unknown */ TERM_STRUCT; } /***************************** * DMI OEM strings (Type 11) * *****************************/ PDMIOEMSTRINGS pOEMStrings = (PDMIOEMSTRINGS)pszStr; CHECKSIZE(sizeof(*pOEMStrings)); pszStr = (char *)(pOEMStrings + 1); iStrNr = 1; #ifdef VBOX_WITH_DMI_OEMSTRINGS pOEMStrings->header.u8Type = 0xb; /* OEM Strings */ #else pOEMStrings->header.u8Type = 0x7e; /* inactive */ #endif pOEMStrings->header.u8Length = sizeof(*pOEMStrings); pOEMStrings->header.u16Handle = 0x0002; pOEMStrings->u8Count = 2; char szTmp[64]; RTStrPrintf(szTmp, sizeof(szTmp), "vboxVer_%u.%u.%u", RTBldCfgVersionMajor(), RTBldCfgVersionMinor(), RTBldCfgVersionBuild()); READCFGSTRDEF(pOEMStrings->u8VBoxVersion, "DmiOEMVBoxVer", szTmp); RTStrPrintf(szTmp, sizeof(szTmp), "vboxRev_%u", RTBldCfgRevision()); READCFGSTRDEF(pOEMStrings->u8VBoxRevision, "DmiOEMVBoxRev", szTmp); TERM_STRUCT; /* End-of-table marker - includes padding to account for fixed table size. */ PDMIHDR pEndOfTable = (PDMIHDR)pszStr; pEndOfTable->u8Type = 0x7f; pEndOfTable->u8Length = cbMax - ((char *)pszStr - (char *)pTable) - 2; pEndOfTable->u16Handle = 0xFEFF; /* If more fields are added here, fix the size check in READCFGSTR */ /* Success! */ break; } #undef READCFGSTR #undef READCFGINT #undef CHECKSIZE return VINF_SUCCESS; }