123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- use crate::driver::base::uevent::kobject_uevent::kobject_uevent_env;
- use core::fmt::Write;
- /*
- Struct
- kset_uevent_ops
- Function
- get_ktype
- kobject_name
- kset_get
- kset_put
- to_kset
- */
- use crate::driver::base::kobject::KObject;
- use crate::driver::net::Iface;
- use crate::filesystem::sysfs::{Attribute, SysFSOpsSupport, SYSFS_ATTR_MODE_RW};
- use alloc::string::{String, ToString};
- use alloc::sync::Arc;
- use alloc::vec::Vec;
- use intertrait::cast::CastArc;
- use log::warn;
- use system_error::SystemError;
- use super::block::block_device::{BlockDevice, BlockDeviceOps};
- use super::char::CharDevice;
- use super::device::{Device, DeviceType};
- pub mod kobject_uevent;
- // https://code.dragonos.org.cn/xref/linux-6.1.9/lib/kobject_uevent.c?fi=kobject_uevent#457
- #[derive(Debug)]
- pub enum KobjectAction {
- KOBJADD,
- KOBJREMOVE, // Kobject(或上层数据结构)的添加/移除事件
- KOBJCHANGE, // Kobject(或上层数据结构)的状态或者内容发生改变; 如果设备驱动需要上报的事件不再上面事件的范围内,或者是自定义的事件,可以使用该event,并携带相应的参数。
- KOBJMOVE, // Kobject(或上层数据结构)更改名称或者更改Parent(意味着在sysfs中更改了目录结构)
- KOBJONLINE,
- KOBJOFFLINE, // Kobject(或上层数据结构)的上线/下线事件,其实是是否使能
- KOBJBIND,
- KOBJUNBIND,
- }
- /// 解析一个字符串,以确定它代表的是哪个 kobject_action,并提取出随后的参数(如果有的话)
- fn kobject_action_type(buf: &[u8]) -> Result<(KobjectAction, Vec<String>), SystemError> {
- let mut action = KobjectAction::KOBJCHANGE;
- let mut action_args: Vec<String> = Vec::new();
- let mut count = buf.len();
- if count != 0 && (buf[count - 1] == b'\n' || buf[count - 1] == b'\0') {
- count -= 1;
- }
- if count == 0 {
- return Err(SystemError::EINVAL);
- }
- let arg_start = buf.iter().position(|&c| c == b' ').unwrap_or(count);
- let count_first = arg_start;
- let args_start = arg_start + 1;
- // 匹配KobjectAction
- match &buf[..count_first] {
- b"add" => action = KobjectAction::KOBJADD,
- b"remove" => action = KobjectAction::KOBJREMOVE,
- b"change" => action = KobjectAction::KOBJCHANGE,
- b"move" => action = KobjectAction::KOBJMOVE,
- b"online" => action = KobjectAction::KOBJONLINE,
- b"offline" => action = KobjectAction::KOBJOFFLINE,
- b"bind" => action = KobjectAction::KOBJBIND,
- b"unbind" => action = KobjectAction::KOBJUNBIND,
- _ => return Err(SystemError::EINVAL),
- }
- // 如果有参数,提取参数
- if count - args_start > 0 {
- action_args = buf[args_start..]
- .split(|&c| c == b' ')
- .map(|s| String::from_utf8_lossy(s).to_string())
- .collect::<Vec<_>>();
- }
- Ok((action, action_args))
- }
- pub const UEVENT_NUM_ENVP: usize = 64;
- pub const UEVENT_BUFFER_SIZE: usize = 2048;
- pub const UEVENT_HELPER_PATH_LEN: usize = 256;
- /// 表示处理内核对象 uevents 的环境
- /// - envp,指针数组,用于保存每个环境变量的地址,最多可支持的环境变量数量为UEVENT_NUM_ENVP。
- /// - envp_idx,用于访问环境变量指针数组的index。
- /// - buf,保存环境变量的buffer,最大为UEVENT_BUFFER_SIZE。
- /// - buflen,访问buf的变量。
- // https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/kobject.h#31
- #[derive(Debug)]
- pub struct KobjUeventEnv {
- argv: Vec<String>,
- envp: Vec<String>,
- envp_idx: usize,
- buf: Vec<u8>,
- buflen: usize,
- }
- // kset_uevent_ops是为kset量身订做的一个数据结构,里面包含filter和uevent两个回调函数,用处如下:
- /*
- filter,当任何Kobject需要上报uevent时,它所属的kset可以通过该接口过滤,阻止不希望上报的event,从而达到从整体上管理的目的。
- name,该接口可以返回kset的名称。如果一个kset没有合法的名称,则其下的所有Kobject将不允许上报uvent
- uevent,当任何Kobject需要上报uevent时,它所属的kset可以通过该接口统一为这些event添加环境变量。因为很多时候上报uevent时的环境变量都是相同的,因此可以由kset统一处理,就不需要让每个Kobject独自添加了。
- */
- /// 设备文件夹下的`uevent`文件的属性
- #[derive(Debug, Clone, Copy)]
- pub struct UeventAttr;
- impl Attribute for UeventAttr {
- fn name(&self) -> &str {
- "uevent"
- }
- fn mode(&self) -> crate::filesystem::vfs::syscall::ModeType {
- SYSFS_ATTR_MODE_RW
- }
- fn support(&self) -> crate::filesystem::sysfs::SysFSOpsSupport {
- SysFSOpsSupport::ATTR_SHOW | SysFSOpsSupport::ATTR_STORE
- }
- /// 用户空间读取 uevent 文件,返回 uevent 信息
- fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
- let device = _kobj.cast::<dyn Device>().map_err(|e: Arc<dyn KObject>| {
- warn!("device:{:?} is not a device!", e);
- SystemError::EINVAL
- })?;
- log::info!("show uevent");
- let device_type = device.dev_type();
- let mut uevent_content = String::new();
- log::info!("device_type: {:?}", device_type);
- match device_type {
- DeviceType::Block => {
- let major = device.id_table().device_number().major().data();
- let minor = device.id_table().device_number().minor();
- let device_name = device.id_table().name();
- writeln!(&mut uevent_content, "MAJOR={:?}", major).unwrap();
- writeln!(&mut uevent_content, "MINOR={:?}", minor).unwrap();
- writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
- writeln!(&mut uevent_content, "DEVTYPE=disk").unwrap();
- }
- DeviceType::Char => {
- let major = device.id_table().device_number().major().data();
- let minor = device.id_table().device_number().minor();
- let device_name = device.id_table().name();
- writeln!(&mut uevent_content, "MAJOR={}", major).unwrap();
- writeln!(&mut uevent_content, "MINOR={}", minor).unwrap();
- writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
- writeln!(&mut uevent_content, "DEVTYPE=char").unwrap();
- }
- DeviceType::Net => {
- let net_device =
- device
- .clone()
- .cast::<dyn Iface>()
- .map_err(|e: Arc<dyn Device>| {
- warn!("device:{:?} is not a net device!", e);
- SystemError::EINVAL
- })?;
- let iface_id = net_device.nic_id();
- let device_name = device.name();
- writeln!(&mut uevent_content, "INTERFACE={}", device_name).unwrap();
- writeln!(&mut uevent_content, "IFINDEX={}", iface_id).unwrap();
- }
- DeviceType::Bus => {
- // 处理总线设备类型
- let device_name = device.name();
- writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
- writeln!(&mut uevent_content, "DEVTYPE=bus").unwrap();
- }
- DeviceType::Rtc => {
- // 处理RTC设备类型
- let device_name = device.name();
- writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
- writeln!(&mut uevent_content, "DEVTYPE=rtc").unwrap();
- }
- DeviceType::Pci => {
- // 处理PCI设备类型
- let device_name = device.name();
- writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
- writeln!(&mut uevent_content, "DEVTYPE=pci").unwrap();
- }
- _ => {
- // 处理其他设备类型
- let device_name = device.name();
- writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
- writeln!(&mut uevent_content, "DEVTYPE={:?}", device_type).unwrap();
- }
- }
- sysfs_emit_str(_buf, &uevent_content)
- }
- /// 捕获来自用户空间对 uevent 文件的写操作,触发uevent事件
- fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
- log::info!("store uevent");
- return kobject_synth_uevent(_buf, _kobj);
- }
- }
- /// 将设备的基本信息写入 uevent 文件
- fn sysfs_emit_str(buf: &mut [u8], content: &str) -> Result<usize, SystemError> {
- log::info!("sysfs_emit_str");
- let bytes = content.as_bytes();
- if buf.len() < bytes.len() {
- return Err(SystemError::ENOMEM);
- }
- buf[..bytes.len()].copy_from_slice(bytes);
- Ok(bytes.len())
- }
- /// 解析用户空间写入的 uevent 信息,触发 uevent 事件
- fn kobject_synth_uevent(buf: &[u8], kobj: Arc<dyn KObject>) -> Result<usize, SystemError> {
- let no_uuid_envp = vec!["SYNTH_UUID=0".to_string()];
- let (action, action_args) = kobject_action_type(buf)?;
- let result = if action_args.is_empty() {
- kobject_uevent_env(kobj.clone(), action, no_uuid_envp)
- } else {
- kobject_uevent_env(kobj.clone(), action, action_args)
- };
- if let Err(e) = result {
- let device = kobj.cast::<dyn Device>().map_err(|e: Arc<dyn KObject>| {
- warn!("device:{:?} is not a device!", e);
- SystemError::EINVAL
- })?;
- let devname = device.name();
- log::error!("synth uevent: {}: {:?}", devname, e);
- return Err(SystemError::EINVAL);
- }
- Ok(buf.len())
- }
|