Changeset 85929 in vbox for trunk/src/VBox/Main/src-server/darwin/iokit.cpp
- Timestamp:
- Aug 28, 2020 2:40:55 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/darwin/iokit.cpp
r85272 r85929 31 31 #include <mach/mach.h> 32 32 #include <Carbon/Carbon.h> 33 #include <CoreFoundation/CFBase.h> 33 34 #include <IOKit/IOKitLib.h> 35 #include <IOKit/IOBSD.h> 34 36 #include <IOKit/storage/IOStorageDeviceCharacteristics.h> 37 #include <IOKit/storage/IOBlockStorageDevice.h> 38 #include <IOKit/storage/IOMedia.h> 39 #include <IOKit/storage/IOCDMedia.h> 35 40 #include <IOKit/scsi/SCSITaskLib.h> 36 41 #include <SystemConfiguration/SystemConfiguration.h> 37 42 #include <mach/mach_error.h> 43 #include <sys/param.h> 44 #include <paths.h> 38 45 #ifdef VBOX_WITH_USB 39 46 # include <IOKit/usb/IOUSBLib.h> 40 47 # include <IOKit/IOCFPlugIn.h> 41 # include <IOKit/storage/IOMedia.h>42 48 #endif 43 49 … … 1570 1576 1571 1577 IOObjectRelease(DVDServices); 1578 1579 return pHead; 1580 } 1581 1582 1583 /** 1584 * Enumerate the fixed drives (HDDs, SSD, ++) returning a FIFO of device paths 1585 * strings and model strings separated by ':'. 1586 * 1587 * @returns Pointer to the head. 1588 * The caller is responsible for calling RTMemFree() on each of the nodes. 1589 */ 1590 PDARWINFIXEDDRIVE DarwinGetFixedDrives(void) 1591 { 1592 AssertReturn(darwinOpenMasterPort(), NULL); 1593 1594 /* 1595 * Create a matching dictionary for searching drives in the IOKit. 1596 * 1597 * The idea is to find all the IOMedia objects with "Whole"="True" which identify the disks but 1598 * not partitions. 1599 */ 1600 CFMutableDictionaryRef RefMatchingDict = IOServiceMatching("IOMedia"); 1601 AssertReturn(RefMatchingDict, NULL); 1602 CFDictionaryAddValue(RefMatchingDict, CFSTR(kIOMediaWholeKey), kCFBooleanTrue); 1603 1604 /* 1605 * Perform the search and get a collection of IOMedia objects. 1606 */ 1607 io_iterator_t MediaServices = IO_OBJECT_NULL; 1608 IOReturn rc = IOServiceGetMatchingServices(g_MasterPort, RefMatchingDict, &MediaServices); 1609 AssertMsgReturn(rc == kIOReturnSuccess, ("rc=%d\n", rc), NULL); 1610 RefMatchingDict = NULL; /* the reference is consumed by IOServiceGetMatchingServices. */ 1611 1612 /* 1613 * Enumerate the matching services. 1614 * (This enumeration must be identical to the one performed in DrvHostBase.cpp.) 1615 */ 1616 PDARWINFIXEDDRIVE pHead = NULL; 1617 PDARWINFIXEDDRIVE pTail = NULL; 1618 unsigned i = 0; 1619 io_object_t MediaService; 1620 while ((MediaService = IOIteratorNext(MediaServices)) != IO_OBJECT_NULL) 1621 { 1622 DARWIN_IOKIT_DUMP_OBJ(MediaService); 1623 1624 /* 1625 * Find the IOMedia parents having the IOBlockStorageDevice type and check they have "device-type" = "Generic". 1626 * If the IOMedia object hasn't IOBlockStorageDevices with such device-type in parents the one is not general 1627 * disk but either CDROM-like device or some another device which has no interest for the function. 1628 */ 1629 1630 /* 1631 * Just avoid parents enumeration if the IOMedia is IOCDMedia, i.e. CDROM-like disk 1632 */ 1633 if (IOObjectConformsTo(MediaService, kIOCDMediaClass)) 1634 { 1635 IOObjectRelease(MediaService); 1636 continue; 1637 } 1638 1639 bool fIsGenericStorage = false; 1640 io_registry_entry_t ChildEntry = MediaService; 1641 io_registry_entry_t ParentEntry = IO_OBJECT_NULL; 1642 kern_return_t krc = KERN_SUCCESS; 1643 while ( !fIsGenericStorage 1644 && (krc = IORegistryEntryGetParentEntry(ChildEntry, kIOServicePlane, &ParentEntry)) == KERN_SUCCESS) 1645 { 1646 if (!IOObjectIsEqualTo(ChildEntry, MediaService)) 1647 IOObjectRelease(ChildEntry); 1648 1649 DARWIN_IOKIT_DUMP_OBJ(ParentEntry); 1650 if (IOObjectConformsTo(ParentEntry, kIOBlockStorageDeviceClass)) 1651 { 1652 CFTypeRef DeviceTypeValueRef = IORegistryEntryCreateCFProperty(ParentEntry, 1653 CFSTR("device-type"), 1654 kCFAllocatorDefault, 0); 1655 if ( DeviceTypeValueRef 1656 && CFGetTypeID(DeviceTypeValueRef) == CFStringGetTypeID() 1657 && CFStringCompare((CFStringRef)DeviceTypeValueRef, CFSTR("Generic"), 1658 kCFCompareCaseInsensitive) == kCFCompareEqualTo) 1659 fIsGenericStorage = true; 1660 1661 if (DeviceTypeValueRef != NULL) 1662 CFRelease(DeviceTypeValueRef); 1663 } 1664 ChildEntry = ParentEntry; 1665 } 1666 if (ChildEntry != IO_OBJECT_NULL && !IOObjectIsEqualTo(ChildEntry, MediaService)) 1667 IOObjectRelease(ChildEntry); 1668 1669 if (!fIsGenericStorage) 1670 { 1671 IOObjectRelease(MediaService); 1672 continue; 1673 } 1674 1675 CFTypeRef DeviceName; 1676 DeviceName = IORegistryEntryCreateCFProperty(MediaService, 1677 CFSTR(kIOBSDNameKey), 1678 kCFAllocatorDefault,0); 1679 if (DeviceName) 1680 { 1681 char szDeviceFilePath[MAXPATHLEN]; 1682 strcpy(szDeviceFilePath, _PATH_DEV); 1683 size_t cchPathSize = strlen(szDeviceFilePath); 1684 if (CFStringGetCString((CFStringRef)DeviceName, 1685 &szDeviceFilePath[cchPathSize], 1686 (CFIndex)(sizeof(szDeviceFilePath) - cchPathSize), 1687 kCFStringEncodingUTF8)) 1688 { 1689 PDARWINFIXEDDRIVE pDuplicate = pHead; 1690 while (pDuplicate && strcmp(szDeviceFilePath, pDuplicate->szName) != 0) 1691 pDuplicate = pDuplicate->pNext; 1692 if (pDuplicate == NULL) 1693 { 1694 /* Get model for the IOMedia object. 1695 * 1696 * Due to vendor and product property names are different and 1697 * depend on interface and device type, the best way to get a drive 1698 * model is get IORegistry name for the IOMedia object. Usually, 1699 * it takes "<vendor> <product> <revision> Media" form. Noticed, 1700 * such naming are used by only IOMedia objects having 1701 * "Whole" = True and "BSDName" properties set. 1702 */ 1703 io_name_t szEntryName = { 0 }; 1704 if ((krc = IORegistryEntryGetName(MediaService, szEntryName)) == KERN_SUCCESS) 1705 { 1706 /* remove " Media" from the end of the name */ 1707 char *pszMedia = strrchr(szEntryName, ' '); 1708 if ( pszMedia != NULL 1709 && (uintptr_t)pszMedia < (uintptr_t)&szEntryName[sizeof(szEntryName)] 1710 && strcmp(pszMedia, " Media") == 0) 1711 { 1712 *pszMedia = '\0'; 1713 RTStrPurgeEncoding(szEntryName); 1714 } 1715 } 1716 /* Create the device path and model name in form "/device/path:model". */ 1717 cchPathSize = strlen(szDeviceFilePath); 1718 size_t const cchModelSize = strlen(szEntryName); 1719 size_t const cbExtra = cchPathSize + 1 + cchModelSize + !!cchModelSize; 1720 PDARWINFIXEDDRIVE pNew = (PDARWINFIXEDDRIVE)RTMemAlloc(RT_UOFFSETOF_DYN(DARWINFIXEDDRIVE, szName[cbExtra])); 1721 if (pNew) 1722 { 1723 pNew->pNext = NULL; 1724 memcpy(pNew->szName, szDeviceFilePath, cchPathSize + 1); 1725 pNew->pszModel = NULL; 1726 if (cchModelSize) 1727 pNew->pszModel = (const char *)memcpy(&pNew->szName[cchPathSize + 1], szEntryName, cchModelSize + 1); 1728 1729 if (pTail) 1730 pTail = pTail->pNext = pNew; 1731 else 1732 pTail = pHead = pNew; 1733 } 1734 } 1735 } 1736 CFRelease(DeviceName); 1737 } 1738 IOObjectRelease(MediaService); 1739 i++; 1740 } 1741 IOObjectRelease(MediaServices); 1572 1742 1573 1743 return pHead;
Note:
See TracChangeset
for help on using the changeset viewer.