速发国际365的最新网站-百特365平台可靠吗-日博365投注网

Linux下固件加载器Firmware Loader

某些Linux外设需要固件才能正常工作,或者调试过程中需要更换固件。为解决设备驱动程序从内核态或者用户态加载固件到外设中,Linux提供了Fir

Linux下固件加载器Firmware Loader

某些Linux外设需要固件才能正常工作,或者调试过程中需要更换固件。为解决设备驱动程序从内核态或者用户态加载固件到外设中,Linux提供了Firmware Loader子系统。

如果固件比较稳定,可以通过builtin方式加载。如果需要经常变动,可放入文件系统指定目录中。如果都无法找到需要根据uevent做异常处理。

1 defconfig配置Firmware

Linux下配置Firmware Loader:

Device Drivers ->Generic Driver Options ->Firmware loader ->Frimware loading facility ->Build named firmware blobs into the kernel binary--指定需要内嵌到kernel中的Firmware文件名。 ->Firmware blobs root directory--指定需要内嵌到Kernel中的Firmware目录。

然后drivers/base/firmware_loader/builtin/Makefile会根据上述两个选项为每个Firmware文件生成xxxx.gen.S并编译。

# SPDX-License-Identifier: GPL-2.0

# Create $(fwdir) from $(CONFIG_EXTRA_FIRMWARE_DIR) -- if it doesn't have a

# leading /, it's relative to $(srctree).

fwdir := $(subst $(quote),,$(CONFIG_EXTRA_FIRMWARE_DIR))

fwdir := $(addprefix $(srctree)/,$(filter-out /%,$(fwdir)))$(filter /%,$(fwdir))

obj-y := $(addsuffix .gen.o, $(subst $(quote),,$(CONFIG_EXTRA_FIRMWARE)))--将CONFIG_EXTRA_FIRMWARE文件编译生成xxxx.gen.o文件。

FWNAME = $(patsubst $(obj)/%.gen.S,%,$@)

comma := ,

FWSTR = $(subst $(comma),_,$(subst /,_,$(subst .,_,$(subst -,_,$(FWNAME)))))

ASM_WORD = $(if $(CONFIG_64BIT),.quad,.long)

ASM_ALIGN = $(if $(CONFIG_64BIT),3,2)

PROGBITS = $(if $(CONFIG_ARM),%,@)progbits

filechk_fwbin = \

echo "/* Generated by $(src)/Makefile */" ;\

echo " .section .rodata" ;\--rodata段。

echo " .p2align 4" ;\

echo "_fw_$(FWSTR)_bin:" ;\

echo " .incbin \"$(fwdir)/$(FWNAME)\"" ;\--将Firmware文件内嵌到xxx.gen.s中。

echo "_fw_end:" ;\

echo " .section .rodata.str,\"aMS\",$(PROGBITS),1" ;\--rodata.str段。

echo " .p2align $(ASM_ALIGN)" ;\

echo "_fw_$(FWSTR)_name:" ;\

echo " .string \"$(FWNAME)\"" ;\--Firmware名称。

echo " .section .builtin_fw,\"a\",$(PROGBITS)" ;\--builtin_fw段。

echo " .p2align $(ASM_ALIGN)" ;\

echo " $(ASM_WORD) _fw_$(FWSTR)_name" ;\--这是一个struct builtin_fw结构体:名称、内存地址、大小。

echo " $(ASM_WORD) _fw_$(FWSTR)_bin" ;\

echo " $(ASM_WORD) _fw_end - _fw_$(FWSTR)_bin"

$(obj)/%.gen.S: FORCE

$(call filechk,fwbin)--生成xxx.gen.s文件。

# The .o files depend on the binaries directly; the .S files don't.

$(addprefix $(obj)/, $(obj-y)): $(obj)/%.gen.o: $(fwdir)/%

targets := $(patsubst $(obj)/%,%, \

$(shell find $(obj) -name \*.gen.S 2>/dev/null))

2 Linux Firmware Loader数据结构和API

2.1 数据结构

struct firmware用于记录申请到的固件。struct biultin_fw用于记录内嵌到Kernel的固件。

struct firmware {

size_t size;--固件大小。

const u8 *data;--固件起始地址。

struct page **pages;--保存固件内容的page页表。

/* firmware loader private fields */

void *priv;

};

struct builtin_fw {--内嵌到Kernel中的固件。

char *name;

void *data;

unsigned long size;

};

Firmware Loader的操作主要是申请固件的request_firmware_*和释放固件的release_firmware函数。

int request_firmware(const struct firmware **fw, const char *name,

struct device *device);

int firmware_request_nowarn(const struct firmware **fw, const char *name,

struct device *device);--类似于request_firmware(),但是当文件找不到时不输出警告信息。

int request_firmware_nowait(

struct module *module, bool uevent,

const char *name, struct device *device, gfp_t gfp, void *context,

void (*cont)(const struct firmware *fw, void *context));--类似于request_firmware(),但是不等待文件读取完成。而是通过回调函数来完成后续操作。

int request_firmware_direct(const struct firmware **fw, const char *name,

struct device *device);

int request_firmware_into_buf(const struct firmware **firmware_p,

const char *name, struct device *device, void *buf, size_t size);

void release_firmware(const struct firmware *fw);

2.2 request_firmware解读

不同的request_firmware()函数变种差异主要在flag不同:

enum fw_opt {

FW_OPT_UEVENT = BIT(0),--Firmware文件找不到时通过uevent通知用户空间负责加载Firmware。

FW_OPT_NOWAIT = BIT(1),--Firmware请求时异步的。

FW_OPT_USERHELPER = BIT(2),--类似于uevent的回调机制。

FW_OPT_NO_WARN = BIT(3),--不输出警告信息。

FW_OPT_NOCACHE = BIT(4),--Firmware缓存可以避免在suspend-resume后频繁读取存储设备。但是如果Firmware过大,也不适合保留缓存。

FW_OPT_NOFALLBACK = BIT(5),--不借助回调机制让用户加载Firmware。

};

结合上面的fw_opt,request_firmware变种是对_request_firmware的包装:

request_firmware--FW_OPT_UEVENTfirmware_request_nowarn--FW_OPT_UEVENT | FW_OPT_NO_WARNrequest_firmware_direct--FW_OPT_UEVENT | FW_OPT_NO_WARN |FW_OPT_NOFALLBACKrequest_firmware_into_buf--FW_OPT_UEVENT | FW_OPT_NOCACHE ->_request_firmware ->_request_firmware_prepare ->fw_get_builtin_firmware--遍历__start_builtin_fw到__end_builtin_fw之间的struct builtin_fw,并将Firmware内容拷贝到指定buf中。 ->alloc_lookup_fw_priv--如果builtin中没找到,则尝试到fw_cache去寻找。没有的话则创建一个struct fw_priv。 ->fw_get_filesystem_firmware--根据fw_priv->fw_name和suffix在fw_path目录列表中读取文件。 ->kernel_read_file_from_path ->kernel_read_file--如果buf已经分配则直接写入;如果没有分配,则通过vmalloc()分配。 ->firmware_fallback_sysfs--在builtin和fs读取都失败后,告诉用户空间进行处理。 ->fw_load_from_user_helper ->firmware_loading_timeout--设置超时时间。 ->fw_create_instance--创建一个struct fw_sysfs,后续用户空间可以通过此sysfs加载Firmware。sysfs包含两个节点:struct bin_attribute类型的data,用于保存Firmware;struct attribute类型的loading,显示或设置loading状态。 ->fw_load_sysfs_fallback--可以通过UEVENT通知用户空间去加载Firmware。超时或成功后sysfs消失。 ->assign_fw

综合来看Firmware Loader提供给的加载固件的方式有:

在Kernel编译阶段固化到到builtin_fw段。

在fw_path目录列表中寻找固件并加载。

发送uevent事件到用户空间,用户空间解析uevent事件然后将固件加载到指定sysfs。

fw_path默认列表为:

static const char * const fw_path[] = {

fw_path_para,

"/lib/firmware/updates/" UTS_RELEASE,

"/lib/firmware/updates",

"/lib/firmware/" UTS_RELEASE,

"/lib/firmware"

};

更多参考《linux驱动- firmware子系统》《linux固件升级接口使用总结》。

3 其他配置

通过在cmdline中增加firmware_class.path=来增加固件路径。

修改firmware_class模块参数/sys/module/firmware_class/parameters/path增加固件路径。

← 上一篇: 全角与半角字符的区别及切换技巧详解
下一篇: CPU性能测试-coremark →

相关推荐

压榨机 - [FID]烟火凡人心 (Flavor Immersed Daily) - MC百科

压榨机 - [FID]烟火凡人心 (Flavor Immersed Daily) - MC百科

压榨机编辑加合成表物品命令:/give @p flavor_immersed_daily:squeezingmachine 64合/用途主要名称:压榨机资料分类:功能方块最大堆叠:64个 / 组用于榨

波兰足球宝贝裸体彩绘变花蝴蝶

波兰足球宝贝裸体彩绘变花蝴蝶

新闻中心意见反馈留言板 新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 通行证注册 | 产品答疑 Copyright © 1996-2025

鸽子是特马是什么生肖(鸽子打一个生肖)

鸽子是特马是什么生肖(鸽子打一个生肖)

鸽子打一个生肖。 十二生肖中,其它生肖被看作是一种吉利的象征。 他们通常用鸽子来象征。 一起来看看吧。 鸽子(wu fang),为中国生肖其一。

焯的音韻方言

焯的音韻方言

粵語,又称廣東話,在粵語使用區中又稱白話,在中國以外地區又稱唐話,是漢藏語系漢語族的一種語言。在中國主要分布於廣東、香港、澳門

贾布里勒·西塞

贾布里勒·西塞

吉布里尔·西塞(法语:Djibril Cissé,1981年8月12日—)是一名前几内亚后裔法国职业足球运动员,他的双亲却是科特迪亚人,司职前锋,目前效

COK列王的纷争(cok列王的纷争折扣端)有哪些游戏攻略

COK列王的纷争(cok列王的纷争折扣端)有哪些游戏攻略

COK列王的纷争(cok列王的纷争折扣端)有哪些游戏攻略 【游戏攻略一:资源管理】 在COK列王的纷争中,有效地管理资源是取得成功的关键。首先,