From ea16a1b55111c5a1deae97cbe16b9b27be28b7e7 Mon Sep 17 00:00:00 2001 From: vasilito Date: Thu, 9 Jul 2026 12:04:39 +0300 Subject: [PATCH] acpi: map FACS before parsing (not identity-mapped on all firmwares) --- src/acpi/mod.rs | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index 2ab2e17168..0ff841214b 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -178,26 +178,23 @@ pub unsafe fn init(already_supplied_rsdp: Option>) { // // 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");