good_os_framework/arch/
acpi.rs1use acpi::mcfg::{Mcfg, McfgEntry};
2use acpi::platform::interrupt::Apic;
3use acpi::InterruptModel;
4use acpi::{AcpiHandler, AcpiTables, HpetInfo, PhysicalMapping};
5use alloc::alloc::Global;
6use alloc::boxed::Box;
7use alloc::vec::Vec;
8use conquer_once::spin::OnceCell;
9use core::ptr::NonNull;
10use limine::request::RsdpRequest;
11use x86_64::{PhysAddr, VirtAddr};
12
13use crate::memory::{convert_physical_to_virtual, convert_virtual_to_physical};
14
15pub static ACPI: OnceCell<Acpi> = OnceCell::uninit();
16
17#[used]
18#[link_section = ".requests"]
19static RSDP_REQUEST: RsdpRequest = RsdpRequest::new();
20
21#[derive(Clone)]
22struct AcpiMemHandler;
23
24impl AcpiHandler for AcpiMemHandler {
25 unsafe fn map_physical_region<T>(
26 &self,
27 physical_address: usize,
28 size: usize,
29 ) -> PhysicalMapping<Self, T> {
30 let virtual_address = {
31 let physical_address = PhysAddr::new(physical_address as u64);
32 let virtual_address = convert_physical_to_virtual(physical_address);
33 NonNull::new_unchecked(virtual_address.as_u64() as *mut T)
34 };
35 PhysicalMapping::new(physical_address, virtual_address, size, size, self.clone())
36 }
37
38 fn unmap_physical_region<T>(_region: &PhysicalMapping<Self, T>) {}
39}
40
41#[derive(Debug)]
42pub struct Acpi<'a> {
43 pub apic_info: Apic<'a, Global>,
44 pub hpet_info: HpetInfo,
45 pub mcfg_info: Vec<McfgEntry>,
46}
47
48pub fn init() {
49 let rsdp_response = RSDP_REQUEST.get_response().unwrap();
50
51 let acpi_tables = unsafe {
52 let rsdp_addr = VirtAddr::new(rsdp_response.address() as u64);
53 let tables = AcpiTables::from_rsdp(
54 AcpiMemHandler,
55 convert_virtual_to_physical(rsdp_addr).as_u64() as usize,
56 );
57 Box::leak(Box::new(tables.unwrap()))
58 };
59
60 log::info!("Find ACPI tables successfully!");
61
62 let platform_info = acpi_tables
63 .platform_info()
64 .expect("Failed to get platform info!");
65
66 let apic_info = match platform_info.interrupt_model {
67 InterruptModel::Unknown => panic!("No APIC support, cannot continue!"),
68 InterruptModel::Apic(apic) => apic,
69 _ => panic!("ACPI does not have interrupt model info!"),
70 };
71
72 let hpet_info = HpetInfo::new(acpi_tables).expect("Failed to get HPET info!");
73
74 let mut mcfg_info = Vec::new();
75 let mcfg = acpi_tables.find_table::<Mcfg>().expect("Cannot get MCFG");
76 for entry in mcfg.entries() {
77 mcfg_info.push(*entry);
78 }
79
80 ACPI.init_once(|| Acpi {
81 apic_info,
82 hpet_info,
83 mcfg_info,
84 });
85}