/** * Converts a partition entry to the host endianness. * * @returns nothing. * @param pPartition The partition to decode. */ static void rtDvmFmtBsdLblDiskLabelDecodePartition(PBsdLabelPartition pPartition) { pPartition->cSectors = RT_LE2H_U32(pPartition->cSectors); pPartition->offSectorStart = RT_LE2H_U32(pPartition->offSectorStart); pPartition->cbFsFragment = RT_LE2H_U32(pPartition->cbFsFragment); pPartition->cFsCylPerGroup = RT_LE2H_U16(pPartition->cFsCylPerGroup); }
/** * Get and a device descriptor and byteswap it appropriately. */ static bool usbProxyGetDeviceDesc(PUSBPROXYDEV pProxyDev, PVUSBDESCDEVICE pOut) { /* * Get the descriptor from the device. */ PVUSBDESCDEVICE pIn = (PVUSBDESCDEVICE)GetStdDescSync(pProxyDev, VUSB_DT_DEVICE, 0, 0, VUSB_DT_DEVICE_MIN_LEN); if (!pIn) { Log(("usbProxyGetDeviceDesc: pProxyDev=%s: GetStdDescSync failed\n", pProxyDev->pUsbIns->pszName)); return false; } if (pIn->bLength < VUSB_DT_DEVICE_MIN_LEN) { Log(("usb-proxy: pProxyDev=%s: Corrupted device descriptor. bLength=%d\n", pProxyDev->pUsbIns->pszName, pIn->bLength)); return false; } /* * Convert it. */ pOut->bLength = VUSB_DT_DEVICE_MIN_LEN; pOut->bDescriptorType = VUSB_DT_DEVICE; pOut->bcdUSB = RT_LE2H_U16(pIn->bcdUSB); pOut->bDeviceClass = pIn->bDeviceClass; pOut->bDeviceSubClass = pIn->bDeviceSubClass; pOut->bDeviceProtocol = pIn->bDeviceProtocol; pOut->bMaxPacketSize0 = pIn->bMaxPacketSize0; pOut->idVendor = RT_LE2H_U16(pIn->idVendor); pOut->idProduct = RT_LE2H_U16(pIn->idProduct); pOut->bcdDevice = RT_LE2H_U16(pIn->bcdDevice); pOut->iManufacturer = pIn->iManufacturer; pOut->iProduct = pIn->iProduct; pOut->iSerialNumber = pIn->iSerialNumber; pOut->bNumConfigurations = pIn->bNumConfigurations; free_desc(pIn); return true; }
/* Synchronously obtain a standard USB descriptor for a device, used in order * to grab configuration descriptors when we first add the device */ static void *GetStdDescSync(PUSBPROXYDEV pProxyDev, uint8_t iDescType, uint8_t iIdx, uint16_t LangId, uint16_t cbHint) { LogFlow(("GetStdDescSync: pProxyDev=%s\n", pProxyDev->pUsbIns->pszName)); for (;;) { /* * Setup a MSG URB, queue and reap it. */ int rc = VINF_SUCCESS; VUSBURB Urb; AssertCompile(RT_SIZEOFMEMB(VUSBURB, abData) >= _4K); Urb.u32Magic = VUSBURB_MAGIC; Urb.enmState = VUSBURBSTATE_IN_FLIGHT; Urb.pszDesc = (char*)"URB sync"; memset(&Urb.VUsb, 0, sizeof(Urb.VUsb)); memset(&Urb.Hci, 0, sizeof(Urb.Hci)); Urb.Dev.pvPrivate = NULL; Urb.Dev.pNext = NULL; Urb.pUsbIns = pProxyDev->pUsbIns; Urb.DstAddress = 0; Urb.EndPt = 0; Urb.enmType = VUSBXFERTYPE_MSG; Urb.enmDir = VUSBDIRECTION_IN; Urb.fShortNotOk = false; Urb.enmStatus = VUSBSTATUS_INVALID; cbHint = RT_MIN(cbHint, sizeof(Urb.abData) - sizeof(VUSBSETUP)); Urb.cbData = cbHint + sizeof(VUSBSETUP); PVUSBSETUP pSetup = (PVUSBSETUP)Urb.abData; pSetup->bmRequestType = VUSB_DIR_TO_HOST | VUSB_REQ_STANDARD | VUSB_TO_DEVICE; pSetup->bRequest = VUSB_REQ_GET_DESCRIPTOR; pSetup->wValue = (iDescType << 8) | iIdx; pSetup->wIndex = LangId; pSetup->wLength = cbHint; rc = pProxyDev->pOps->pfnUrbQueue(pProxyDev, &Urb); if (RT_FAILURE(rc)) break; /* Don't wait forever, it's just a simple request that should return immediately. Since we're executing in the EMT thread it's important not to get stuck here. (Some of the builtin iMac devices may not refuse respond for instance.) */ PVUSBURB pUrbReaped = pProxyDev->pOps->pfnUrbReap(pProxyDev, 10000 /* ms */); if (!pUrbReaped) { rc = pProxyDev->pOps->pfnUrbCancel(pProxyDev, &Urb); AssertRC(rc); /** @todo: This breaks the comment above... */ pUrbReaped = pProxyDev->pOps->pfnUrbReap(pProxyDev, RT_INDEFINITE_WAIT); } if (pUrbReaped != &Urb) { Log(("GetStdDescSync: pfnUrbReap failed, pUrbReaped=%p\n", pUrbReaped)); break; } if (Urb.enmStatus != VUSBSTATUS_OK) { Log(("GetStdDescSync: Urb.enmStatus=%d\n", Urb.enmStatus)); break; } /* * Check the length, config descriptors have total_length field */ uint8_t *pbDesc = (uint8_t *)(pSetup + 1); uint32_t cbDesc; if (iDescType == VUSB_DT_CONFIG) { if (Urb.cbData < sizeof(VUSBSETUP) + 4) { Log(("GetStdDescSync: Urb.cbData=%#x (min 4)\n", Urb.cbData)); break; } cbDesc = RT_LE2H_U16(((uint16_t *)pbDesc)[1]); } else { if (Urb.cbData < sizeof(VUSBSETUP) + 1) { Log(("GetStdDescSync: Urb.cbData=%#x (min 1)\n", Urb.cbData)); break; } cbDesc = ((uint8_t *)pbDesc)[0]; } Log(("GetStdDescSync: got Urb.cbData=%u, cbDesc=%u cbHint=%u\n", Urb.cbData, cbDesc, cbHint)); if ( Urb.cbData == cbHint + sizeof(VUSBSETUP) && cbDesc > Urb.cbData - sizeof(VUSBSETUP)) { cbHint = cbDesc; if (cbHint > sizeof(Urb.abData)) { AssertMsgFailed(("cbHint=%u\n", cbHint)); break; } continue; } Assert(cbDesc <= Urb.cbData - sizeof(VUSBSETUP)); #ifdef LOG_ENABLED vusbUrbTrace(&Urb, "GetStdDescSync", true); #endif /* * Fine, we got everything return a heap duplicate of the descriptor. */ return RTMemDup(pbDesc, cbDesc); } return NULL; }
RTDECL(int) RTUuidFromUtf16(PRTUUID pUuid, PCRTUTF16 pwszString) { bool fHaveBraces; /* * Validate parameters. */ AssertPtrReturn(pUuid, VERR_INVALID_PARAMETER); AssertPtrReturn(pwszString, VERR_INVALID_PARAMETER); fHaveBraces = pwszString[0] == '{'; pwszString += fHaveBraces; #define MY_CHECK(expr) do { if (RT_UNLIKELY(!(expr))) return VERR_INVALID_UUID_FORMAT; } while (0) #define MY_ISXDIGIT(ch) (!((ch) & 0xff00) && g_au8Digits[(ch) & 0xff] != 0xff) MY_CHECK(MY_ISXDIGIT(pwszString[ 0])); MY_CHECK(MY_ISXDIGIT(pwszString[ 1])); MY_CHECK(MY_ISXDIGIT(pwszString[ 2])); MY_CHECK(MY_ISXDIGIT(pwszString[ 3])); MY_CHECK(MY_ISXDIGIT(pwszString[ 4])); MY_CHECK(MY_ISXDIGIT(pwszString[ 5])); MY_CHECK(MY_ISXDIGIT(pwszString[ 6])); MY_CHECK(MY_ISXDIGIT(pwszString[ 7])); MY_CHECK(pwszString[ 8] == '-'); MY_CHECK(MY_ISXDIGIT(pwszString[ 9])); MY_CHECK(MY_ISXDIGIT(pwszString[10])); MY_CHECK(MY_ISXDIGIT(pwszString[11])); MY_CHECK(MY_ISXDIGIT(pwszString[12])); MY_CHECK(pwszString[13] == '-'); MY_CHECK(MY_ISXDIGIT(pwszString[14])); MY_CHECK(MY_ISXDIGIT(pwszString[15])); MY_CHECK(MY_ISXDIGIT(pwszString[16])); MY_CHECK(MY_ISXDIGIT(pwszString[17])); MY_CHECK(pwszString[18] == '-'); MY_CHECK(MY_ISXDIGIT(pwszString[19])); MY_CHECK(MY_ISXDIGIT(pwszString[20])); MY_CHECK(MY_ISXDIGIT(pwszString[21])); MY_CHECK(MY_ISXDIGIT(pwszString[22])); MY_CHECK(pwszString[23] == '-'); MY_CHECK(MY_ISXDIGIT(pwszString[24])); MY_CHECK(MY_ISXDIGIT(pwszString[25])); MY_CHECK(MY_ISXDIGIT(pwszString[26])); MY_CHECK(MY_ISXDIGIT(pwszString[27])); MY_CHECK(MY_ISXDIGIT(pwszString[28])); MY_CHECK(MY_ISXDIGIT(pwszString[29])); MY_CHECK(MY_ISXDIGIT(pwszString[30])); MY_CHECK(MY_ISXDIGIT(pwszString[31])); MY_CHECK(MY_ISXDIGIT(pwszString[32])); MY_CHECK(MY_ISXDIGIT(pwszString[33])); MY_CHECK(MY_ISXDIGIT(pwszString[34])); MY_CHECK(MY_ISXDIGIT(pwszString[35])); if (fHaveBraces) MY_CHECK(pwszString[36] == '}'); MY_CHECK(!pwszString[36 + fHaveBraces]); #undef MY_ISXDIGIT #undef MY_CHECK /* * Inverse of RTUuidToUtf8 (see above). */ #define MY_TONUM(ch) (g_au8Digits[(ch) & 0xff]) pUuid->Gen.u32TimeLow = RT_LE2H_U32((uint32_t)MY_TONUM(pwszString[ 0]) << 28 | (uint32_t)MY_TONUM(pwszString[ 1]) << 24 | (uint32_t)MY_TONUM(pwszString[ 2]) << 20 | (uint32_t)MY_TONUM(pwszString[ 3]) << 16 | (uint32_t)MY_TONUM(pwszString[ 4]) << 12 | (uint32_t)MY_TONUM(pwszString[ 5]) << 8 | (uint32_t)MY_TONUM(pwszString[ 6]) << 4 | (uint32_t)MY_TONUM(pwszString[ 7])); pUuid->Gen.u16TimeMid = RT_LE2H_U16((uint16_t)MY_TONUM(pwszString[ 9]) << 12 | (uint16_t)MY_TONUM(pwszString[10]) << 8 | (uint16_t)MY_TONUM(pwszString[11]) << 4 | (uint16_t)MY_TONUM(pwszString[12])); pUuid->Gen.u16TimeHiAndVersion = RT_LE2H_U16( (uint16_t)MY_TONUM(pwszString[14]) << 12 | (uint16_t)MY_TONUM(pwszString[15]) << 8 | (uint16_t)MY_TONUM(pwszString[16]) << 4 | (uint16_t)MY_TONUM(pwszString[17])); pUuid->Gen.u8ClockSeqHiAndReserved = (uint16_t)MY_TONUM(pwszString[19]) << 4 | (uint16_t)MY_TONUM(pwszString[20]); pUuid->Gen.u8ClockSeqLow = (uint16_t)MY_TONUM(pwszString[21]) << 4 | (uint16_t)MY_TONUM(pwszString[22]); pUuid->Gen.au8Node[0] = (uint8_t)MY_TONUM(pwszString[24]) << 4 | (uint8_t)MY_TONUM(pwszString[25]); pUuid->Gen.au8Node[1] = (uint8_t)MY_TONUM(pwszString[26]) << 4 | (uint8_t)MY_TONUM(pwszString[27]); pUuid->Gen.au8Node[2] = (uint8_t)MY_TONUM(pwszString[28]) << 4 | (uint8_t)MY_TONUM(pwszString[29]); pUuid->Gen.au8Node[3] = (uint8_t)MY_TONUM(pwszString[30]) << 4 | (uint8_t)MY_TONUM(pwszString[31]); pUuid->Gen.au8Node[4] = (uint8_t)MY_TONUM(pwszString[32]) << 4 | (uint8_t)MY_TONUM(pwszString[33]); pUuid->Gen.au8Node[5] = (uint8_t)MY_TONUM(pwszString[34]) << 4 | (uint8_t)MY_TONUM(pwszString[35]); #undef MY_TONUM return VINF_SUCCESS; }
/** * Converts the on disk BSD label to the host endianness. * * @returns Whether the given label structure is a valid BSD disklabel. * @param pBsdLabel Pointer to the BSD disklabel to decode. */ static bool rtDvmFmtBsdLblDiskLabelDecode(PBsdLabel pBsdLabel) { pBsdLabel->u32Magic = RT_LE2H_U32(pBsdLabel->u32Magic); pBsdLabel->u16DriveType = RT_LE2H_U16(pBsdLabel->u16DriveType); pBsdLabel->u16SubType = RT_LE2H_U16(pBsdLabel->u16SubType); pBsdLabel->cbSector = RT_LE2H_U32(pBsdLabel->cbSector); pBsdLabel->cSectorsPerTrack = RT_LE2H_U32(pBsdLabel->cSectorsPerTrack); pBsdLabel->cTracksPerCylinder = RT_LE2H_U32(pBsdLabel->cTracksPerCylinder); pBsdLabel->cDataCylindersPerUnit = RT_LE2H_U32(pBsdLabel->cDataCylindersPerUnit); pBsdLabel->cDataSectorsPerCylinder = RT_LE2H_U32(pBsdLabel->cDataSectorsPerCylinder); pBsdLabel->cSectorsPerUnit = RT_LE2H_U32(pBsdLabel->cSectorsPerUnit); pBsdLabel->cSpareSectorsPerTrack = RT_LE2H_U16(pBsdLabel->cSpareSectorsPerTrack); pBsdLabel->cSpareSectorsPerCylinder = RT_LE2H_U16(pBsdLabel->cSpareSectorsPerCylinder); pBsdLabel->cSpareCylindersPerUnit = RT_LE2H_U32(pBsdLabel->cSpareCylindersPerUnit); pBsdLabel->cRotationsPerMinute = RT_LE2H_U16(pBsdLabel->cRotationsPerMinute); pBsdLabel->uSectorInterleave = RT_LE2H_U16(pBsdLabel->uSectorInterleave); pBsdLabel->uSectorSkewPerTrack = RT_LE2H_U16(pBsdLabel->uSectorSkewPerTrack); pBsdLabel->uSectorSkewPerCylinder = RT_LE2H_U16(pBsdLabel->uSectorSkewPerCylinder); pBsdLabel->usHeadSwitch = RT_LE2H_U16(pBsdLabel->usHeadSwitch); pBsdLabel->usTrackSeek = RT_LE2H_U16(pBsdLabel->usTrackSeek); pBsdLabel->fFlags = RT_LE2H_U32(pBsdLabel->fFlags); for (unsigned i = 0; i < RT_ELEMENTS(pBsdLabel->au32DriveData); i++) pBsdLabel->au32DriveData[i] = RT_LE2H_U32(pBsdLabel->au32DriveData[i]); for (unsigned i = 0; i < RT_ELEMENTS(pBsdLabel->au32Reserved); i++) pBsdLabel->au32Reserved[i] = RT_LE2H_U32(pBsdLabel->au32Reserved[i]); pBsdLabel->u32Magic2 = RT_LE2H_U32(pBsdLabel->u32Magic2); pBsdLabel->u16ChkSum = RT_LE2H_U16(pBsdLabel->u16ChkSum); pBsdLabel->cPartitions = RT_LE2H_U16(pBsdLabel->cPartitions); pBsdLabel->cbBootArea = RT_LE2H_U32(pBsdLabel->cbBootArea); pBsdLabel->cbFsSuperBlock = RT_LE2H_U32(pBsdLabel->cbFsSuperBlock); /* Check the magics now. */ if ( pBsdLabel->u32Magic != RTDVM_BSDLBL_MAGIC || pBsdLabel->u32Magic2 != RTDVM_BSDLBL_MAGIC || pBsdLabel->cPartitions != RTDVM_BSDLBL_MAX_PARTITIONS) return false; /* Convert the partitions array. */ for (unsigned i = 0; i < RT_ELEMENTS(pBsdLabel->aPartitions); i++) rtDvmFmtBsdLblDiskLabelDecodePartition(&pBsdLabel->aPartitions[i]); /* Check the checksum now. */ uint16_t u16ChkSumSaved = pBsdLabel->u16ChkSum; pBsdLabel->u16ChkSum = 0; if (u16ChkSumSaved != rtDvmFmtBsdLblDiskLabelChkSum(pBsdLabel)) return false; pBsdLabel->u16ChkSum = u16ChkSumSaved; return true; }