1cc5feaf6SJomo use core::{fmt::Debug, hint::spin_loop, ptr::NonNull}; 27ae679ddSLoGin 3cc5feaf6SJomo use acpi::{AcpiHandler, AcpiTables, PlatformInfo}; 47eda31b2SLoGin use alloc::{string::ToString, sync::Arc}; 57ae679ddSLoGin 67ae679ddSLoGin use crate::{ 7cc5feaf6SJomo arch::MMArch, 87eda31b2SLoGin driver::base::firmware::sys_firmware_kset, 97ae679ddSLoGin kinfo, 10cc5feaf6SJomo libs::align::{page_align_down, page_align_up, AlignedBox}, 117ae679ddSLoGin mm::{ 127ae679ddSLoGin mmio_buddy::{mmio_pool, MMIOSpaceGuard}, 13cc5feaf6SJomo MemoryManagementArch, PhysAddr, VirtAddr, 147ae679ddSLoGin }, 157ae679ddSLoGin }; 16*91e9d4abSLoGin use system_error::SystemError; 177ae679ddSLoGin 187eda31b2SLoGin use super::base::kset::KSet; 197eda31b2SLoGin 207eda31b2SLoGin extern crate acpi; 217eda31b2SLoGin 22a03c4f9dSLoGin pub mod bus; 237ae679ddSLoGin mod c_adapter; 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)] 35a03c4f9dSLoGin pub fn acpi_manager() -> &'static AcpiManager { 36a03c4f9dSLoGin &AcpiManager 37a03c4f9dSLoGin } 38a03c4f9dSLoGin 397eda31b2SLoGin #[inline(always)] 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 /// 587eda31b2SLoGin /// https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1390 59cc5feaf6SJomo pub fn init(&self, rsdp_vaddr1: u64, rsdp_vaddr2: u64) -> Result<(), SystemError> { 607ae679ddSLoGin kinfo!("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 } 68cc5feaf6SJomo self.map_tables(rsdp_vaddr1, rsdp_vaddr2)?; 697eda31b2SLoGin self.bus_init()?; 707eda31b2SLoGin kinfo!("Acpi Manager initialized."); 717eda31b2SLoGin return Ok(()); 727eda31b2SLoGin } 737eda31b2SLoGin 74cc5feaf6SJomo fn map_tables(&self, rsdp_vaddr1: u64, rsdp_vaddr2: u64) -> Result<(), SystemError> { 75cc5feaf6SJomo let rsdp_paddr1 = Self::rsdp_paddr(rsdp_vaddr1); 76cc5feaf6SJomo let res1 = unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr1.data()) }; 77cc5feaf6SJomo let e1; 78cc5feaf6SJomo match res1 { 79cc5feaf6SJomo // 如果rsdpv1能够获取到acpi_table,则就用该表,不用rsdpv2了 80cc5feaf6SJomo Ok(acpi_table) => { 81cc5feaf6SJomo Self::set_acpi_table(acpi_table); 82cc5feaf6SJomo return Ok(()); 83cc5feaf6SJomo } 84cc5feaf6SJomo Err(e) => { 85cc5feaf6SJomo e1 = e; 86cc5feaf6SJomo Self::drop_rsdp_tmp_box(); 87cc5feaf6SJomo } 88cc5feaf6SJomo } 897ae679ddSLoGin 90cc5feaf6SJomo let rsdp_paddr2 = Self::rsdp_paddr(rsdp_vaddr2); 91cc5feaf6SJomo let res2 = unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr2.data()) }; 92cc5feaf6SJomo match res2 { 93cc5feaf6SJomo Ok(acpi_table) => { 94cc5feaf6SJomo Self::set_acpi_table(acpi_table); 95cc5feaf6SJomo } 96cc5feaf6SJomo // 如果rsdpv1和rsdpv2都无法获取到acpi_table,说明有问题,打印报错信息后进入死循环 97cc5feaf6SJomo Err(e2) => { 98cc5feaf6SJomo kerror!("acpi_init(): failed to parse acpi tables, error: (rsdpv1: {:?}) or (rsdpv2: {:?})", e1, e2); 99cc5feaf6SJomo Self::drop_rsdp_tmp_box(); 100cc5feaf6SJomo loop { 101cc5feaf6SJomo spin_loop(); 102cc5feaf6SJomo } 103cc5feaf6SJomo } 1047ae679ddSLoGin } 1057eda31b2SLoGin 1067eda31b2SLoGin return Ok(()); 1077ae679ddSLoGin } 1087ae679ddSLoGin 109cc5feaf6SJomo /// 通过RSDP虚拟地址获取RSDP物理地址 110cc5feaf6SJomo /// 111cc5feaf6SJomo /// ## 参数 112cc5feaf6SJomo /// 113cc5feaf6SJomo /// - `rsdp_vaddr`: RSDP的虚拟地址 114cc5feaf6SJomo /// 115cc5feaf6SJomo /// ## 返回值 116cc5feaf6SJomo /// 117cc5feaf6SJomo /// RSDP物理地址 118cc5feaf6SJomo fn rsdp_paddr(rsdp_vaddr: u64) -> PhysAddr { 119cc5feaf6SJomo unsafe { 120cc5feaf6SJomo RSDP_TMP_BOX = Some(AlignedBox::new_zeroed().expect("rs_acpi_init(): failed to alloc")) 121cc5feaf6SJomo }; 122cc5feaf6SJomo let size = core::mem::size_of::<acpi::rsdp::Rsdp>(); 123cc5feaf6SJomo let tmp_data = 124cc5feaf6SJomo unsafe { core::slice::from_raw_parts(rsdp_vaddr as usize as *const u8, size) }; 125cc5feaf6SJomo unsafe { RSDP_TMP_BOX.as_mut().unwrap()[0..size].copy_from_slice(tmp_data) }; 126cc5feaf6SJomo let rsdp_paddr = unsafe { 127cc5feaf6SJomo MMArch::virt_2_phys(VirtAddr::new( 128cc5feaf6SJomo RSDP_TMP_BOX.as_ref().unwrap().as_ptr() as usize 129cc5feaf6SJomo )) 130cc5feaf6SJomo .unwrap() 131cc5feaf6SJomo }; 132cc5feaf6SJomo 133cc5feaf6SJomo return rsdp_paddr; 134cc5feaf6SJomo } 135cc5feaf6SJomo 136cc5feaf6SJomo fn set_acpi_table(acpi_table: AcpiTables<AcpiHandlerImpl>) { 137cc5feaf6SJomo unsafe { 138cc5feaf6SJomo __ACPI_TABLE = Some(acpi_table); 139cc5feaf6SJomo } 140cc5feaf6SJomo } 141cc5feaf6SJomo 142cc5feaf6SJomo fn drop_rsdp_tmp_box() { 143cc5feaf6SJomo unsafe { 144cc5feaf6SJomo RSDP_TMP_BOX = None; 145cc5feaf6SJomo } 146cc5feaf6SJomo } 147cc5feaf6SJomo 1487ae679ddSLoGin #[allow(dead_code)] 1497eda31b2SLoGin pub fn tables(&self) -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>> { 1507ae679ddSLoGin unsafe { __ACPI_TABLE.as_ref() } 1517ae679ddSLoGin } 152d7f5742aSLoGin 153d7f5742aSLoGin /// 从acpi获取平台的信息 154d7f5742aSLoGin /// 155d7f5742aSLoGin /// 包括: 156d7f5742aSLoGin /// 157d7f5742aSLoGin /// - PowerProfile 158d7f5742aSLoGin /// - InterruptModel 159d7f5742aSLoGin /// - ProcessorInfo 160d7f5742aSLoGin /// - PmTimer 161d7f5742aSLoGin pub fn platform_info(&self) -> Option<PlatformInfo<'_, alloc::alloc::Global>> { 162d7f5742aSLoGin let r = self.tables()?.platform_info(); 163d7f5742aSLoGin if let Err(ref e) = r { 164d7f5742aSLoGin kerror!( 165d7f5742aSLoGin "AcpiManager::platform_info(): failed to get platform info, error: {:?}", 166d7f5742aSLoGin e 167d7f5742aSLoGin ); 168d7f5742aSLoGin return None; 169d7f5742aSLoGin } 170d7f5742aSLoGin 171d7f5742aSLoGin return Some(r.unwrap()); 172d7f5742aSLoGin } 1737ae679ddSLoGin } 1747ae679ddSLoGin 1757ae679ddSLoGin #[derive(Debug, Clone, Copy)] 1767ae679ddSLoGin pub struct AcpiHandlerImpl; 1777ae679ddSLoGin 1787ae679ddSLoGin impl AcpiHandler for AcpiHandlerImpl { 1797ae679ddSLoGin unsafe fn map_physical_region<T>( 1807ae679ddSLoGin &self, 1817ae679ddSLoGin physical_address: usize, 1827ae679ddSLoGin size: usize, 1837ae679ddSLoGin ) -> acpi::PhysicalMapping<Self, T> { 1847ae679ddSLoGin let offset = physical_address - page_align_down(physical_address); 1857ae679ddSLoGin let size_fix = page_align_up(size + offset); 1867ae679ddSLoGin 1877ae679ddSLoGin let mmio_guard = mmio_pool() 1887ae679ddSLoGin .create_mmio(size_fix) 1897ae679ddSLoGin .expect("AcpiHandlerImpl::map_physical_region(): failed to create mmio"); 1907ae679ddSLoGin 1917ae679ddSLoGin mmio_guard 1927ae679ddSLoGin .map_phys(PhysAddr::new(page_align_down(physical_address)), size_fix) 1937ae679ddSLoGin .expect("AcpiHandlerImpl::map_physical_region(): failed to map phys"); 1947ae679ddSLoGin let virtual_start = mmio_guard.vaddr().data() + offset; 1957ae679ddSLoGin 1967ae679ddSLoGin let virtual_start = NonNull::new(virtual_start as *mut T).unwrap(); 1977ae679ddSLoGin 1987ae679ddSLoGin let result: acpi::PhysicalMapping<AcpiHandlerImpl, T> = acpi::PhysicalMapping::new( 1997ae679ddSLoGin physical_address, 2007ae679ddSLoGin virtual_start, 2017ae679ddSLoGin size, 2027ae679ddSLoGin mmio_guard.size(), 2037ae679ddSLoGin AcpiHandlerImpl, 2047ae679ddSLoGin ); 2057ae679ddSLoGin 2067ae679ddSLoGin MMIOSpaceGuard::leak(mmio_guard); 2077ae679ddSLoGin 2087ae679ddSLoGin return result; 2097ae679ddSLoGin } 2107ae679ddSLoGin 2117ae679ddSLoGin fn unmap_physical_region<T>(region: &acpi::PhysicalMapping<Self, T>) { 2127ae679ddSLoGin let mmio_guard = unsafe { 2137ae679ddSLoGin MMIOSpaceGuard::from_raw( 2147ae679ddSLoGin VirtAddr::new(page_align_down( 2157ae679ddSLoGin region.virtual_start().as_ref() as *const T as usize 2167ae679ddSLoGin )), 2177ae679ddSLoGin region.mapped_length(), 2187ae679ddSLoGin true, 2197ae679ddSLoGin ) 2207ae679ddSLoGin }; 2217ae679ddSLoGin drop(mmio_guard); 2227ae679ddSLoGin } 2237ae679ddSLoGin } 224