123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- use crate::driver::base::uevent::kobject_uevent::kobject_uevent_env;
- use core::fmt::Write;
- 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;
- #[derive(Debug)]
- pub enum KobjectAction {
- KOBJADD,
- KOBJREMOVE,
- KOBJCHANGE,
- KOBJMOVE,
- KOBJONLINE,
- KOBJOFFLINE,
- KOBJBIND,
- KOBJUNBIND,
- }
- 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;
-
- 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;
- #[derive(Debug)]
- pub struct KobjUeventEnv {
- argv: Vec<String>,
- envp: Vec<String>,
- envp_idx: usize,
- buf: Vec<u8>,
- buflen: usize,
- }
- #[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
- }
-
- 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 => {
-
- let device_name = device.name();
- writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
- writeln!(&mut uevent_content, "DEVTYPE=rtc").unwrap();
- }
- DeviceType::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)
- }
-
- fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
- log::info!("store uevent");
- return kobject_synth_uevent(_buf, _kobj);
- }
- }
- 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())
- }
- 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())
- }
|