From e1e0ac2ee3fcc40b027e83b33bf3a3b1fd2e9fa5 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Tue, 22 Oct 2019 14:39:11 +0100 Subject: [PATCH] acpi_tables: aml: Add support for creating IO and interrupt resources As per ACPI spec: "6.4.2.5 I/O Port Descriptor" and "6.4.3.6 Extended Interrupt Descriptor" Signed-off-by: Rob Bradford --- acpi_tables/src/aml.rs | 110 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/acpi_tables/src/aml.rs b/acpi_tables/src/aml.rs index dba0923cf..076a2d938 100644 --- a/acpi_tables/src/aml.rs +++ b/acpi_tables/src/aml.rs @@ -456,6 +456,83 @@ impl Aml for AddressSpace { } } +pub struct IO { + min: u16, + max: u16, + alignment: u8, + length: u8, +} + +impl IO { + pub fn new(min: u16, max: u16, alignment: u8, length: u8) -> Self { + IO { + min, + max, + alignment, + length, + } + } +} + +impl Aml for IO { + fn to_bytes(&self) -> Vec { + let mut bytes = Vec::new(); + + bytes.push(0x47); /* IO Port Descriptor */ + bytes.push(1); /* IODecode16 */ + bytes.append(&mut self.min.to_le_bytes().to_vec()); + bytes.append(&mut self.max.to_le_bytes().to_vec()); + bytes.push(self.alignment); + bytes.push(self.length); + + bytes + } +} + +pub struct Interrupt { + consumer: bool, + edge_triggered: bool, + active_low: bool, + shared: bool, + number: u32, +} + +impl Interrupt { + pub fn new( + consumer: bool, + edge_triggered: bool, + active_low: bool, + shared: bool, + number: u32, + ) -> Self { + Interrupt { + consumer, + edge_triggered, + active_low, + shared, + number, + } + } +} + +impl Aml for Interrupt { + fn to_bytes(&self) -> Vec { + let mut bytes = Vec::new(); + + bytes.push(0x89); /* Extended IRQ Descriptor */ + bytes.append(&mut 6u16.to_le_bytes().to_vec()); + let flags = (self.shared as u8) << 3 + | (self.active_low as u8) << 2 + | (self.edge_triggered as u8) << 1 + | self.consumer as u8; + bytes.push(flags); + bytes.push(1u8); /* count */ + bytes.append(&mut self.number.to_le_bytes().to_vec()); + + bytes + } +} + #[cfg(test)] mod tests { use super::*; @@ -621,6 +698,39 @@ mod tests { .to_bytes(), &crs_qword_memory[..] ); + + /* + Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings + { + Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, ) + { + 0x00000004, + } + IO (Decode16, + 0x03F8, // Range Minimum + 0x03F8, // Range Maximum + 0x00, // Alignment + 0x08, // Length + ) + }) + + */ + let interrupt_io_data = [ + 0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x16, 0x0A, 0x13, 0x89, 0x06, 0x00, 0x03, 0x01, + 0x04, 0x00, 0x00, 0x00, 0x47, 0x01, 0xF8, 0x03, 0xF8, 0x03, 0x00, 0x08, 0x79, 0x00, + ]; + + assert_eq!( + Name::new( + "_CRS".into(), + &ResourceTemplate::new(vec![ + &Interrupt::new(true, true, false, false, 4), + &IO::new(0x3f8, 0x3f8, 0, 0x8) + ]) + ) + .to_bytes(), + &interrupt_io_data[..] + ); } #[test]