Browse Source

在Sysfs中引入ACPI Firmware (#405)

- bugfix: multiboot2启动的信息因为没及时转存导致后面无法从其中进行查询的bug
- feature: 把acpi表、acpi bus加入sysfs
LoGin 1 year ago
parent
commit
7eda31b2f0

+ 1 - 2
kernel/Cargo.toml

@@ -31,7 +31,7 @@ elf = { version = "0.7.2", default-features = false }
 memoffset = "0.9.0"
 atomic_enum = "0.2.0"
 raw-cpuid = "11.0.1"
-acpi = "5.0.0"
+acpi = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/acpi-rs.git", rev = "fb69243dcf" }
 intertrait = { path = "src/libs/intertrait" }
 linkme = "0.2"
 ida = { path = "src/libs/ida" }
@@ -51,4 +51,3 @@ features = ["spin_no_std"]
 [profile.release]
 debug = false
 
-

+ 4 - 4
kernel/src/driver/acpi/acpi.c

@@ -181,7 +181,7 @@ void acpi_init()
 
         // 申请mmio空间
         uint64_t size = 0;
-        mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_rsdt_virt_addr_base, &size);
+        rs_mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_rsdt_virt_addr_base, &size);
 
         // 映射rsdt表
         paddr = (uint64_t)rsdt_phys_base;
@@ -200,7 +200,7 @@ void acpi_init()
         printk_color(ORANGE, BLACK, "RSDT Entry num=%d\n", acpi_RSDT_Entry_num);
 
         // 申请mmio空间
-        mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_description_header_base, &size);
+        rs_mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_description_header_base, &size);
 
         // 映射所有的Entry的物理地址
         acpi_RSDT_entry_phys_base = ((ul)(rsdt->Entry)) & PAGE_2M_MASK;
@@ -220,7 +220,7 @@ void acpi_init()
         kdebug("rsdpv1->RsdtAddress=%#018lx", rsdpv1->RsdtAddress);
         // 申请mmio空间
         uint64_t size = 0;
-        mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_rsdt_virt_addr_base, &size);
+        rs_mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_rsdt_virt_addr_base, &size);
         // acpi_rsdt_virt_addr_base = 0xffffb00000000000UL;
         kdebug("ACPI: mmio created. acpi_rsdt_virt_addr_base = %#018lx,size= %#010lx", acpi_rsdt_virt_addr_base, size);
 
@@ -243,7 +243,7 @@ void acpi_init()
         printk_color(ORANGE, BLACK, "RSDT Entry num=%d\n", acpi_RSDT_Entry_num);
 
         // 申请mmio空间
-        mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_description_header_base, &size);
+        rs_mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_description_header_base, &size);
 
         // 映射所有的Entry的物理地址
         acpi_RSDT_entry_phys_base = ((ul)(rsdt->Entry)) & PAGE_2M_MASK;

+ 106 - 2
kernel/src/driver/acpi/bus.rs

@@ -1,7 +1,17 @@
-use alloc::sync::Arc;
+use alloc::{
+    string::{String, ToString},
+    sync::{Arc, Weak},
+};
 
 use crate::{
-    driver::base::device::{driver::Driver, Device},
+    driver::base::{
+        device::{
+            bus::{bus_manager, Bus},
+            driver::Driver,
+            Device,
+        },
+        subsys::SubSysPrivate,
+    },
     syscall::SystemError,
 };
 
@@ -20,4 +30,98 @@ impl AcpiManager {
 
         return Ok(false);
     }
+
+    /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1286
+    pub(super) fn bus_init(&self) -> Result<(), SystemError> {
+        self.acpi_sysfs_init()?;
+
+        let acpi_bus = AcpiBus::new();
+        bus_manager()
+            .register(acpi_bus as Arc<dyn Bus>)
+            .expect("acpi_bus register failed");
+        return Ok(());
+    }
+}
+
+/// ACPI总线
+///
+/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1072
+#[derive(Debug)]
+pub(super) struct AcpiBus {
+    private: SubSysPrivate,
+}
+
+impl AcpiBus {
+    pub fn new() -> Arc<Self> {
+        let default_weak: Weak<Self> = Weak::new();
+        let bus = Arc::new(Self {
+            private: SubSysPrivate::new("acpi".to_string(), default_weak, &[]),
+        });
+        bus.subsystem()
+            .set_bus(Arc::downgrade(&(bus.clone() as Arc<dyn Bus>)));
+        return bus;
+    }
 }
+
+impl Bus for AcpiBus {
+    fn name(&self) -> String {
+        return self.private.subsys().as_kobject().name();
+    }
+
+    fn dev_name(&self) -> String {
+        self.name()
+    }
+
+    /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1056
+    fn remove(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
+        todo!("acpi_bus: remove")
+    }
+
+    fn shutdown(&self, _device: &Arc<dyn Device>) {
+        return;
+    }
+
+    fn resume(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
+        return Ok(());
+    }
+
+    /// 通过acpi来匹配驱动
+    ///
+    /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1005
+    fn match_device(
+        &self,
+        _device: &Arc<dyn Device>,
+        _driver: &Arc<dyn Driver>,
+    ) -> Result<bool, SystemError> {
+        // todo: 通过acpi来匹配驱动
+        return Ok(false);
+    }
+
+    /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1019
+    fn probe(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
+        todo!("acpi_bus: probe")
+    }
+
+    fn subsystem(&self) -> &SubSysPrivate {
+        return &self.private;
+    }
+}
+
+/// Acpi设备应当实现的trait
+///
+/// 所有的实现了 AcpiDevice trait的结构体,都应该在结构体上方标注`#[cast_to([sync] AcpiDevice)]
+///
+/// todo: 仿照linux的acpi_device去设计这个trait
+///
+///
+/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/include/acpi/acpi_bus.h#364
+pub trait AcpiDevice: Device {}
+
+/// Acpi驱动应当实现的trait
+///
+/// 所有的实现了 AcpiDriver trait的结构体,都应该在结构体上方标注`#[cast_to([sync] AcpiDriver)]
+///
+/// todo: 仿照linux的acpi_driver去设计这个trait
+///
+/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/include/acpi/acpi_bus.h#163
+pub trait AcpiDriver: Driver {}

+ 4 - 2
kernel/src/driver/acpi/c_adapter.rs

@@ -4,7 +4,7 @@ use crate::{
     mm::{MemoryManagementArch, VirtAddr},
 };
 
-use super::AcpiManager;
+use super::acpi_manager;
 
 static mut RSDP_TMP_BOX: Option<AlignedBox<[u8; 4096], 4096>> = None;
 
@@ -20,5 +20,7 @@ unsafe extern "C" fn rs_acpi_init(rsdp_vaddr: u64) {
     ))
     .unwrap();
 
-    AcpiManager::init(rsdp_paddr);
+    acpi_manager()
+        .init(rsdp_paddr)
+        .expect("rs_acpi_init(): failed to init acpi");
 }

+ 56 - 22
kernel/src/driver/acpi/mod.rs

@@ -1,56 +1,90 @@
 use core::{fmt::Debug, ptr::NonNull};
 
 use acpi::AcpiHandler;
+use alloc::{string::ToString, sync::Arc};
 
 use crate::{
+    driver::base::firmware::sys_firmware_kset,
     kinfo,
-    libs::{
-        align::{page_align_down, page_align_up},
-        once::Once,
-    },
+    libs::align::{page_align_down, page_align_up},
     mm::{
         mmio_buddy::{mmio_pool, MMIOSpaceGuard},
         PhysAddr, VirtAddr,
     },
+    syscall::SystemError,
 };
 
+use super::base::kset::KSet;
+
+extern crate acpi;
+
 pub mod bus;
 mod c_adapter;
 pub mod glue;
 pub mod old;
-
-extern crate acpi;
+mod sysfs;
 
 static mut __ACPI_TABLE: Option<acpi::AcpiTables<AcpiHandlerImpl>> = None;
+/// `/sys/firmware/acpi`的kset
+static mut ACPI_KSET_INSTANCE: Option<Arc<KSet>> = None;
 
 #[inline(always)]
 pub fn acpi_manager() -> &'static AcpiManager {
     &AcpiManager
 }
 
+#[inline(always)]
+pub fn acpi_kset() -> Arc<KSet> {
+    unsafe { ACPI_KSET_INSTANCE.clone().unwrap() }
+}
+
 #[derive(Debug)]
 pub struct AcpiManager;
 
 impl AcpiManager {
-    pub fn init(rsdp_paddr: PhysAddr) {
-        static INIT: Once = Once::new();
-        INIT.call_once(|| {
-            kinfo!("Initializing Acpi Manager...");
-            let acpi_table: acpi::AcpiTables<AcpiHandlerImpl> =
-                unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr.data()) }
-                    .unwrap_or_else(|e| {
-                        panic!("acpi_init(): failed to parse acpi tables, error: {:?}", e)
-                    });
-
-            unsafe {
-                __ACPI_TABLE = Some(acpi_table);
-            }
-            kinfo!("Acpi Manager initialized.");
-        });
+    /// 初始化ACPI
+    ///
+    /// ## 参数
+    ///
+    /// - `rsdp_paddr`: RSDP的物理地址
+    ///
+    ///
+    /// ## 参考资料
+    ///
+    /// https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1390
+    pub fn init(&self, rsdp_paddr: PhysAddr) -> Result<(), SystemError> {
+        kinfo!("Initializing Acpi Manager...");
+
+        // 初始化`/sys/firmware/acpi`的kset
+        let kset = KSet::new("acpi".to_string());
+        kset.register(Some(sys_firmware_kset()))?;
+        unsafe {
+            ACPI_KSET_INSTANCE = Some(kset.clone());
+        }
+        self.map_tables(rsdp_paddr)?;
+        self.bus_init()?;
+        kinfo!("Acpi Manager initialized.");
+        return Ok(());
+    }
+
+    fn map_tables(&self, rsdp_paddr: PhysAddr) -> Result<(), SystemError> {
+        let acpi_table: acpi::AcpiTables<AcpiHandlerImpl> =
+            unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr.data()) }.map_err(
+                |e| {
+                    kerror!("acpi_init(): failed to parse acpi tables, error: {:?}", e);
+                    SystemError::ENOMEM
+                },
+            )?;
+
+        unsafe {
+            __ACPI_TABLE = Some(acpi_table);
+        }
+
+        return Ok(());
     }
 
     #[allow(dead_code)]
-    pub fn tables() -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>> {
+    pub fn tables(&self) -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>> {
         unsafe { __ACPI_TABLE.as_ref() }
     }
 }

+ 510 - 0
kernel/src/driver/acpi/sysfs.rs

@@ -0,0 +1,510 @@
+use acpi::sdt::SdtHeader;
+use alloc::{
+    string::{String, ToString},
+    sync::Arc,
+    vec::Vec,
+};
+
+use crate::{
+    driver::{
+        acpi::acpi_manager,
+        base::{kobject::KObject, kset::KSet},
+    },
+    filesystem::{
+        sysfs::{file::sysfs_emit_str, sysfs_instance, Attribute, BinAttribute, SysFSOpsSupport},
+        vfs::syscall::ModeType,
+    },
+    libs::rwlock::RwLock,
+    syscall::SystemError,
+};
+
+use super::{acpi_kset, AcpiManager};
+
+static mut __HOTPLUG_KSET_INSTANCE: Option<Arc<KSet>> = None;
+static mut __ACPI_TABLES_KSET_INSTANCE: Option<Arc<KSet>> = None;
+static mut __ACPI_TABLES_DATA_KSET_INSTANCE: Option<Arc<KSet>> = None;
+static mut __ACPI_TABLES_DYNAMIC_KSET_INSTANCE: Option<Arc<KSet>> = None;
+static mut __ACPI_TABLE_ATTR_LIST: Option<RwLock<Vec<Arc<AttrAcpiTable>>>> = None;
+
+const ACPI_MAX_TABLE_INSTANCES: usize = 999;
+
+#[inline(always)]
+#[allow(dead_code)]
+pub fn hotplug_kset() -> Arc<KSet> {
+    unsafe { __HOTPLUG_KSET_INSTANCE.clone().unwrap() }
+}
+
+#[inline(always)]
+pub fn acpi_tables_kset() -> Arc<KSet> {
+    unsafe { __ACPI_TABLES_KSET_INSTANCE.clone().unwrap() }
+}
+
+#[inline(always)]
+#[allow(dead_code)]
+pub fn acpi_tables_data_kset() -> Arc<KSet> {
+    unsafe { __ACPI_TABLES_DATA_KSET_INSTANCE.clone().unwrap() }
+}
+
+#[inline(always)]
+#[allow(dead_code)]
+pub fn acpi_tables_dynamic_kset() -> Arc<KSet> {
+    unsafe { __ACPI_TABLES_DYNAMIC_KSET_INSTANCE.clone().unwrap() }
+}
+
+#[inline(always)]
+fn acpi_table_attr_list() -> &'static RwLock<Vec<Arc<AttrAcpiTable>>> {
+    unsafe {
+        return __ACPI_TABLE_ATTR_LIST.as_ref().unwrap();
+    }
+}
+
+impl AcpiManager {
+    pub(super) fn acpi_sysfs_init(&self) -> Result<(), SystemError> {
+        unsafe {
+            __ACPI_TABLE_ATTR_LIST = Some(RwLock::new(Vec::new()));
+        }
+        self.acpi_tables_sysfs_init()?;
+
+        let hotplug_kset = KSet::new("hotplug".to_string());
+        hotplug_kset.register(Some(acpi_kset()))?;
+
+        unsafe {
+            __HOTPLUG_KSET_INSTANCE = Some(hotplug_kset.clone());
+        }
+
+        let hotplug_kobj = hotplug_kset as Arc<dyn KObject>;
+        sysfs_instance().create_file(&hotplug_kobj, &AttrForceRemove)?;
+
+        return Ok(());
+    }
+
+    /// 在 sysfs 中创建 ACPI 表目录
+    ///
+    /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/sysfs.c?fi=acpi_sysfs_init#488
+    fn acpi_tables_sysfs_init(&self) -> Result<(), SystemError> {
+        // 创建 `/sys/firmware/acpi/tables` 目录
+        let acpi_tables_kset = KSet::new("tables".to_string());
+        acpi_tables_kset.register(Some(acpi_kset()))?;
+        unsafe {
+            __ACPI_TABLES_KSET_INSTANCE = Some(acpi_tables_kset.clone());
+        }
+
+        // 创建 `/sys/firmware/acpi/tables/data` 目录
+        let acpi_tables_data_kset = KSet::new("data".to_string());
+        acpi_tables_data_kset.register(Some(acpi_tables_kset.clone()))?;
+        unsafe {
+            __ACPI_TABLES_DATA_KSET_INSTANCE = Some(acpi_tables_data_kset);
+        }
+
+        // 创建 `/sys/firmware/acpi/tables/dynamic` 目录
+        let acpi_tables_dynamic_kset = KSet::new("dynamic".to_string());
+        acpi_tables_dynamic_kset.register(Some(acpi_tables_kset.clone()))?;
+        unsafe {
+            __ACPI_TABLES_DYNAMIC_KSET_INSTANCE = Some(acpi_tables_dynamic_kset);
+        }
+
+        // todo: get acpi tables.
+        let tables = self.tables().unwrap();
+        let headers = tables.headers();
+        for header in headers {
+            kdebug!("ACPI header: {:?}", header);
+            let attr = AttrAcpiTable::new(&header)?;
+            acpi_table_attr_list().write().push(attr);
+            self.acpi_table_data_init(&header)?;
+        }
+
+        return Ok(());
+    }
+
+    /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/sysfs.c?fi=acpi_sysfs_init#469
+    fn acpi_table_data_init(&self, _header: &SdtHeader) -> Result<(), SystemError> {
+        // todo!("AcpiManager::acpi_table_data_init()")
+        return Ok(());
+    }
+}
+
+#[derive(Debug)]
+struct AttrForceRemove;
+
+impl Attribute for AttrForceRemove {
+    fn name(&self) -> &str {
+        "force_remove"
+    }
+
+    fn mode(&self) -> ModeType {
+        return ModeType::from_bits_truncate(0o444);
+    }
+
+    fn support(&self) -> SysFSOpsSupport {
+        return SysFSOpsSupport::SHOW;
+    }
+
+    fn show(&self, _kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
+        return sysfs_emit_str(buf, "0\n");
+    }
+}
+
+/// ACPI 表在 sysfs 中的属性
+#[derive(Debug)]
+struct AttrAcpiTable {
+    name: String,
+    filename: String,
+    instance: isize,
+    size: usize,
+}
+
+impl AttrAcpiTable {
+    pub fn new(header: &SdtHeader) -> Result<Arc<Self>, SystemError> {
+        let mut r = Self {
+            name: header.signature.to_string(),
+            filename: "".to_string(),
+            instance: 0,
+            size: header.length as usize,
+        };
+
+        for attr in acpi_table_attr_list().read().iter() {
+            if attr.name == r.name {
+                r.instance = attr.instance;
+            }
+        }
+        // 将当前实例的序号加1
+        r.instance += 1;
+        if r.instance > ACPI_MAX_TABLE_INSTANCES as isize {
+            kwarn!("too many table instances. name: {}", r.name);
+            return Err(SystemError::ERANGE);
+        }
+
+        let mut has_multiple_instances: bool = false;
+        let mut tmpcnt = 0;
+        for h in acpi_manager().tables().unwrap().headers() {
+            if h.signature == header.signature {
+                tmpcnt += 1;
+                if tmpcnt > 1 {
+                    has_multiple_instances = true;
+                    break;
+                }
+            }
+        }
+
+        if r.instance > 1 || (r.instance == 1 && has_multiple_instances) {
+            r.filename = format!("{}{}", r.name, r.instance);
+        } else {
+            r.filename = r.name.clone();
+        }
+
+        let result = Arc::new(r);
+        sysfs_instance().create_bin_file(
+            &(acpi_tables_kset() as Arc<dyn KObject>),
+            &(result.clone() as Arc<dyn BinAttribute>),
+        )?;
+        return Ok(result);
+    }
+}
+
+impl Attribute for AttrAcpiTable {
+    fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
+        return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
+    }
+
+    fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
+        return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
+    }
+
+    fn name(&self) -> &str {
+        return &self.filename;
+    }
+
+    fn mode(&self) -> ModeType {
+        return ModeType::from_bits_truncate(0o400);
+    }
+
+    fn support(&self) -> SysFSOpsSupport {
+        return SysFSOpsSupport::empty();
+    }
+}
+
+impl BinAttribute for AttrAcpiTable {
+    fn support_battr(&self) -> SysFSOpsSupport {
+        return SysFSOpsSupport::READ;
+    }
+    fn write(
+        &self,
+        _kobj: Arc<dyn KObject>,
+        _buf: &[u8],
+        _offset: usize,
+    ) -> Result<usize, SystemError> {
+        return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
+    }
+
+    /// 展示 ACPI 表的内容
+    ///
+    /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/sysfs.c?fi=acpi_sysfs_init#320
+    fn read(
+        &self,
+        _kobj: Arc<dyn KObject>,
+        buf: &mut [u8],
+        offset: usize,
+    ) -> Result<usize, SystemError> {
+        macro_rules! copy_data {
+            ($table:expr) => {
+                let from = unsafe {
+                    core::slice::from_raw_parts(
+                        $table.virtual_start().as_ptr() as *const u8,
+                        $table.region_length(),
+                    )
+                };
+                if offset >= from.len() {
+                    return Ok(0);
+                }
+                let mut count = buf.len();
+                if count > from.len() - offset {
+                    count = from.len() - offset;
+                }
+                buf[0..count].copy_from_slice(&from[offset..offset + count]);
+                return Ok(count);
+            };
+        }
+
+        macro_rules! define_struct {
+            ($name:ident) => {
+                #[repr(transparent)]
+                #[allow(non_snake_case)]
+                #[allow(non_camel_case_types)]
+                struct $name {
+                    header: SdtHeader,
+                }
+
+                unsafe impl acpi::AcpiTable for $name {
+                    const SIGNATURE: acpi::sdt::Signature = acpi::sdt::Signature::$name;
+                    fn header(&self) -> &acpi::sdt::SdtHeader {
+                        return &self.header;
+                    }
+                }
+            };
+        }
+
+        macro_rules! handle {
+            ($name: ident, $tables: expr) => {
+                define_struct!($name);
+                let table = $tables.find_entire_table::<$name>().map_err(|e| {
+                    kwarn!(
+                        "AttrAcpiTable::read(): failed to find table. name: {}, error: {:?}",
+                        self.name,
+                        e
+                    );
+                    SystemError::ENODEV
+                })?;
+
+                copy_data!(table);
+            };
+        }
+
+        let tables = acpi_manager().tables().unwrap();
+        match self.name.as_str() {
+            "RSDT" => {
+                handle!(RSDT, tables);
+            }
+            "XSDT" => {
+                handle!(XSDT, tables);
+            }
+            "FACP" => {
+                handle!(FADT, tables);
+            }
+            "HPET" => {
+                handle!(HPET, tables);
+            }
+            "APIC" => {
+                handle!(MADT, tables);
+            }
+            "MCFG" => {
+                handle!(MCFG, tables);
+            }
+            "SSDT" => {
+                handle!(SSDT, tables);
+            }
+            "BERT" => {
+                handle!(BERT, tables);
+            }
+            "BGRT" => {
+                handle!(BGRT, tables);
+            }
+            "CPEP" => {
+                handle!(CPEP, tables);
+            }
+            "DSDT" => {
+                handle!(DSDT, tables);
+            }
+            "ECDT" => {
+                handle!(ECDT, tables);
+            }
+            "EINJ" => {
+                handle!(EINJ, tables);
+            }
+            "ERST" => {
+                handle!(ERST, tables);
+            }
+            "FACS" => {
+                handle!(FACS, tables);
+            }
+            "FPDT" => {
+                handle!(FPDT, tables);
+            }
+            "GTDT" => {
+                handle!(GTDT, tables);
+            }
+            "HEST" => {
+                handle!(HEST, tables);
+            }
+            "MSCT" => {
+                handle!(MSCT, tables);
+            }
+            "MPST" => {
+                handle!(MPST, tables);
+            }
+            "NFIT" => {
+                handle!(NFIT, tables);
+            }
+            "PCCT" => {
+                handle!(PCCT, tables);
+            }
+            "PHAT" => {
+                handle!(PHAT, tables);
+            }
+            "PMTT" => {
+                handle!(PMTT, tables);
+            }
+            "PSDT" => {
+                handle!(PSDT, tables);
+            }
+            "RASF" => {
+                handle!(RASF, tables);
+            }
+            "SBST" => {
+                handle!(SBST, tables);
+            }
+            "SDEV" => {
+                handle!(SDEV, tables);
+            }
+            "SLIT" => {
+                handle!(SLIT, tables);
+            }
+            "SRAT" => {
+                handle!(SRAT, tables);
+            }
+            "AEST" => {
+                handle!(AEST, tables);
+            }
+            "BDAT" => {
+                handle!(BDAT, tables);
+            }
+            "CDIT" => {
+                handle!(CDIT, tables);
+            }
+            "CEDT" => {
+                handle!(CEDT, tables);
+            }
+            "CRAT" => {
+                handle!(CRAT, tables);
+            }
+            "CSRT" => {
+                handle!(CSRT, tables);
+            }
+            "DBGP" => {
+                handle!(DBGP, tables);
+            }
+            "DBG2" => {
+                handle!(DBG2, tables);
+            }
+            "DMAR" => {
+                handle!(DMAR, tables);
+            }
+            "DRTM" => {
+                handle!(DRTM, tables);
+            }
+            "ETDT" => {
+                handle!(ETDT, tables);
+            }
+            "IBFT" => {
+                handle!(IBFT, tables);
+            }
+            "IORT" => {
+                handle!(IORT, tables);
+            }
+            "IVRS" => {
+                handle!(IVRS, tables);
+            }
+            "LPIT" => {
+                handle!(LPIT, tables);
+            }
+            "MCHI" => {
+                handle!(MCHI, tables);
+            }
+            "MPAM" => {
+                handle!(MPAM, tables);
+            }
+            "MSDM" => {
+                handle!(MSDM, tables);
+            }
+            "PRMT" => {
+                handle!(PRMT, tables);
+            }
+            "RGRT" => {
+                handle!(RGRT, tables);
+            }
+            "SDEI" => {
+                handle!(SDEI, tables);
+            }
+            "SLIC" => {
+                handle!(SLIC, tables);
+            }
+            "SPCR" => {
+                handle!(SPCR, tables);
+            }
+            "SPMI" => {
+                handle!(SPMI, tables);
+            }
+            "STAO" => {
+                handle!(STAO, tables);
+            }
+            "SVKL" => {
+                handle!(SVKL, tables);
+            }
+            "TCPA" => {
+                handle!(TCPA, tables);
+            }
+            "TPM2" => {
+                handle!(TPM2, tables);
+            }
+            "UEFI" => {
+                handle!(UEFI, tables);
+            }
+            "WAET" => {
+                handle!(WAET, tables);
+            }
+            "WDAT" => {
+                handle!(WDAT, tables);
+            }
+            "WDRT" => {
+                handle!(WDRT, tables);
+            }
+            "WPBT" => {
+                handle!(WPBT, tables);
+            }
+            "WSMT" => {
+                handle!(WSMT, tables);
+            }
+            "XENV" => {
+                handle!(XENV, tables);
+            }
+
+            _ => {
+                kerror!("AttrAcpiTable::read(): unknown table. name: {}", self.name);
+                return Err(SystemError::ENODEV);
+            }
+        };
+    }
+
+    fn size(&self) -> usize {
+        return self.size;
+    }
+}

+ 1 - 0
kernel/src/driver/base/device/bus.rs

@@ -97,6 +97,7 @@ impl From<BusState> for DeviceState {
 /// https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/device/bus.h#84
 pub trait Bus: Debug + Send + Sync {
     fn name(&self) -> String;
+    /// Used for subsystems to enumerate devices like ("foo%u", dev->id).
     fn dev_name(&self) -> String;
     fn root_device(&self) -> Option<Arc<dyn Device>> {
         None

+ 32 - 0
kernel/src/driver/base/kobject.rs

@@ -161,6 +161,20 @@ impl SysFSOps for KObjectSysFSOps {
 pub struct KObjectManager;
 
 impl KObjectManager {
+    #[allow(dead_code)]
+    pub fn init_and_add_kobj(
+        kobj: Arc<dyn KObject>,
+        join_kset: Option<Arc<KSet>>,
+    ) -> Result<(), SystemError> {
+        Self::kobj_init(&kobj);
+        Self::add_kobj(kobj, join_kset)
+    }
+
+    #[allow(dead_code)]
+    pub fn kobj_init(kobj: &Arc<dyn KObject>) {
+        kobj.set_kobj_type(Some(&DynamicKObjKType));
+    }
+
     pub fn add_kobj(
         kobj: Arc<dyn KObject>,
         join_kset: Option<Arc<KSet>>,
@@ -212,3 +226,21 @@ impl KObjectManager {
         return Ok(());
     }
 }
+
+/// 动态创建的kobject对象的ktype
+#[derive(Debug)]
+pub struct DynamicKObjKType;
+
+impl KObjType for DynamicKObjKType {
+    fn release(&self, kobj: Arc<dyn KObject>) {
+        kdebug!("DynamicKObjKType::release() kobj:{:?}", kobj.name());
+    }
+
+    fn sysfs_ops(&self) -> Option<&dyn SysFSOps> {
+        Some(&KObjectSysFSOps)
+    }
+
+    fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
+        None
+    }
+}

+ 7 - 21
kernel/src/driver/base/kset.rs

@@ -7,16 +7,13 @@ use alloc::{
 use core::hash::Hash;
 
 use crate::{
-    filesystem::{
-        kernfs::KernFSInode,
-        sysfs::{AttributeGroup, SysFSOps},
-    },
+    filesystem::kernfs::KernFSInode,
     libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
     syscall::SystemError,
 };
 
 use super::kobject::{
-    KObjType, KObject, KObjectManager, KObjectState, KObjectSysFSOps, LockedKObjectState,
+    DynamicKObjKType, KObjType, KObject, KObjectManager, KObjectState, LockedKObjectState,
 };
 
 #[derive(Debug)]
@@ -164,11 +161,11 @@ impl KObject for KSet {
     }
 
     fn kobj_type(&self) -> Option<&'static dyn KObjType> {
-        Some(&KSetKObjType)
+        self.inner.read().ktype
     }
 
-    fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
-        todo!("KSet::set_kobj_type")
+    fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
+        self.inner.write().ktype = ktype;
     }
 
     fn kset(&self) -> Option<Arc<KSet>> {
@@ -208,6 +205,7 @@ impl KSetParentData {
 struct InnerKSet {
     kern_inode: Option<Arc<KernFSInode>>,
     name: String,
+    ktype: Option<&'static dyn KObjType>,
 }
 
 impl InnerKSet {
@@ -215,19 +213,7 @@ impl InnerKSet {
         Self {
             kern_inode: None,
             name,
+            ktype: Some(&DynamicKObjKType),
         }
     }
 }
-
-#[derive(Debug)]
-pub struct KSetKObjType;
-
-impl KObjType for KSetKObjType {
-    fn sysfs_ops(&self) -> Option<&dyn SysFSOps> {
-        Some(&KObjectSysFSOps)
-    }
-
-    fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
-        None
-    }
-}

+ 66 - 51
kernel/src/driver/multiboot2/multiboot2.c

@@ -2,37 +2,52 @@
 
 #include <common/glib.h>
 #include <common/kprint.h>
-uintptr_t multiboot2_boot_info_addr;
-unsigned int multiboot2_magic;
+// uintptr_t multiboot2_boot_info_addr;
+// unsigned int multiboot2_magic;
 unsigned int multiboot2_boot_info_size;
 
-bool multiboot2_init(void)
+#define MBI_RAW_MAX_SIZE 409600
+// 由于启动时传递的mb2 info所在的地址,在内存管理初始化之后会被覆盖,所以需要将其拷贝到一个固定的位置
+static uint8_t mbi_raw[MBI_RAW_MAX_SIZE] = {0};
+bool multiboot2_init(uint64_t mb2_info_paddr, uint32_t mb2_magic)
 {
-    uintptr_t *addr = (uintptr_t *)multiboot2_boot_info_addr;
-    if (multiboot2_magic != MULTIBOOT2_BOOTLOADER_MAGIC)
-        return false;
-    // addr+0 处保存了大小
-    multiboot2_boot_info_size = *(unsigned int *)addr;
-    return true;
+  uint64_t vaddr = phys_2_virt(mb2_info_paddr);
+  if (mb2_magic != MULTIBOOT2_BOOTLOADER_MAGIC)
+    return false;
+  // vaddr+0 处保存了大小
+  multiboot2_boot_info_size = *(uint32_t *)vaddr;
+  if (multiboot2_boot_info_size > MBI_RAW_MAX_SIZE)
+    return false;
+
+  memcpy((void *)mbi_raw, (void *)vaddr, multiboot2_boot_info_size);
+  
+  return true;
 }
 
 void multiboot2_iter(bool (*_fun)(const struct iter_data_t *, void *, unsigned int *),
                      void *data, unsigned int *count)
 {
+  // kdebug("multiboot2_boot_info_addr=%#018lx", multiboot2_boot_info_addr);
 
-    uintptr_t addr = multiboot2_boot_info_addr;
-    // 接下来的第8字节开始,为 tag 信息
-    struct iter_data_t *tag = (struct iter_data_t *)((void *)addr + 8);
-    for (; tag->type != MULTIBOOT_TAG_TYPE_END;
-         tag = (struct iter_data_t *)((uint8_t *)tag + ALIGN(tag->size, 8)))
-    {
+  // uintptr_t addr = multiboot2_boot_info_addr;
 
-        if (_fun(tag, data, count) == true)
-        {
-            return;
-        }
+  // for(int i=0;i<8192;i++)
+  // {
+  //   mbi_raw[i] = ((uint8_t *)multiboot2_boot_info_addr)[i];
+  // }
+  uint8_t * addr = mbi_raw;
+  // 接下来的第8字节开始,为 tag 信息
+  struct iter_data_t *tag = (struct iter_data_t *)((void *)addr + 8);
+  for (; tag->type != MULTIBOOT_TAG_TYPE_END;
+       tag = (struct iter_data_t *)((uint8_t *)tag + ALIGN(tag->size, 8)))
+  {
+
+    if (_fun(tag, data, count) == true)
+    {
+      return;
     }
-    return;
+  }
+  return;
 }
 
 // 读取 grub2 传递的物理内存信息,保存到 e820map_t 结构体中
@@ -55,21 +70,21 @@ void multiboot2_iter(bool (*_fun)(const struct iter_data_t *, void *, unsigned i
  */
 bool multiboot2_get_memory(const struct iter_data_t *_iter_data, void *data, unsigned int *count)
 {
-    if (_iter_data->type != MULTIBOOT_TAG_TYPE_MMAP)
-        return false;
-
-    struct multiboot_mmap_entry_t *resource = (struct multiboot_mmap_entry_t *)data;
-    struct multiboot_mmap_entry_t *mmap = ((struct multiboot_tag_mmap_t *)_iter_data)->entries;
-    *count = 0;
-    for (; (uint8_t *)mmap < (uint8_t *)_iter_data + _iter_data->size;
-         mmap = (struct multiboot_mmap_entry_t *)((uint8_t *)mmap + ((struct multiboot_tag_mmap_t *)_iter_data)->entry_size))
-    {
-        *resource = *mmap;
-        // 将指针进行增加
-        resource = (struct multiboot_mmap_entry_t *)((uint8_t *)resource + ((struct multiboot_tag_mmap_t *)_iter_data)->entry_size);
-        ++(*count);
-    }
-    return true;
+  if (_iter_data->type != MULTIBOOT_TAG_TYPE_MMAP)
+    return false;
+
+  struct multiboot_mmap_entry_t *resource = (struct multiboot_mmap_entry_t *)data;
+  struct multiboot_mmap_entry_t *mmap = ((struct multiboot_tag_mmap_t *)_iter_data)->entries;
+  *count = 0;
+  for (; (uint8_t *)mmap < (uint8_t *)_iter_data + _iter_data->size;
+       mmap = (struct multiboot_mmap_entry_t *)((uint8_t *)mmap + ((struct multiboot_tag_mmap_t *)_iter_data)->entry_size))
+  {
+    *resource = *mmap;
+    // 将指针进行增加
+    resource = (struct multiboot_mmap_entry_t *)((uint8_t *)resource + ((struct multiboot_tag_mmap_t *)_iter_data)->entry_size);
+    ++(*count);
+  }
+  return true;
 }
 
 /**
@@ -81,10 +96,10 @@ bool multiboot2_get_memory(const struct iter_data_t *_iter_data, void *data, uns
 bool multiboot2_get_VBE_info(const struct iter_data_t *_iter_data, void *data, unsigned int *reserved)
 {
 
-    if (_iter_data->type != MULTIBOOT_TAG_TYPE_VBE)
-        return false;
-    *(struct multiboot_tag_vbe_t *)data = *(struct multiboot_tag_vbe_t *)_iter_data;
-    return true;
+  if (_iter_data->type != MULTIBOOT_TAG_TYPE_VBE)
+    return false;
+  *(struct multiboot_tag_vbe_t *)data = *(struct multiboot_tag_vbe_t *)_iter_data;
+  return true;
 }
 
 /**
@@ -95,10 +110,10 @@ bool multiboot2_get_VBE_info(const struct iter_data_t *_iter_data, void *data, u
  */
 bool multiboot2_get_Framebuffer_info(const struct iter_data_t *_iter_data, void *data, unsigned int *reserved)
 {
-    if (_iter_data->type != MULTIBOOT_TAG_TYPE_FRAMEBUFFER)
-        return false;
-    *(struct multiboot_tag_framebuffer_info_t *)data = *(struct multiboot_tag_framebuffer_info_t *)_iter_data;
-    return true;
+  if (_iter_data->type != MULTIBOOT_TAG_TYPE_FRAMEBUFFER)
+    return false;
+  *(struct multiboot_tag_framebuffer_info_t *)data = *(struct multiboot_tag_framebuffer_info_t *)_iter_data;
+  return true;
 }
 
 /**
@@ -111,12 +126,12 @@ bool multiboot2_get_Framebuffer_info(const struct iter_data_t *_iter_data, void
  */
 bool multiboot2_get_acpi_old_RSDP(const struct iter_data_t *_iter_data, void *data, unsigned int *reserved)
 {
-    if (_iter_data->type != MULTIBOOT_TAG_TYPE_ACPI_OLD)
-        return false;
+  if (_iter_data->type != MULTIBOOT_TAG_TYPE_ACPI_OLD)
+    return false;
 
-    *(struct multiboot_tag_old_acpi_t *)data = *(struct multiboot_tag_old_acpi_t *)_iter_data;
+  *(struct multiboot_tag_old_acpi_t *)data = *(struct multiboot_tag_old_acpi_t *)_iter_data;
 
-    return true;
+  return true;
 }
 
 /**
@@ -129,8 +144,8 @@ bool multiboot2_get_acpi_old_RSDP(const struct iter_data_t *_iter_data, void *da
  */
 bool multiboot2_get_acpi_new_RSDP(const struct iter_data_t *_iter_data, void *data, unsigned int *reserved)
 {
-    if (_iter_data->type != MULTIBOOT_TAG_TYPE_ACPI_NEW)
-        return false;
-    *(struct multiboot_tag_new_acpi_t *)data = *(struct multiboot_tag_new_acpi_t *)_iter_data;
-    return true;
+  if (_iter_data->type != MULTIBOOT_TAG_TYPE_ACPI_NEW)
+    return false;
+  *(struct multiboot_tag_new_acpi_t *)data = *(struct multiboot_tag_new_acpi_t *)_iter_data;
+  return true;
 }

+ 1 - 4
kernel/src/driver/multiboot2/multiboot2.h

@@ -26,9 +26,6 @@
  * @brief MULTIBOOT2 接口抽象
  */
 
-extern unsigned int multiboot2_magic;
-extern uintptr_t multiboot2_boot_info_addr;
-
 /*  How many bytes from the start of the file we search for the header. */
 static const unsigned int MULTIBOOT_SEARCH = 32768;
 static const unsigned int MULTIBOOT_HEADER_ALIGN = 8;
@@ -416,7 +413,7 @@ struct iter_data_t
  * @return true            成功
  * @return false           失败
  */
-static bool multiboot2_init(void);
+bool multiboot2_init(uint64_t mb2_info_paddr, uint32_t mb2_magic);
 
 /**
  * @brief 迭代器

+ 17 - 7
kernel/src/filesystem/kernfs/mod.rs

@@ -439,7 +439,7 @@ impl KernFSInode {
             return Err(SystemError::ENOTDIR);
         }
 
-        return self.inner_create(name, KernInodeType::Dir, mode, private_data, callback);
+        return self.inner_create(name, KernInodeType::Dir, mode, 0, private_data, callback);
     }
 
     /// 在当前inode下增加文件
@@ -448,9 +448,11 @@ impl KernFSInode {
     ///
     /// - `name`:文件名称
     /// - `mode`:文件权限
+    /// - `size`:文件大小(如果不指定,则默认为4096)
     /// - `private_data`:文件私有数据
     /// - `callback`:文件回调函数
     ///
+    ///
     /// ## 返回值
     ///
     /// - 成功:文件inode
@@ -461,6 +463,7 @@ impl KernFSInode {
         &self,
         name: String,
         mode: ModeType,
+        size: Option<usize>,
         private_data: Option<KernInodePrivateData>,
         callback: Option<&'static dyn KernFSCallback>,
     ) -> Result<Arc<KernFSInode>, SystemError> {
@@ -468,7 +471,15 @@ impl KernFSInode {
             return Err(SystemError::ENOTDIR);
         }
 
-        return self.inner_create(name, KernInodeType::File, mode, private_data, callback);
+        let size = size.unwrap_or(4096);
+        return self.inner_create(
+            name,
+            KernInodeType::File,
+            mode,
+            size,
+            private_data,
+            callback,
+        );
     }
 
     fn inner_create(
@@ -476,21 +487,19 @@ impl KernFSInode {
         name: String,
         file_type: KernInodeType,
         mode: ModeType,
+        mut size: usize,
         private_data: Option<KernInodePrivateData>,
         callback: Option<&'static dyn KernFSCallback>,
     ) -> Result<Arc<KernFSInode>, SystemError> {
-        let size;
         match file_type {
             KernInodeType::Dir | KernInodeType::SymLink => {
                 size = 0;
             }
-            KernInodeType::File => {
-                size = 4096;
-            }
+            _ => {}
         }
 
         let metadata = Metadata {
-            size,
+            size: size as i64,
             mode,
             uid: 0,
             gid: 0,
@@ -570,6 +579,7 @@ impl KernFSInode {
             name,
             KernInodeType::SymLink,
             ModeType::S_IFLNK | ModeType::from_bits_truncate(0o777),
+            0,
             None,
             None,
         )?;

+ 143 - 17
kernel/src/filesystem/sysfs/file.rs

@@ -19,23 +19,36 @@ use crate::{
     syscall::SystemError,
 };
 
-use super::{Attribute, SysFS, SysFSKernPrivateData};
+use super::{Attribute, BinAttribute, SysFS, SysFSKernPrivateData};
 
 #[derive(Debug)]
 pub struct SysKernFilePriv {
     attribute: Option<&'static dyn Attribute>,
+    /// bin attribute和attribute二选一,只能有一个为Some
+    bin_attribute: Option<Arc<dyn BinAttribute>>,
     /// 当前文件对应的kobject
     kobj: Weak<dyn KObject>,
-    // todo: 增加bin attribute,它和attribute二选一,只能有一个为Some
 }
 
 impl SysKernFilePriv {
-    pub fn new(kobj: &Arc<dyn KObject>, attribute: Option<&'static dyn Attribute>) -> Self {
-        if attribute.is_none() {
-            panic!("attribute can't be None");
+    pub fn new(
+        kobj: &Arc<dyn KObject>,
+        attribute: Option<&'static dyn Attribute>,
+        bin_attribute: Option<Arc<dyn BinAttribute>>,
+    ) -> Self {
+        if attribute.is_none() && bin_attribute.is_none() {
+            panic!("attribute and bin_attribute can't be both None");
+        }
+        if attribute.is_some() && bin_attribute.is_some() {
+            panic!("attribute and bin_attribute can't be both Some");
         }
+
         let kobj = Arc::downgrade(kobj);
-        return Self { kobj, attribute };
+        return Self {
+            kobj,
+            attribute,
+            bin_attribute,
+        };
     }
 
     #[allow(dead_code)]
@@ -44,18 +57,41 @@ impl SysKernFilePriv {
         self.attribute
     }
 
-    pub fn callback_read(&self, buf: &mut [u8]) -> Result<usize, SystemError> {
-        let attribute = self.attribute.ok_or(SystemError::EINVAL)?;
-        // 当前文件所指向的kobject已经被释放
-        let kobj = self.kobj.upgrade().expect("kobj is None");
-        return attribute.show(kobj, buf);
+    pub fn callback_read(&self, buf: &mut [u8], offset: usize) -> Result<usize, SystemError> {
+        if let Some(attribute) = self.attribute {
+            // 当前文件所指向的kobject已经被释放
+            let kobj = self.kobj.upgrade().expect("kobj is None");
+            let len = attribute.show(kobj, buf)?;
+            if offset > 0 {
+                if len <= offset {
+                    return Ok(0);
+                }
+                let len = len - offset;
+                buf.copy_within(offset..offset + len, 0);
+                buf[len] = 0;
+            }
+            return Ok(len);
+        } else if let Some(bin_attribute) = self.bin_attribute.as_ref() {
+            // 当前文件所指向的kobject已经被释放
+            let kobj = self.kobj.upgrade().expect("kobj is None");
+            return bin_attribute.read(kobj, buf, offset);
+        } else {
+            panic!("attribute and bin_attribute can't be both None");
+        }
     }
 
-    pub fn callback_write(&self, buf: &[u8]) -> Result<usize, SystemError> {
-        let attribute = self.attribute.ok_or(SystemError::EINVAL)?;
-        // 当前文件所指向的kobject已经被释放
-        let kobj = self.kobj.upgrade().expect("kobj is None");
-        return attribute.store(kobj, buf);
+    pub fn callback_write(&self, buf: &[u8], offset: usize) -> Result<usize, SystemError> {
+        if let Some(attribute) = self.attribute {
+            // 当前文件所指向的kobject已经被释放
+            let kobj = self.kobj.upgrade().expect("kobj is None");
+            return attribute.store(kobj, buf);
+        } else if let Some(bin_attribute) = self.bin_attribute.as_ref() {
+            // 当前文件所指向的kobject已经被释放
+            let kobj = self.kobj.upgrade().expect("kobj is None");
+            return bin_attribute.write(kobj, buf, offset);
+        } else {
+            panic!("attribute and bin_attribute can't be both None");
+        }
     }
 }
 
@@ -115,10 +151,11 @@ impl SysFS {
             kern_callback = &PreallocKFOpsEmpty;
         }
 
-        let sys_priv = SysFSKernPrivateData::File(SysKernFilePriv::new(&kobj, Some(attr)));
+        let sys_priv = SysFSKernPrivateData::File(SysKernFilePriv::new(&kobj, Some(attr), None));
         let r = parent.add_file(
             attr.name().to_string(),
             mode.bitand(ModeType::from_bits_truncate(0o777)),
+            Some(4096),
             Some(KernInodePrivateData::SysFS(sys_priv)),
             Some(kern_callback),
         );
@@ -155,6 +192,95 @@ impl SysFS {
             }
         }
     }
+
+    /// 在sysfs中,为指定的kobject创建一个动态申请的bin属性文件
+    ///
+    /// ## 参数
+    ///
+    /// - `kobj` 要创建属性文件的kobject
+    /// - `attr` 属性
+    ///
+    /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/file.c#558
+    pub fn create_bin_file(
+        &self,
+        kobj: &Arc<dyn KObject>,
+        attr: &Arc<dyn BinAttribute>,
+    ) -> Result<(), SystemError> {
+        let inode = kobj.inode().ok_or(SystemError::EINVAL)?;
+        return self.add_bin_file_with_mode(&inode, attr, attr.mode());
+    }
+
+    /// 在sysfs中删除某个kobject的bin属性文件
+    ///
+    /// 如果属性文件不存在,则发出一个警告
+    #[allow(dead_code)]
+    pub fn remove_bin_file(&self, kobj: &Arc<dyn KObject>, attr: &Arc<dyn BinAttribute>) {
+        let parent = kobj.inode();
+
+        if let Some(parent) = parent {
+            let r = parent.remove(attr.name());
+            if unlikely(r.is_err()) {
+                kwarn!(
+                    "failed to remove file '{}' from '{}'",
+                    attr.name(),
+                    kobj.name()
+                );
+            }
+        }
+    }
+
+    /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/file.c#304
+    pub(super) fn add_bin_file_with_mode(
+        &self,
+        parent: &Arc<KernFSInode>,
+        attr: &Arc<dyn BinAttribute>,
+        mode: ModeType,
+    ) -> Result<(), SystemError> {
+        let x = parent.private_data_mut();
+        let kobj: Arc<dyn KObject>;
+        if let Some(KernInodePrivateData::SysFS(SysFSKernPrivateData::Dir(dt))) = x.as_ref() {
+            kobj = dt.kobj().unwrap();
+        } else {
+            drop(x);
+            let path = self.kernfs_path(parent);
+            panic!("parent '{path}' is not a dir");
+        }
+        drop(x);
+
+        let kern_callback: &'static dyn KernFSCallback;
+        let bin_support = attr.support_battr();
+
+        if bin_support.contains(SysFSOpsSupport::READ)
+            && bin_support.contains(SysFSOpsSupport::WRITE)
+        {
+            kern_callback = &PreallocKFOpsRW;
+        } else if bin_support.contains(SysFSOpsSupport::READ) {
+            kern_callback = &PreallocKFOpsReadOnly;
+        } else if bin_support.contains(SysFSOpsSupport::WRITE) {
+            kern_callback = &PreallocKFOpsWriteOnly;
+        } else {
+            kern_callback = &PreallocKFOpsEmpty;
+        }
+
+        let sys_priv =
+            SysFSKernPrivateData::File(SysKernFilePriv::new(&kobj, None, Some(attr.clone())));
+        let r = parent.add_file(
+            attr.name().to_string(),
+            mode.bitand(ModeType::from_bits_truncate(0o777)),
+            Some(attr.size()),
+            Some(KernInodePrivateData::SysFS(sys_priv)),
+            Some(kern_callback),
+        );
+
+        if let Err(e) = r {
+            if e == SystemError::EEXIST {
+                self.warn_duplicate(parent, attr.name());
+            }
+
+            return Err(e);
+        }
+        return Ok(());
+    }
 }
 
 #[derive(Debug)]

+ 37 - 12
kernel/src/filesystem/sysfs/mod.rs

@@ -69,15 +69,8 @@ impl SysFSKernPrivateData {
     pub fn callback_read(&self, buf: &mut [u8], offset: usize) -> Result<usize, SystemError> {
         match self {
             SysFSKernPrivateData::File(file) => {
-                let len = file.callback_read(buf)?;
-                if offset > 0 {
-                    if len <= offset {
-                        return Ok(0);
-                    }
-                    let len = len - offset;
-                    buf.copy_within(offset..offset + len, 0);
-                    buf[len] = 0;
-                }
+                let len = file.callback_read(buf, offset)?;
+
                 return Ok(len);
             }
             _ => {
@@ -87,10 +80,10 @@ impl SysFSKernPrivateData {
     }
 
     #[inline(always)]
-    pub fn callback_write(&self, buf: &[u8], _offset: usize) -> Result<usize, SystemError> {
+    pub fn callback_write(&self, buf: &[u8], offset: usize) -> Result<usize, SystemError> {
         match self {
             SysFSKernPrivateData::File(file) => {
-                return file.callback_write(buf);
+                return file.callback_write(buf, offset);
             }
             _ => {
                 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
@@ -114,7 +107,7 @@ pub trait AttributeGroup: Debug + Send + Sync {
     ///
     /// 如果返回Some,则使用返回的权限。
     /// 如果要标识属性不可见,则返回Some(ModeType::empty())
-    fn is_visible(&self, kobj: Arc<dyn KObject>, attr: &dyn Attribute) -> Option<ModeType>;
+    fn is_visible(&self, kobj: Arc<dyn KObject>, attr: &'static dyn Attribute) -> Option<ModeType>;
 }
 
 /// sysfs文件的属性
@@ -133,12 +126,40 @@ pub trait Attribute: Debug + Send + Sync {
     }
 }
 
+pub trait BinAttribute: Attribute {
+    fn support_battr(&self) -> SysFSOpsSupport;
+
+    fn write(
+        &self,
+        _kobj: Arc<dyn KObject>,
+        _buf: &[u8],
+        _offset: usize,
+    ) -> Result<usize, SystemError> {
+        return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
+    }
+
+    fn read(
+        &self,
+        _kobj: Arc<dyn KObject>,
+        _buf: &mut [u8],
+        _offset: usize,
+    ) -> Result<usize, SystemError> {
+        return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
+    }
+
+    fn size(&self) -> usize;
+}
+
 pub trait SysFSOps: Debug {
     /// 获取当前文件的支持的操作
     fn support(&self, attr: &dyn Attribute) -> SysFSOpsSupport {
         return attr.support();
     }
 
+    fn support_battr(&self, attr: &Arc<dyn BinAttribute>) -> SysFSOpsSupport {
+        return attr.support();
+    }
+
     fn show(
         &self,
         kobj: Arc<dyn KObject>,
@@ -156,8 +177,12 @@ pub trait SysFSOps: Debug {
 
 bitflags! {
     pub struct SysFSOpsSupport: u8{
+        // === for attribute ===
         const SHOW = 1 << 0;
         const STORE = 1 << 1;
+        // === for bin attribute ===
+        const READ = 1 << 2;
+        const WRITE = 1 << 3;
     }
 }
 

+ 1 - 1
kernel/src/filesystem/vfs/syscall.rs

@@ -693,7 +693,7 @@ impl Syscall {
         kstat.rdev = metadata.raw_dev as i64;
         kstat.mode = metadata.mode;
         match file.lock().file_type() {
-            FileType::File => kstat.mode.insert(ModeType::S_IFMT),
+            FileType::File => kstat.mode.insert(ModeType::S_IFREG),
             FileType::Dir => kstat.mode.insert(ModeType::S_IFDIR),
             FileType::BlockDevice => kstat.mode.insert(ModeType::S_IFBLK),
             FileType::CharDevice => kstat.mode.insert(ModeType::S_IFCHR),

+ 6 - 8
kernel/src/main.c

@@ -71,7 +71,6 @@ void reload_idt()
 void system_initialize()
 {
     rs_init_before_mem_init();
-
     // 重新加载gdt和idt
     ul tss_item_addr = (ul)phys_2_virt(0x7c00);
 
@@ -82,13 +81,12 @@ void system_initialize()
     rs_load_current_core_tss();
 
     cpu_core_info[0].stack_start = _stack_start;
-
+    
     // 初始化中断描述符表
     sys_vector_init();
     //  初始化内存管理单元
     // mm_init();
     rs_mm_init();
-
     // 内存管理单元初始化完毕后,需要立即重新初始化显示驱动。
     // 原因是,系统启动初期,framebuffer被映射到48M地址处,
     // mm初始化完毕后,若不重新初始化显示驱动,将会导致错误的数据写入内存,从而造成其他模块崩溃
@@ -101,7 +99,10 @@ void system_initialize()
     rs_init_intertrait();
     // kinfo("vaddr:%#018lx", video_frame_buffer_info.vaddr);
     io_mfence();
-
+    vfs_init();
+    
+    rs_driver_init();
+    
     acpi_init();
     io_mfence();
     irq_init();
@@ -124,9 +125,7 @@ void system_initialize()
 
     rs_jiffies_init();
     io_mfence();
-    vfs_init();
     
-    rs_driver_init();
 
     rs_kthread_init();
     io_mfence();
@@ -183,8 +182,7 @@ void Start_Kernel(void)
 
     mb2_info &= 0xffffffff;
     mb2_magic &= 0xffffffff;
-    multiboot2_magic = (uint)mb2_magic;
-    multiboot2_boot_info_addr = mb2_info + PAGE_OFFSET;
+    multiboot2_init(mb2_info, mb2_magic);
     io_mfence();
     system_initialize();
     io_mfence();

+ 50 - 3
kernel/src/mm/c_adapter.rs

@@ -7,7 +7,7 @@ use hashbrown::HashMap;
 
 use crate::{
     arch::mm::LowAddressRemapping,
-    include::bindings::bindings::{gfp_t, PAGE_U_S},
+    include::bindings::bindings::{gfp_t, vm_flags_t, PAGE_U_S},
     kerror,
     libs::{align::page_align_up, spinlock::SpinLock},
     mm::MMArch,
@@ -15,8 +15,8 @@ use crate::{
 };
 
 use super::{
-    allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, no_init::pseudo_map_phys,
-    page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr,
+    allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, mmio_buddy::mmio_pool,
+    no_init::pseudo_map_phys, page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr,
 };
 
 lazy_static! {
@@ -125,3 +125,50 @@ pub unsafe extern "C" fn rs_unmap_at_low_addr() -> usize {
     LowAddressRemapping::unmap_at_low_address(true);
     return 0;
 }
+
+/// @brief 创建一块mmio区域,并将vma绑定到initial_mm
+///
+/// @param size mmio区域的大小(字节)
+///
+/// @param vm_flags 要把vma设置成的标志
+///
+/// @param res_vaddr 返回值-分配得到的虚拟地址
+///
+/// @param res_length 返回值-分配的虚拟地址空间长度
+///
+/// @return int 错误码
+#[no_mangle]
+unsafe extern "C" fn rs_mmio_create(
+    size: u32,
+    _vm_flags: vm_flags_t,
+    res_vaddr: *mut u64,
+    res_length: *mut u64,
+) -> i32 {
+    // kdebug!("mmio_create");
+    let r = mmio_pool().create_mmio(size as usize);
+    if r.is_err() {
+        return r.unwrap_err().to_posix_errno();
+    }
+    let space_guard = r.unwrap();
+    *res_vaddr = space_guard.vaddr().data() as u64;
+    *res_length = space_guard.size() as u64;
+    // 由于space_guard drop的时候会自动释放内存,所以这里要忽略它的释放
+    core::mem::forget(space_guard);
+    return 0;
+}
+
+/// @brief 取消mmio的映射并将地址空间归还到buddy中
+///
+/// @param vaddr 起始的虚拟地址
+///
+/// @param length 要归还的地址空间的长度
+///
+/// @return Ok(i32) 成功返回0
+///
+/// @return Err(i32) 失败返回错误码
+#[no_mangle]
+pub unsafe extern "C" fn rs_mmio_release(vaddr: u64, length: u64) -> i32 {
+    return mmio_pool()
+        .release_mmio(VirtAddr::new(vaddr as usize), length as usize)
+        .unwrap_or_else(|err| err.to_posix_errno());
+}

+ 2 - 2
kernel/src/mm/mmio.h

@@ -1,5 +1,5 @@
 #pragma once
 #include "mm.h"
 
-extern void mmio_create(uint32_t size, uint64_t vm_flagsu, uint64_t* res_vaddr, uint64_t* res_length);
-extern int mmio_release(int vaddr, int length);
+extern int rs_mmio_create(uint32_t size, uint64_t vm_flags, uint64_t* res_vaddr, uint64_t* res_length);
+extern int rs_mmio_release(uint64_t vaddr, uint64_t length);

+ 2 - 48
kernel/src/mm/mmio_buddy.rs

@@ -3,7 +3,7 @@ use crate::mm::kernel_mapper::KernelMapper;
 use crate::process::ProcessManager;
 use crate::syscall::SystemError;
 use crate::{
-    include::bindings::bindings::{vm_flags_t, PAGE_1G_SHIFT, PAGE_4K_SHIFT, PAGE_4K_SIZE},
+    include::bindings::bindings::{PAGE_1G_SHIFT, PAGE_4K_SHIFT, PAGE_4K_SIZE},
     kdebug,
     mm::{MMArch, MemoryManagementArch},
 };
@@ -520,7 +520,7 @@ impl MmioBuddyMemPool {
     /// @return Ok(i32) 成功返回0
     ///
     /// @return Err(SystemError) 失败返回错误码
-    fn release_mmio(&self, vaddr: VirtAddr, length: usize) -> Result<i32, SystemError> {
+    pub fn release_mmio(&self, vaddr: VirtAddr, length: usize) -> Result<i32, SystemError> {
         assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
         assert!(length & (MMArch::PAGE_SIZE - 1) == 0);
         if vaddr < self.pool_start_addr
@@ -707,49 +707,3 @@ pub fn mmio_init() {
 
     kinfo!("MMIO buddy memory pool init done");
 }
-/// @brief 创建一块mmio区域,并将vma绑定到initial_mm
-///
-/// @param size mmio区域的大小(字节)
-///
-/// @param vm_flags 要把vma设置成的标志
-///
-/// @param res_vaddr 返回值-分配得到的虚拟地址
-///
-/// @param res_length 返回值-分配的虚拟地址空间长度
-///
-/// @return int 错误码
-#[no_mangle]
-pub unsafe extern "C" fn mmio_create(
-    size: u32,
-    _vm_flags: vm_flags_t,
-    res_vaddr: *mut u64,
-    res_length: *mut u64,
-) -> i32 {
-    // kdebug!("mmio_create");
-    let r = mmio_pool().create_mmio(size as usize);
-    if r.is_err() {
-        return r.unwrap_err().to_posix_errno();
-    }
-    let space_guard = r.unwrap();
-    *res_vaddr = space_guard.vaddr().data() as u64;
-    *res_length = space_guard.size() as u64;
-    // 由于space_guard drop的时候会自动释放内存,所以这里要忽略它的释放
-    core::mem::forget(space_guard);
-    return 0;
-}
-
-/// @brief 取消mmio的映射并将地址空间归还到buddy中
-///
-/// @param vaddr 起始的虚拟地址
-///
-/// @param length 要归还的地址空间的长度
-///
-/// @return Ok(i32) 成功返回0
-///
-/// @return Err(i32) 失败返回错误码
-#[no_mangle]
-pub unsafe extern "C" fn mmio_release(vaddr: u64, length: u64) -> i32 {
-    return mmio_pool()
-        .release_mmio(VirtAddr::new(vaddr as usize), length as usize)
-        .unwrap_or_else(|err| err.to_posix_errno());
-}