How does the driver work? Detailed explanation of Linux device driver firmware loading

As a driver author, you may find that you face a device that must download firmware into it before it can support the job. The competition in many parts of the hardware market is so strong that even the cost of EEPROM, which is used as a device control firmware, is not willing to spend. So the firmware is released on a CD with the hardware, and the operating system is responsible for transferring the firmware to the device itself.

The hardware is more and more complex, many functions of the hardware use the program to realize, compared with the direct hardware implementation, the firmware has the advantage of dealing with complex things and ease of upgrading, maintenance and other advantages. Firmware is such a program that is executed in the device hardware itself. The firmware can be used to implement specific machine operations. For example, optical drives, recorders, etc. have internal firmware.

The firmware is usually stored in the flash memory on the device, but for cost and flexibility, many devices store the image of the firmware on the hard disk as a file, and the device driver is loaded into the device when it is initialized. Memory. This facilitates the firmware upgrade and omits the device's flash memory.

How does the driver work? Detailed explanation of Linux device driver firmware loading

First, the difference between driver and firmware

In the computer field, drivers and firmware have never been clearly defined. It is as if we say memory today. Most people use it to represent SDRAM, but some people also call "cured Flash/Storage" in Android "memory." You can't say this is wrong, because this is really an "internal storage."

But in the Linux Kernel, Driver and Firmware have clear meanings.

1, drive

Driver is a code segment that controls an external device managed by the operating system. Many times Driver will be implemented as LKM, but this is not a necessary condition. The driver is registered to the bus_type through driver_register(), which means that the system has the ability to drive a certain device. When a device is registered to the same bus (usually the device was discovered when the bus is enumerated), the bus driver will bind (ie, match) the driver and device with a certain policy. If the Binding succeeds, Bus driver will call driver's probe () function, the device information (port, interrupt number, etc.) is passed to the driver, the driver can initialize the real physical components, and register the control interface of the device to Linux On other subsystems (such as character devices, v4l2 subsystems, etc.). This allows other parts of the operating system to access the device through these common interfaces.

2, the firmware

Firmware refers to a program that runs in a non-control processor (a processor that does not directly run an operating system, such as a processor in a peripheral, or is used in some of the cores of a bare metal's main processor). Many of these programs use a completely different set of instructions than the ones the operating system runs on. These programs exist in binary form in the source tree of the Linux kernel. When the target system is generated, they are usually copied to the /lib/firmware directory. When the driver initializes the device, the specified firmware can be loaded into the memory and transferred to the specified device with the help of a user-mode helper program through an interface such as request_firmware().

So, in general, there is no direct relationship between driver and firmware, but firmware is usually loaded by the driver. The OS we talked about generally does not need to understand what the firmware is and just treats it as data. What is the firmware, only the device that uses the data knows. Like you use a phone, there is a software in the phone, this software you do not care about how to work, when you change this software, you can call this software "firmware", but if you use a smart phone, you want Careful relationship What is the above application, Android platform, plug-ins and other details, you may not call this thing called "firmware".

How to solve the firmware problem? You may want to solve the firmware issue using a statement like this:

Static char my_firmware[] = { 0x34, 0x78, 0xa4, . .. };

However, this method is almost certainly a mistake. Encoding the firmware into a driver-enlarged driver code makes it difficult to upgrade the firmware and is very likely to create licensing issues. Vendors may not have released firmware images under the GPL, so mixing with the GPL-licensed code is often a mistake. For this reason, drivers containing embedded firmware may not be accepted into the mainstream kernel or included by the Linux publisher.

Second, the kernel firmware interface

The correct way is to get it from user space when you need it. However, resist the temptation of trying to open the file containing the firmware directly from kernel space; it is an error-prone operation, and it places the policy (in the form of a file name) into the kernel. Instead, the correct method is to use the firmware interface, which is created for this purpose:

[cpp] view plain copy

1. #include

2.

3. int request_firmware(const struct firmware **fw, char *name, struct device *device);

The function request_firmware requests a user-space request with a name firmware image file and waits for completion. The parameter device is the device loaded by the firmware. The content of the file is stored in request_firmware. If the firmware request is successful, 0 is returned. The function does not check any data obtained from the user space. When the user writes the driver program, the user should do a data security check on the firmware image. The check direction is determined by the device firmware provider. Usually, there are methods such as checking the identifier and checksum.

Calling request_firmware requires the user to spatially locate and provide a firmware image to the kernel; we will look at the details of how it works. Name should identify the required firmware; normal usage is the vendor-supplied firmware file name. Some of the names like my_firmware.bin are typical. If the firmware is successfully loaded, the return value is 0 (responsible for common error codes is returned), and the fw parameter points to one of these structures:

[cpp] view plain copy

1. struct firmware {

2. size_t size;

3. u8 *data;

4. };

That structure contains the actual firmware, which can now be downloaded to the device. Be careful that this firmware is unchecked data from user space; you should use any and all checks you can think of to convince yourself that it is the correct firmware image before sending it to the hardware. Device firmware often contains identification strings, checksums, and so on; all are checked before trusting the data.

Before you have sent the firmware to the device, you should release the in-kernel structure using:

[cpp] view plain copy

1. void release_firmware(struct firmware *fw);

Because request_firmware requests user space to help, it guarantees to sleep before returning. If your driver is not sleeping when it must request firmware, an alternative to asynchronous might use:

[cpp] view plain copy

1. int request_firmware_nowait(struct module *module,

2. char *name, struct device *device, void *context,

3. void (*cont)(const struct firmware *fw, void *context));

The extra parameters here are moudle (it will always be THIS_MODULE), context (a private data pointer not used by the firmware subsystem), and cont. If everything goes well, request_firmware_nowait starts the firmware loading process and returns 0. Sometime in the future , cont will be called with the result of the load. If for some reason the firmware fails to load, fw is NULL.

Third, how the firmware works

The firmware subsystem uses sysfs and hot-swap mechanisms. When calling request_firmware, a new directory is created under /sys/class/firmware using your driver's name. That directory contains 3 attributes:

Loading

This attribute should be set to 1. The user-space process that loads the firmware is set to 1. When the loading process completes, it should be set to 0. Writing a value -1 to loading will abort the firmware loading process.

Data

Data is a binary property of the receiving firmware data itself. After setting loading, the user space process should write firmware to this property.

Device

This attribute is a symbolic link to the associated entry entry under /sys/devices.

Once the sysfs entry is created, the kernel generates a hotplug event for your device. The environment passed to the hot swap handler includes a variable FIRMWARE, which is set to the name of the request_firmware. This handler should locate the firmware file and copy it to the kernel using the provided attributes. If this file cannot be found, the processor should set the loading attribute to -1.

If a firmware request is not serviced within 10 seconds, the kernel gives up and returns a failed status to the driver. The timeout period can be changed by the sysfs attribute /sys/class/firmware/timeout attribute.

Using the request_firmware interface allows you to publish the device firmware with your driver. When properly integrated into a hot-swap mechanism, the firmware loading subsystem allows the device to simplify its work "outside the box." Clearly this is the best way to handle the problem.

However, please allow us to make one more warning: The device firmware should not be released without the manufacturer's permission. Many manufacturers will agree to license their firmware under reasonable terms, politely requesting; some others may not be. In any case, copying and distributing their firmware without a license is a violation of copyright law and causes trouble.

Fourth, the use of firmware interface functions

When the driver needs to use the firmware driver, the following code needs to be added during driver initialization:

[cpp] view plain copy

1. if(request_firmware(&fw_entry, $FIRMWARE, device) == 0) /* request image data from user space */

2.

3. /* Copy the firmware image to the hardware's memory. The copy function is written by the user */

4. copy_fw_to_device(fw_entry-"data, fw_entry-"size);

5. release(fw_entry);

The user also needs to provide scripts in the user space to read the firmware image file into the kernel's buffer through the file data in the file system sysfs. The script sample is listed as follows:

[cpp] view plain copy

1. The #variables $DEVPATH (path of the firmware device) and $FIRMWARE (firmware image name) should already be provided in the environment variable

2.

3. HOTPLUG_FW_DIR=http:// #firmware image file directory

4.

5. echo 1 "/sys/$DEVPATH/loading

6. cat $HOTPLUG_FW_DIR/$FIRMWARE ”/sysfs/$DEVPATH/data

7. echo 0 ”/sys/$DEVPATH/loading

Fifth, the firmware request function request_firmware

The function request_firmware requests a copy of the firmware image file from the user space to the kernel buffer. The workflow for this function is listed below:

a -- Creates the file /sys/class/firmware/xxx/loading and data in the filesystem sysfs. "xxx" indicates the name of the firmware. It has read and write functions for the file loading and data, and sets the file attributes. The file loading indicates on/ Turn off the firmware image file loading function; the write operation of the file data writes the data of the image file into the kernel buffer, and the read operation reads data from the kernel buffer.

b -- Sends the uevent of the added firmware ("add") to the user space through the kernel object model.

c - The background process of user space management uevent event After udevd receives the event, it looks for the udev rule file and the actions defined by the running rule. The rules related to the firmware are listed as follows:

[cpp] view plain copy

1. $ /etc/udev/rules.d/50-udev-default.rules

2. ……

3. # firmware class requests

4. SUBSYSTEM=="firmware", ACTION=="add", RUN+="firmware.sh"

5. ...

As can be seen from the above rules, the firmware addition event will cause the script.firm.sh to be run.

d -- The script firmware.sh opens the "Load" function, with the command "cat image file" /sys/class/firmware/xxx/data" Writes the image file data to the kernel's buffer.

e -- After the image data copy is completed, the function request_firmware unregisters the directory "xxx" of the firmware device from the file system /sysfs. If the request is successful, the function returns 0.

f - The user copies the firmware image data of the kernel buffer into the firmware's memory. Then, the function release_firmware(fw_entry) is called to release the buffer allocated for the firmware image.

Upholstery And Decoration Staple

Zhejiang Best Nail Industrial Co., Ltd. , https://www.beststaple.com