acpi: map FACS before parsing (not identity-mapped on all firmwares)

This commit is contained in:
2026-07-09 12:04:39 +03:00
parent feb8dc26aa
commit ea16a1b551
+14 -17
View File
@@ -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");