A general method for firmware loading
LWN 32997: https://lwn.net/Articles/32997/
[Posted May 20, 2003 by corbet]
While most computer peripherals work right “out of the box,” some will not function properly until the host system has downloaded a blob of binary firmware. Often as not, this firmware is proprietary software. In the past, a number of drivers have gone into the kernel with proprietary firmware bundled in. In the eyes of many, all devices have proprietary firmware in them; there is little reason to be upset if, in some cases, that firmware arrives via the kernel. But others (notably, the Debian project) object to linking any sort of non-free software into their kernel.
The end result is that the recommended way of dealing with devices needing firmware downloads is to have a user-space process handle it. That way, no non-free software need be linked into the kernel; as a side benefit, it also gets easier to upgrade that firmware. The downloads have typically been handled by way of a device-specific ioctl() call; each driver includes its own, slightly different implementation.
用于升级固件 使用用于特定设备的 ioctl() 函数
In 2.5, the device model provides a framework which can be used to clean up the handling of firmware downloads. All that was missing was an actual implementation. Manuel Estrada Sainz has filled that gap, however, with a patch adding an interface for firmware loads.
In the new scheme, a device driver needing firmware for a particular device makes a call to:
int request_firmware(struct firmware **fw, const char *name,
struct device *device);
Here, name is the name of the relevant device, and device is its device model entry. This call will create a directory with the given name under /sys/class/firmware and populate it with two files called loading and data. A hotplug event is then generated which, presumably, will inspire user space to find some firmware to feed the device.
调用函数 request_firmware() 将会在 /sys/class/firmware 目录下创建与设备名称相同的文件夹, 然后在这个文件夹下填充两个文件 loading 和 data.
然后会生成一个热插拔事件. 该事件可能会激发用户空间给这个设备寻找一些固件.
The resulting user-space process starts by setting the loading sysfs attribute to a value of one. The actual firmware can then be written to the data file; when the process is complete, the loading file should be set back to zero. At that point, request_firmware() will return to the driver with fw pointing to the actual firmware data. The user-space process can chose to abort the firmware load by writing -1 to the loading attribute.
最终的用户空间过程通过将 loading sysfs 属性设置为值 1开 始. 然后可以将实际的固件写入到 data 文件中. 写完后, 应当将 loading 文件设置为零.
此时 request_firmware() 将返回驱动程序. 其中, fw 指向实际的固件数据.
用户空间进程可以选择通过向 loading 属性写入 -1 来终止固件加载.
When the driver has loaded the firmware into its device, it should free up the associated memory with:
void release_firmware(struct firmware *fw);
There has been talk of maintaining firmware within the kernel so that subsequent requests can be satisfied without going back to user space. No such mechanism has been implemented at this point, however. For situations where it is not possible to wait for user space to react, there is a request_firmware_nowait() function which will call back into the driver when the firmware is available.
As of this writing, the new firmware code has not yet been merged into the mainline kernel. Changes to the interface would not be surprising, but it seems likely that 2.6 will have a generic firmware support interface that is not vastly different from what is described here.