c++macosiokitkernel-extensionxnu

IOKit driver is loaded but not started


I've got IOKit base driver that is non-hardware triggered and derives from IOResources. it also provides to user-space client class using IOServiceOpen but I think it's irrelevant for my problem... The main driver has IOKit dependency as mentioned in the derived driver Info.plist file :

<key>OSBundleLibraries</key>
<dict>
    ...
    ..
    .
    <key>com.derived.driver</key>
    <string>1.0.0</string>
</dict> 

the other driver (identified by com.derived.driver) is implemented as generic kernel extension and stored in /Library/Extensions.

When I load the base driver, the derived is loading automatically. since the derived driver resides in /Library/Extensions it can also be loaded before triggering the derived driver by kextcache.

However, It stop working when I convert the derived driver from generic to IOKit format so that now both drivers IOProviderClass is IOResources.

It seems like the derived driver simply refuse the start it's IOService based class, with no sign of errors in the output logs (I've used debugger and saw that it actually reaches IOService::probeCandidates but not IOService::startCandidate. since the kernel compiled with optimization, I couldn't put my finger for the exact flow).

When I look at the currently loaded drivers by kextstat it seems that both drivers are loaded, but according to ioreg only the base driver have active instances (I was expecting that both drivers will share the same provider which is IOResources).

Moreover, after a while, it seems that the higher driver simple removed from the loaded kexts (probably due to idleness) ..

Does my design seem legal or do I also have to change the IOProviderClass field in base driver from IOResources to the derived driver IOService based class.

<key>IOKitPersonalities</key>
<dict>
        <key>myDriver</key>
        <dict>
                <key>CFBundleIdentifier</key>
                <string>com.base.driver</string>
                <key>IOClass</key>
                <string>com_base_driver</string>
                <key>IOProviderClass</key>
                <string>com_derived_driver</string>

EDIT : I actually did it, and it worked (all instances have been initialized according to ioreg).

  +-o com_derived_driver  <class com_derived_driver, id 0x10000091f, registered, matched, active, busy 0 (804415 ms), retain 6>
    +-o com_base_driver  <class com_base_mng, id 0x100000920, registered, matched, active, busy 0 (0 ms), retain 9>

but I honestly don't know why, any explanation will be highly appreciated.

thanks !


Solution

  • I can only take a guess because you haven't yet provided complete information - in particular, you haven't provided the complete IOKit personality dictionaries of your two drivers.

    Note that normally, only one service will successfully match an IOService to become its client. If you wish for multiple different types of client to match, they need to define distinct match categories through the IOMatchCategory key in the personality dictionary. Many drivers need to match IOResources specifically, so the rule for that case is to use the bundle identifier as match category. I suspect this is what you've been missing?

    Finally, regarding your side note about having trouble with the default release kernels: the Kernel Debug Kits (KDKs) provide alternate development and debug kernels which are compiled with far less aggressive optimisation settings. You may find them helpful - check the KDK's readme documentation for details on how to enable them.