1 use core::{fmt::Debug, hint::spin_loop, ptr::NonNull};
2
3 use acpi::{AcpiHandler, AcpiTables, PlatformInfo};
4 use alloc::{string::ToString, sync::Arc};
5
6 use crate::{
7 arch::MMArch,
8 driver::base::firmware::sys_firmware_kset,
9 kinfo,
10 libs::align::{page_align_down, page_align_up, AlignedBox},
11 mm::{
12 mmio_buddy::{mmio_pool, MMIOSpaceGuard},
13 MemoryManagementArch, PhysAddr, VirtAddr,
14 },
15 };
16 use system_error::SystemError;
17
18 use super::base::kset::KSet;
19
20 extern crate acpi;
21
22 pub mod bus;
23 mod c_adapter;
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, rsdp_vaddr1: u64, rsdp_vaddr2: u64) -> Result<(), SystemError>59 pub fn init(&self, rsdp_vaddr1: u64, rsdp_vaddr2: u64) -> Result<(), SystemError> {
60 kinfo!("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 self.map_tables(rsdp_vaddr1, rsdp_vaddr2)?;
69 self.bus_init()?;
70 kinfo!("Acpi Manager initialized.");
71 return Ok(());
72 }
73
map_tables(&self, rsdp_vaddr1: u64, rsdp_vaddr2: u64) -> Result<(), SystemError>74 fn map_tables(&self, rsdp_vaddr1: u64, rsdp_vaddr2: u64) -> Result<(), SystemError> {
75 let rsdp_paddr1 = Self::rsdp_paddr(rsdp_vaddr1);
76 let res1 = unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr1.data()) };
77 let e1;
78 match res1 {
79 // 如果rsdpv1能够获取到acpi_table,则就用该表,不用rsdpv2了
80 Ok(acpi_table) => {
81 Self::set_acpi_table(acpi_table);
82 return Ok(());
83 }
84 Err(e) => {
85 e1 = e;
86 Self::drop_rsdp_tmp_box();
87 }
88 }
89
90 let rsdp_paddr2 = Self::rsdp_paddr(rsdp_vaddr2);
91 let res2 = unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr2.data()) };
92 match res2 {
93 Ok(acpi_table) => {
94 Self::set_acpi_table(acpi_table);
95 }
96 // 如果rsdpv1和rsdpv2都无法获取到acpi_table,说明有问题,打印报错信息后进入死循环
97 Err(e2) => {
98 kerror!("acpi_init(): failed to parse acpi tables, error: (rsdpv1: {:?}) or (rsdpv2: {:?})", e1, e2);
99 Self::drop_rsdp_tmp_box();
100 loop {
101 spin_loop();
102 }
103 }
104 }
105
106 return Ok(());
107 }
108
109 /// 通过RSDP虚拟地址获取RSDP物理地址
110 ///
111 /// ## 参数
112 ///
113 /// - `rsdp_vaddr`: RSDP的虚拟地址
114 ///
115 /// ## 返回值
116 ///
117 /// RSDP物理地址
rsdp_paddr(rsdp_vaddr: u64) -> PhysAddr118 fn rsdp_paddr(rsdp_vaddr: u64) -> PhysAddr {
119 unsafe {
120 RSDP_TMP_BOX = Some(AlignedBox::new_zeroed().expect("rs_acpi_init(): failed to alloc"))
121 };
122 let size = core::mem::size_of::<acpi::rsdp::Rsdp>();
123 let tmp_data =
124 unsafe { core::slice::from_raw_parts(rsdp_vaddr as usize as *const u8, size) };
125 unsafe { RSDP_TMP_BOX.as_mut().unwrap()[0..size].copy_from_slice(tmp_data) };
126 let rsdp_paddr = unsafe {
127 MMArch::virt_2_phys(VirtAddr::new(
128 RSDP_TMP_BOX.as_ref().unwrap().as_ptr() as usize
129 ))
130 .unwrap()
131 };
132
133 return rsdp_paddr;
134 }
135
set_acpi_table(acpi_table: AcpiTables<AcpiHandlerImpl>)136 fn set_acpi_table(acpi_table: AcpiTables<AcpiHandlerImpl>) {
137 unsafe {
138 __ACPI_TABLE = Some(acpi_table);
139 }
140 }
141
drop_rsdp_tmp_box()142 fn drop_rsdp_tmp_box() {
143 unsafe {
144 RSDP_TMP_BOX = None;
145 }
146 }
147
148 #[allow(dead_code)]
tables(&self) -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>>149 pub fn tables(&self) -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>> {
150 unsafe { __ACPI_TABLE.as_ref() }
151 }
152
153 /// 从acpi获取平台的信息
154 ///
155 /// 包括:
156 ///
157 /// - PowerProfile
158 /// - InterruptModel
159 /// - ProcessorInfo
160 /// - PmTimer
platform_info(&self) -> Option<PlatformInfo<'_, alloc::alloc::Global>>161 pub fn platform_info(&self) -> Option<PlatformInfo<'_, alloc::alloc::Global>> {
162 let r = self.tables()?.platform_info();
163 if let Err(ref e) = r {
164 kerror!(
165 "AcpiManager::platform_info(): failed to get platform info, error: {:?}",
166 e
167 );
168 return None;
169 }
170
171 return Some(r.unwrap());
172 }
173 }
174
175 #[derive(Debug, Clone, Copy)]
176 pub struct AcpiHandlerImpl;
177
178 impl AcpiHandler for AcpiHandlerImpl {
map_physical_region<T>( &self, physical_address: usize, size: usize, ) -> acpi::PhysicalMapping<Self, T>179 unsafe fn map_physical_region<T>(
180 &self,
181 physical_address: usize,
182 size: usize,
183 ) -> acpi::PhysicalMapping<Self, T> {
184 let offset = physical_address - page_align_down(physical_address);
185 let size_fix = page_align_up(size + offset);
186
187 let mmio_guard = mmio_pool()
188 .create_mmio(size_fix)
189 .expect("AcpiHandlerImpl::map_physical_region(): failed to create mmio");
190
191 mmio_guard
192 .map_phys(PhysAddr::new(page_align_down(physical_address)), size_fix)
193 .expect("AcpiHandlerImpl::map_physical_region(): failed to map phys");
194 let virtual_start = mmio_guard.vaddr().data() + offset;
195
196 let virtual_start = NonNull::new(virtual_start as *mut T).unwrap();
197
198 let result: acpi::PhysicalMapping<AcpiHandlerImpl, T> = acpi::PhysicalMapping::new(
199 physical_address,
200 virtual_start,
201 size,
202 mmio_guard.size(),
203 AcpiHandlerImpl,
204 );
205
206 MMIOSpaceGuard::leak(mmio_guard);
207
208 return result;
209 }
210
unmap_physical_region<T>(region: &acpi::PhysicalMapping<Self, T>)211 fn unmap_physical_region<T>(region: &acpi::PhysicalMapping<Self, T>) {
212 let mmio_guard = unsafe {
213 MMIOSpaceGuard::from_raw(
214 VirtAddr::new(page_align_down(
215 region.virtual_start().as_ref() as *const T as usize
216 )),
217 region.mapped_length(),
218 true,
219 )
220 };
221 drop(mmio_guard);
222 }
223 }
224