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 <linux/firmware.h>
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.
|