1use crate::binary_reader::{BinaryReader, DowncastFrom};
8use crate::structures::{
9 ACPI_MADT_FLAG_ENABLED, ACPI_MADT_TYPE_INT_SOURCE_OVERRIDE, ACPI_MADT_TYPE_IO_APIC,
10 ACPI_MADT_TYPE_LOCAL_APIC, AcpiMadtIntSourceOverrideEntry, AcpiMadtIoApicEntry,
11 AcpiMadtLocalApicEntry, AcpiMadtTable, AcpiSubTableHeader, VariableSized,
12};
13use crate::{AcpiParserInterface, get_table_by_type};
14use zx_status::Status;
15
16impl_downcast_from!(AcpiSubTableHeader =>
17 AcpiMadtLocalApicEntry,
18 AcpiMadtIoApicEntry,
19 AcpiMadtIntSourceOverrideEntry,
20);
21
22fn for_each_madt_entry_of_type<'a, T, F>(
23 parser: &'a dyn AcpiParserInterface,
24 r#type: u8,
25 mut visitor: F,
26) -> Result<(), Status>
27where
28 T: VariableSized + DowncastFrom<AcpiSubTableHeader> + 'a,
29 F: FnMut(&T) -> Result<(), Status>,
30{
31 let table = get_table_by_type::<AcpiMadtTable>(parser).ok_or(Status::NOT_FOUND)?;
32 let mut reader = BinaryReader::from_payload_of_struct(table);
33 while !reader.is_empty() {
34 let header = reader.read::<AcpiSubTableHeader>().ok_or(Status::INTERNAL)?;
35 if header.r#type != r#type {
36 continue;
37 }
38 let entry = unsafe { T::downcast_from(header) }.ok_or(Status::INTERNAL)?;
41 visitor(entry)?;
42 }
43 Ok(())
44}
45
46pub fn enumerate_processor_local_apics<F>(
56 parser: &dyn AcpiParserInterface,
57 mut callback: F,
58) -> Result<(), Status>
59where
60 F: FnMut(&AcpiMadtLocalApicEntry) -> Result<(), Status>,
61{
62 for_each_madt_entry_of_type::<AcpiMadtLocalApicEntry, _>(
63 parser,
64 ACPI_MADT_TYPE_LOCAL_APIC,
65 |record| {
66 let flags = record.flags;
67 if (flags & ACPI_MADT_FLAG_ENABLED) == 0 {
68 return Ok(());
69 }
70 callback(record)
71 },
72 )
73}
74
75pub fn enumerate_io_apics<F>(parser: &dyn AcpiParserInterface, callback: F) -> Result<(), Status>
81where
82 F: FnMut(&AcpiMadtIoApicEntry) -> Result<(), Status>,
83{
84 for_each_madt_entry_of_type::<AcpiMadtIoApicEntry, F>(parser, ACPI_MADT_TYPE_IO_APIC, callback)
85}
86
87pub fn enumerate_io_apic_isa_overrides<F>(
98 parser: &dyn AcpiParserInterface,
99 callback: F,
100) -> Result<(), Status>
101where
102 F: FnMut(&AcpiMadtIntSourceOverrideEntry) -> Result<(), Status>,
103{
104 for_each_madt_entry_of_type::<AcpiMadtIntSourceOverrideEntry, F>(
105 parser,
106 ACPI_MADT_TYPE_INT_SOURCE_OVERRIDE,
107 callback,
108 )
109}