14.8. Dealing with Firmware
As a driver author, you may find yourself confronted with a device that must have firmware downloaded into it before it functions properly. The competition in many parts of the hardware market is so intense that even the cost of a bit of EEPROM for the device's controlling firmware is more than the manufacturer is willing to spend. So the firmware is distributed on a CD with the hardware, and the operating system is charged with conveying the firmware to the device itself.
You may be tempted to solve the firmware problem with a declaration like this:
static char my_firmware[ ] = { 0x34, 0x78, 0xa4, ... };
That approach is almost certainly a mistake, however. Coding firmware into a driver bloats the driver code, makes upgrading the firmware hard, and is very likely to run into licensing problems. It is highly unlikely that the vendor has released the firmware image under the GPL, so mixing it with GPL-licensed code is usually a mistake. For this reason, drivers containing wired-in firmware are unlikely to be accepted into the mainline kernel or included by Linux distributors.
14.8.1. The Kernel Firmware Interface
The proper solution is to obtain the firmware from user space when you need it. Please resist the temptation to try to open a file containing firmware directly from kernel space, however; that is an error-prone operation, and it puts policy (in the form of a file name) into the kernel. Instead, the correct approach is to use the firmware interface, which was created just for this purpose:
#include
int request_firmware(const struct firmware **fw, char *name,
struct device *device);
A call to request_firmware requests that user space locate and provide a firmware image to the kernel; we look at the details of how it works in a moment. The name should identify the firmware that is desired; the normal usage is the name of the firmware file as provided by the vendor. Something like my_firmware.bin is typical. If the firmware is successfully loaded, the return value is 0 (otherwise the usual error code is returned), and the fw argument is pointed to one of these structures:
struct firmware {
size_t size;
u8 *data;
};
That structure contains the actual firmware, which can now be downloaded to the device. Be aware that this firmware is unchecked data from user space; you should apply any and all tests you can think of to convince yourself that it is a proper firmware image before sending it to the hardware. Device firmware usually contains identification strings, checksums, and so on; check them all before trusting the data.
After you have sent the firmware to the device, you should release the in-kernel structure with:
void release_firmware(struct firmware *fw);
Since request_firmware asks user space to help, it is guaranteed to sleep before returning. If your driver is not in a position to sleep when it must ask for firmware, the asynchronous alternative may be used:
int request_firmware_nowait(struct module *module,
char *name, struct device *device, void *context,
void (*cont)(const struct firmware *fw, void *context));
The additional arguments here are module (which will almost always be THIS_MODULE), context (a private data pointer that is not used by the firmware subsystem), and cont. If all goes well, request_firmware_nowait begins the firmware load process and returns 0. At some future time, cont will be called with the result of the load. If the firmware load fails for some reason, fw is NULL.
14.8.2. How It Works
The firmware subsystem works with sysfs and the hotplug mechanism. When a call is made to request_firmware, a new directory is created under /sys/class/firmware using your device's name. That directory contains three attributes:
loading
This attribute should be set to one by the user-space process that is loading the firmware. When the load process is complete, it should be set to 0. Writing a value of -1 to loading aborts the firmware loading process.
data
data is a binary attribute that receives the firmware data itself. After setting loading, the user-space process should write the firmware to this attribute.
device
This attribute is a symbolic link to the associated entry under /sys/devices.
Once the sysfs entries have been created, the kernel generates a hotplug event for your device. The environment passed to the hotplug handler includes a variable FIRMWARE, which is set to the name provided to request_firmware. The handler should locate the firmware file, and copy it into the kernel using the attributes provided. If the file cannot be found, the handler should set the loading attribute to -1.
If a firmware request is not serviced within 10 seconds, the kernel gives up and returns a failure status to the driver. That time-out period can be changed via the sysfs attribute /sys/class/firmware/timeout.
Using the request_firmware interface allows you to distribute the device firmware with your driver. When properly integrated into the hotplug mechanism, the firmware loading subsystem allows devices to simply work "out of the box." It is clearly the best way of handling the problem.
Please indulge us as we pass on one more warning, however: device firmware should not be distributed without the permission of the manufacturer. Many manufacturers will agree to license their firmware under reasonable terms when asked politely; some others can be less cooperative. Either way, copying and distributing their firmware without permission is a violation of copyright law and an invitation for trouble.
As a driver author, you may find yourself confronted with a device that must have firmware downloaded into it before it functions properly. The competition in many parts of the hardware market is so intense that even the cost of a bit of EEPROM for the device's controlling firmware is more than the manufacturer is willing to spend. So the firmware is distributed on a CD with the hardware, and the operating system is charged with conveying the firmware to the device itself.
You may be tempted to solve the firmware problem with a declaration like this:
static char my_firmware[ ] = { 0x34, 0x78, 0xa4, ... };
That approach is almost certainly a mistake, however. Coding firmware into a driver bloats the driver code, makes upgrading the firmware hard, and is very likely to run into licensing problems. It is highly unlikely that the vendor has released the firmware image under the GPL, so mixing it with GPL-licensed code is usually a mistake. For this reason, drivers containing wired-in firmware are unlikely to be accepted into the mainline kernel or included by Linux distributors.
14.8.1. The Kernel Firmware Interface
The proper solution is to obtain the firmware from user space when you need it. Please resist the temptation to try to open a file containing firmware directly from kernel space, however; that is an error-prone operation, and it puts policy (in the form of a file name) into the kernel. Instead, the correct approach is to use the firmware interface, which was created just for this purpose:
#include
int request_firmware(const struct firmware **fw, char *name,
struct device *device);
A call to request_firmware requests that user space locate and provide a firmware image to the kernel; we look at the details of how it works in a moment. The name should identify the firmware that is desired; the normal usage is the name of the firmware file as provided by the vendor. Something like my_firmware.bin is typical. If the firmware is successfully loaded, the return value is 0 (otherwise the usual error code is returned), and the fw argument is pointed to one of these structures:
struct firmware {
size_t size;
u8 *data;
};
That structure contains the actual firmware, which can now be downloaded to the device. Be aware that this firmware is unchecked data from user space; you should apply any and all tests you can think of to convince yourself that it is a proper firmware image before sending it to the hardware. Device firmware usually contains identification strings, checksums, and so on; check them all before trusting the data.
After you have sent the firmware to the device, you should release the in-kernel structure with:
void release_firmware(struct firmware *fw);
Since request_firmware asks user space to help, it is guaranteed to sleep before returning. If your driver is not in a position to sleep when it must ask for firmware, the asynchronous alternative may be used:
int request_firmware_nowait(struct module *module,
char *name, struct device *device, void *context,
void (*cont)(const struct firmware *fw, void *context));
The additional arguments here are module (which will almost always be THIS_MODULE), context (a private data pointer that is not used by the firmware subsystem), and cont. If all goes well, request_firmware_nowait begins the firmware load process and returns 0. At some future time, cont will be called with the result of the load. If the firmware load fails for some reason, fw is NULL.
14.8.2. How It Works
The firmware subsystem works with sysfs and the hotplug mechanism. When a call is made to request_firmware, a new directory is created under /sys/class/firmware using your device's name. That directory contains three attributes:
loading
This attribute should be set to one by the user-space process that is loading the firmware. When the load process is complete, it should be set to 0. Writing a value of -1 to loading aborts the firmware loading process.
data
data is a binary attribute that receives the firmware data itself. After setting loading, the user-space process should write the firmware to this attribute.
device
This attribute is a symbolic link to the associated entry under /sys/devices.
Once the sysfs entries have been created, the kernel generates a hotplug event for your device. The environment passed to the hotplug handler includes a variable FIRMWARE, which is set to the name provided to request_firmware. The handler should locate the firmware file, and copy it into the kernel using the attributes provided. If the file cannot be found, the handler should set the loading attribute to -1.
If a firmware request is not serviced within 10 seconds, the kernel gives up and returns a failure status to the driver. That time-out period can be changed via the sysfs attribute /sys/class/firmware/timeout.
Using the request_firmware interface allows you to distribute the device firmware with your driver. When properly integrated into the hotplug mechanism, the firmware loading subsystem allows devices to simply work "out of the box." It is clearly the best way of handling the problem.
Please indulge us as we pass on one more warning, however: device firmware should not be distributed without the permission of the manufacturer. Many manufacturers will agree to license their firmware under reasonable terms when asked politely; some others can be less cooperative. Either way, copying and distributing their firmware without permission is a violation of copyright law and an invitation for trouble.
Комментариев нет:
Отправить комментарий
Примечание. Отправлять комментарии могут только участники этого блога.