ostd/arch/x86/kernel/acpi/
mod.rs1pub(in crate::arch) mod dmar;
4pub(in crate::arch) mod remapping;
5
6use core::{num::NonZeroU8, ptr::NonNull};
7
8use acpi::{
9 AcpiHandler, AcpiTables,
10 address::AddressSpace,
11 fadt::{Fadt, IaPcBootArchFlags},
12 rsdp::Rsdp,
13};
14use log::warn;
15use spin::Once;
16
17use crate::{
18 boot::{self, BootloaderAcpiArg},
19 mm::paddr_to_vaddr,
20};
21
22#[derive(Debug, Clone)]
23pub(crate) struct AcpiMemoryHandler {}
24
25impl AcpiHandler for AcpiMemoryHandler {
26 unsafe fn map_physical_region<T>(
27 &self,
28 physical_address: usize,
29 size: usize,
30 ) -> acpi::PhysicalMapping<Self, T> {
31 let virtual_address = NonNull::new(paddr_to_vaddr(physical_address) as *mut T).unwrap();
32
33 unsafe {
39 acpi::PhysicalMapping::new(physical_address, virtual_address, size, size, self.clone())
40 }
41 }
42
43 fn unmap_physical_region<T>(_region: &acpi::PhysicalMapping<Self, T>) {}
44}
45
46pub(crate) fn get_acpi_tables() -> Option<AcpiTables<AcpiMemoryHandler>> {
47 let acpi_tables = match boot::EARLY_INFO.get().unwrap().acpi_arg {
48 BootloaderAcpiArg::Rsdp(addr) => unsafe {
49 AcpiTables::from_rsdp(AcpiMemoryHandler {}, addr).unwrap()
50 },
51 BootloaderAcpiArg::Rsdt(addr) => unsafe {
52 AcpiTables::from_rsdt(AcpiMemoryHandler {}, 0, addr).unwrap()
53 },
54 BootloaderAcpiArg::Xsdt(addr) => unsafe {
55 AcpiTables::from_rsdt(AcpiMemoryHandler {}, 1, addr).unwrap()
56 },
57 BootloaderAcpiArg::NotProvided => {
58 let rsdp = unsafe { Rsdp::search_for_on_bios(AcpiMemoryHandler {}) };
60 match rsdp {
61 Ok(map) => unsafe {
62 AcpiTables::from_rsdp(AcpiMemoryHandler {}, map.physical_start()).unwrap()
63 },
64 Err(_) => {
65 warn!("ACPI info not found!");
66 return None;
67 }
68 }
69 }
70 };
71
72 Some(acpi_tables)
73}
74
75#[derive(Debug)]
81pub struct AcpiInfo {
82 pub century_register: Option<NonZeroU8>,
84 pub boot_flags: Option<IaPcBootArchFlags>,
86 pub reset_port_and_val: Option<(u16, u8)>,
88}
89
90pub static ACPI_INFO: Once<AcpiInfo> = Once::new();
92
93pub(in crate::arch) fn init() {
94 let mut acpi_info = AcpiInfo {
95 century_register: None,
96 boot_flags: None,
97 reset_port_and_val: None,
98 };
99
100 if let Some(acpi_tables) = get_acpi_tables()
101 && let Ok(fadt) = acpi_tables.find_table::<Fadt>()
102 {
103 acpi_info.century_register = NonZeroU8::new(fadt.century);
105 acpi_info.boot_flags = Some(fadt.iapc_boot_arch);
106 if let Ok(reset_reg) = fadt.reset_register()
107 && reset_reg.address_space == AddressSpace::SystemIo
108 && let Ok(reset_port) = reset_reg.address.try_into()
109 {
110 acpi_info.reset_port_and_val = Some((reset_port, fadt.reset_value));
111 }
112 };
113
114 log::info!("[ACPI]: Collected information {:?}", acpi_info);
115
116 ACPI_INFO.call_once(|| acpi_info);
117}