繁体   English   中英

将无代码 KEXT 迁移到无代码 DEXT

[英]Migrating a codeless KEXT to a codeless DEXT

我正在将无代码 KEXT 迁移到无代码 DEXT。 我观看了 WWDC 视频并阅读了 Apple Developer 网站上的大部分信息。 我遇到的困难不是找到做什么,而是如何开始。 带有示例项目的不错的教程会有所帮助。

在我的无代码 KEXT 中,对于 4 个单独的设备,我有 IOKitPersonalities 用于 IOUSBDevice 和 IOUSBInterface 用于每个设备。 KEXT 允许我将我的设备与我的“驱动程序”相匹配,这样 Apple HID 驱动程序就不会抓取它们。 我希望在无代码 DEXT 中做同样或类似的事情。

到目前为止,我已经在应用程序中创建了一个名为 MyUsbDriver 的 DriverKit 目标(用于 DriverKit.framework),并添加了一个 USBDriverKit.framework。 这在我的项目中添加了一个文件夹 MyUsbDriver,其中包含文件 MyUsbDriver.cpp、MyUsbDriver.iig、Info.plist 和 MyUsbDriver.entitlements。 以下是我的问题:

  1. 看起来 IOService 的默认子类对于 USB 来说是可以的——这与 KEXT 中的 IOClass 相同。 真的吗?

  2. DEXT 世界中的 IOUSBHostInterface 是否等同于 KEXT 世界中的 IOUSBInterface?

  3. IOUSBHostDevice 是否等同于 IOUSBDevice?

  4. 对于无代码 DEXT,我是否需要对 .cpp 或 .iig 做任何事情? 我的大部分工作不是在 plist 和 entitlements 文件中完成吗?

  5. 我的 MyUsbDriver 目标的框架和库中是否需要 USBDriverKit.framework?

  6. 我在哪里可以找到如何完成此迁移的体面示例?

任何帮助将不胜感激。

更新:

使用答案中的示例和其他链接,我能够得到一些东西。 我确实有一个“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,这是我尝试 go 的方向。

更新第二个:

进步!

我最终不得不手动更改我的 pbxproj 文件中的签名规定。 禁用 SIP,在我的应用程序中设置系统扩展激活/停用并进行命令行签名。 我发现这个存储库对激活码的一个像样的 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 运行时,仍然出现错误。 当我从 Finder 运行我的应用程序时,我得到了系统首选项对话框。 之后,Xcode 的结果仍然相同,现在从 Finder 运行时,只有应用程序的 flash。 我重新启动 - 仍然是相同的结果。 但是,从终端运行 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/产品 ID 组合禁用了 Apple HID 驱动程序。 我们已获得供应商 ID 的 DriverKit 权利。

  1. 看起来 IOService 的默认子类对于 USB 来说是可以的——这与 KEXT 中的 IOClass 相同。 真的吗?

这对我有用。 我尝试完全删除.iig.cpp文件,但与 KEXT 不同,似乎需要编译一些代码才能使签名正常工作。 所以我最终得到了一个空的IOService子类。

  1. DEXT 世界中的 IOUSBHostInterface 是否等同于 KEXT 世界中的 IOUSBInterface?

我相信是这样。 我使用了IOUSBHostInterface ,我们的 KEXT 中有IOUSBInterface

  1. IOUSBHostDevice 是否等同于 IOUSBDevice?

我不知道,但我相信是的。

  1. 对于无代码 DEXT,我是否需要对 .cpp 或 .iig 做任何事情? 我的大部分工作不是在 plist 和 entitlements 文件中完成吗?

我不需要更改.cpp.iig文件中的任何内容。 您可能想要删除os_log(OS_LOG_DEFAULT, "Hello World"); .cpp文件中的行,然后再发布它。 但是在调试时,判断 DEXT 是否实际加载对我很有用。 您可以运行log stream --source | grep 'HELLO' log stream --source | grep 'HELLO'在终端中查找日志。

  1. 我的 MyUsbDriver 目标的框架和库中是否需要 USBDriverKit.framework?

我的 DEXT 链接到DriverKit.framework 我不知道它是否需要。

  1. 我在哪里可以找到如何完成此迁移的体面示例?

也许这些可以帮助:

我为自己和未来的开发人员记下的一些笔记

在开发 DriverKit 扩展 (dext) 期间,请执行以下操作:

  • 禁用系统完整性保护 (SIP): https://apple.stackexchange.com/a/208481/21491 (在恢复模式下重新启动,运行csrutil disable )。 记得重新启用它!

  • 通过运行systemextensionsctl developer on启用系统扩展开发模式

  • 确保您没有安装旧的无代码 KEXT。 (从/Library/Extensions和/或/System/Library/Extensions中删除它。确保之后重新启动)

提示和注意事项

  • 您可能需要包含 DriverKit 权利的手动配置文件。 我认为我的问题是我在企业开发团队而不是公共开发团队中获得了 DriverKit 权利。

  • 加载扩展的应用程序需要“系统扩展”权利,但不需要手动配置配置文件。

  • 当心系统偏好设置中的一个愚蠢的错误。 每次加载时,您都需要同意加载 dext。 但是,如果“安全和隐私”窗格已打开,则不会显示表示同意的按钮。 您需要重新启动系统偏好设置才能显示它。 我一直在使用命令pkill -9 "System Preferences"; open /System/Library/PreferencePanes/Security.prefPane 从终端慷慨地pkill -9 "System Preferences"; open /System/Library/PreferencePanes/Security.prefPane以解决此问题。

  • 您可以使用systemextensionsctl卸载 dext 或重置系统 state。 但是,这实际上并没有改变驱动匹配,所以你需要重新启动。 大方。 我使用这个终端命令是因为我很懒: osascript -e 'tell app "System Events" to restart'

  • 您可以使用ioreg检查设备是否与扩展名匹配: ioreg -lirc IOUSBHostInterface

  • 使扩展工作的关键是将IOProviderClass设置为IOUSBHostInterface而不是 Info.plist 文件中的IOResources (作为参考,KEXT 使用IOUSBInterface这是 Apple 已弃用的类之一)

  • 每次更改 DEXT 时,您可能希望在Info.plist更改版本,以确保您实际使用的是正确的版本。 systemextensionsctl将显示它已加载的版本)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM