Linux firmware subsystem-how to update firmware

Source: Internet
Author: User

In general use, you may need to use the firmware update function. In Linux, the device model of the firmware subsystem is provided to help you quickly upgrade the firmware.

Here we will first describe the common interfaces provided in Linux:
Kernel firmware interface:

# Include <Linux/firmware. h> int request_firmware (const struct firmware ** firmware_p, const char * Name, struct device * Device) // request_firmware () the call requires the user space to locate the kernel and provide a firmware image file. // Firmware_p: pointer to firmware image; // name: firmware file name; // device: device to be loaded with firmware; /*** @ name will be used as $ firmware in the uevent environment and * shocould be distinctive enough not to be confused with any other * firmware image for this or any other device. **/

After the firmware is sent to the device, use the following function to release the kernel structure:

void release_firmware(struct firmware *fw);

Because request_firmware () requires user space operations, it will remain asleep before returning. If the driver must use a firmware and cannot sleep, you can use the following asynchronous function:

int request_firmware_nowait(struct module *module, char *name, struct device *device, void *context, void (*cont)(const struct firmware *fw, void *context));

The firmware subsystem uses sysfs and hot swapping mechanisms. When request_firmware is called, a directory is created in/sys/class/firmware and the device name is used as its directory name. This directory contains three attributes:
Loading:
This attribute is set by the user space process responsible for loading the firmware to 1. When the loading process is complete, it is set to 0. The loading is set to-1, and the firmware loading process is terminated.
Data:
Data is a binary attribute used to receive firmware data. After loading is set, the user space process writes the firmware to this attribute;
Device:
This attribute is a symbolic link to the corresponding entry under/sys/devices;

After learning about the basic functions, we need to learn about how to upgrade the firmware system:
1. To send requests from the kernel layer to the application layer, we need to use the request_firmware we mentioned to implement this step;
2. Copy the firmware from the application layer to the kernel layer. Here is the compilation of the application layer, simple open and write;
3. the kernel writes the received firmware to the hardware device through the inherent protocol;

These three steps can be used to complete the upgrade. For simple use, here is a simple demo for you. You just need to change this code to yours.
Example:

Retval = request_firmware (& cust_firmware, devices-> fw_fname, Dev); If (retval <0) {pr_err ("% s: % s request firmware failed (% d) \ n ", _ FUNC __, devices-> fw_fname, retval);} else {/* Check and start upgrade */devices_upgrade_start (); // here is the self-implemented function, which is related to the actual physical hardware release_firmware (cust_firmware );}

If you just want to use it, it will end here. This is how to upgrade the firmware interface in the kernel. If you want to see how it is implemented, continue with the discussion. Of course, what you understand is not necessarily true.
For analysis, we will look at the function entry used to see how this kind of thing is handled in the kernel.
Request_firmware ()
----> Fw_get_builtin_firmware () // check whether firmware is specified between _ start_builtin_fw and _ end_builtin_fw.
----> Fw_create_instance () // you can use device_create_bin_file to create an interface for updating firmware in SYS.
----> Kobject_uevent () // use kobject to report uevent. the application layer must update firmware.
----> Wait_for_completion // wait for the application to load tens of thousands of firmware;

Of course, we can see that we can simply report the firmware uevent event to the application layer for processing. Here we will track who is receiving this event.
Here we will look at the init. c file in the system. As for why we need to check this file, we can see from the underlying request_firmware that the application layer is notified through kobject uevent. If there is a need at the underlying layer, the application needs to meet the requirements.
The uevent listener is created in the INIT process.

Ueventd_main ----> device_init () -----> open_uevent_socket () -----> S = socket (pf_netlink, sock_dgram, callback); // create a socket to listen to kobject_uevent; ----> handle_device_fd (); // call the socket processing function of netlink_kobject_uevent of uevent -----> parse_event (MSG, & uevent); // parse the uploaded uevent data; -----> handle_firmware_event (); // start processing firmware event -----> process_firmware_event (); // open the ATTR node of Dev ----> load_firmware (); // download firmwar E ----> write (loading_fd, "1", 1);/* Start transfer */----> write firmware ----> If (! RET) write (loading_fd, "0", 1);/* successful end of Transfer */elsewrite (loading_fd, "-1", 2);/* abort transfer */

Here, we can see that the entire user space download process is over.
Next, let's take a look at the process of establishing bin_attr in sys in the kernel mentioned above. This process is actually encapsulated in request_firmware.
Of course, you can also use the following method to establish your own, of course, this process requires the application to initiate the initiative, rather than the driver to initiate the initiative.

Static initialize firmware_write (struct kobject * kobj, struct bin_attribute * bin_attr, char * Buf, loff_t POs, size_t size) {struct device * Dev = container_of (kobj, struct device, kobj ); struct cust_devices * Ts = dev_get_drvdata (Dev); lock (ts-> mutex); // process firmware write operations, which involves interacting with specific hardware; unlock (ts-> mutex); Return size;} static ssize_t firmware_read (struct kobject * kobj, struct bin_attribute * Ba, char * Buf, loff_t POs, size_t size) {int COUNT = 0; u8 reg_data; struct device * Dev = container_of (kobj, struct device, kobj); struct cust_devices * Ts = dev_get_drvdata (Dev ); lock (ts-> mutex); // read the underlying firmware mode and other attributes, which can be implemented here; unlock (ts-> mutex); Return count ;} static struct bin_attribute cust_devices_firmware = {. ATTR = {. name = "firmware ",. mode = 0644 ,},. size = xxx, // can it exceed page_size ????. Read = firmware_read ,. write = firmware_write,}; struct bin_attribute {struct attributeattr; size_tsize; void * private; ssize_t (* read) (struct file *, struct kobject *, struct bin_attribute *, char *, loff_t, size_t); ssize_t (* write) (struct file *, struct kobject *, struct bin_attribute *, char *, loff_t, size_t); int (* MMAP) (struct file *, struct kobject *, struct bin_attribute * ATTR, struct vm_area_struct * VMA) ;}; if (sysfs_create_bin_file (& Dev-> kobj, & devices_firmware )) printk (kern_err "% s: Unable to create file \ n" ,__ func __);

The code is here and it can be finished. The underlying layer is also implemented, and the upper layer knows where to obtain the code.

Have fun!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.