OSX kext: Can't open IOResouces in ::start() due to owned by some other

262 views Asked by At

part of my work over the least years is USB virtulization under OSX and I found myself confused once again in front of a closed door.

One of the first steps my kext (derived from IOUSBControllerV3) like to do is, after my provider (IOResources, because I'm virtuall) called my ::start() (::init() done), inside super class, to try a provider->open(this).

This is the normal way and works fine till the day, another (not from me) virtualisation kext is already loaded. Then the call failed and in consequence my ::start() and the kext installation failed at all (is non functional).

Grabbing the source code of the IOService class and get inforamtion by provider->isOpen() is true and provider->isOpen(this) is false IOResouces seemed to be owned by the other (virtulisation) kext. Which means the IOService internal __owner is occupied exclusive by some other.

How can this be?? How can IOResources be handle only one __owner at one time?

The provider->open() call is done inside my base class IOUSBController::start() and is still keep open till ::stop() is called, which means end of life.

The failure returns from the call provider->open(this) inside my super class IOUSBController::start() inside my ::start() and depends on if another kext with provider IOResources is already loaded or not.

At this state there can't be any resouces conflict, because it is the very beginning of loading the kext. And in my imagination there can't be any resource conflict at all, because all is virtuall.

Or is it true, that IOResources can only handle (be provider for) one kext?

No, unbelievable. My next idea was, that the foreigen kext is bad implemented (it's not perfect, because kextunload is not possible) but the provider->open(this) and ->close(this) calls are done in the holy apple base classes, which must be correct.

Sorry, lot of text and thanks in advance for any constructive comment.

2

There are 2 answers

7
pmdj On

Is there a good reason why you need to open() IOResources? The point of open() in the context of IOServices is specifically for providing exclusive or at least reserved access to resources which don't support an arbitrary number of clients. (e.g. a physical device can usually only have one driver loaded) IOResources is a dummy service which doesn't provide any features apart from the publishResource/resourceMatching mechanism. I'm not aware of any reason why you'd need to call open() on it.

Edit: I'd missed that the call to open() is made by Apple's superclass, not the asker's code. In this case, as with any base classes that have special requirements on a provider object, I recommend writing your own provider class. This provider class can be a client of IOResources, and the driver with the fussy base class can be a client of it.

1
Markus Steinmann On

Following Phils (pmdj) very constructive proposals, he is obviously a member of the apple kext IOKit olymp, a simple enhancement seems to fix my problem.

In ::start(provider) I create (OSTypeAlloc()) a dummy IOService class dumprov, make dumprov->init() and dumprov->start(provider) and then call my superclass IOUSBController::start(dumprov) with success:-)

When I'm called finaly to ::stop(), I call IOUSBController::stop(dumprov) and make a dumprov->release(). Fine!

Many thanks to pmdj!!