mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-22 19:33:26 +00:00
在Sysfs中引入ACPI Firmware (#405)
- bugfix: multiboot2启动的信息因为没及时转存导致后面无法从其中进行查询的bug - feature: 把acpi表、acpi bus加入sysfs
This commit is contained in:
@ -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;
|
||||
|
@ -1,7 +1,17 @@
|
||||
use alloc::sync::Arc;
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
driver::base::device::{driver::Driver, Device},
|
||||
driver::base::{
|
||||
device::{
|
||||
bus::{bus_manager, Bus},
|
||||
driver::Driver,
|
||||
Device,
|
||||
},
|
||||
subsys::SubSysPrivate,
|
||||
},
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
@ -20,4 +30,98 @@ impl AcpiManager {
|
||||
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1286
|
||||
pub(super) fn bus_init(&self) -> Result<(), SystemError> {
|
||||
self.acpi_sysfs_init()?;
|
||||
|
||||
let acpi_bus = AcpiBus::new();
|
||||
bus_manager()
|
||||
.register(acpi_bus as Arc<dyn Bus>)
|
||||
.expect("acpi_bus register failed");
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
/// ACPI总线
|
||||
///
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1072
|
||||
#[derive(Debug)]
|
||||
pub(super) struct AcpiBus {
|
||||
private: SubSysPrivate,
|
||||
}
|
||||
|
||||
impl AcpiBus {
|
||||
pub fn new() -> Arc<Self> {
|
||||
let default_weak: Weak<Self> = Weak::new();
|
||||
let bus = Arc::new(Self {
|
||||
private: SubSysPrivate::new("acpi".to_string(), default_weak, &[]),
|
||||
});
|
||||
bus.subsystem()
|
||||
.set_bus(Arc::downgrade(&(bus.clone() as Arc<dyn Bus>)));
|
||||
return bus;
|
||||
}
|
||||
}
|
||||
|
||||
impl Bus for AcpiBus {
|
||||
fn name(&self) -> String {
|
||||
return self.private.subsys().as_kobject().name();
|
||||
}
|
||||
|
||||
fn dev_name(&self) -> String {
|
||||
self.name()
|
||||
}
|
||||
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1056
|
||||
fn remove(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
todo!("acpi_bus: remove")
|
||||
}
|
||||
|
||||
fn shutdown(&self, _device: &Arc<dyn Device>) {
|
||||
return;
|
||||
}
|
||||
|
||||
fn resume(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// 通过acpi来匹配驱动
|
||||
///
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1005
|
||||
fn match_device(
|
||||
&self,
|
||||
_device: &Arc<dyn Device>,
|
||||
_driver: &Arc<dyn Driver>,
|
||||
) -> Result<bool, SystemError> {
|
||||
// todo: 通过acpi来匹配驱动
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1019
|
||||
fn probe(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
todo!("acpi_bus: probe")
|
||||
}
|
||||
|
||||
fn subsystem(&self) -> &SubSysPrivate {
|
||||
return &self.private;
|
||||
}
|
||||
}
|
||||
|
||||
/// Acpi设备应当实现的trait
|
||||
///
|
||||
/// 所有的实现了 AcpiDevice trait的结构体,都应该在结构体上方标注`#[cast_to([sync] AcpiDevice)]
|
||||
///
|
||||
/// todo: 仿照linux的acpi_device去设计这个trait
|
||||
///
|
||||
///
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/include/acpi/acpi_bus.h#364
|
||||
pub trait AcpiDevice: Device {}
|
||||
|
||||
/// Acpi驱动应当实现的trait
|
||||
///
|
||||
/// 所有的实现了 AcpiDriver trait的结构体,都应该在结构体上方标注`#[cast_to([sync] AcpiDriver)]
|
||||
///
|
||||
/// todo: 仿照linux的acpi_driver去设计这个trait
|
||||
///
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/include/acpi/acpi_bus.h#163
|
||||
pub trait AcpiDriver: Driver {}
|
||||
|
@ -4,7 +4,7 @@ use crate::{
|
||||
mm::{MemoryManagementArch, VirtAddr},
|
||||
};
|
||||
|
||||
use super::AcpiManager;
|
||||
use super::acpi_manager;
|
||||
|
||||
static mut RSDP_TMP_BOX: Option<AlignedBox<[u8; 4096], 4096>> = None;
|
||||
|
||||
@ -20,5 +20,7 @@ unsafe extern "C" fn rs_acpi_init(rsdp_vaddr: u64) {
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
AcpiManager::init(rsdp_paddr);
|
||||
acpi_manager()
|
||||
.init(rsdp_paddr)
|
||||
.expect("rs_acpi_init(): failed to init acpi");
|
||||
}
|
||||
|
@ -1,56 +1,90 @@
|
||||
use core::{fmt::Debug, ptr::NonNull};
|
||||
|
||||
use acpi::AcpiHandler;
|
||||
use alloc::{string::ToString, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
driver::base::firmware::sys_firmware_kset,
|
||||
kinfo,
|
||||
libs::{
|
||||
align::{page_align_down, page_align_up},
|
||||
once::Once,
|
||||
},
|
||||
libs::align::{page_align_down, page_align_up},
|
||||
mm::{
|
||||
mmio_buddy::{mmio_pool, MMIOSpaceGuard},
|
||||
PhysAddr, VirtAddr,
|
||||
},
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
use super::base::kset::KSet;
|
||||
|
||||
extern crate acpi;
|
||||
|
||||
pub mod bus;
|
||||
mod c_adapter;
|
||||
pub mod glue;
|
||||
pub mod old;
|
||||
|
||||
extern crate acpi;
|
||||
mod sysfs;
|
||||
|
||||
static mut __ACPI_TABLE: Option<acpi::AcpiTables<AcpiHandlerImpl>> = None;
|
||||
/// `/sys/firmware/acpi`的kset
|
||||
static mut ACPI_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
||||
|
||||
#[inline(always)]
|
||||
pub fn acpi_manager() -> &'static AcpiManager {
|
||||
&AcpiManager
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn acpi_kset() -> Arc<KSet> {
|
||||
unsafe { ACPI_KSET_INSTANCE.clone().unwrap() }
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AcpiManager;
|
||||
|
||||
impl AcpiManager {
|
||||
pub fn init(rsdp_paddr: PhysAddr) {
|
||||
static INIT: Once = Once::new();
|
||||
INIT.call_once(|| {
|
||||
kinfo!("Initializing Acpi Manager...");
|
||||
let acpi_table: acpi::AcpiTables<AcpiHandlerImpl> =
|
||||
unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr.data()) }
|
||||
.unwrap_or_else(|e| {
|
||||
panic!("acpi_init(): failed to parse acpi tables, error: {:?}", e)
|
||||
});
|
||||
/// 初始化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<AcpiHandlerImpl> =
|
||||
unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr.data()) }.map_err(
|
||||
|e| {
|
||||
kerror!("acpi_init(): failed to parse acpi tables, error: {:?}", e);
|
||||
SystemError::ENOMEM
|
||||
},
|
||||
)?;
|
||||
|
||||
unsafe {
|
||||
__ACPI_TABLE = Some(acpi_table);
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn tables() -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>> {
|
||||
pub fn tables(&self) -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>> {
|
||||
unsafe { __ACPI_TABLE.as_ref() }
|
||||
}
|
||||
}
|
||||
|
510
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
|
||||
pub trait Bus: Debug + Send + Sync {
|
||||
fn name(&self) -> String;
|
||||
/// Used for subsystems to enumerate devices like ("foo%u", dev->id).
|
||||
fn dev_name(&self) -> String;
|
||||
fn root_device(&self) -> Option<Arc<dyn Device>> {
|
||||
None
|
||||
|
@ -161,6 +161,20 @@ impl SysFSOps for KObjectSysFSOps {
|
||||
pub struct KObjectManager;
|
||||
|
||||
impl KObjectManager {
|
||||
#[allow(dead_code)]
|
||||
pub fn init_and_add_kobj(
|
||||
kobj: Arc<dyn KObject>,
|
||||
join_kset: Option<Arc<KSet>>,
|
||||
) -> Result<(), SystemError> {
|
||||
Self::kobj_init(&kobj);
|
||||
Self::add_kobj(kobj, join_kset)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn kobj_init(kobj: &Arc<dyn KObject>) {
|
||||
kobj.set_kobj_type(Some(&DynamicKObjKType));
|
||||
}
|
||||
|
||||
pub fn add_kobj(
|
||||
kobj: Arc<dyn KObject>,
|
||||
join_kset: Option<Arc<KSet>>,
|
||||
@ -212,3 +226,21 @@ impl KObjectManager {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
/// 动态创建的kobject对象的ktype
|
||||
#[derive(Debug)]
|
||||
pub struct DynamicKObjKType;
|
||||
|
||||
impl KObjType for DynamicKObjKType {
|
||||
fn release(&self, kobj: Arc<dyn KObject>) {
|
||||
kdebug!("DynamicKObjKType::release() kobj:{:?}", kobj.name());
|
||||
}
|
||||
|
||||
fn sysfs_ops(&self) -> Option<&dyn SysFSOps> {
|
||||
Some(&KObjectSysFSOps)
|
||||
}
|
||||
|
||||
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -7,16 +7,13 @@ use alloc::{
|
||||
use core::hash::Hash;
|
||||
|
||||
use crate::{
|
||||
filesystem::{
|
||||
kernfs::KernFSInode,
|
||||
sysfs::{AttributeGroup, SysFSOps},
|
||||
},
|
||||
filesystem::kernfs::KernFSInode,
|
||||
libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
use super::kobject::{
|
||||
KObjType, KObject, KObjectManager, KObjectState, KObjectSysFSOps, LockedKObjectState,
|
||||
DynamicKObjKType, KObjType, KObject, KObjectManager, KObjectState, LockedKObjectState,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -164,11 +161,11 @@ impl KObject for KSet {
|
||||
}
|
||||
|
||||
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
|
||||
Some(&KSetKObjType)
|
||||
self.inner.read().ktype
|
||||
}
|
||||
|
||||
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
|
||||
todo!("KSet::set_kobj_type")
|
||||
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
|
||||
self.inner.write().ktype = ktype;
|
||||
}
|
||||
|
||||
fn kset(&self) -> Option<Arc<KSet>> {
|
||||
@ -208,6 +205,7 @@ impl KSetParentData {
|
||||
struct InnerKSet {
|
||||
kern_inode: Option<Arc<KernFSInode>>,
|
||||
name: String,
|
||||
ktype: Option<&'static dyn KObjType>,
|
||||
}
|
||||
|
||||
impl InnerKSet {
|
||||
@ -215,19 +213,7 @@ impl InnerKSet {
|
||||
Self {
|
||||
kern_inode: None,
|
||||
name,
|
||||
ktype: Some(&DynamicKObjKType),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct KSetKObjType;
|
||||
|
||||
impl KObjType for KSetKObjType {
|
||||
fn sysfs_ops(&self) -> Option<&dyn SysFSOps> {
|
||||
Some(&KObjectSysFSOps)
|
||||
}
|
||||
|
||||
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -2,37 +2,52 @@
|
||||
|
||||
#include <common/glib.h>
|
||||
#include <common/kprint.h>
|
||||
uintptr_t multiboot2_boot_info_addr;
|
||||
unsigned int multiboot2_magic;
|
||||
// uintptr_t multiboot2_boot_info_addr;
|
||||
// unsigned int multiboot2_magic;
|
||||
unsigned int multiboot2_boot_info_size;
|
||||
|
||||
bool multiboot2_init(void)
|
||||
#define MBI_RAW_MAX_SIZE 409600
|
||||
// 由于启动时传递的mb2 info所在的地址,在内存管理初始化之后会被覆盖,所以需要将其拷贝到一个固定的位置
|
||||
static uint8_t mbi_raw[MBI_RAW_MAX_SIZE] = {0};
|
||||
bool multiboot2_init(uint64_t mb2_info_paddr, uint32_t mb2_magic)
|
||||
{
|
||||
uintptr_t *addr = (uintptr_t *)multiboot2_boot_info_addr;
|
||||
if (multiboot2_magic != MULTIBOOT2_BOOTLOADER_MAGIC)
|
||||
return false;
|
||||
// addr+0 处保存了大小
|
||||
multiboot2_boot_info_size = *(unsigned int *)addr;
|
||||
return true;
|
||||
uint64_t vaddr = phys_2_virt(mb2_info_paddr);
|
||||
if (mb2_magic != MULTIBOOT2_BOOTLOADER_MAGIC)
|
||||
return false;
|
||||
// vaddr+0 处保存了大小
|
||||
multiboot2_boot_info_size = *(uint32_t *)vaddr;
|
||||
if (multiboot2_boot_info_size > MBI_RAW_MAX_SIZE)
|
||||
return false;
|
||||
|
||||
memcpy((void *)mbi_raw, (void *)vaddr, multiboot2_boot_info_size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void multiboot2_iter(bool (*_fun)(const struct iter_data_t *, void *, unsigned int *),
|
||||
void *data, unsigned int *count)
|
||||
{
|
||||
// kdebug("multiboot2_boot_info_addr=%#018lx", multiboot2_boot_info_addr);
|
||||
|
||||
uintptr_t addr = multiboot2_boot_info_addr;
|
||||
// 接下来的第8字节开始,为 tag 信息
|
||||
struct iter_data_t *tag = (struct iter_data_t *)((void *)addr + 8);
|
||||
for (; tag->type != MULTIBOOT_TAG_TYPE_END;
|
||||
tag = (struct iter_data_t *)((uint8_t *)tag + ALIGN(tag->size, 8)))
|
||||
// uintptr_t addr = multiboot2_boot_info_addr;
|
||||
|
||||
// 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;
|
||||
}
|
@ -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 迭代器
|
||||
|
Reference in New Issue
Block a user