浅析frmware的加载和init通过netlink处理uevent事件的一般流程

来源:互联网 发布:中学生免费辅导软件 编辑:程序博客网 时间:2024/06/05 13:32
 

浅析frmware的加载和init通过netlink处理uevent事件的一般流程

当总线检测代id相macth的设备或者驱动时调用,wlan_probe
=>wlan_probe
=>wlan_add_card
=>sbi_register_dev
=>priv->hotplug_device= &func->dev;这样priv->hotplug_device就指向了/sys/bus/sdio/devices下的设备节点描述结构体
接下来下载wlan的firmware固件驱动,
=>wlan_init_fw
=>request_firmware(&priv->firmware, fw_name, priv->hotplug_device);给priv->hotplug_device设备申请名字为fw_name的firmware
  数据,让后将结果放到&priv->firmware中,
  struct firmware {
    size_t size;
    u8 *data;
  };
  可以看到,如果应用层的程序成功load了firmware固件文件,那么firmware.data将指向固件数据,firmware.size为固件大小.
module_param(fw_name, charp, 0);
MODULE_PARM_DESC(fw_name,"Firmware name");这里可以看到fw_name是作为参数可以自由指定的,如果没有指定,那么将使用如下默认名:
#define DEFAULT_FW_NAME"mrvl/sd8688.bin"
=================================================================
request_firmware
=>_request_firmware
=>fw_setup_device
=>fw_register_device//添加临时download firmware的dev设备节点,注册该inode的class为
=>fw_priv->attr_data= firmware_attr_data_tmpl;//文件属性操作函数集
=>strlcpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX);//拷贝参数就是我们的fw_name即默认的"mrvl/sd8688.bin"
=>sysfs_create_bin_file(&f_dev->kobj,&fw_priv->attr_data);//创建DEVPATH/data文件,操作该文件的方法为firmware_attr_data_tmpl
//这样init程序就可以打开这个DEVPATH/data文件,然后向这个DEVPATH/data文件写入firmware固件bin内容,然后kernel的driver就可以通过
//firmware->data和firmware->size来读取有uevent处理程序init加载进来的firmware数据了[luther.gliethttp]
=>f_dev->class= &firmware_class;
=>if(uevent) kobject_uevent(&f_dev->kobj, KOBJ_ADD);发送uevent消息.
=>wait_for_completion(&fw_priv->completion);等待完成


static struct bin_attribute firmware_attr_data_tmpl= {
    .attr = {.name ="data", .mode = 0644},
    .size = 0,
    .read = firmware_data_read,
    .write = firmware_data_write,
};
=>firmware_data_write
=>fw_realloc_buffer//类似realloc实现,释放原有的,申请新加的
=>fw_priv->fw->data= new_data;


=>kobject_uevent
=>kobject_uevent_env
/*
devices_init
=>devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
static struct kset_uevent_ops device_uevent_ops = {
    .filter =    dev_uevent_filter,
    .name =        dev_uevent_name,
    .uevent =    dev_uevent,
};
=>dev_uevent
=>dev->class->dev_uevent

void device_initialize(struct device *dev)
{
    dev->kobj.kset = devices_kset;
    ...
}
*/

=>uevent_ops = kset->uevent_ops;//这里uevent_ops就指向device_uevent_ops了
=>uevent_ops->uevent(kset, kobj, env);建立环境变量
=>device_uevent_ops
=>dev_uevent
=>dev->class->dev_uevent就是firmware_class的dev_uevent,即:firmware_uevent
=>firmware_uevent
=>
/*
static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env)
{
    struct firmware_priv *fw_priv = dev_get_drvdata(dev);

    if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->fw_id))即默认的"mrvl/sd8688.bin"
        return -ENOMEM;
    if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout))
        return -ENOMEM;

    return 0;
}
*/

=>if(uevent_sock) { 那么通过netlink将该uevent事件广播出去,
=>netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL);
=>在include/linux/autoconf.h中
#define CONFIG_UEVENT_HELPER_PATH"/sbin/hotplug"
=>但是我们的root文件系统/sbin/下没有hotplug这个文件,只有一个adbd程序,所以这样看来就不能运行了,所以这里应该将char uevent_helper[UEVENT_HELPER_PATH_LEN]= 清0才对,让if(uevent_helper[0])失败,进而不继续执行和hotplug的相关操作,但是现在autoconf.h中
include/linux/autoconf.h
#define CONFIG_NET 1
#define CONFIG_HOTPLUG 1
仍然被设置成1,不知道为什么kernel team还要这样设置[luther.gliethttp].
.
所以我们的系统使用的是netlink接收事件广播,我的ubuntu8.04的/sbin下也没有找到hotplug这个文件,可能正如大家所说的,hotplug的诸多
缺陷导致它已经淡出了linux世界,而天生丽质的netlink已经在linx世界中全面开花[luther.gliethttp].

然后init进程开始处理这个firmware请求,
init
=>main
=>handle_device_fd调用uevent的NETLINK_KOBJECT_UEVENT的socket处理函数
=>parse_event
=>handle_firmware_event
=>pid = fork();子进程执行process_firmware_event
=>process_firmware_event
#define SYSFS_PREFIX"/sys"
=>asprintf(&root, SYSFS_PREFIX"%s/", uevent->path);
//这里的uevent->path是parse_event函数解析时对应的"DEVPATH="节内容,也就是dev设备路径
=>asprintf(&loading,"%sloading", root);//在该路径下创建loading文件
=>asprintf(&data,"%sdata", root);//该路径下的data文件
=>loading_fd= open(loading, O_WRONLY);//创建该loading文件,然后向其中写入"1"表示开始加载,加载成功写入"0",失败写入"-1".
=>data_fd= open(data, O_WRONLY
#define FIRMWARE_DIR"/system/lib/firmware" 原来路径是/etc/firmware,我的mrvl/sd8688.bin也放在那里,
//但是虽然ramdisk虽然经过压缩,可是存储ramdisk.img的总大小才512k,所以不能将有可能不断扩大大小的firmware放到那里,
//于是最近将init进程搜索路径改为"/system/lib/firmware".
=>asprintf(&file, FIRMWARE_DIR"/%s", uevent->firmware);
=>fw_fd = open(file, O_RDONLY);//打开通过uevent传递过来的firmware文件,然后拷贝过去
=>load_firmware(fw_fd, loading_fd, data_fd))这样加载
=================================================================
#define module_param_named(name, value, type, perm)             \
    param_check_##type(name,&(value));                 \
    module_param_call(name, param_set_##type, param_get_##type,&value, perm); \
    __MODULE_PARM_TYPE(name,#type)

#define module_param(name, type, perm)                \
    module_param_named(name, name, type, perm)
//对应param_check_##type检测参数类型函数如下,可以检测如下参数类型[luther.gliehttp]
param_check_bool param_check_int param_check_short param_check_ushort
param_check_byte param_check_invbool param_check_uint param_check_proto_abbrev
param_check_charp param_check_long param_check_ulong param_check_scroll
=================================================================
比如usb通用驱动的使用,这样所有usb设备都可以通过serial方式进行访问,因为不是该usb设备专有的usb驱动,所以速度可能慢一些[luther.gliethttp].
sudo insmod /lib/modules/2.6.22-14-generic/kernel/drivers/usb/serial/usbserial.ko vendor=0x8086 product=0xd001
在drivers/usb/serial/generic.c驱动中,
module_param(vendor, ushort, 0);
MODULE_PARM_DESC(vendor,"User specified USB idVendor");

module_param(product, ushort, 0);
MODULE_PARM_DESC(product,"User specified USB idProduct");

所以通过module_param可以方便的给ko驱动传递参数,很方便的咚咚,kernel那群人真能整[luther.gliethttp].

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 被苍蝇咬了屁股怎么办 牛苍蝇咬了肿了怎么办 眼睛被苍蝇咬了怎么办 小孩被仓鼠咬了怎么办 压水井不上水了怎么办 小鸟拉屎在鞋上怎么办 解完大便屁眼疼怎么办 拉大便后肛门痛怎么办 3岁宝宝肛裂怎么办 无臂人大便后怎么办 老婆移情别恋了怎么办 自己移情别恋了怎么办 嘴巴里破了变白怎么办 上嘴唇里面长泡怎么办 嘴皮里面长泡怎么办 嘴巴里经常长泡怎么办 嘴唇上长透明泡怎么办 嘴唇上长很多泡怎么办 嘴巴里长白色泡怎么办 做了漂唇起泡了怎么办 漂唇之后起泡了怎么办 漂唇后起了水泡怎么办 嘴唇起泡,弄破了怎么办 九个月的宝宝上火了怎么办 8岁儿童嘴唇起泡怎么办 宝宝嘴皮上火起泡了怎么办 上嘴唇起泡肿了怎么办 上嘴唇突然肿了怎么办? 醒来上嘴唇肿了怎么办 嘴巴突然肿了怎么办呢 下嘴唇肿起来了怎么办 上嘴唇肿了起泡怎么办 上火下嘴唇肿了怎么办 上火嘴唇都肿了怎么办 嘴唇起泡后肿了怎么办 嘴唇上有白点颗粒状怎么办 嘴唇缺了一块红怎么办 人得钩端螺旋体怎么办 脖子上有鸡皮肤怎么办 不结婚老了以后怎么办 丁克族老了怎么办知乎