1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#![allow(dead_code)]
use acpi::Acpi;
use acpi::AcpiHandler;
use acpi::PhysicalMapping;
use crate::sync::Once;
use crate::mem::{VirtualAddress, PhysicalAddress};
use crate::paging;
use crate::paging::PageState;
use crate::paging::PAGE_SIZE;
use crate::paging::MappingAccessRights;
use crate::frame_allocator::PhysicalMemRegion;
use crate::utils;
use super::multiboot;
static ACPI_INFO: Once<Acpi> = Once::new();
pub fn get_acpi_information() -> &'static Acpi {
ACPI_INFO.r#try().expect("Acpi is not availaible")
}
pub fn try_get_acpi_information() -> Option<&'static Acpi> {
ACPI_INFO.r#try()
}
struct MemoryHandler;
impl AcpiHandler for MemoryHandler {
fn map_physical_region<T>(
&mut self,
physical_address: usize,
size: usize,
) -> PhysicalMapping<T> {
let physical_address_aligned = utils::align_down(physical_address, PAGE_SIZE);
let offset = physical_address - physical_address_aligned;
let aligned_size = utils::align_up(offset + size, PAGE_SIZE);
let physical_mem = unsafe { PhysicalMemRegion::new_unchecked(PhysicalAddress(physical_address_aligned), aligned_size) };
let virtual_address = paging::kernel_memory::get_kernel_memory().map_phys_region(physical_mem, MappingAccessRights::k_r());
PhysicalMapping {
physical_start: physical_address,
virtual_start: unsafe { core::ptr::NonNull::new_unchecked((virtual_address.0 + offset) as *mut T) },
region_length: aligned_size,
mapped_length: aligned_size,
}
}
fn unmap_physical_region<T>(&mut self, region: PhysicalMapping<T>) {
let virtual_address_aligned = utils::align_down(region.virtual_start.as_ptr() as usize, PAGE_SIZE);
paging::kernel_memory::get_kernel_memory().unmap_no_dealloc(VirtualAddress(virtual_address_aligned), region.mapped_length);
}
}
unsafe fn parse_rsdp_tag(memory_handler: &mut MemoryHandler, rsdp_virtual_address: usize) -> bool {
let rsdp_virtual_address_aligned = utils::align_down(rsdp_virtual_address, PAGE_SIZE);
let offset = rsdp_virtual_address - rsdp_virtual_address_aligned;
let rsdp_physical_address = match paging::kernel_memory::get_kernel_memory().mapping_state(VirtualAddress(rsdp_virtual_address_aligned)) {
PageState::Present(rsdp_physical_address) => rsdp_physical_address.addr() + offset,
_ => panic!("RSDP VIRTUAL MAPPING DOESN'T MAP TO ANYTHING???")
};
if let Ok(acpi) = acpi::parse_rsdp(memory_handler, rsdp_physical_address) {
ACPI_INFO.call_once(|| {
acpi
});
true
} else {
false
}
}
pub unsafe fn init() {
let mut handler = MemoryHandler;
let mut is_init = false;
if let Some(multiboot_info) = multiboot::try_get_boot_information() {
if let Some(rsdp_v1_info) = multiboot_info.rsdp_v1_tag() {
info!("Found RSDP v1 multiboot2 tag at address {:x}", rsdp_v1_info.rsdt_address());
let rsdp_virtual_address = (rsdp_v1_info as *const _ as usize) + 0x8;
is_init = parse_rsdp_tag(&mut handler, rsdp_virtual_address);
}
else if let Some(rsdp_v2_info) = multiboot_info.rsdp_v2_tag() {
info!("Found RSDP v2 multiboot2 tag at address {:x}", rsdp_v2_info.xsdt_address());
let rsdp_virtual_address = (rsdp_v2_info as *const _ as usize) + 0x8;
is_init = parse_rsdp_tag(&mut handler, rsdp_virtual_address);
}
}
if !is_init {
if let Ok(acpi) = acpi::search_for_rsdp_bios(&mut handler) {
info!("Found RSDP inside BIOS memory");
ACPI_INFO.call_once(|| {
acpi
});
is_init = true;
}
}
if !is_init {
info!("ACPI is not supported by this system");
} else {
info!("ACPI is supported by this system")
}
}