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)]
acpi_manager() -> &'static AcpiManager35 pub fn acpi_manager() -> &'static AcpiManager {
36 &AcpiManager
37 }
38
39 #[inline(always)]
acpi_kset() -> Arc<KSet>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
init(&self) -> Result<(), SystemError>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
map_tables(&self, acpi_args: BootloaderAcpiArg) -> Result<(), SystemError>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物理地址
rsdp_paddr(rsdp_instance: &acpi::rsdp::Rsdp) -> PhysAddr118 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
set_acpi_table(acpi_table: AcpiTables<AcpiHandlerImpl>)141 fn set_acpi_table(acpi_table: AcpiTables<AcpiHandlerImpl>) {
142 unsafe {
143 __ACPI_TABLE = Some(acpi_table);
144 }
145 }
146
drop_rsdp_tmp_box()147 fn drop_rsdp_tmp_box() {
148 unsafe {
149 RSDP_TMP_BOX = None;
150 }
151 }
152
153 #[allow(dead_code)]
tables(&self) -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>>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
platform_info(&self) -> Option<PlatformInfo<'_, alloc::alloc::Global>>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 {
map_physical_region<T>( &self, physical_address: usize, size: usize, ) -> acpi::PhysicalMapping<Self, T>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
unmap_physical_region<T>(region: &acpi::PhysicalMapping<Self, T>)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)]
acpi_init() -> Result<(), SystemError>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