将无代码 KEXT 迁移到无代码 DEXT
Migrating a codeless KEXT to a codeless DEXT
我正在将无代码 KEXT 迁移到无代码 DEXT。我观看了 WWDC 视频并阅读了 Apple Developer 网站上的大部分信息。我遇到的困难不是要做什么,而是如何开始。带有示例项目的不错教程会有所帮助。
在我的无代码 KEXT 中,对于 4 个独立的设备,我为每个设备的 IOUSBDevice 和 IOUSBInterface 设置了 IOKitPersonalities。 KEXT 允许我将我的设备与我的“驱动程序”相匹配,这样 Apple HID 驱动程序就不会抓住它们。我希望在无代码 DEXT 中做相同或类似的事情。
到目前为止,我已经在一个应用程序中创建了一个名为 MyUsbDriver 的 DriverKit 目标(对于 DriverKit.framework)并添加了一个 USBDriverKit.framework。这向我的项目添加了一个文件夹 MyUsbDriver,其中包含文件 MyUsbDriver.cpp、MyUsbDriver.iig、Info.plist 和 MyUsbDriver.entitlements。这是我的问题:
看起来 IOService 的默认子类适用于 USB - 这与 KEXT 中的 IOClass 相同。是真的吗?
DEXT-world中的IOUSBHostInterface是否等同于KEXT-world中的IOUSBInterface?
IOUSBHostDevice是否等同于IOUSBDevice?
我需要对无代码 DEXT 的 .cpp 或 .iig 做任何事情吗?我的大部分工作不是在 plist 和 entitlements 文件中完成吗?
我的 MyUsbDriver 目标框架和库中是否需要 USBDriverKit.framework?
在哪里可以找到如何完成此迁移的合适示例?
如有任何帮助,我们将不胜感激。
更新:
使用示例和答案中的其他链接,我能够得到一些东西。我确实有一个“Doh”时刻:我最初的测试项目类型是命令行工具,我永远无法嵌入 DEXT。我几乎只是手动编辑了 pbxproj 文件。然而,在查看来自 Scott Knight 的原始示例 USBApp 时,我意识到他使用的项目类型是 App,事后看来,这是有道理的,但当时令人困惑。
这里是 info.plist 目前为止我在我们已弃用的设备之一上进行匹配:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>IOKitPersonalities</key>
<dict>
<key>MyUsbDrver</key>
<dict>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleIdentifierKernel</key>
<string>com.apple.kpi.iokit</string>
<key>IOClass</key>
<string>IOUserService</string>
<key>IOMatchCategory</key>
<string>com.apple.null.driver</string>
<key>IOProviderClass</key>
<string>IOUsbHostInterface</string>
<key>IOResourceMatch</key>
<string>IOKit</string>
<key>IOUserClass</key>
<string>MyUsbDrver</string>
<key>IOUserServerName</key>
<string>Home.MyUsbDrver</string>
<key>bConfigurationValue</key>
<integer>1</integer>
<key>bInterfaceNumber</key>
<integer>0</integer>
<key>idProduct</key>
<integer>2</integer>
<key>idVendor</key>
<integer>5843</integer>
</dict>
</dict>
<key>OSBundleUsageDescription</key>
<string>Codless DEXT to match on IOKit.</string>
</dict>
</plist>
我不确定 IOResourceMatch - 值是 IOKit,这是我尝试去的方向。
更新第二个:
进步!
我最终不得不手动更改我的 pbxproj 文件中的签名条款。禁用 SIP,在我的应用程序中设置系统扩展 activation/deactivation 并进行命令行签名。我发现此存储库对于激活代码的体面 Objective-C 示例很有帮助 - https://github.com/google/santa.git。一切构建和代码签名似乎都是成功的。得到有趣的错误
SystemExtension "Home.MyUsbDrver" request did fail: Error Domain=OSSystemExtensionErrorDomain Code=8 "(null)"
更新 3:
我检查了我的 DEXT 和应用授权,看起来应用授权需要更新。这就是我现在的应用程序:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.developer.system-extension.install</key>
<true/>
<key>com.apple.developer.system-extension.uninstall</key>
<true/>
</dict>
</plist>
我错过了最后两个。清理我的项目,构建,再次签名。当我从 Xcode 尝试 运行ning 时,仍然出现错误。当我从 Finder 运行 我的应用程序时,我得到了系统首选项对话框。在那之后,Xcode 的结果仍然相同,现在只有 Finder 运行 时应用程序的闪光。我重新启动 - 仍然是相同的结果。但是,当我从终端 运行 systemextensionsctl -list 时,我得到:
3 extension(s)
--- com.apple.system_extension.driver_extension
enabled active teamID bundleID (version) name [state]
<REDACTED> Home.MyUsbDrver (1.0/1) Home.MyUsbDrver [terminated waiting to uninstall on reboot]
* * <REDACTED> Home.MyUsbDrver (1.0/1) Home.MyUsbDrver [activated enabled]
<REDACTED> Home.MyUsbDrver (1.0/1) Home.MyUsbDrver [activated waiting to upgrade]
重启后我得到这个:
1 extension(s)
--- com.apple.system_extension.driver_extension
enabled active teamID bundleID (version) name [state]
* * <REDACTED> Home.MyUsbDrver (1.0/1) Home.MyUsbDrver [activated enabled]
所以,看起来我的系统扩展已经到位,但实际上我不确定为什么,因为我刚刚重新启动并且没有 运行 我的应用程序。
更新 4:
我发现我的权利的问题只是文件的格式。我在 TextEdit 中更改了它,现在我可以与我的设备通信。这是我最终得到的结果:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.driverkit</key>
<true/>
<key>com.apple.developer.driverkit.transport.usb</key>
<array>
<dict>
<key>idVendor</key>
<integer>VID0</integer>
<key>idProductArray</key>
<array>
<integer>PID0</integer>
<integer>PID1</integer>
<integer>PID2</integer>
<integer>PID3</integer>
<integer>PID4</integer>
</array>
</dict>
</array>
<key>com.apple.security.app-sandbox</key>
<true/>
</dict>
</plist>
我一直在努力反对让同样的事情发挥作用。最后,我设法获得了一个有效的 DEXT,它禁用了特定供应商 ID/product ID 组合的 Apple HID 驱动程序。我们已经为我们的供应商 ID 获得了 DriverKit 授权。
- It looks like the default subclass of IOService is OK for USB - that is the same as the IOClass from the KEXT. Is that true?
这对我有用。我尝试完全删除 .iig
和 .cpp
文件,但与 KEXT 不同的是,似乎需要编译一些代码才能使签名正常工作。所以我最终得到了 IOService
.
的一个空子类
- Is IOUSBHostInterface in DEXT-world equivalent to IOUSBInterface in KEXT-world?
我相信是的。我使用了 IOUSBHostInterface
,我们的 KEXT 中有 IOUSBInterface
。
- Is IOUSBHostDevice equivalent to IOUSBDevice?
我不知道,但我相信。
- Do I need to do anything to the .cpp or .iig for codeless DEXT? Isn't most of my work to be done in the plist and entitlements files?
我不需要更改 .cpp
和 .iig
文件中的任何内容。在释放 .cpp
文件之前,您可能希望删除 os_log(OS_LOG_DEFAULT, "Hello World");
行。但是在调试时,判断 DEXT 是否实际加载对我很有用。您可以 运行 log stream --source | grep 'HELLO'
在终端中查找日志。
- Do I need the USBDriverKit.framework in my Frameworks and Libraries of MyUsbDriver target?
我的 DEXT 链接到 DriverKit.framework
。不知道有没有必要
- Where can I find a decent example of how to complete this migration?
也许这些可以帮助:
- https://github.com/stuartlynne/USBApp-updated
- Migrating from codeless KEXT to DEXT. Usb interfaces disappeared
我为自己和未来的开发者记下的一些笔记
在开发 DriverKit 扩展 (dext) 期间,执行以下操作:
禁用系统完整性保护 (SIP):https://apple.stackexchange.com/a/208481/21491。 (在恢复模式下重启,运行 csrutil disable
)。记得再次开启!
通过运行ning systemextensionsctl developer on
启用系统扩展开发模式
确保您没有安装旧的无代码 KEXT。 (从 /Library/Extensions
and/or /System/Library/Extensions
中删除它。确保之后重新启动)
提示和注意事项
您可能需要包含 DriverKit 授权的手动配置文件。我认为我的问题是我在企业开发团队而不是 public 开发团队中获得了 DriverKit 权利。
加载扩展的应用程序需要“系统扩展”授权,但不需要手动配置文件。
注意系统偏好设置中的一个愚蠢错误。每次加载 dext 时,您都需要同意加载它。但是,如果“安全和隐私”窗格已经打开,则不会显示同意按钮。您需要重新启动系统偏好设置才能显示。我一直在慷慨地使用终端中的命令 pkill -9 "System Preferences"; open /System/Library/PreferencePanes/Security.prefPane
来解决这个问题。
您可以使用systemextensionsctl
卸载dext或重置系统状态。但是,这实际上并没有改变驱动程序匹配,因此您需要重新启动。慷慨地。我使用这个终端命令是因为我很懒:osascript -e 'tell app "System Events" to restart'
.
您可以使用ioreg
检查设备是否匹配到扩展名:ioreg -lirc IOUSBHostInterface
.
让扩展正常工作的关键是将 IOProviderClass
设置为
IOUSBHostInterface
而不是 Info.plist 文件中的 IOResources
。 (为了
参考,KEXT 使用 IOUSBInterface
这是 类 之一
Apple 已弃用)
您可能希望在每次对 DEXT 进行更改时更改 Info.plist
中的版本,以确保您实际使用的是正确的版本。 (systemextensionsctl
将显示它加载的版本)。
我正在将无代码 KEXT 迁移到无代码 DEXT。我观看了 WWDC 视频并阅读了 Apple Developer 网站上的大部分信息。我遇到的困难不是要做什么,而是如何开始。带有示例项目的不错教程会有所帮助。
在我的无代码 KEXT 中,对于 4 个独立的设备,我为每个设备的 IOUSBDevice 和 IOUSBInterface 设置了 IOKitPersonalities。 KEXT 允许我将我的设备与我的“驱动程序”相匹配,这样 Apple HID 驱动程序就不会抓住它们。我希望在无代码 DEXT 中做相同或类似的事情。
到目前为止,我已经在一个应用程序中创建了一个名为 MyUsbDriver 的 DriverKit 目标(对于 DriverKit.framework)并添加了一个 USBDriverKit.framework。这向我的项目添加了一个文件夹 MyUsbDriver,其中包含文件 MyUsbDriver.cpp、MyUsbDriver.iig、Info.plist 和 MyUsbDriver.entitlements。这是我的问题:
看起来 IOService 的默认子类适用于 USB - 这与 KEXT 中的 IOClass 相同。是真的吗?
DEXT-world中的IOUSBHostInterface是否等同于KEXT-world中的IOUSBInterface?
IOUSBHostDevice是否等同于IOUSBDevice?
我需要对无代码 DEXT 的 .cpp 或 .iig 做任何事情吗?我的大部分工作不是在 plist 和 entitlements 文件中完成吗?
我的 MyUsbDriver 目标框架和库中是否需要 USBDriverKit.framework?
在哪里可以找到如何完成此迁移的合适示例?
如有任何帮助,我们将不胜感激。
更新:
使用示例和答案中的其他链接,我能够得到一些东西。我确实有一个“Doh”时刻:我最初的测试项目类型是命令行工具,我永远无法嵌入 DEXT。我几乎只是手动编辑了 pbxproj 文件。然而,在查看来自 Scott Knight 的原始示例 USBApp 时,我意识到他使用的项目类型是 App,事后看来,这是有道理的,但当时令人困惑。
这里是 info.plist 目前为止我在我们已弃用的设备之一上进行匹配:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>IOKitPersonalities</key>
<dict>
<key>MyUsbDrver</key>
<dict>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleIdentifierKernel</key>
<string>com.apple.kpi.iokit</string>
<key>IOClass</key>
<string>IOUserService</string>
<key>IOMatchCategory</key>
<string>com.apple.null.driver</string>
<key>IOProviderClass</key>
<string>IOUsbHostInterface</string>
<key>IOResourceMatch</key>
<string>IOKit</string>
<key>IOUserClass</key>
<string>MyUsbDrver</string>
<key>IOUserServerName</key>
<string>Home.MyUsbDrver</string>
<key>bConfigurationValue</key>
<integer>1</integer>
<key>bInterfaceNumber</key>
<integer>0</integer>
<key>idProduct</key>
<integer>2</integer>
<key>idVendor</key>
<integer>5843</integer>
</dict>
</dict>
<key>OSBundleUsageDescription</key>
<string>Codless DEXT to match on IOKit.</string>
</dict>
</plist>
我不确定 IOResourceMatch - 值是 IOKit,这是我尝试去的方向。
更新第二个:
进步!
我最终不得不手动更改我的 pbxproj 文件中的签名条款。禁用 SIP,在我的应用程序中设置系统扩展 activation/deactivation 并进行命令行签名。我发现此存储库对于激活代码的体面 Objective-C 示例很有帮助 - https://github.com/google/santa.git。一切构建和代码签名似乎都是成功的。得到有趣的错误
SystemExtension "Home.MyUsbDrver" request did fail: Error Domain=OSSystemExtensionErrorDomain Code=8 "(null)"
更新 3:
我检查了我的 DEXT 和应用授权,看起来应用授权需要更新。这就是我现在的应用程序:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.developer.system-extension.install</key>
<true/>
<key>com.apple.developer.system-extension.uninstall</key>
<true/>
</dict>
</plist>
我错过了最后两个。清理我的项目,构建,再次签名。当我从 Xcode 尝试 运行ning 时,仍然出现错误。当我从 Finder 运行 我的应用程序时,我得到了系统首选项对话框。在那之后,Xcode 的结果仍然相同,现在只有 Finder 运行 时应用程序的闪光。我重新启动 - 仍然是相同的结果。但是,当我从终端 运行 systemextensionsctl -list 时,我得到:
3 extension(s)
--- com.apple.system_extension.driver_extension
enabled active teamID bundleID (version) name [state]
<REDACTED> Home.MyUsbDrver (1.0/1) Home.MyUsbDrver [terminated waiting to uninstall on reboot]
* * <REDACTED> Home.MyUsbDrver (1.0/1) Home.MyUsbDrver [activated enabled]
<REDACTED> Home.MyUsbDrver (1.0/1) Home.MyUsbDrver [activated waiting to upgrade]
重启后我得到这个:
1 extension(s)
--- com.apple.system_extension.driver_extension
enabled active teamID bundleID (version) name [state]
* * <REDACTED> Home.MyUsbDrver (1.0/1) Home.MyUsbDrver [activated enabled]
所以,看起来我的系统扩展已经到位,但实际上我不确定为什么,因为我刚刚重新启动并且没有 运行 我的应用程序。
更新 4:
我发现我的权利的问题只是文件的格式。我在 TextEdit 中更改了它,现在我可以与我的设备通信。这是我最终得到的结果:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.driverkit</key>
<true/>
<key>com.apple.developer.driverkit.transport.usb</key>
<array>
<dict>
<key>idVendor</key>
<integer>VID0</integer>
<key>idProductArray</key>
<array>
<integer>PID0</integer>
<integer>PID1</integer>
<integer>PID2</integer>
<integer>PID3</integer>
<integer>PID4</integer>
</array>
</dict>
</array>
<key>com.apple.security.app-sandbox</key>
<true/>
</dict>
</plist>
我一直在努力反对让同样的事情发挥作用。最后,我设法获得了一个有效的 DEXT,它禁用了特定供应商 ID/product ID 组合的 Apple HID 驱动程序。我们已经为我们的供应商 ID 获得了 DriverKit 授权。
- It looks like the default subclass of IOService is OK for USB - that is the same as the IOClass from the KEXT. Is that true?
这对我有用。我尝试完全删除 .iig
和 .cpp
文件,但与 KEXT 不同的是,似乎需要编译一些代码才能使签名正常工作。所以我最终得到了 IOService
.
- Is IOUSBHostInterface in DEXT-world equivalent to IOUSBInterface in KEXT-world?
我相信是的。我使用了 IOUSBHostInterface
,我们的 KEXT 中有 IOUSBInterface
。
- Is IOUSBHostDevice equivalent to IOUSBDevice?
我不知道,但我相信。
- Do I need to do anything to the .cpp or .iig for codeless DEXT? Isn't most of my work to be done in the plist and entitlements files?
我不需要更改 .cpp
和 .iig
文件中的任何内容。在释放 .cpp
文件之前,您可能希望删除 os_log(OS_LOG_DEFAULT, "Hello World");
行。但是在调试时,判断 DEXT 是否实际加载对我很有用。您可以 运行 log stream --source | grep 'HELLO'
在终端中查找日志。
- Do I need the USBDriverKit.framework in my Frameworks and Libraries of MyUsbDriver target?
我的 DEXT 链接到 DriverKit.framework
。不知道有没有必要
- Where can I find a decent example of how to complete this migration?
也许这些可以帮助:
- https://github.com/stuartlynne/USBApp-updated
- Migrating from codeless KEXT to DEXT. Usb interfaces disappeared
我为自己和未来的开发者记下的一些笔记
在开发 DriverKit 扩展 (dext) 期间,执行以下操作:
禁用系统完整性保护 (SIP):https://apple.stackexchange.com/a/208481/21491。 (在恢复模式下重启,运行
csrutil disable
)。记得再次开启!通过运行ning
启用系统扩展开发模式systemextensionsctl developer on
确保您没有安装旧的无代码 KEXT。 (从
/Library/Extensions
and/or/System/Library/Extensions
中删除它。确保之后重新启动)
提示和注意事项
您可能需要包含 DriverKit 授权的手动配置文件。我认为我的问题是我在企业开发团队而不是 public 开发团队中获得了 DriverKit 权利。
加载扩展的应用程序需要“系统扩展”授权,但不需要手动配置文件。
注意系统偏好设置中的一个愚蠢错误。每次加载 dext 时,您都需要同意加载它。但是,如果“安全和隐私”窗格已经打开,则不会显示同意按钮。您需要重新启动系统偏好设置才能显示。我一直在慷慨地使用终端中的命令
pkill -9 "System Preferences"; open /System/Library/PreferencePanes/Security.prefPane
来解决这个问题。您可以使用
systemextensionsctl
卸载dext或重置系统状态。但是,这实际上并没有改变驱动程序匹配,因此您需要重新启动。慷慨地。我使用这个终端命令是因为我很懒:osascript -e 'tell app "System Events" to restart'
.您可以使用
ioreg
检查设备是否匹配到扩展名:ioreg -lirc IOUSBHostInterface
.让扩展正常工作的关键是将
IOProviderClass
设置为IOUSBHostInterface
而不是 Info.plist 文件中的IOResources
。 (为了 参考,KEXT 使用IOUSBInterface
这是 类 之一 Apple 已弃用)您可能希望在每次对 DEXT 进行更改时更改
Info.plist
中的版本,以确保您实际使用的是正确的版本。 (systemextensionsctl
将显示它加载的版本)。