acpi: map FACS before parsing (not identity-mapped on all firmwares)
This commit is contained in:
+14
-17
@@ -178,26 +178,23 @@ pub unsafe fn init(already_supplied_rsdp: Option<NonNull<u8>>) {
|
||||
//
|
||||
// The FACS is found via the FADT's x_firmware_ctrl
|
||||
// field (64-bit) or firmware_ctrl field (32-bit).
|
||||
// The FADT parser caches the FACS address. We use
|
||||
// the FADT's x_firmware_ctrl to find the FACS SDT.
|
||||
let facs_addr = fadt::x_firmware_ctrl();
|
||||
// The FADT parser caches the FACS address. We map the
|
||||
// FACS here because it is not listed in the RSDT/XSDT
|
||||
// and therefore was not mapped during table discovery.
|
||||
const FACS_MIN_SIZE: usize = 64;
|
||||
let mut facs_addr = fadt::x_firmware_ctrl();
|
||||
if facs_addr == 0 {
|
||||
facs_addr = fadt::firmware_ctrl() as u64;
|
||||
}
|
||||
if facs_addr != 0 {
|
||||
// SAFETY: The FACS address is a physical
|
||||
// address stored in the FADT. The boot-time page
|
||||
// table maps the FACS into the kernel's address
|
||||
// space (firmware tables are below 4GB on x86_64).
|
||||
let facs_sdt = unsafe { &*(facs_addr as *const Sdt) };
|
||||
let facs_phys = PhysicalAddress::new(facs_addr as usize);
|
||||
map_linearly(facs_phys, FACS_MIN_SIZE, &mut KernelMapper::lock_rw());
|
||||
let facs_sdt = unsafe {
|
||||
&*(RmmA::phys_to_virt(facs_phys).data() as *const Sdt)
|
||||
};
|
||||
facs::init(facs_sdt);
|
||||
} else {
|
||||
let facs_addr = fadt::firmware_ctrl() as u64;
|
||||
if facs_addr != 0 {
|
||||
// SAFETY: same as above.
|
||||
let facs_sdt =
|
||||
unsafe { &*(facs_addr as *const Sdt) };
|
||||
facs::init(facs_sdt);
|
||||
} else {
|
||||
warn!("ACPI: no FACS found (neither x_firmware_ctrl nor firmware_ctrl), S3 resume path disabled");
|
||||
}
|
||||
warn!("ACPI: no FACS found (neither x_firmware_ctrl nor firmware_ctrl), S3 resume path disabled");
|
||||
}
|
||||
} else {
|
||||
error!("NO RSDP FOUND");
|
||||
|
||||
Reference in New Issue
Block a user