diff --git a/src/aml/interrupt_model_used.rs b/src/aml/interrupt_model_used.rs new file mode 100644 index 00000000..cf25062b --- /dev/null +++ b/src/aml/interrupt_model_used.rs @@ -0,0 +1,61 @@ +use alloc::vec; +use core::str::FromStr; + +use crate::{ + Handler, + aml::{ + AmlError, + BaseInterpreter, + namespace::AmlName, + object::{Object, WrappedObject}, + op_region::RegionHandler, + }, +}; + +/// See the [the docs for the `\_PIC` method](https://uefi.org/specs/ACPI/6.6/05_ACPI_Software_Programming_Model.html#pic-method). +#[non_exhaustive] +#[derive(Debug, Clone, Copy)] +pub enum InterruptModelUsed { + /// 0 - PIC mode + PicMode, + /// 1 - APIC mode + ApicMode, + /// 2 - SAPIC mode + SapicMode, + /// 4 – GIC model + GicModel = 4, + /// 5 – LPIC model + LpicModel = 5, + /// 6 – RINTC model + RintcModel = 6, +} + +impl From for Object { + fn from(value: InterruptModelUsed) -> Self { + Self::Integer(match value { + InterruptModelUsed::PicMode => 0, + InterruptModelUsed::ApicMode => 1, + InterruptModelUsed::SapicMode => 2, + InterruptModelUsed::GicModel => 4, + InterruptModelUsed::LpicModel => 5, + InterruptModelUsed::RintcModel => 6, + }) + } +} + +impl BaseInterpreter +where + H: Handler, + R: RegionHandler + ?Sized, +{ + /// Calls the [`\_PIC` method](https://uefi.org/specs/ACPI/6.6/05_ACPI_Software_Programming_Model.html#pic-method). + /// The method is optional, so if it doesn't exist this function returns success. Returns `true` is the method was called, `false` if it doesn't exist. + pub fn set_interrupt_model_used(&self, model: InterruptModelUsed) -> Result { + Ok(self + .evaluate_if_present( + AmlName::from_str(r#"\_PIC"#).expect("valid name"), + vec![WrappedObject::new(model.into())], + )? + .is_some()) + } +} diff --git a/src/aml/mod.rs b/src/aml/mod.rs index 44ef3583..b3e5dcf3 100644 --- a/src/aml/mod.rs +++ b/src/aml/mod.rs @@ -16,6 +16,7 @@ * - Fuzzing and guarantee panic-free interpretation */ +mod interrupt_model_used; pub mod namespace; pub mod object; pub mod op_region; @@ -47,6 +48,7 @@ use core::{ str::FromStr, sync::atomic::{AtomicU64, Ordering}, }; +pub use interrupt_model_used::InterruptModelUsed; use log::{error, info, trace, warn}; use namespace::{AmlName, Namespace, NamespaceLevelKind}; use object::{ diff --git a/src/aml/pci_routing.rs b/src/aml/pci_routing.rs index 47df1b13..4cbb48aa 100644 --- a/src/aml/pci_routing.rs +++ b/src/aml/pci_routing.rs @@ -58,6 +58,10 @@ impl PciRoutingTable { /// `AmlError::InvalidOperationOnObject` if the value passed is not a package, or if any of the /// values within it are not packages. Returns the various `AmlError::Prt*` errors if the /// internal structure of the entries is invalid. + /// + /// Before calling this method, `\_PIC` should be called. See [`Interpreter::set_interrupt_model_used`]. + /// The evaluation of `_PRT` can depend on the interrupt model being used. If `\_PIC` is not called, + /// the evaluation of PCI interrupts to GSI numbers can return incorrect results. pub fn from_prt_path( prt_path: AmlName, interpreter: &Interpreter,