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 BootloaderAcpiArg::Rsdp(rsdp) => rsdp,
85 _ => {
86 error!(
87 "AcpiManager::map_tables(): unsupported acpi_args: {:?}",
88 acpi_args
89 );
90 return Err(SystemError::ENODEV);
91 }
92 };
93 let res = unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, table_paddr.data()) };
94 match res {
95 Ok(acpi_table) => {
96 Self::set_acpi_table(acpi_table);
97 return Ok(());
98 }
99 Err(e) => {
100 error!(
101 "AcpiManager::map_tables(): failed to map tables, error: {:?}",
102 e
103 );
104 Self::drop_rsdp_tmp_box();
105 return Err(SystemError::ENODEV);
106 }
107 }
108 }
109
110 /// 通过RSDP虚拟地址获取RSDP物理地址
111 ///
112 /// ## 参数
113 ///
114 /// - `rsdp_vaddr`: RSDP的虚拟地址
115 ///
116 /// ## 返回值
117 ///
118 /// RSDP物理地址
rsdp_paddr(rsdp_instance: &acpi::rsdp::Rsdp) -> PhysAddr119 fn rsdp_paddr(rsdp_instance: &acpi::rsdp::Rsdp) -> PhysAddr {
120 unsafe {
121 RSDP_TMP_BOX = Some(AlignedBox::new_zeroed().expect("rs_acpi_init(): failed to alloc"))
122 };
123
124 let size = core::mem::size_of::<acpi::rsdp::Rsdp>();
125 let tmp_data = unsafe {
126 core::slice::from_raw_parts(
127 rsdp_instance as *const acpi::rsdp::Rsdp as usize as *const u8,
128 size,
129 )
130 };
131 unsafe { RSDP_TMP_BOX.as_mut().unwrap()[0..size].copy_from_slice(tmp_data) };
132 let rsdp_paddr = unsafe {
133 MMArch::virt_2_phys(VirtAddr::new(
134 RSDP_TMP_BOX.as_ref().unwrap().as_ptr() as usize
135 ))
136 .unwrap()
137 };
138
139 return rsdp_paddr;
140 }
141
set_acpi_table(acpi_table: AcpiTables<AcpiHandlerImpl>)142 fn set_acpi_table(acpi_table: AcpiTables<AcpiHandlerImpl>) {
143 unsafe {
144 __ACPI_TABLE = Some(acpi_table);
145 }
146 }
147
drop_rsdp_tmp_box()148 fn drop_rsdp_tmp_box() {
149 unsafe {
150 RSDP_TMP_BOX = None;
151 }
152 }
153
154 #[allow(dead_code)]
tables(&self) -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>>155 pub fn tables(&self) -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>> {
156 unsafe { __ACPI_TABLE.as_ref() }
157 }
158
159 /// 从acpi获取平台的信息
160 ///
161 /// 包括:
162 ///
163 /// - PowerProfile
164 /// - InterruptModel
165 /// - ProcessorInfo
166 /// - PmTimer
platform_info(&self) -> Option<PlatformInfo<'_, alloc::alloc::Global>>167 pub fn platform_info(&self) -> Option<PlatformInfo<'_, alloc::alloc::Global>> {
168 let r = self.tables()?.platform_info();
169 if let Err(ref e) = r {
170 error!(
171 "AcpiManager::platform_info(): failed to get platform info, error: {:?}",
172 e
173 );
174 return None;
175 }
176
177 return Some(r.unwrap());
178 }
179 }
180
181 #[derive(Debug, Clone, Copy)]
182 pub struct AcpiHandlerImpl;
183
184 impl AcpiHandler for AcpiHandlerImpl {
map_physical_region<T>( &self, physical_address: usize, size: usize, ) -> acpi::PhysicalMapping<Self, T>185 unsafe fn map_physical_region<T>(
186 &self,
187 physical_address: usize,
188 size: usize,
189 ) -> acpi::PhysicalMapping<Self, T> {
190 let offset = physical_address - page_align_down(physical_address);
191 let size_fix = page_align_up(size + offset);
192
193 let mmio_guard = mmio_pool()
194 .create_mmio(size_fix)
195 .expect("AcpiHandlerImpl::map_physical_region(): failed to create mmio");
196
197 mmio_guard
198 .map_phys(PhysAddr::new(page_align_down(physical_address)), size_fix)
199 .expect("AcpiHandlerImpl::map_physical_region(): failed to map phys");
200 let virtual_start = mmio_guard.vaddr().data() + offset;
201
202 let virtual_start = NonNull::new(virtual_start as *mut T).unwrap();
203
204 let result: acpi::PhysicalMapping<AcpiHandlerImpl, T> = acpi::PhysicalMapping::new(
205 physical_address,
206 virtual_start,
207 size,
208 mmio_guard.size(),
209 AcpiHandlerImpl,
210 );
211
212 MMIOSpaceGuard::leak(mmio_guard);
213
214 return result;
215 }
216
unmap_physical_region<T>(region: &acpi::PhysicalMapping<Self, T>)217 fn unmap_physical_region<T>(region: &acpi::PhysicalMapping<Self, T>) {
218 let mmio_guard = unsafe {
219 MMIOSpaceGuard::from_raw(
220 VirtAddr::new(page_align_down(
221 region.virtual_start().as_ref() as *const T as usize
222 )),
223 region.mapped_length(),
224 true,
225 )
226 };
227 drop(mmio_guard);
228 }
229 }
230
231 #[inline(never)]
acpi_init() -> Result<(), SystemError>232 pub fn acpi_init() -> Result<(), SystemError> {
233 #[cfg(target_arch = "x86_64")]
234 {
235 acpi_manager().init()
236 }
237
238 #[cfg(not(target_arch = "x86_64"))]
239 {
240 log::warn!("acpi_init(): unsupported arch");
241 return Ok(());
242 }
243 }
244