From 7eda31b2f07c6ef41dc0d2bd13051f0fce5e5976 Mon Sep 17 00:00:00 2001 From: LoGin Date: Sun, 22 Oct 2023 22:00:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9C=A8Sysfs=E4=B8=AD=E5=BC=95=E5=85=A5ACPI?= =?UTF-8?q?=20Firmware=20(#405)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - bugfix: multiboot2启动的信息因为没及时转存导致后面无法从其中进行查询的bug - feature: 把acpi表、acpi bus加入sysfs --- kernel/Cargo.toml | 3 +- kernel/src/driver/acpi/acpi.c | 8 +- kernel/src/driver/acpi/bus.rs | 108 ++++- kernel/src/driver/acpi/c_adapter.rs | 6 +- kernel/src/driver/acpi/mod.rs | 76 +++- kernel/src/driver/acpi/sysfs.rs | 510 ++++++++++++++++++++++ kernel/src/driver/base/device/bus.rs | 1 + kernel/src/driver/base/kobject.rs | 32 ++ kernel/src/driver/base/kset.rs | 28 +- kernel/src/driver/multiboot2/multiboot2.c | 115 ++--- kernel/src/driver/multiboot2/multiboot2.h | 5 +- kernel/src/filesystem/kernfs/mod.rs | 24 +- kernel/src/filesystem/sysfs/file.rs | 160 ++++++- kernel/src/filesystem/sysfs/mod.rs | 49 ++- kernel/src/filesystem/vfs/syscall.rs | 2 +- kernel/src/main.c | 14 +- kernel/src/mm/c_adapter.rs | 53 ++- kernel/src/mm/mmio.h | 4 +- kernel/src/mm/mmio_buddy.rs | 50 +-- 19 files changed, 1044 insertions(+), 204 deletions(-) create mode 100644 kernel/src/driver/acpi/sysfs.rs diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 7f7bedb0..4c539f15 100644 --- a/kernel/Cargo.toml +++ b/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 - diff --git a/kernel/src/driver/acpi/acpi.c b/kernel/src/driver/acpi/acpi.c index 632941a8..ff3cf11f 100644 --- a/kernel/src/driver/acpi/acpi.c +++ b/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; diff --git a/kernel/src/driver/acpi/bus.rs b/kernel/src/driver/acpi/bus.rs index 46f2cac6..4da1e11d 100644 --- a/kernel/src/driver/acpi/bus.rs +++ b/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) + .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 { + let default_weak: Weak = 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))); + 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) -> Result<(), SystemError> { + todo!("acpi_bus: remove") + } + + fn shutdown(&self, _device: &Arc) { + return; + } + + fn resume(&self, _device: &Arc) -> 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, + _driver: &Arc, + ) -> Result { + // todo: 通过acpi来匹配驱动 + return Ok(false); + } + + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1019 + fn probe(&self, _device: &Arc) -> 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 {} diff --git a/kernel/src/driver/acpi/c_adapter.rs b/kernel/src/driver/acpi/c_adapter.rs index b942b977..dfa4d538 100644 --- a/kernel/src/driver/acpi/c_adapter.rs +++ b/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> = 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"); } diff --git a/kernel/src/driver/acpi/mod.rs b/kernel/src/driver/acpi/mod.rs index 4feffc46..1a258a1d 100644 --- a/kernel/src/driver/acpi/mod.rs +++ b/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> = None; +/// `/sys/firmware/acpi`的kset +static mut ACPI_KSET_INSTANCE: Option> = None; #[inline(always)] pub fn acpi_manager() -> &'static AcpiManager { &AcpiManager } +#[inline(always)] +pub fn acpi_kset() -> Arc { + 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 = - unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr.data()) } - .unwrap_or_else(|e| { - panic!("acpi_init(): failed to parse acpi tables, error: {:?}", e) - }); + /// 初始化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..."); - unsafe { - __ACPI_TABLE = Some(acpi_table); - } - kinfo!("Acpi Manager initialized."); - }); + // 初始化`/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 = + 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> { + pub fn tables(&self) -> Option<&'static acpi::AcpiTables> { unsafe { __ACPI_TABLE.as_ref() } } } diff --git a/kernel/src/driver/acpi/sysfs.rs b/kernel/src/driver/acpi/sysfs.rs new file mode 100644 index 00000000..ef55d27c --- /dev/null +++ b/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> = None; +static mut __ACPI_TABLES_KSET_INSTANCE: Option> = None; +static mut __ACPI_TABLES_DATA_KSET_INSTANCE: Option> = None; +static mut __ACPI_TABLES_DYNAMIC_KSET_INSTANCE: Option> = None; +static mut __ACPI_TABLE_ATTR_LIST: Option>>> = None; + +const ACPI_MAX_TABLE_INSTANCES: usize = 999; + +#[inline(always)] +#[allow(dead_code)] +pub fn hotplug_kset() -> Arc { + unsafe { __HOTPLUG_KSET_INSTANCE.clone().unwrap() } +} + +#[inline(always)] +pub fn acpi_tables_kset() -> Arc { + unsafe { __ACPI_TABLES_KSET_INSTANCE.clone().unwrap() } +} + +#[inline(always)] +#[allow(dead_code)] +pub fn acpi_tables_data_kset() -> Arc { + unsafe { __ACPI_TABLES_DATA_KSET_INSTANCE.clone().unwrap() } +} + +#[inline(always)] +#[allow(dead_code)] +pub fn acpi_tables_dynamic_kset() -> Arc { + unsafe { __ACPI_TABLES_DYNAMIC_KSET_INSTANCE.clone().unwrap() } +} + +#[inline(always)] +fn acpi_table_attr_list() -> &'static RwLock>> { + 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; + 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, buf: &mut [u8]) -> Result { + 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, 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), + &(result.clone() as Arc), + )?; + return Ok(result); + } +} + +impl Attribute for AttrAcpiTable { + fn show(&self, _kobj: Arc, _buf: &mut [u8]) -> Result { + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + fn store(&self, _kobj: Arc, _buf: &[u8]) -> Result { + 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, + _buf: &[u8], + _offset: usize, + ) -> Result { + 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, + buf: &mut [u8], + offset: usize, + ) -> Result { + 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; + } +} diff --git a/kernel/src/driver/base/device/bus.rs b/kernel/src/driver/base/device/bus.rs index ad1b0439..de14885a 100644 --- a/kernel/src/driver/base/device/bus.rs +++ b/kernel/src/driver/base/device/bus.rs @@ -97,6 +97,7 @@ impl From 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> { None diff --git a/kernel/src/driver/base/kobject.rs b/kernel/src/driver/base/kobject.rs index 111df93e..279ae934 100644 --- a/kernel/src/driver/base/kobject.rs +++ b/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, + join_kset: Option>, + ) -> Result<(), SystemError> { + Self::kobj_init(&kobj); + Self::add_kobj(kobj, join_kset) + } + + #[allow(dead_code)] + pub fn kobj_init(kobj: &Arc) { + kobj.set_kobj_type(Some(&DynamicKObjKType)); + } + pub fn add_kobj( kobj: Arc, join_kset: Option>, @@ -212,3 +226,21 @@ impl KObjectManager { return Ok(()); } } + +/// 动态创建的kobject对象的ktype +#[derive(Debug)] +pub struct DynamicKObjKType; + +impl KObjType for DynamicKObjKType { + fn release(&self, kobj: Arc) { + 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 + } +} diff --git a/kernel/src/driver/base/kset.rs b/kernel/src/driver/base/kset.rs index 5a1304e0..5c97a5fc 100644 --- a/kernel/src/driver/base/kset.rs +++ b/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> { @@ -208,6 +205,7 @@ impl KSetParentData { struct InnerKSet { kern_inode: Option>, 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 - } -} diff --git a/kernel/src/driver/multiboot2/multiboot2.c b/kernel/src/driver/multiboot2/multiboot2.c index aadda442..eb0a9c5a 100644 --- a/kernel/src/driver/multiboot2/multiboot2.c +++ b/kernel/src/driver/multiboot2/multiboot2.c @@ -2,37 +2,52 @@ #include #include -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; + + // 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) { - - if (_fun(tag, data, count) == true) - { - return; - } + 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; + 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; + 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; } \ No newline at end of file diff --git a/kernel/src/driver/multiboot2/multiboot2.h b/kernel/src/driver/multiboot2/multiboot2.h index f0a31190..f090938e 100644 --- a/kernel/src/driver/multiboot2/multiboot2.h +++ b/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 迭代器 diff --git a/kernel/src/filesystem/kernfs/mod.rs b/kernel/src/filesystem/kernfs/mod.rs index dc194563..cbce18f4 100644 --- a/kernel/src/filesystem/kernfs/mod.rs +++ b/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, private_data: Option, callback: Option<&'static dyn KernFSCallback>, ) -> Result, 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, callback: Option<&'static dyn KernFSCallback>, ) -> Result, 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, )?; diff --git a/kernel/src/filesystem/sysfs/file.rs b/kernel/src/filesystem/sysfs/file.rs index 66833cb1..552d49f1 100644 --- a/kernel/src/filesystem/sysfs/file.rs +++ b/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>, /// 当前文件对应的kobject kobj: Weak, - // todo: 增加bin attribute,它和attribute二选一,只能有一个为Some } impl SysKernFilePriv { - pub fn new(kobj: &Arc, attribute: Option<&'static dyn Attribute>) -> Self { - if attribute.is_none() { - panic!("attribute can't be None"); + pub fn new( + kobj: &Arc, + attribute: Option<&'static dyn Attribute>, + bin_attribute: Option>, + ) -> 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 { - 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 { + 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 { - 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 { + 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, + attr: &Arc, + ) -> 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, attr: &Arc) { + 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, + attr: &Arc, + mode: ModeType, + ) -> Result<(), SystemError> { + let x = parent.private_data_mut(); + let kobj: Arc; + 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)] diff --git a/kernel/src/filesystem/sysfs/mod.rs b/kernel/src/filesystem/sysfs/mod.rs index 5c9e2ec5..d9e3af71 100644 --- a/kernel/src/filesystem/sysfs/mod.rs +++ b/kernel/src/filesystem/sysfs/mod.rs @@ -69,15 +69,8 @@ impl SysFSKernPrivateData { pub fn callback_read(&self, buf: &mut [u8], offset: usize) -> Result { 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 { + pub fn callback_write(&self, buf: &[u8], offset: usize) -> Result { 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, attr: &dyn Attribute) -> Option; + fn is_visible(&self, kobj: Arc, attr: &'static dyn Attribute) -> Option; } /// 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, + _buf: &[u8], + _offset: usize, + ) -> Result { + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + fn read( + &self, + _kobj: Arc, + _buf: &mut [u8], + _offset: usize, + ) -> Result { + 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) -> SysFSOpsSupport { + return attr.support(); + } + fn show( &self, kobj: Arc, @@ -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; } } diff --git a/kernel/src/filesystem/vfs/syscall.rs b/kernel/src/filesystem/vfs/syscall.rs index bdcd6611..6a39570d 100644 --- a/kernel/src/filesystem/vfs/syscall.rs +++ b/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), diff --git a/kernel/src/main.c b/kernel/src/main.c index 44646567..72c062be 100644 --- a/kernel/src/main.c +++ b/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(); diff --git a/kernel/src/mm/c_adapter.rs b/kernel/src/mm/c_adapter.rs index 8a7c5c35..b704bd07 100644 --- a/kernel/src/mm/c_adapter.rs +++ b/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()); +} diff --git a/kernel/src/mm/mmio.h b/kernel/src/mm/mmio.h index 78706442..6042611b 100644 --- a/kernel/src/mm/mmio.h +++ b/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); diff --git a/kernel/src/mm/mmio_buddy.rs b/kernel/src/mm/mmio_buddy.rs index 2b0853b6..29f4cb48 100644 --- a/kernel/src/mm/mmio_buddy.rs +++ b/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 { + pub fn release_mmio(&self, vaddr: VirtAddr, length: usize) -> Result { 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()); -}