本文主要介绍“linux固件的意义是什么?”主机频道通过实际案例向你展示操作流程。操作方法简单、快捷、实用。希望这篇文章《linux固件的意义是什么?可以帮你解决问题。
在linux中,firmware指的是“固件”,是由硬件设备本身执行的程序,一般存储在设备的flash中。在Linux系统中,设备驱动程序处于内核态,固件文件处于用户态,因此需要一种安全、稳定、可靠的机制来保证设备驱动程序成功加载固件文件。
什么是linux固件?
固件是由硬件设备本身执行的程序。固件通常存储在设备闪存中。出于成本和方便的考虑,通常将硬件设备的运行程序打包成特定格式的固件文件存储在终端系统中,通过终端系统对硬件设备进行升级。
在Linux内核开发过程中,开发人员调试外围驱动,如触控、充电、直线电机、存储、WIFI设备等。,也有固件需要更新的情况。在Linux系统中,设备驱动程序处于内核态,固件文件处于用户态,因此需要一种安全、稳定、可靠的机制来保证设备驱动程序成功加载固件文件。
为了解决设备驱动从内核态稳定加载用户态固件文件的问题,Linux系统提供了固件子系统。
Linux固件子系统进程简介
Linux固件子系统是基于sysfs和uevent机制实现的。
驱动程序调用固件系统函数接口申请固件后,固件子系统采用固件编译内核的方式获取固件;如果获取失败,使用固件缓存获取固件;如果采集仍然失败,使用默认路径内核直接查找固件。如果采集仍然失败,向init进程报告uevent消息。init进程接收uevent消息,并使用子系统类型固件过滤掉消息。init进程根据uevent消息中指向的固件信息寻找固件,并通过sysfs提供的文件节点接口将获取的固件内容从用户态写入内核态,这样驱动就可以获取固件文件的数据。
Linux固件系统在不同的场景下提供了多种获取固件文件的方法。
1)直接编译进内核的方式;
2)固件缓存的方式;
3)直接按照内核指定路径的方式:
4)通过init进程协助处理的方式;
Linux固件子系统流程图
Linux固件子系统的主要功能界面
主功能界面:
固件接口的主要类型有同步和异步。
通常申请固件的过程比较耗时,处理固件升级的过程也比较耗时,所以可以通过异步函数接口来实现,或者在驱动中创建一个工作队列,先调用同步函数接口来实现。
其中包括:
内核应用固件文件是通过调用request_firmware函数实现的。
内核获取固件文件后,调用release_firmware释放相关内存。
其中包括:
request_firmware_direct接口只在内核指定的路径中寻找固件,不使用uevent机制获取固件。
request_firmware_nowait接口通过异步工作队列获取固件,可以起到不阻塞驱动探针时间的作用。
Linux固件子系统的实现过程
请求_固件实施流程
request_firmware函数通过调用_request_firmware_prepare函数来设置不同的标志位,以实现不同的功能。
_请求_固件_准备函数:
在打开CONFIG_FW_LOADER宏开关的基础上,首先通过调用fw _ get fw_get_builtin_firmware函数判断固件文件是否编译到内核中。
然后调用fw_lookup_and_allocate_buf函数,判断当前请求的固件名称是否已经记录在全局fw_cache结构的链表中。如果当前请求的固件的名称不存在,则相应的存储空间被动态分配,并且当前请求的固件的名称被添加到全局fw_cache结构中的链表中。
固件获取文件系统固件函数
主要是通过内核提供的默认路径查找固件文件并调用kernel_read_file_from_path函数。如果没有找到固件文件,则通过标志位FW_OPT_USERHELPER判断是否启用USER_HELPER模式。
其中包括:
固件系统中的默认路径如下:
默认路径可以通过内核命令行添加,新路径可以通过module_param_string接口传递给变量path进行自定义。
用户助手模式
在内核打开CONFIG_FW_LOADER_USER_HELPER之前,不支持此函数。主要功能是通过内核向init进程上报uevent消息,通过init进程获取固件信息并写入底层sysfs节点。
Fw_load_from_user_helper函数:
调用fw_create_instance函数创建device设备、类文件和属性文件,分配firmware_priv结构。
然后将在/sys/class/firmware下创建一个目录,该目录使用设备名作为其目录名。
该目录包含三个属性:
加载:
设置为1:该属性从负责加载固件的用户空间设置1开始;
设置为0:加载过程完成时;
设置为-1:固件加载过程将终止。
数据:
用于接收固件数据。设置加载后,用户空间进程将固件写入该属性。
设备:
/sys/devices下相应条目的符号链接。
超时:
默认情况下,通过uevent申请固件的最大超时是60S,支持上层写超时。
_请求_固件_加载函数:
首先,UE event报告被禁用,通过调用device_add函数添加设备,这将触发firmware _ uevent函数的调用。其中,填写uevent上报的信息格式,包括固件名称、超时、是否异步。
接下来启用uevent报告函数,同时调用kobject_uevent函数向上层uevent报告添加动作类型。
然后调用fw_state_wait_timeout函数,在预设的超时时间内等待对upper ueventd的处理。
如果超时时间已到或收到唤醒呼叫,则释放之前应用的内存,并释放设备和类等内存信息。
Ueventd相关固件处理流程
Ueventd是init进程中的重要模块,主要处理selinux、dev设备创建、监控内核上报UEventd消息、固件加载等。
FirmwareHandler处理流程:
firmwareHandler中的HandleUevent方法主要处理固件固件加载与底层节点的交互过程。
首先在处理之前判断uevent消息的子系统类型是固件字段,这个类型只会被内核中的固件模块上报。
HandleUevent主要通过一个主线程创建不同的子线程,并行处理来自内核的不同驱动的固件请求。
ProcessFirmwareEvent函数
首先,循环判断在ueventd支持的路径中检索到的固件文件是否存在;如果存在,将底层加载属性文件写入1,并将获得的固件文件复制写入底层数据文件。完成后,将基础加载属性文件写为0。
此时,内核已经获得了写入用户空间的固件文件信息。
其中包括:
默认情况下,Ueventd支持搜索固件的路径:
从ueventd.rc文件中指定的固件目录。
评论前必须登录!
注册