【request_firmware】 linux内核下载模块固件接口【转】
转自:http://blog.csdn.net/magod/article/details/6049558
14.8. 处理固件
作为一个驱动作者, 你可能发现你面对一个设备必须在它能支持工作前下载固件到它里面. 硬件市场的许多地方的竞争是如此得强烈, 以至于甚至一点用作设备控制固件的 EEPROM 的成本制造商都不愿意花费. 因此固件发布在随硬件一起的一张 CD 上, 并且操作系统负责传送固件到设备自身.
你可能想解决固件问题使用这样的一个声明:
static char my_firmware[] = { 0x34, 0x78, 0xa4, ... };
但是, 这个方法几乎肯定是一个错误. 将固件编码到一个驱动扩大了驱动的代码, 使固件升级困难, 并且非常可能产生许可问题. 供应商不可能已经发布固件映象在 GPL 之下, 因此和 GPL-许可的代码混合常常是一个错误. 为此, 包含内嵌固件的驱动不可能被接受到主流内核或者被 Linux 发布者包含.
14.8.1. 内核固件接口
正确的方法是当你需要它时从用户空间获取它. 但是, 请抵制试图从内核空间直接打开包含固件的文件的诱惑; 那是一个易出错的操作, 并且它安放了策略(以一个文件名的形式)到内核. 相反, 正确的方法时使用固件接口, 它就是为此而创建的:
#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.
14.8.2. 它如何工作
固件子系统使用 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 接口允许你随你的驱动发布设备固件. 当正确地集成到热插拔机制, 固件加载子系统允许设备简化工作"在盒子之外" 显然这是处理问题的最好方法.
但是, 请允许我们提出多一条警告: 设备固件没有制造商的许可不应当发布. 许多制造商会同意在合理的条款下许可它们的固件, 如果客气地请求; 一些其他的可能不何在. 无论如何, 在没有许可时拷贝和发布它们的固件是对版权法的破坏并且招致麻烦.
【request_firmware】 linux内核下载模块固件接口【转】的更多相关文章
- 【引用】Linux 内核驱动--多点触摸接口
本文转载自James<Linux 内核驱动--多点触摸接口> 译自:linux-2.6.31.14\Documentation\input\multi-touch-protocol.t ...
- linux内核中的排序接口--sort函数
linux内核中的sort函数,其实跟我们所说的qsort函数很像,我们来看看qsort: qsort 的函数原型是 void qsort(void*base,size_t num,size_t wi ...
- Linux内核-模块编译和安装
我安装Ubuntu的时候是没有安装源码的,在没有安装源码前 /usr/src/ 目录下是只有两个包含内核的头文件的文件夹的: 我的内核版本是: 所以接下来就是先安装内核源码: 执行后,/usr/src ...
- Linux内核(6) - 模块机制与“Hello World!
有一种感动,叫内牛满面,有一种机制,叫模块机制.显然,这种模块机制给那些Linux的发烧友们带来了方便,因为模块机制意味着人们可以把庞大的Linux内核划分为许许多多个小的模块.对于编写设备驱动程序的 ...
- linux内核及其模块的查询,加载,卸载 lsusb等
http://blog.sina.com.cn/s/blog_53e81e2a0100zkxi.html 1,/sbin/update-modules文件,他是一个linux通用的模块管理脚本程序. ...
- Linux 内核 编译模块
背景: 由于调试内核或者由于分区大小限制,有时候内核组件不一定完全需要编进内核中. 所以,在开发中经常将内核组件编译成为模块,等到在恰当的时机加载. 概览: Linux内核模块的编译方法有两种: 1. ...
- linux内核netfilter模块分析之:HOOKs点的注册及调用
转自;http://blog.csdn.net/suiyuan19840208/article/details/19684883 -1: 为什么要写这个东西?最近在找工作,之前netfilter 这一 ...
- linux内核添加模块
参考: http://blog.csdn.net/gaoguoxin2/article/details/50220665 动态添加模块不需要编译内核. LINUX的模块主要由6部分组成: 1.模块的加 ...
- linux内核下载
01最新版:https://www.kernel.org/ 02老旧版:https://www.kernel.org/pub/linux/kernel/v3.x/ ------------------ ...
随机推荐
- jQuery的常用事件
1.$(document).ready() $(document).ready()是jQuery中响应JavaScript内置的onload事件并执行任务的一种典型方式.它和onload具有类似的效果 ...
- 对Oracle10g rac srvctl命令使用理解
srvctl命令是RAC维护中最常用到的命令,也最为复杂,使用这个命令可以操作CRS上的Database,Instance,ASM,Service.Listener和Node Application资 ...
- zju(3)内核编译与运行
1.实验目的 学习和掌握Linux配置和编译的基本步骤. 二.实验内容 1. 对Linux内核及用户程序进行配置: 2. 编译生成内核映像文件: 3. 把编译的映像文件烧写到FLASH中,查看运行结果 ...
- service mysql start出错,mysql启动不了,解决mysql: unrecognized service错误
service mysql start出错,mysql启动不了,解决mysql: unrecognized service错误的方法如下: [root@ctohome.com ~]# service ...
- 20145337 《Java程序设计》第二周学习总结
20145337 <Java程序设计>第二周学习总结 教材学习内容总结 Java可分基本类型与类类型: 基本类型分整数(short.int.long).字节(byte).浮点数(float ...
- 给RecyclerView实现的GridView加上HeaderView和FooterView
给RecyclerView设置布局管理器 GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3); 写适配器,添加子项 ...
- c语言的输入输出函数
参考文章: http://blog.sina.com.cn/s/blog_784f40b80100psg9.html C语言输入输出函数分为两类: 1.格式化输入输出函数 2.非格式化输入输出 --- ...
- Java 学习第一步-JDK安装和Java环境变量配置
Java学习第一步——JDK安装及Java环境变量配置 [原文] 2014-05-30 9:09 Java SE 阿超 9046 views Java作为当下很主流的编程语言,学习Java的朋 ...
- VC 菜单前的勾的切换
if (pMenu->GetSubMenu(2)->GetMenuState(ID_STOP_SPOT_OP_MOSUE,MF_BYCOMMAND) == MF_UNCHECKED) { ...
- 阅读廖雪峰老师git教程笔记
1.首先git是目前世界上最先进的分布式版本控制系统之一.所谓版本控制是针对工作中一些普遍的现象的. 比如,你写一份文档,期间,不断的改善,每次修改都会进行备份,久而久之,会有很多版本的同一份文档,但 ...