From f5f6c967b7540e5aa00c1d8824d699544dda7d1e Mon Sep 17 00:00:00 2001 From: longjin Date: Sat, 21 Oct 2023 13:43:44 +0000 Subject: [PATCH] Add `SdtHeaderIterator` to get all headers. --- acpi/src/lib.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/acpi/src/lib.rs b/acpi/src/lib.rs index 83facc5..330d09e 100644 --- a/acpi/src/lib.rs +++ b/acpi/src/lib.rs @@ -302,6 +302,11 @@ where .ok_or(AcpiError::TableMissing(T::SIGNATURE)) } + /// Iterates through all of the table headers. + pub fn headers(&self) -> SdtHeaderIterator<'_, H> { + SdtHeaderIterator { tables_phys_ptrs: self.tables_phys_ptrs(), handler: self.handler.clone() } + } + /// Finds and returns the DSDT AML table, if it exists. pub fn dsdt(&self) -> AcpiResult { self.find_table::().and_then(|fadt| { @@ -446,3 +451,37 @@ where }) } } + +pub struct SdtHeaderIterator<'t, H> +where + H: AcpiHandler, +{ + tables_phys_ptrs: TablesPhysPtrsIter<'t>, + handler: H, +} + +impl<'t, H> Iterator for SdtHeaderIterator<'t, H> +where + H: AcpiHandler, +{ + type Item = SdtHeader; + + fn next(&mut self) -> Option { + loop { + let table_phys_ptr = self.tables_phys_ptrs.next()?; + // SAFETY: `address` needs to be valid for the size of `SdtHeader`, or the ACPI tables are malformed (not a + // software issue). + let header_mapping = unsafe { + self.handler.map_physical_region::(table_phys_ptr as usize, mem::size_of::()) + }; + let r = header_mapping.validate(header_mapping.signature); + if r.is_err() { + log::warn!("Found invalid SSDT at physical address {:p}: {:?}", table_phys_ptr, r); + continue; + } + let result = header_mapping.clone(); + drop(header_mapping); + return Some(result); + } + } +}