Loading Resources

The I/O Kit does not provide any classes or functions that provide a driver with access to the file system. This is a deliberate design decision, not an oversight in the I/O Kit design. In theory, a driver should not need to access files on disk. The driver's role is to respond to requests from the operating system to manage its own hardware device, and not to initiate requests of its own. In practice, however, there are many reasons why a driver may need to access data from the file system. One of the most common reasons is to read resource data, such as the firmware data for the driver's hardware.

Although the I/O Kit doesn't allow general file system access, it does provide a means for a driver to access files from the “Resources” directory inside the driver bundle. The I/O Kit's resource-loading API is defined in the header file <libkern/OSKextLib.h>. The API is asynchronous; a driver makes a request for the resource that it wishes to load and provides a callback function that the I/O Kit uses to notify the driver when the data is available.

We mentioned that the I/O Kit doesn't provide general file system access, but in addition to this, the I/O Kit itself doesn't have access to the file system. In order to load the resource file for a driver, the I/O Kit relies on a user space helper process, which reads the requested file on behalf of the I/O Kit and passes the file's contents back to the I/O Kit. The I/O Kit then notifies the driver that made the request.

Since the I/O Kit relies on a user space helper process to load resources, it is not possible to load resources in the boot process until the helper process has been launched. However, in most cases this does not cause a problem for the driver, since the I/O Kit will queue the request until the helper process is available to receive requests from the kernel.

A driver can request that the I/O Kit load a file from the driver's resources directory by calling the function OSKextRequestResource(). This function's definition is as follows:

OSReturn OSKextRequestResource(const char* kextIdentifier,
                               const char* resourceName,
                               OSKextRequestResourceCallback  callback,
                               void* context,
                               OSKextRequestTag* requestTagOut);

The first parameter, kextIdentifier, specifies the bundle identifier of the driver that contains the resource to load; this will almost always be the value specified by the CFBundleIdentifier key of the driver's Info.plist file. The second parameter, resourceName, is the name of the resource file to be loaded from the driver's bundle. The next two parameters are the callback function and an associated context argument that is passed to the callback function when the resource has been loaded. The final parameter, requestTagOut, is returned immediately to the caller and can be used to track the operation to load the resource.

If the call to OSKextRequestResource succeeds, the driver will be notified through its specified callback function when the request has completed. The completion callback has the following signature:

typedef void (*OSKextRequestResourceCallback)(OSKextRequestTag requestTag,
                                              OSReturn result,
                                              const void* resourceData,
                                              uint32_t resourceDataLength,
                                              void* context);

The first parameter provided to the callback, requestTag, identifies the resource that this completion callback refers to. The second parameter, result, informs the caller whether the operation was completed successfully. If the value of result is kIOReturnSuccess, the resource data has been successfully read from the disk and the next two parameters, resourceData and resourceDataLength, contain the contents of the requested resource file. The resourceData buffer is valid only within the callback, so if the driver wishes to refer to the resource data outside the callback, it must make a copy of the data. The final parameter, context, contains the value of the context parameter that was passed to the OSKextRequestResource function.

The remaining step is to add the resource file to the driver's bundle. Any resource loaded through the OSKextRequestResource function must be present in the “Resources” subdirectory of the driver's bundle. In most cases, this can be achieved by adding the file to the Xcode project for the driver. For file types other than source code, Xcode will default to copying the file to the bundle's resource directory when the project is built.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.221.116