mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 15:26:47 +00:00
在Sysfs中引入ACPI Firmware (#405)
- bugfix: multiboot2启动的信息因为没及时转存导致后面无法从其中进行查询的bug - feature: 把acpi表、acpi bus加入sysfs
This commit is contained in:
parent
01bd5258cf
commit
7eda31b2f0
@ -31,7 +31,7 @@ elf = { version = "0.7.2", default-features = false }
|
|||||||
memoffset = "0.9.0"
|
memoffset = "0.9.0"
|
||||||
atomic_enum = "0.2.0"
|
atomic_enum = "0.2.0"
|
||||||
raw-cpuid = "11.0.1"
|
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" }
|
intertrait = { path = "src/libs/intertrait" }
|
||||||
linkme = "0.2"
|
linkme = "0.2"
|
||||||
ida = { path = "src/libs/ida" }
|
ida = { path = "src/libs/ida" }
|
||||||
@ -51,4 +51,3 @@ features = ["spin_no_std"]
|
|||||||
[profile.release]
|
[profile.release]
|
||||||
debug = false
|
debug = false
|
||||||
|
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ void acpi_init()
|
|||||||
|
|
||||||
// 申请mmio空间
|
// 申请mmio空间
|
||||||
uint64_t size = 0;
|
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表
|
// 映射rsdt表
|
||||||
paddr = (uint64_t)rsdt_phys_base;
|
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);
|
printk_color(ORANGE, BLACK, "RSDT Entry num=%d\n", acpi_RSDT_Entry_num);
|
||||||
|
|
||||||
// 申请mmio空间
|
// 申请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的物理地址
|
// 映射所有的Entry的物理地址
|
||||||
acpi_RSDT_entry_phys_base = ((ul)(rsdt->Entry)) & PAGE_2M_MASK;
|
acpi_RSDT_entry_phys_base = ((ul)(rsdt->Entry)) & PAGE_2M_MASK;
|
||||||
@ -220,7 +220,7 @@ void acpi_init()
|
|||||||
kdebug("rsdpv1->RsdtAddress=%#018lx", rsdpv1->RsdtAddress);
|
kdebug("rsdpv1->RsdtAddress=%#018lx", rsdpv1->RsdtAddress);
|
||||||
// 申请mmio空间
|
// 申请mmio空间
|
||||||
uint64_t size = 0;
|
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;
|
// acpi_rsdt_virt_addr_base = 0xffffb00000000000UL;
|
||||||
kdebug("ACPI: mmio created. acpi_rsdt_virt_addr_base = %#018lx,size= %#010lx", acpi_rsdt_virt_addr_base, size);
|
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);
|
printk_color(ORANGE, BLACK, "RSDT Entry num=%d\n", acpi_RSDT_Entry_num);
|
||||||
|
|
||||||
// 申请mmio空间
|
// 申请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的物理地址
|
// 映射所有的Entry的物理地址
|
||||||
acpi_RSDT_entry_phys_base = ((ul)(rsdt->Entry)) & PAGE_2M_MASK;
|
acpi_RSDT_entry_phys_base = ((ul)(rsdt->Entry)) & PAGE_2M_MASK;
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
use alloc::sync::Arc;
|
use alloc::{
|
||||||
|
string::{String, ToString},
|
||||||
|
sync::{Arc, Weak},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::base::device::{driver::Driver, Device},
|
driver::base::{
|
||||||
|
device::{
|
||||||
|
bus::{bus_manager, Bus},
|
||||||
|
driver::Driver,
|
||||||
|
Device,
|
||||||
|
},
|
||||||
|
subsys::SubSysPrivate,
|
||||||
|
},
|
||||||
syscall::SystemError,
|
syscall::SystemError,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -20,4 +30,98 @@ impl AcpiManager {
|
|||||||
|
|
||||||
return Ok(false);
|
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,7 +4,7 @@ use crate::{
|
|||||||
mm::{MemoryManagementArch, VirtAddr},
|
mm::{MemoryManagementArch, VirtAddr},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::AcpiManager;
|
use super::acpi_manager;
|
||||||
|
|
||||||
static mut RSDP_TMP_BOX: Option<AlignedBox<[u8; 4096], 4096>> = None;
|
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();
|
.unwrap();
|
||||||
|
|
||||||
AcpiManager::init(rsdp_paddr);
|
acpi_manager()
|
||||||
|
.init(rsdp_paddr)
|
||||||
|
.expect("rs_acpi_init(): failed to init acpi");
|
||||||
}
|
}
|
||||||
|
@ -1,56 +1,90 @@
|
|||||||
use core::{fmt::Debug, ptr::NonNull};
|
use core::{fmt::Debug, ptr::NonNull};
|
||||||
|
|
||||||
use acpi::AcpiHandler;
|
use acpi::AcpiHandler;
|
||||||
|
use alloc::{string::ToString, sync::Arc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
driver::base::firmware::sys_firmware_kset,
|
||||||
kinfo,
|
kinfo,
|
||||||
libs::{
|
libs::align::{page_align_down, page_align_up},
|
||||||
align::{page_align_down, page_align_up},
|
|
||||||
once::Once,
|
|
||||||
},
|
|
||||||
mm::{
|
mm::{
|
||||||
mmio_buddy::{mmio_pool, MMIOSpaceGuard},
|
mmio_buddy::{mmio_pool, MMIOSpaceGuard},
|
||||||
PhysAddr, VirtAddr,
|
PhysAddr, VirtAddr,
|
||||||
},
|
},
|
||||||
|
syscall::SystemError,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::base::kset::KSet;
|
||||||
|
|
||||||
|
extern crate acpi;
|
||||||
|
|
||||||
pub mod bus;
|
pub mod bus;
|
||||||
mod c_adapter;
|
mod c_adapter;
|
||||||
pub mod glue;
|
pub mod glue;
|
||||||
pub mod old;
|
pub mod old;
|
||||||
|
mod sysfs;
|
||||||
extern crate acpi;
|
|
||||||
|
|
||||||
static mut __ACPI_TABLE: Option<acpi::AcpiTables<AcpiHandlerImpl>> = None;
|
static mut __ACPI_TABLE: Option<acpi::AcpiTables<AcpiHandlerImpl>> = None;
|
||||||
|
/// `/sys/firmware/acpi`的kset
|
||||||
|
static mut ACPI_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn acpi_manager() -> &'static AcpiManager {
|
pub fn acpi_manager() -> &'static AcpiManager {
|
||||||
&AcpiManager
|
&AcpiManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn acpi_kset() -> Arc<KSet> {
|
||||||
|
unsafe { ACPI_KSET_INSTANCE.clone().unwrap() }
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AcpiManager;
|
pub struct AcpiManager;
|
||||||
|
|
||||||
impl AcpiManager {
|
impl AcpiManager {
|
||||||
pub fn init(rsdp_paddr: PhysAddr) {
|
/// 初始化ACPI
|
||||||
static INIT: Once = Once::new();
|
///
|
||||||
INIT.call_once(|| {
|
/// ## 参数
|
||||||
kinfo!("Initializing Acpi Manager...");
|
///
|
||||||
let acpi_table: acpi::AcpiTables<AcpiHandlerImpl> =
|
/// - `rsdp_paddr`: RSDP的物理地址
|
||||||
unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr.data()) }
|
///
|
||||||
.unwrap_or_else(|e| {
|
///
|
||||||
panic!("acpi_init(): failed to parse acpi tables, error: {:?}", e)
|
/// ## 参考资料
|
||||||
});
|
///
|
||||||
|
/// 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 {
|
// 初始化`/sys/firmware/acpi`的kset
|
||||||
__ACPI_TABLE = Some(acpi_table);
|
let kset = KSet::new("acpi".to_string());
|
||||||
}
|
kset.register(Some(sys_firmware_kset()))?;
|
||||||
kinfo!("Acpi Manager initialized.");
|
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)]
|
#[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() }
|
unsafe { __ACPI_TABLE.as_ref() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
510
kernel/src/driver/acpi/sysfs.rs
Normal file
510
kernel/src/driver/acpi/sysfs.rs
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -97,6 +97,7 @@ impl From<BusState> for DeviceState {
|
|||||||
/// https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/device/bus.h#84
|
/// https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/device/bus.h#84
|
||||||
pub trait Bus: Debug + Send + Sync {
|
pub trait Bus: Debug + Send + Sync {
|
||||||
fn name(&self) -> String;
|
fn name(&self) -> String;
|
||||||
|
/// Used for subsystems to enumerate devices like ("foo%u", dev->id).
|
||||||
fn dev_name(&self) -> String;
|
fn dev_name(&self) -> String;
|
||||||
fn root_device(&self) -> Option<Arc<dyn Device>> {
|
fn root_device(&self) -> Option<Arc<dyn Device>> {
|
||||||
None
|
None
|
||||||
|
@ -161,6 +161,20 @@ impl SysFSOps for KObjectSysFSOps {
|
|||||||
pub struct KObjectManager;
|
pub struct KObjectManager;
|
||||||
|
|
||||||
impl 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(
|
pub fn add_kobj(
|
||||||
kobj: Arc<dyn KObject>,
|
kobj: Arc<dyn KObject>,
|
||||||
join_kset: Option<Arc<KSet>>,
|
join_kset: Option<Arc<KSet>>,
|
||||||
@ -212,3 +226,21 @@ impl KObjectManager {
|
|||||||
return Ok(());
|
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,16 +7,13 @@ use alloc::{
|
|||||||
use core::hash::Hash;
|
use core::hash::Hash;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
filesystem::{
|
filesystem::kernfs::KernFSInode,
|
||||||
kernfs::KernFSInode,
|
|
||||||
sysfs::{AttributeGroup, SysFSOps},
|
|
||||||
},
|
|
||||||
libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
|
libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||||
syscall::SystemError,
|
syscall::SystemError,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::kobject::{
|
use super::kobject::{
|
||||||
KObjType, KObject, KObjectManager, KObjectState, KObjectSysFSOps, LockedKObjectState,
|
DynamicKObjKType, KObjType, KObject, KObjectManager, KObjectState, LockedKObjectState,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -164,11 +161,11 @@ impl KObject for KSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
|
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
|
||||||
Some(&KSetKObjType)
|
self.inner.read().ktype
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
|
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
|
||||||
todo!("KSet::set_kobj_type")
|
self.inner.write().ktype = ktype;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kset(&self) -> Option<Arc<KSet>> {
|
fn kset(&self) -> Option<Arc<KSet>> {
|
||||||
@ -208,6 +205,7 @@ impl KSetParentData {
|
|||||||
struct InnerKSet {
|
struct InnerKSet {
|
||||||
kern_inode: Option<Arc<KernFSInode>>,
|
kern_inode: Option<Arc<KernFSInode>>,
|
||||||
name: String,
|
name: String,
|
||||||
|
ktype: Option<&'static dyn KObjType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InnerKSet {
|
impl InnerKSet {
|
||||||
@ -215,19 +213,7 @@ impl InnerKSet {
|
|||||||
Self {
|
Self {
|
||||||
kern_inode: None,
|
kern_inode: None,
|
||||||
name,
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -2,37 +2,52 @@
|
|||||||
|
|
||||||
#include <common/glib.h>
|
#include <common/glib.h>
|
||||||
#include <common/kprint.h>
|
#include <common/kprint.h>
|
||||||
uintptr_t multiboot2_boot_info_addr;
|
// uintptr_t multiboot2_boot_info_addr;
|
||||||
unsigned int multiboot2_magic;
|
// unsigned int multiboot2_magic;
|
||||||
unsigned int multiboot2_boot_info_size;
|
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;
|
uint64_t vaddr = phys_2_virt(mb2_info_paddr);
|
||||||
if (multiboot2_magic != MULTIBOOT2_BOOTLOADER_MAGIC)
|
if (mb2_magic != MULTIBOOT2_BOOTLOADER_MAGIC)
|
||||||
return false;
|
return false;
|
||||||
// addr+0 处保存了大小
|
// vaddr+0 处保存了大小
|
||||||
multiboot2_boot_info_size = *(unsigned int *)addr;
|
multiboot2_boot_info_size = *(uint32_t *)vaddr;
|
||||||
return true;
|
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 multiboot2_iter(bool (*_fun)(const struct iter_data_t *, void *, unsigned int *),
|
||||||
void *data, unsigned int *count)
|
void *data, unsigned int *count)
|
||||||
{
|
{
|
||||||
|
// kdebug("multiboot2_boot_info_addr=%#018lx", multiboot2_boot_info_addr);
|
||||||
|
|
||||||
uintptr_t addr = 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(int i=0;i<8192;i++)
|
||||||
for (; tag->type != MULTIBOOT_TAG_TYPE_END;
|
// {
|
||||||
tag = (struct iter_data_t *)((uint8_t *)tag + ALIGN(tag->size, 8)))
|
// 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;
|
||||||
if (_fun(tag, data, count) == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 读取 grub2 传递的物理内存信息,保存到 e820map_t 结构体中
|
// 读取 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)
|
bool multiboot2_get_memory(const struct iter_data_t *_iter_data, void *data, unsigned int *count)
|
||||||
{
|
{
|
||||||
if (_iter_data->type != MULTIBOOT_TAG_TYPE_MMAP)
|
if (_iter_data->type != MULTIBOOT_TAG_TYPE_MMAP)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
struct multiboot_mmap_entry_t *resource = (struct multiboot_mmap_entry_t *)data;
|
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;
|
struct multiboot_mmap_entry_t *mmap = ((struct multiboot_tag_mmap_t *)_iter_data)->entries;
|
||||||
*count = 0;
|
*count = 0;
|
||||||
for (; (uint8_t *)mmap < (uint8_t *)_iter_data + _iter_data->size;
|
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))
|
mmap = (struct multiboot_mmap_entry_t *)((uint8_t *)mmap + ((struct multiboot_tag_mmap_t *)_iter_data)->entry_size))
|
||||||
{
|
{
|
||||||
*resource = *mmap;
|
*resource = *mmap;
|
||||||
// 将指针进行增加
|
// 将指针进行增加
|
||||||
resource = (struct multiboot_mmap_entry_t *)((uint8_t *)resource + ((struct multiboot_tag_mmap_t *)_iter_data)->entry_size);
|
resource = (struct multiboot_mmap_entry_t *)((uint8_t *)resource + ((struct multiboot_tag_mmap_t *)_iter_data)->entry_size);
|
||||||
++(*count);
|
++(*count);
|
||||||
}
|
}
|
||||||
return true;
|
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)
|
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)
|
if (_iter_data->type != MULTIBOOT_TAG_TYPE_VBE)
|
||||||
return false;
|
return false;
|
||||||
*(struct multiboot_tag_vbe_t *)data = *(struct multiboot_tag_vbe_t *)_iter_data;
|
*(struct multiboot_tag_vbe_t *)data = *(struct multiboot_tag_vbe_t *)_iter_data;
|
||||||
return true;
|
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)
|
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)
|
if (_iter_data->type != MULTIBOOT_TAG_TYPE_FRAMEBUFFER)
|
||||||
return false;
|
return false;
|
||||||
*(struct multiboot_tag_framebuffer_info_t *)data = *(struct multiboot_tag_framebuffer_info_t *)_iter_data;
|
*(struct multiboot_tag_framebuffer_info_t *)data = *(struct multiboot_tag_framebuffer_info_t *)_iter_data;
|
||||||
return true;
|
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)
|
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)
|
if (_iter_data->type != MULTIBOOT_TAG_TYPE_ACPI_OLD)
|
||||||
return false;
|
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)
|
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)
|
if (_iter_data->type != MULTIBOOT_TAG_TYPE_ACPI_NEW)
|
||||||
return false;
|
return false;
|
||||||
*(struct multiboot_tag_new_acpi_t *)data = *(struct multiboot_tag_new_acpi_t *)_iter_data;
|
*(struct multiboot_tag_new_acpi_t *)data = *(struct multiboot_tag_new_acpi_t *)_iter_data;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
@ -26,9 +26,6 @@
|
|||||||
* @brief MULTIBOOT2 接口抽象
|
* @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. */
|
/* 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_SEARCH = 32768;
|
||||||
static const unsigned int MULTIBOOT_HEADER_ALIGN = 8;
|
static const unsigned int MULTIBOOT_HEADER_ALIGN = 8;
|
||||||
@ -416,7 +413,7 @@ struct iter_data_t
|
|||||||
* @return true 成功
|
* @return true 成功
|
||||||
* @return false 失败
|
* @return false 失败
|
||||||
*/
|
*/
|
||||||
static bool multiboot2_init(void);
|
bool multiboot2_init(uint64_t mb2_info_paddr, uint32_t mb2_magic);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 迭代器
|
* @brief 迭代器
|
||||||
|
@ -439,7 +439,7 @@ impl KernFSInode {
|
|||||||
return Err(SystemError::ENOTDIR);
|
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下增加文件
|
/// 在当前inode下增加文件
|
||||||
@ -448,9 +448,11 @@ impl KernFSInode {
|
|||||||
///
|
///
|
||||||
/// - `name`:文件名称
|
/// - `name`:文件名称
|
||||||
/// - `mode`:文件权限
|
/// - `mode`:文件权限
|
||||||
|
/// - `size`:文件大小(如果不指定,则默认为4096)
|
||||||
/// - `private_data`:文件私有数据
|
/// - `private_data`:文件私有数据
|
||||||
/// - `callback`:文件回调函数
|
/// - `callback`:文件回调函数
|
||||||
///
|
///
|
||||||
|
///
|
||||||
/// ## 返回值
|
/// ## 返回值
|
||||||
///
|
///
|
||||||
/// - 成功:文件inode
|
/// - 成功:文件inode
|
||||||
@ -461,6 +463,7 @@ impl KernFSInode {
|
|||||||
&self,
|
&self,
|
||||||
name: String,
|
name: String,
|
||||||
mode: ModeType,
|
mode: ModeType,
|
||||||
|
size: Option<usize>,
|
||||||
private_data: Option<KernInodePrivateData>,
|
private_data: Option<KernInodePrivateData>,
|
||||||
callback: Option<&'static dyn KernFSCallback>,
|
callback: Option<&'static dyn KernFSCallback>,
|
||||||
) -> Result<Arc<KernFSInode>, SystemError> {
|
) -> Result<Arc<KernFSInode>, SystemError> {
|
||||||
@ -468,7 +471,15 @@ impl KernFSInode {
|
|||||||
return Err(SystemError::ENOTDIR);
|
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(
|
fn inner_create(
|
||||||
@ -476,21 +487,19 @@ impl KernFSInode {
|
|||||||
name: String,
|
name: String,
|
||||||
file_type: KernInodeType,
|
file_type: KernInodeType,
|
||||||
mode: ModeType,
|
mode: ModeType,
|
||||||
|
mut size: usize,
|
||||||
private_data: Option<KernInodePrivateData>,
|
private_data: Option<KernInodePrivateData>,
|
||||||
callback: Option<&'static dyn KernFSCallback>,
|
callback: Option<&'static dyn KernFSCallback>,
|
||||||
) -> Result<Arc<KernFSInode>, SystemError> {
|
) -> Result<Arc<KernFSInode>, SystemError> {
|
||||||
let size;
|
|
||||||
match file_type {
|
match file_type {
|
||||||
KernInodeType::Dir | KernInodeType::SymLink => {
|
KernInodeType::Dir | KernInodeType::SymLink => {
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
KernInodeType::File => {
|
_ => {}
|
||||||
size = 4096;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let metadata = Metadata {
|
let metadata = Metadata {
|
||||||
size,
|
size: size as i64,
|
||||||
mode,
|
mode,
|
||||||
uid: 0,
|
uid: 0,
|
||||||
gid: 0,
|
gid: 0,
|
||||||
@ -570,6 +579,7 @@ impl KernFSInode {
|
|||||||
name,
|
name,
|
||||||
KernInodeType::SymLink,
|
KernInodeType::SymLink,
|
||||||
ModeType::S_IFLNK | ModeType::from_bits_truncate(0o777),
|
ModeType::S_IFLNK | ModeType::from_bits_truncate(0o777),
|
||||||
|
0,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
|
@ -19,23 +19,36 @@ use crate::{
|
|||||||
syscall::SystemError,
|
syscall::SystemError,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Attribute, SysFS, SysFSKernPrivateData};
|
use super::{Attribute, BinAttribute, SysFS, SysFSKernPrivateData};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SysKernFilePriv {
|
pub struct SysKernFilePriv {
|
||||||
attribute: Option<&'static dyn Attribute>,
|
attribute: Option<&'static dyn Attribute>,
|
||||||
|
/// bin attribute和attribute二选一,只能有一个为Some
|
||||||
|
bin_attribute: Option<Arc<dyn BinAttribute>>,
|
||||||
/// 当前文件对应的kobject
|
/// 当前文件对应的kobject
|
||||||
kobj: Weak<dyn KObject>,
|
kobj: Weak<dyn KObject>,
|
||||||
// todo: 增加bin attribute,它和attribute二选一,只能有一个为Some
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SysKernFilePriv {
|
impl SysKernFilePriv {
|
||||||
pub fn new(kobj: &Arc<dyn KObject>, attribute: Option<&'static dyn Attribute>) -> Self {
|
pub fn new(
|
||||||
if attribute.is_none() {
|
kobj: &Arc<dyn KObject>,
|
||||||
panic!("attribute can't be None");
|
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);
|
let kobj = Arc::downgrade(kobj);
|
||||||
return Self { kobj, attribute };
|
return Self {
|
||||||
|
kobj,
|
||||||
|
attribute,
|
||||||
|
bin_attribute,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -44,18 +57,41 @@ impl SysKernFilePriv {
|
|||||||
self.attribute
|
self.attribute
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn callback_read(&self, buf: &mut [u8]) -> Result<usize, SystemError> {
|
pub fn callback_read(&self, buf: &mut [u8], offset: usize) -> Result<usize, SystemError> {
|
||||||
let attribute = self.attribute.ok_or(SystemError::EINVAL)?;
|
if let Some(attribute) = self.attribute {
|
||||||
// 当前文件所指向的kobject已经被释放
|
// 当前文件所指向的kobject已经被释放
|
||||||
let kobj = self.kobj.upgrade().expect("kobj is None");
|
let kobj = self.kobj.upgrade().expect("kobj is None");
|
||||||
return attribute.show(kobj, buf);
|
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> {
|
pub fn callback_write(&self, buf: &[u8], offset: usize) -> Result<usize, SystemError> {
|
||||||
let attribute = self.attribute.ok_or(SystemError::EINVAL)?;
|
if let Some(attribute) = self.attribute {
|
||||||
// 当前文件所指向的kobject已经被释放
|
// 当前文件所指向的kobject已经被释放
|
||||||
let kobj = self.kobj.upgrade().expect("kobj is None");
|
let kobj = self.kobj.upgrade().expect("kobj is None");
|
||||||
return attribute.store(kobj, buf);
|
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;
|
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(
|
let r = parent.add_file(
|
||||||
attr.name().to_string(),
|
attr.name().to_string(),
|
||||||
mode.bitand(ModeType::from_bits_truncate(0o777)),
|
mode.bitand(ModeType::from_bits_truncate(0o777)),
|
||||||
|
Some(4096),
|
||||||
Some(KernInodePrivateData::SysFS(sys_priv)),
|
Some(KernInodePrivateData::SysFS(sys_priv)),
|
||||||
Some(kern_callback),
|
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)]
|
#[derive(Debug)]
|
||||||
|
@ -69,15 +69,8 @@ impl SysFSKernPrivateData {
|
|||||||
pub fn callback_read(&self, buf: &mut [u8], offset: usize) -> Result<usize, SystemError> {
|
pub fn callback_read(&self, buf: &mut [u8], offset: usize) -> Result<usize, SystemError> {
|
||||||
match self {
|
match self {
|
||||||
SysFSKernPrivateData::File(file) => {
|
SysFSKernPrivateData::File(file) => {
|
||||||
let len = file.callback_read(buf)?;
|
let len = file.callback_read(buf, offset)?;
|
||||||
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);
|
return Ok(len);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@ -87,10 +80,10 @@ impl SysFSKernPrivateData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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 {
|
match self {
|
||||||
SysFSKernPrivateData::File(file) => {
|
SysFSKernPrivateData::File(file) => {
|
||||||
return file.callback_write(buf);
|
return file.callback_write(buf, offset);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||||||
@ -114,7 +107,7 @@ pub trait AttributeGroup: Debug + Send + Sync {
|
|||||||
///
|
///
|
||||||
/// 如果返回Some,则使用返回的权限。
|
/// 如果返回Some,则使用返回的权限。
|
||||||
/// 如果要标识属性不可见,则返回Some(ModeType::empty())
|
/// 如果要标识属性不可见,则返回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文件的属性
|
/// 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 {
|
pub trait SysFSOps: Debug {
|
||||||
/// 获取当前文件的支持的操作
|
/// 获取当前文件的支持的操作
|
||||||
fn support(&self, attr: &dyn Attribute) -> SysFSOpsSupport {
|
fn support(&self, attr: &dyn Attribute) -> SysFSOpsSupport {
|
||||||
return attr.support();
|
return attr.support();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn support_battr(&self, attr: &Arc<dyn BinAttribute>) -> SysFSOpsSupport {
|
||||||
|
return attr.support();
|
||||||
|
}
|
||||||
|
|
||||||
fn show(
|
fn show(
|
||||||
&self,
|
&self,
|
||||||
kobj: Arc<dyn KObject>,
|
kobj: Arc<dyn KObject>,
|
||||||
@ -156,8 +177,12 @@ pub trait SysFSOps: Debug {
|
|||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub struct SysFSOpsSupport: u8{
|
pub struct SysFSOpsSupport: u8{
|
||||||
|
// === for attribute ===
|
||||||
const SHOW = 1 << 0;
|
const SHOW = 1 << 0;
|
||||||
const STORE = 1 << 1;
|
const STORE = 1 << 1;
|
||||||
|
// === for bin attribute ===
|
||||||
|
const READ = 1 << 2;
|
||||||
|
const WRITE = 1 << 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,7 +693,7 @@ impl Syscall {
|
|||||||
kstat.rdev = metadata.raw_dev as i64;
|
kstat.rdev = metadata.raw_dev as i64;
|
||||||
kstat.mode = metadata.mode;
|
kstat.mode = metadata.mode;
|
||||||
match file.lock().file_type() {
|
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::Dir => kstat.mode.insert(ModeType::S_IFDIR),
|
||||||
FileType::BlockDevice => kstat.mode.insert(ModeType::S_IFBLK),
|
FileType::BlockDevice => kstat.mode.insert(ModeType::S_IFBLK),
|
||||||
FileType::CharDevice => kstat.mode.insert(ModeType::S_IFCHR),
|
FileType::CharDevice => kstat.mode.insert(ModeType::S_IFCHR),
|
||||||
|
@ -71,7 +71,6 @@ void reload_idt()
|
|||||||
void system_initialize()
|
void system_initialize()
|
||||||
{
|
{
|
||||||
rs_init_before_mem_init();
|
rs_init_before_mem_init();
|
||||||
|
|
||||||
// 重新加载gdt和idt
|
// 重新加载gdt和idt
|
||||||
ul tss_item_addr = (ul)phys_2_virt(0x7c00);
|
ul tss_item_addr = (ul)phys_2_virt(0x7c00);
|
||||||
|
|
||||||
@ -82,13 +81,12 @@ void system_initialize()
|
|||||||
rs_load_current_core_tss();
|
rs_load_current_core_tss();
|
||||||
|
|
||||||
cpu_core_info[0].stack_start = _stack_start;
|
cpu_core_info[0].stack_start = _stack_start;
|
||||||
|
|
||||||
// 初始化中断描述符表
|
// 初始化中断描述符表
|
||||||
sys_vector_init();
|
sys_vector_init();
|
||||||
// 初始化内存管理单元
|
// 初始化内存管理单元
|
||||||
// mm_init();
|
// mm_init();
|
||||||
rs_mm_init();
|
rs_mm_init();
|
||||||
|
|
||||||
// 内存管理单元初始化完毕后,需要立即重新初始化显示驱动。
|
// 内存管理单元初始化完毕后,需要立即重新初始化显示驱动。
|
||||||
// 原因是,系统启动初期,framebuffer被映射到48M地址处,
|
// 原因是,系统启动初期,framebuffer被映射到48M地址处,
|
||||||
// mm初始化完毕后,若不重新初始化显示驱动,将会导致错误的数据写入内存,从而造成其他模块崩溃
|
// mm初始化完毕后,若不重新初始化显示驱动,将会导致错误的数据写入内存,从而造成其他模块崩溃
|
||||||
@ -101,7 +99,10 @@ void system_initialize()
|
|||||||
rs_init_intertrait();
|
rs_init_intertrait();
|
||||||
// kinfo("vaddr:%#018lx", video_frame_buffer_info.vaddr);
|
// kinfo("vaddr:%#018lx", video_frame_buffer_info.vaddr);
|
||||||
io_mfence();
|
io_mfence();
|
||||||
|
vfs_init();
|
||||||
|
|
||||||
|
rs_driver_init();
|
||||||
|
|
||||||
acpi_init();
|
acpi_init();
|
||||||
io_mfence();
|
io_mfence();
|
||||||
irq_init();
|
irq_init();
|
||||||
@ -124,9 +125,7 @@ void system_initialize()
|
|||||||
|
|
||||||
rs_jiffies_init();
|
rs_jiffies_init();
|
||||||
io_mfence();
|
io_mfence();
|
||||||
vfs_init();
|
|
||||||
|
|
||||||
rs_driver_init();
|
|
||||||
|
|
||||||
rs_kthread_init();
|
rs_kthread_init();
|
||||||
io_mfence();
|
io_mfence();
|
||||||
@ -183,8 +182,7 @@ void Start_Kernel(void)
|
|||||||
|
|
||||||
mb2_info &= 0xffffffff;
|
mb2_info &= 0xffffffff;
|
||||||
mb2_magic &= 0xffffffff;
|
mb2_magic &= 0xffffffff;
|
||||||
multiboot2_magic = (uint)mb2_magic;
|
multiboot2_init(mb2_info, mb2_magic);
|
||||||
multiboot2_boot_info_addr = mb2_info + PAGE_OFFSET;
|
|
||||||
io_mfence();
|
io_mfence();
|
||||||
system_initialize();
|
system_initialize();
|
||||||
io_mfence();
|
io_mfence();
|
||||||
|
@ -7,7 +7,7 @@ use hashbrown::HashMap;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::mm::LowAddressRemapping,
|
arch::mm::LowAddressRemapping,
|
||||||
include::bindings::bindings::{gfp_t, PAGE_U_S},
|
include::bindings::bindings::{gfp_t, vm_flags_t, PAGE_U_S},
|
||||||
kerror,
|
kerror,
|
||||||
libs::{align::page_align_up, spinlock::SpinLock},
|
libs::{align::page_align_up, spinlock::SpinLock},
|
||||||
mm::MMArch,
|
mm::MMArch,
|
||||||
@ -15,8 +15,8 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, no_init::pseudo_map_phys,
|
allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, mmio_buddy::mmio_pool,
|
||||||
page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr,
|
no_init::pseudo_map_phys, page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr,
|
||||||
};
|
};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
@ -125,3 +125,50 @@ pub unsafe extern "C" fn rs_unmap_at_low_addr() -> usize {
|
|||||||
LowAddressRemapping::unmap_at_low_address(true);
|
LowAddressRemapping::unmap_at_low_address(true);
|
||||||
return 0;
|
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());
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "mm.h"
|
#include "mm.h"
|
||||||
|
|
||||||
extern void mmio_create(uint32_t size, uint64_t vm_flagsu, uint64_t* res_vaddr, uint64_t* res_length);
|
extern int rs_mmio_create(uint32_t size, uint64_t vm_flags, uint64_t* res_vaddr, uint64_t* res_length);
|
||||||
extern int mmio_release(int vaddr, int length);
|
extern int rs_mmio_release(uint64_t vaddr, uint64_t length);
|
||||||
|
@ -3,7 +3,7 @@ use crate::mm::kernel_mapper::KernelMapper;
|
|||||||
use crate::process::ProcessManager;
|
use crate::process::ProcessManager;
|
||||||
use crate::syscall::SystemError;
|
use crate::syscall::SystemError;
|
||||||
use crate::{
|
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,
|
kdebug,
|
||||||
mm::{MMArch, MemoryManagementArch},
|
mm::{MMArch, MemoryManagementArch},
|
||||||
};
|
};
|
||||||
@ -520,7 +520,7 @@ impl MmioBuddyMemPool {
|
|||||||
/// @return Ok(i32) 成功返回0
|
/// @return Ok(i32) 成功返回0
|
||||||
///
|
///
|
||||||
/// @return Err(SystemError) 失败返回错误码
|
/// @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!(vaddr.check_aligned(MMArch::PAGE_SIZE));
|
||||||
assert!(length & (MMArch::PAGE_SIZE - 1) == 0);
|
assert!(length & (MMArch::PAGE_SIZE - 1) == 0);
|
||||||
if vaddr < self.pool_start_addr
|
if vaddr < self.pool_start_addr
|
||||||
@ -707,49 +707,3 @@ pub fn mmio_init() {
|
|||||||
|
|
||||||
kinfo!("MMIO buddy memory pool init done");
|
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());
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user