我们在使用Ralink芯片的WiFi时,很多型号是需要在加载模块时也加载固件的,这样做是有好处的,一可以省成本(少了保存固件的存储芯片和生产烧录),二是解决硬件BUG(通过更新固件来解决批量硬件存在的严重BUG),三是功能升级。总之好处多多,怎么都可以挖掘到。
在Linux中关于固件常用到如下函数,其在include/linux/firmware.h声明,在drivers/base/firmware_class.c实现,相应的函数原型如下:
static inline int request_firmware(const struct firmware **fw, const char *name, struct device *device) ;
static inline void release_firmware(const struct firmware *fw) ;
其中firmware结构体定义如下:
struct firmware {
size_t size;
const u8 *data;
struct page **pages;
/* firmware loader private fields */
void *priv;
};
而相应的device结构体在include/linux/device.h中定义,我们等会只是构建一个临时的device,该部分在后期的内核模型中再说明,其使用device_initialize函数来初始化,在drivers/base/core.c中定义。 接下来上代码吧:
#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/device.h>
#define SLAM_TEST_FIRMWARE "rt73.bin"
static const struct firmware * fwp;
static struct device slam_device = {
.init_name = "slam0",
};
static void print_firmware_data(char * fw, int size)
{
u8 buf[size+1];
memcpy(buf, fw, size);
buf[size] = '\0';
printk("firmware data:%x\n", buf);
}
static __init int firmware_operate_init(void)
{
int ret = 0;
device_initialize(&slam_device);
ret = request_firmware(&fwp, SLAM_TEST_FIRMWARE, &slam_device);
if (ret) {
printk("Load firmware failed!\n");
return -1;
}
print_firmware_data(fwp->data, fwp->size);
release_firmware(fwp);
return 0;
}
static __exit void firmware_operate_exit(void)
{
printk("%s\n", __func__);
}
module_init(firmware_operate_init);
module_exit(firmware_operate_exit);
MODULE_AUTHOR("xinu");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(SLAM_TEST_FIRMWARE);
相应的Makefile文件内容如下:
obj-m += firmware_operate_example.o
CUR_PATH:=$(shell pwd)
LINUX_KERNEL_PATH:=/home/xinu/linux-3.13.6
all:
make -C $(LINUX_KERNEL_PATH) M=$(CUR_PATH) modules
clean:
make -C $(LINUX_KERNEL_PATH) M=$(CUR_PATH) clean
对应的源码文件目录树如下:
/home/xinu/xinu/linux_kernel_driver_l1/firmware_operate_example/
├── firmware_operate_example.c
└── Makefile
在源码里我读取并打印了rt73.bin的内容,具体请查看你的/lib/firmware目录,可换成你的目录里其他文件试试看。从源码里我们看到对固件操作很简单,其实现在只是涉及到读取固件,读完后还需要使用其来初始化对应芯片呢,这个可以找下Ralink的WiFi源码研究研究。