1 use core::{fmt::Debug, ptr::NonNull}; 2 3 use acpi::{AcpiHandler, AcpiTables, PlatformInfo}; 4 use alloc::{string::ToString, sync::Arc}; 5 use log::{error, info}; 6 7 use crate::{ 8 arch::MMArch, 9 driver::base::firmware::sys_firmware_kset, 10 init::{boot::BootloaderAcpiArg, boot_params}, 11 libs::align::{page_align_down, page_align_up, AlignedBox}, 12 mm::{ 13 mmio_buddy::{mmio_pool, MMIOSpaceGuard}, 14 MemoryManagementArch, PhysAddr, VirtAddr, 15 }, 16 }; 17 use system_error::SystemError; 18 19 use super::base::kset::KSet; 20 21 extern crate acpi; 22 23 pub mod bus; 24 pub mod glue; 25 pub mod pmtmr; 26 mod sysfs; 27 28 static mut __ACPI_TABLE: Option<acpi::AcpiTables<AcpiHandlerImpl>> = None; 29 /// `/sys/firmware/acpi`的kset 30 static mut ACPI_KSET_INSTANCE: Option<Arc<KSet>> = None; 31 32 static mut RSDP_TMP_BOX: Option<AlignedBox<[u8; 4096], 4096>> = None; 33 34 #[inline(always)] 35 pub fn acpi_manager() -> &'static AcpiManager { 36 &AcpiManager 37 } 38 39 #[inline(always)] 40 pub fn acpi_kset() -> Arc<KSet> { 41 unsafe { ACPI_KSET_INSTANCE.clone().unwrap() } 42 } 43 44 #[derive(Debug)] 45 pub struct AcpiManager; 46 47 impl AcpiManager { 48 /// 初始化ACPI 49 /// 50 /// ## 参数 51 /// 52 /// - `rsdp_vaddr1`: RSDP(v1)的虚拟地址 53 /// - `rsdp_vaddr2`: RSDP(v2)的虚拟地址 54 /// 55 /// 56 /// ## 参考资料 57 /// 58 /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1390 59 fn init(&self) -> Result<(), SystemError> { 60 info!("Initializing Acpi Manager..."); 61 62 // 初始化`/sys/firmware/acpi`的kset 63 let kset = KSet::new("acpi".to_string()); 64 kset.register(Some(sys_firmware_kset()))?; 65 unsafe { 66 ACPI_KSET_INSTANCE = Some(kset.clone()); 67 } 68 let acpi_args = boot_params().read().acpi; 69 if let BootloaderAcpiArg::NotProvided = acpi_args { 70 error!("acpi_init(): ACPI not provided by bootloader"); 71 return Err(SystemError::ENODEV); 72 } 73 74 self.map_tables(acpi_args)?; 75 self.bus_init()?; 76 info!("Acpi Manager initialized."); 77 return Ok(()); 78 } 79 80 fn map_tables(&self, acpi_args: BootloaderAcpiArg) -> Result<(), SystemError> { 81 let table_paddr: PhysAddr = match acpi_args { 82 BootloaderAcpiArg::Rsdt(rsdpv1) => Self::rsdp_paddr(&rsdpv1), 83 BootloaderAcpiArg::Xsdt(rsdpv2) => Self::rsdp_paddr(&rsdpv2), 84 _ => { 85 error!( 86 "AcpiManager::map_tables(): unsupported acpi_args: {:?}", 87 acpi_args 88 ); 89 return Err(SystemError::ENODEV); 90 } 91 }; 92 let res = unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, table_paddr.data()) }; 93 match res { 94 Ok(acpi_table) => { 95 Self::set_acpi_table(acpi_table); 96 return Ok(()); 97 } 98 Err(e) => { 99 error!( 100 "AcpiManager::map_tables(): failed to map tables, error: {:?}", 101 e 102 ); 103 Self::drop_rsdp_tmp_box(); 104 return Err(SystemError::ENODEV); 105 } 106 } 107 } 108 109 /// 通过RSDP虚拟地址获取RSDP物理地址 110 /// 111 /// ## 参数 112 /// 113 /// - `rsdp_vaddr`: RSDP的虚拟地址 114 /// 115 /// ## 返回值 116 /// 117 /// RSDP物理地址 118 fn rsdp_paddr(rsdp_instance: &acpi::rsdp::Rsdp) -> PhysAddr { 119 unsafe { 120 RSDP_TMP_BOX = Some(AlignedBox::new_zeroed().expect("rs_acpi_init(): failed to alloc")) 121 }; 122 123 let size = core::mem::size_of::<acpi::rsdp::Rsdp>(); 124 let tmp_data = unsafe { 125 core::slice::from_raw_parts( 126 rsdp_instance as *const acpi::rsdp::Rsdp as usize as *const u8, 127 size, 128 ) 129 }; 130 unsafe { RSDP_TMP_BOX.as_mut().unwrap()[0..size].copy_from_slice(tmp_data) }; 131 let rsdp_paddr = unsafe { 132 MMArch::virt_2_phys(VirtAddr::new( 133 RSDP_TMP_BOX.as_ref().unwrap().as_ptr() as usize 134 )) 135 .unwrap() 136 }; 137 138 return rsdp_paddr; 139 } 140 141 fn set_acpi_table(acpi_table: AcpiTables<AcpiHandlerImpl>) { 142 unsafe { 143 __ACPI_TABLE = Some(acpi_table); 144 } 145 } 146 147 fn drop_rsdp_tmp_box() { 148 unsafe { 149 RSDP_TMP_BOX = None; 150 } 151 } 152 153 #[allow(dead_code)] 154 pub fn tables(&self) -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>> { 155 unsafe { __ACPI_TABLE.as_ref() } 156 } 157 158 /// 从acpi获取平台的信息 159 /// 160 /// 包括: 161 /// 162 /// - PowerProfile 163 /// - InterruptModel 164 /// - ProcessorInfo 165 /// - PmTimer 166 pub fn platform_info(&self) -> Option<PlatformInfo<'_, alloc::alloc::Global>> { 167 let r = self.tables()?.platform_info(); 168 if let Err(ref e) = r { 169 error!( 170 "AcpiManager::platform_info(): failed to get platform info, error: {:?}", 171 e 172 ); 173 return None; 174 } 175 176 return Some(r.unwrap()); 177 } 178 } 179 180 #[derive(Debug, Clone, Copy)] 181 pub struct AcpiHandlerImpl; 182 183 impl AcpiHandler for AcpiHandlerImpl { 184 unsafe fn map_physical_region<T>( 185 &self, 186 physical_address: usize, 187 size: usize, 188 ) -> acpi::PhysicalMapping<Self, T> { 189 let offset = physical_address - page_align_down(physical_address); 190 let size_fix = page_align_up(size + offset); 191 192 let mmio_guard = mmio_pool() 193 .create_mmio(size_fix) 194 .expect("AcpiHandlerImpl::map_physical_region(): failed to create mmio"); 195 196 mmio_guard 197 .map_phys(PhysAddr::new(page_align_down(physical_address)), size_fix) 198 .expect("AcpiHandlerImpl::map_physical_region(): failed to map phys"); 199 let virtual_start = mmio_guard.vaddr().data() + offset; 200 201 let virtual_start = NonNull::new(virtual_start as *mut T).unwrap(); 202 203 let result: acpi::PhysicalMapping<AcpiHandlerImpl, T> = acpi::PhysicalMapping::new( 204 physical_address, 205 virtual_start, 206 size, 207 mmio_guard.size(), 208 AcpiHandlerImpl, 209 ); 210 211 MMIOSpaceGuard::leak(mmio_guard); 212 213 return result; 214 } 215 216 fn unmap_physical_region<T>(region: &acpi::PhysicalMapping<Self, T>) { 217 let mmio_guard = unsafe { 218 MMIOSpaceGuard::from_raw( 219 VirtAddr::new(page_align_down( 220 region.virtual_start().as_ref() as *const T as usize 221 )), 222 region.mapped_length(), 223 true, 224 ) 225 }; 226 drop(mmio_guard); 227 } 228 } 229 230 #[inline(never)] 231 pub fn acpi_init() -> Result<(), SystemError> { 232 #[cfg(target_arch = "x86_64")] 233 { 234 acpi_manager().init() 235 } 236 237 #[cfg(not(target_arch = "x86_64"))] 238 { 239 log::warn!("acpi_init(): unsupported arch"); 240 return Ok(()); 241 } 242 } 243