1*2b7818e8SLoGin use core::{fmt::Debug, ptr::NonNull};
27ae679ddSLoGin
3cc5feaf6SJomo use acpi::{AcpiHandler, AcpiTables, PlatformInfo};
47eda31b2SLoGin use alloc::{string::ToString, sync::Arc};
52eab6dd7S曾俊 use log::{error, info};
67ae679ddSLoGin
77ae679ddSLoGin use crate::{
8cc5feaf6SJomo arch::MMArch,
97eda31b2SLoGin driver::base::firmware::sys_firmware_kset,
10*2b7818e8SLoGin init::{boot::BootloaderAcpiArg, boot_params},
11cc5feaf6SJomo libs::align::{page_align_down, page_align_up, AlignedBox},
127ae679ddSLoGin mm::{
137ae679ddSLoGin mmio_buddy::{mmio_pool, MMIOSpaceGuard},
14cc5feaf6SJomo MemoryManagementArch, PhysAddr, VirtAddr,
157ae679ddSLoGin },
167ae679ddSLoGin };
1791e9d4abSLoGin use system_error::SystemError;
187ae679ddSLoGin
197eda31b2SLoGin use super::base::kset::KSet;
207eda31b2SLoGin
217eda31b2SLoGin extern crate acpi;
227eda31b2SLoGin
23a03c4f9dSLoGin pub mod bus;
2406d5e247SLoGin pub mod glue;
25fbe6becdSLoGin pub mod pmtmr;
267eda31b2SLoGin mod sysfs;
277ae679ddSLoGin
287ae679ddSLoGin static mut __ACPI_TABLE: Option<acpi::AcpiTables<AcpiHandlerImpl>> = None;
297eda31b2SLoGin /// `/sys/firmware/acpi`的kset
307eda31b2SLoGin static mut ACPI_KSET_INSTANCE: Option<Arc<KSet>> = None;
317ae679ddSLoGin
32cc5feaf6SJomo static mut RSDP_TMP_BOX: Option<AlignedBox<[u8; 4096], 4096>> = None;
33cc5feaf6SJomo
34a03c4f9dSLoGin #[inline(always)]
acpi_manager() -> &'static AcpiManager35a03c4f9dSLoGin pub fn acpi_manager() -> &'static AcpiManager {
36a03c4f9dSLoGin &AcpiManager
37a03c4f9dSLoGin }
38a03c4f9dSLoGin
397eda31b2SLoGin #[inline(always)]
acpi_kset() -> Arc<KSet>407eda31b2SLoGin pub fn acpi_kset() -> Arc<KSet> {
417eda31b2SLoGin unsafe { ACPI_KSET_INSTANCE.clone().unwrap() }
427eda31b2SLoGin }
437eda31b2SLoGin
447ae679ddSLoGin #[derive(Debug)]
457ae679ddSLoGin pub struct AcpiManager;
467ae679ddSLoGin
477ae679ddSLoGin impl AcpiManager {
487eda31b2SLoGin /// 初始化ACPI
497eda31b2SLoGin ///
507eda31b2SLoGin /// ## 参数
517eda31b2SLoGin ///
52cc5feaf6SJomo /// - `rsdp_vaddr1`: RSDP(v1)的虚拟地址
53cc5feaf6SJomo /// - `rsdp_vaddr2`: RSDP(v2)的虚拟地址
547eda31b2SLoGin ///
557eda31b2SLoGin ///
567eda31b2SLoGin /// ## 参考资料
577eda31b2SLoGin ///
58e7071df6SLoGin /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1390
init(&self) -> Result<(), SystemError>59*2b7818e8SLoGin fn init(&self) -> Result<(), SystemError> {
602eab6dd7S曾俊 info!("Initializing Acpi Manager...");
617eda31b2SLoGin
627eda31b2SLoGin // 初始化`/sys/firmware/acpi`的kset
637eda31b2SLoGin let kset = KSet::new("acpi".to_string());
647eda31b2SLoGin kset.register(Some(sys_firmware_kset()))?;
657eda31b2SLoGin unsafe {
667eda31b2SLoGin ACPI_KSET_INSTANCE = Some(kset.clone());
677eda31b2SLoGin }
68*2b7818e8SLoGin let acpi_args = boot_params().read().acpi;
69*2b7818e8SLoGin if let BootloaderAcpiArg::NotProvided = acpi_args {
70*2b7818e8SLoGin error!("acpi_init(): ACPI not provided by bootloader");
71*2b7818e8SLoGin return Err(SystemError::ENODEV);
72*2b7818e8SLoGin }
73*2b7818e8SLoGin
74*2b7818e8SLoGin self.map_tables(acpi_args)?;
757eda31b2SLoGin self.bus_init()?;
762eab6dd7S曾俊 info!("Acpi Manager initialized.");
777eda31b2SLoGin return Ok(());
787eda31b2SLoGin }
797eda31b2SLoGin
map_tables(&self, acpi_args: BootloaderAcpiArg) -> Result<(), SystemError>80*2b7818e8SLoGin fn map_tables(&self, acpi_args: BootloaderAcpiArg) -> Result<(), SystemError> {
81*2b7818e8SLoGin let table_paddr: PhysAddr = match acpi_args {
82*2b7818e8SLoGin BootloaderAcpiArg::Rsdt(rsdpv1) => Self::rsdp_paddr(&rsdpv1),
83*2b7818e8SLoGin BootloaderAcpiArg::Xsdt(rsdpv2) => Self::rsdp_paddr(&rsdpv2),
84*2b7818e8SLoGin _ => {
85*2b7818e8SLoGin error!(
86*2b7818e8SLoGin "AcpiManager::map_tables(): unsupported acpi_args: {:?}",
87*2b7818e8SLoGin acpi_args
88*2b7818e8SLoGin );
89*2b7818e8SLoGin return Err(SystemError::ENODEV);
90*2b7818e8SLoGin }
91*2b7818e8SLoGin };
92*2b7818e8SLoGin let res = unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, table_paddr.data()) };
93*2b7818e8SLoGin match res {
94cc5feaf6SJomo Ok(acpi_table) => {
95cc5feaf6SJomo Self::set_acpi_table(acpi_table);
96cc5feaf6SJomo return Ok(());
97cc5feaf6SJomo }
98cc5feaf6SJomo Err(e) => {
99*2b7818e8SLoGin error!(
100*2b7818e8SLoGin "AcpiManager::map_tables(): failed to map tables, error: {:?}",
101*2b7818e8SLoGin e
102*2b7818e8SLoGin );
103cc5feaf6SJomo Self::drop_rsdp_tmp_box();
104*2b7818e8SLoGin return Err(SystemError::ENODEV);
105cc5feaf6SJomo }
106cc5feaf6SJomo }
1077ae679ddSLoGin }
1087ae679ddSLoGin
109cc5feaf6SJomo /// 通过RSDP虚拟地址获取RSDP物理地址
110cc5feaf6SJomo ///
111cc5feaf6SJomo /// ## 参数
112cc5feaf6SJomo ///
113cc5feaf6SJomo /// - `rsdp_vaddr`: RSDP的虚拟地址
114cc5feaf6SJomo ///
115cc5feaf6SJomo /// ## 返回值
116cc5feaf6SJomo ///
117cc5feaf6SJomo /// RSDP物理地址
rsdp_paddr(rsdp_instance: &acpi::rsdp::Rsdp) -> PhysAddr118*2b7818e8SLoGin fn rsdp_paddr(rsdp_instance: &acpi::rsdp::Rsdp) -> PhysAddr {
119cc5feaf6SJomo unsafe {
120cc5feaf6SJomo RSDP_TMP_BOX = Some(AlignedBox::new_zeroed().expect("rs_acpi_init(): failed to alloc"))
121cc5feaf6SJomo };
122*2b7818e8SLoGin
123cc5feaf6SJomo let size = core::mem::size_of::<acpi::rsdp::Rsdp>();
124*2b7818e8SLoGin let tmp_data = unsafe {
125*2b7818e8SLoGin core::slice::from_raw_parts(
126*2b7818e8SLoGin rsdp_instance as *const acpi::rsdp::Rsdp as usize as *const u8,
127*2b7818e8SLoGin size,
128*2b7818e8SLoGin )
129*2b7818e8SLoGin };
130cc5feaf6SJomo unsafe { RSDP_TMP_BOX.as_mut().unwrap()[0..size].copy_from_slice(tmp_data) };
131cc5feaf6SJomo let rsdp_paddr = unsafe {
132cc5feaf6SJomo MMArch::virt_2_phys(VirtAddr::new(
133cc5feaf6SJomo RSDP_TMP_BOX.as_ref().unwrap().as_ptr() as usize
134cc5feaf6SJomo ))
135cc5feaf6SJomo .unwrap()
136cc5feaf6SJomo };
137cc5feaf6SJomo
138cc5feaf6SJomo return rsdp_paddr;
139cc5feaf6SJomo }
140cc5feaf6SJomo
set_acpi_table(acpi_table: AcpiTables<AcpiHandlerImpl>)141cc5feaf6SJomo fn set_acpi_table(acpi_table: AcpiTables<AcpiHandlerImpl>) {
142cc5feaf6SJomo unsafe {
143cc5feaf6SJomo __ACPI_TABLE = Some(acpi_table);
144cc5feaf6SJomo }
145cc5feaf6SJomo }
146cc5feaf6SJomo
drop_rsdp_tmp_box()147cc5feaf6SJomo fn drop_rsdp_tmp_box() {
148cc5feaf6SJomo unsafe {
149cc5feaf6SJomo RSDP_TMP_BOX = None;
150cc5feaf6SJomo }
151cc5feaf6SJomo }
152cc5feaf6SJomo
1537ae679ddSLoGin #[allow(dead_code)]
tables(&self) -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>>1547eda31b2SLoGin pub fn tables(&self) -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>> {
1557ae679ddSLoGin unsafe { __ACPI_TABLE.as_ref() }
1567ae679ddSLoGin }
157d7f5742aSLoGin
158d7f5742aSLoGin /// 从acpi获取平台的信息
159d7f5742aSLoGin ///
160d7f5742aSLoGin /// 包括:
161d7f5742aSLoGin ///
162d7f5742aSLoGin /// - PowerProfile
163d7f5742aSLoGin /// - InterruptModel
164d7f5742aSLoGin /// - ProcessorInfo
165d7f5742aSLoGin /// - PmTimer
platform_info(&self) -> Option<PlatformInfo<'_, alloc::alloc::Global>>166d7f5742aSLoGin pub fn platform_info(&self) -> Option<PlatformInfo<'_, alloc::alloc::Global>> {
167d7f5742aSLoGin let r = self.tables()?.platform_info();
168d7f5742aSLoGin if let Err(ref e) = r {
1692eab6dd7S曾俊 error!(
170d7f5742aSLoGin "AcpiManager::platform_info(): failed to get platform info, error: {:?}",
171d7f5742aSLoGin e
172d7f5742aSLoGin );
173d7f5742aSLoGin return None;
174d7f5742aSLoGin }
175d7f5742aSLoGin
176d7f5742aSLoGin return Some(r.unwrap());
177d7f5742aSLoGin }
1787ae679ddSLoGin }
1797ae679ddSLoGin
1807ae679ddSLoGin #[derive(Debug, Clone, Copy)]
1817ae679ddSLoGin pub struct AcpiHandlerImpl;
1827ae679ddSLoGin
1837ae679ddSLoGin impl AcpiHandler for AcpiHandlerImpl {
map_physical_region<T>( &self, physical_address: usize, size: usize, ) -> acpi::PhysicalMapping<Self, T>1847ae679ddSLoGin unsafe fn map_physical_region<T>(
1857ae679ddSLoGin &self,
1867ae679ddSLoGin physical_address: usize,
1877ae679ddSLoGin size: usize,
1887ae679ddSLoGin ) -> acpi::PhysicalMapping<Self, T> {
1897ae679ddSLoGin let offset = physical_address - page_align_down(physical_address);
1907ae679ddSLoGin let size_fix = page_align_up(size + offset);
1917ae679ddSLoGin
1927ae679ddSLoGin let mmio_guard = mmio_pool()
1937ae679ddSLoGin .create_mmio(size_fix)
1947ae679ddSLoGin .expect("AcpiHandlerImpl::map_physical_region(): failed to create mmio");
1957ae679ddSLoGin
1967ae679ddSLoGin mmio_guard
1977ae679ddSLoGin .map_phys(PhysAddr::new(page_align_down(physical_address)), size_fix)
1987ae679ddSLoGin .expect("AcpiHandlerImpl::map_physical_region(): failed to map phys");
1997ae679ddSLoGin let virtual_start = mmio_guard.vaddr().data() + offset;
2007ae679ddSLoGin
2017ae679ddSLoGin let virtual_start = NonNull::new(virtual_start as *mut T).unwrap();
2027ae679ddSLoGin
2037ae679ddSLoGin let result: acpi::PhysicalMapping<AcpiHandlerImpl, T> = acpi::PhysicalMapping::new(
2047ae679ddSLoGin physical_address,
2057ae679ddSLoGin virtual_start,
2067ae679ddSLoGin size,
2077ae679ddSLoGin mmio_guard.size(),
2087ae679ddSLoGin AcpiHandlerImpl,
2097ae679ddSLoGin );
2107ae679ddSLoGin
2117ae679ddSLoGin MMIOSpaceGuard::leak(mmio_guard);
2127ae679ddSLoGin
2137ae679ddSLoGin return result;
2147ae679ddSLoGin }
2157ae679ddSLoGin
unmap_physical_region<T>(region: &acpi::PhysicalMapping<Self, T>)2167ae679ddSLoGin fn unmap_physical_region<T>(region: &acpi::PhysicalMapping<Self, T>) {
2177ae679ddSLoGin let mmio_guard = unsafe {
2187ae679ddSLoGin MMIOSpaceGuard::from_raw(
2197ae679ddSLoGin VirtAddr::new(page_align_down(
2207ae679ddSLoGin region.virtual_start().as_ref() as *const T as usize
2217ae679ddSLoGin )),
2227ae679ddSLoGin region.mapped_length(),
2237ae679ddSLoGin true,
2247ae679ddSLoGin )
2257ae679ddSLoGin };
2267ae679ddSLoGin drop(mmio_guard);
2277ae679ddSLoGin }
2287ae679ddSLoGin }
229*2b7818e8SLoGin
230*2b7818e8SLoGin #[inline(never)]
acpi_init() -> Result<(), SystemError>231*2b7818e8SLoGin pub fn acpi_init() -> Result<(), SystemError> {
232*2b7818e8SLoGin #[cfg(target_arch = "x86_64")]
233*2b7818e8SLoGin {
234*2b7818e8SLoGin acpi_manager().init()
235*2b7818e8SLoGin }
236*2b7818e8SLoGin
237*2b7818e8SLoGin #[cfg(not(target_arch = "x86_64"))]
238*2b7818e8SLoGin {
239*2b7818e8SLoGin log::warn!("acpi_init(): unsupported arch");
240*2b7818e8SLoGin return Ok(());
241*2b7818e8SLoGin }
242*2b7818e8SLoGin }
243