【request_firmware】 linux内核下载模块固件接口【转】

news/2024/7/7 16:00:01 标签: 操作系统

转自:http://blog.csdn.net/magod/article/details/6049558

[-]

  1. 8 处理固件
    1. 1481 内核固件接口
    2. 1482 它如何工作

14.8. 处理固件

作为一个驱动作者, 你可能发现你面对一个设备必须在它能支持工作前下载固件到它里面. 硬件市场的许多地方的竞争是如此得强烈, 以至于甚至一点用作设备控制固件的 EEPROM 的成本制造商都不愿意花费. 因此固件发布在随硬件一起的一张 CD 上, 并且操作系统负责传送固件到设备自身.

你可能想解决固件问题使用这样的一个声明:

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

但是, 这个方法几乎肯定是一个错误. 将固件编码到一个驱动扩大了驱动的代码, 使固件升级困难, 并且非常可能产生许可问题. 供应商不可能已经发布固件映象在 GPL 之下, 因此和 GPL-许可的代码混合常常是一个错误. 为此, 包含内嵌固件的驱动不可能被接受到主流内核或者被 Linux 发布者包含.

正确的方法是当你需要它时从用户空间获取它. 但是, 请抵制试图从内核空间直接打开包含固件的文件的诱惑; 那是一个易出错的操作, 并且它安放了策略(以一个文件名的形式)到内核. 相反, 正确的方法时使用固件接口, 它就是为此而创建的:

#include <linux/firmware.h>

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

struct device *device);

调用 request_firmware 要求用户空间定位并提供一个固件映象给内核; 我们一会儿看它如何工作的细节. name 应当标识需要的固件; 正常的用法是供应者提供的固件文件名. 某些象 my_firmware.bin 的名子是典型的. 如果固件被成功加载, 返回值是 0(负责常用的错误码被返回), 并且 fw 参数指向一个这些结构:

struct firmware {

size_t size;

u8 *data;

};

那个结构包含实际的固件, 它现在可被下载到设备中. 小心这个固件是来自用户空间的未被检查的数据; 你应当在发送它到硬件之前运用任何并且所有的你能够想到的检查来说服你自己它是正确的固件映象. 设备固件常常包含标识串, 校验和, 等等; 在信任数据前全部检查它们.

在你已经发送固件到设备前, 你应当释放 in-kernel 结构, 使用:

void release_firmware(struct firmware *fw); 

因为 request_firmware 请求用户空间来帮忙, 它保证在返回前睡眠. 如果你的驱动当它必须请求固件时不在睡眠的位置, 异步的替代方法可能要使用:

int request_firmware_nowait(struct module *module,

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

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

这里额外的参数是 moudle( 它将一直是 THIS_MODULE), context (一个固件子系统不使用的私有数据指针), 和 cont. 如果都进行顺利, request_firmware_nowait 开始固件加载过程并且返回 0. 在将来某个时间, cont 将用加载的结果被调用. 如果由于某些原因固件加载失败, fw 是 NULL.

固件子系统使用 sysfs 和热插拔机制. 当调用 request_firmware, 一个新目录在 /sys/class/firmware 下使用你的驱动的名子被创建. 那个目录包含 3 个属性:

loading

这个属性应当被加载固件的用户空间进程设置为 1. 当加载进程完成, 它应当设为 0. 写一个值 -1 到 loading 会中止固件加载进程.

data

data 是一个二进制的接收固件数据自身的属性. 在设置 loading 后, 用户空间进程应当写固件到这个属性.

device

这个属性是一个符号连接到 /sys/devices 下面的被关联入口项.

一旦创建了 sysfs 入口项, 内核为你的设备产生一个热插拔事件. 传递给热插拔处理者的环境包括一个变量 FIRMWARE, 它被设置为提供给 request_firmware 的名子. 这个处理者应当定位固件文件, 并且拷贝它到内核使用提供的属性. 如果这个文件无法找到, 处理者应当设置 loading 属性为 -1.

如果一个固件请求在 10 秒内没有被服务, 内核就放弃并返回一个失败状态给驱动. 超时周期可通过 sysfs 属性 /sys/class/firmware/timeout 属性改变.

使用 request_firmware 接口允许你随你的驱动发布设备固件. 当正确地集成到热插拔机制, 固件加载子系统允许设备简化工作"在盒子之外" 显然这是处理问题的最好方法.

但是, 请允许我们提出多一条警告: 设备固件没有制造商的许可不应当发布. 许多制造商会同意在合理的条款下许可它们的固件, 如果客气地请求; 一些其他的可能不何在. 无论如何, 在没有许可时拷贝和发布它们的固件是对版权法的破坏并且招致麻烦.


http://www.niftyadmin.cn/n/1412376.html

相关文章

用C#编写ActiveX控件(三)

在前面我们已经完成了ActiveX控件的开发&#xff0c;接下来的就是发布它了。 首先&#xff0c;我们建立一个windows安装项目&#xff0c;并将ActiveX控件的主输出添加到项目输出中。然后&#xff0c;改动ActiveX控件的主输出文件&#xff0c;将其Register属性改为vsdrpCOM.如图…

[linux指令]SSH远程文件/目录传输命令scp

原文&#xff1a;http://www.vpser.net/manage/scp.html 1、获取远程服务器上的文件 scp -P 2222 rootwww.vpser.net:/root/lnmp0.4.tar.gz /home/lnmp0.4.tar.gz 上端口大写P 为参数&#xff0c;2222 表示更改SSH端口后的端口&#xff0c;如果没有更改SSH端口可以不用添加该参…

MIT6.824 lab3 KVRaft实验分析

本实验中&#xff0c;不同clientId的用户会向当前认为是leader的kvServer发送请求 集群中有多个kvServer&#xff0c;每个绑定了一个Raft 集群中的kvServer会不断执行指令更新自身状态&#xff0c;也因此在写代码时要对ops的来源进行区分 来源1&#xff1a;client认为当前kvS…

网络安全合规-数据安全治理的发展

数据安全治理的核心思想&#xff1a; 从某种意义上讲&#xff0c;要保证数据的绝对安全&#xff0c;就要将数据全部物理隔绝&#xff0c;变成“死”数据&#xff0c;这样是最“安全”的&#xff0c;既拿不走&#xff0c;也破坏不了。但这样做是否有意义&#xff1f;上面我们讲过…

洛谷P1993 小 K 的农场

题目描述 小 K 在 Minecraft 里面建立很多很多的农场&#xff0c;总共 n 个&#xff0c;以至于他自己都忘记了每个 农场中种植作物的具体数量了&#xff0c;他只记得一些含糊的信息&#xff08;共 m 个&#xff09;&#xff0c;以下列三种形式描 述&#xff1a; 农场 a 比农场 …

.Net用DataTable导出Excel通用函数

1,首先要导入Com文件Microsoft Excel 11.0 Object Library.2,要添加Interop.Excel.dll文件http://files.cnblogs.com/ghostljj/Interop.Excel.rar3.执行下面步骤 /// <summary> /// 导出Excel /// </summary> /// <param name"dt">要导…

分布式计算细节

数据库的设计还是要结合业务模式来分析&#xff0c;例如OLTP通常采用航储存&#xff0c;OLAP通常采用列储存等等。 如果等值查询较多的话&#xff0c;那么按照哈希存储数据比较好&#xff1b;如果范围查询较多的话&#xff0c;那么按照有序数组储存数据比较好。 聚合操作&…

ELK

E&#xff1a;Elasticsearch 基于开源分布式搜索引擎Lucene实现&#xff0c;接近实时&#xff08;NRT&#xff0c;Near Realtime&#xff09;的搜索平台 基本概念 Cluster - Node&#xff1a;集群 - 节点 Index&#xff1a;索引 Document&#xff1a;文档&#xff0c;可以被索引…