Skip to content

Commit 588a602

Browse files
committed
Re-merge RegionMapper and Handler into a single trait
This was unneeded complexity in the end and came unstuck when we realised the library needs to do I/O port accesses for register accesses. Users can just not implement parts of the API they're unable/will not use and deal with the consequences. Also catches changes to cache a mapping to the FACS in the AML interpreter.
1 parent b839d84 commit 588a602

File tree

10 files changed

+209
-214
lines changed

10 files changed

+209
-214
lines changed

src/aml/mod.rs

Lines changed: 28 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,15 @@ pub mod op_region;
1818
pub mod pci_routing;
1919
pub mod resource;
2020

21-
pub use pci_types::PciAddress;
22-
23-
use crate::{AcpiError, AcpiTables, AmlTable, RegionMapper, sdt::SdtHeader};
21+
use crate::{
22+
AcpiError,
23+
AcpiTables,
24+
AmlTable,
25+
Handle,
26+
Handler,
27+
PhysicalMapping,
28+
sdt::{SdtHeader, facs::Facs, fadt::Fadt},
29+
};
2430
use alloc::{
2531
boxed::Box,
2632
collections::btree_map::BTreeMap,
@@ -29,7 +35,7 @@ use alloc::{
2935
vec::Vec,
3036
};
3137
use bit_field::BitField;
32-
use core::{mem, slice, str::FromStr};
38+
use core::{mem, slice, str::FromStr, sync::atomic::Ordering};
3339
use log::{info, trace, warn};
3440
use namespace::{AmlName, Namespace, NamespaceLevelKind};
3541
use object::{
@@ -46,6 +52,7 @@ use object::{
4652
WrappedObject,
4753
};
4854
use op_region::{OpRegion, RegionHandler, RegionSpace};
55+
use pci_types::PciAddress;
4956
use spinning_top::Spinlock;
5057

5158
/// `Interpreter` implements a virtual machine for the dynamic AML bytecode. It can be used by a
@@ -61,7 +68,9 @@ where
6168
context_stack: Spinlock<Vec<MethodContext>>,
6269
dsdt_revision: u8,
6370
region_handlers: Spinlock<BTreeMap<RegionSpace, Box<dyn RegionHandler>>>,
71+
6472
global_lock_mutex: Handle,
73+
facs: PhysicalMapping<H, Facs>,
6574
}
6675

6776
unsafe impl<H> Send for Interpreter<H> where H: Handler + Send {}
@@ -76,7 +85,7 @@ where
7685
{
7786
/// Construct a new `Interpreter`. This does not load any tables - if you have an `AcpiTables`
7887
/// already, use [`Interpreter::new_from_tables`] instead.
79-
pub fn new(handler: H, dsdt_revision: u8) -> Interpreter<H> {
88+
pub fn new(handler: H, dsdt_revision: u8, facs: PhysicalMapping<H, Facs>) -> Interpreter<H> {
8089
info!("Initializing AML interpreter v{}", env!("CARGO_PKG_VERSION"));
8190

8291
let global_lock_mutex = handler.create_mutex();
@@ -89,23 +98,17 @@ where
8998
dsdt_revision,
9099
region_handlers: Spinlock::new(BTreeMap::new()),
91100
global_lock_mutex,
101+
facs,
92102
}
93103
}
94104

95105
/// Construct a new `Interpreter` with the given set of ACPI tables. This will automatically
96106
/// load the DSDT and any SSDTs in the supplied [`AcpiTables`].
97-
pub fn new_from_tables<M: RegionMapper>(
98-
mapper: M,
99-
handler: H,
100-
tables: &AcpiTables<M>,
101-
) -> Result<Interpreter<H>, AcpiError> {
102-
fn load_table<M: RegionMapper, H: Handler>(
103-
interpreter: &Interpreter<H>,
104-
mapper: &M,
105-
table: AmlTable,
106-
) -> Result<(), AcpiError> {
107-
let mapping =
108-
unsafe { mapper.map_physical_region::<SdtHeader>(table.phys_address, table.length as usize) };
107+
pub fn new_from_tables(handler: H, tables: &AcpiTables<H>) -> Result<Interpreter<H>, AcpiError> {
108+
fn load_table(interpreter: &Interpreter<impl Handler>, table: AmlTable) -> Result<(), AcpiError> {
109+
let mapping = unsafe {
110+
interpreter.handler.map_physical_region::<SdtHeader>(table.phys_address, table.length as usize)
111+
};
109112
let stream = unsafe {
110113
slice::from_raw_parts(
111114
mapping.virtual_start.as_ptr().byte_add(mem::size_of::<SdtHeader>()) as *const u8,
@@ -116,12 +119,17 @@ where
116119
Ok(())
117120
}
118121

122+
let facs = {
123+
let fadt = tables.find_table::<Fadt>().unwrap();
124+
unsafe { handler.map_physical_region(fadt.facs_address()?, mem::size_of::<Facs>()) }
125+
};
126+
119127
let dsdt = tables.dsdt()?;
120-
let interpreter = Interpreter::new(handler, dsdt.revision);
121-
load_table(&interpreter, &mapper, dsdt)?;
128+
let interpreter = Interpreter::new(handler, dsdt.revision, facs);
129+
load_table(&interpreter, dsdt)?;
122130

123131
for ssdt in tables.ssdts() {
124-
load_table(&interpreter, &mapper, ssdt)?;
132+
load_table(&interpreter, ssdt)?;
125133
}
126134

127135
Ok(interpreter)
@@ -2905,144 +2913,3 @@ pub enum AmlError {
29052913
PrtInvalidSource,
29062914
PrtNoEntry,
29072915
}
2908-
2909-
/// A `Handle` is an opaque reference to an object that is managed by the user of this library.
2910-
/// They should be returned by the `create_*` methods on `Handler`, and are then used by methods to
2911-
/// refer to a specific object.
2912-
///
2913-
/// The library will treat the value of a handle as entirely opaque. You may manage handles
2914-
/// however you wish, and the same value can be used to refer to objects of different types, if
2915-
/// desired.
2916-
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
2917-
pub struct Handle(pub u32);
2918-
2919-
/// This trait represents the interface from the `Interpreter` to the hosting kernel, and allows
2920-
/// AML to interact with the underlying hardware.
2921-
///
2922-
/// ### Implementation notes
2923-
/// Reads and writes to PCI devices must succeed for devices that are not detected during
2924-
/// enumeration of the PCI bus / do not exist.
2925-
pub trait Handler: Send + Sync {
2926-
fn read_u8(&self, address: usize) -> u8;
2927-
fn read_u16(&self, address: usize) -> u16;
2928-
fn read_u32(&self, address: usize) -> u32;
2929-
fn read_u64(&self, address: usize) -> u64;
2930-
2931-
fn write_u8(&self, address: usize, value: u8);
2932-
fn write_u16(&self, address: usize, value: u16);
2933-
fn write_u32(&self, address: usize, value: u32);
2934-
fn write_u64(&self, address: usize, value: u64);
2935-
2936-
fn read_io_u8(&self, port: u16) -> u8;
2937-
fn read_io_u16(&self, port: u16) -> u16;
2938-
fn read_io_u32(&self, port: u16) -> u32;
2939-
2940-
fn write_io_u8(&self, port: u16, value: u8);
2941-
fn write_io_u16(&self, port: u16, value: u16);
2942-
fn write_io_u32(&self, port: u16, value: u32);
2943-
2944-
fn read_pci_u8(&self, address: PciAddress, offset: u16) -> u8;
2945-
fn read_pci_u16(&self, address: PciAddress, offset: u16) -> u16;
2946-
fn read_pci_u32(&self, address: PciAddress, offset: u16) -> u32;
2947-
2948-
fn write_pci_u8(&self, address: PciAddress, offset: u16, value: u8);
2949-
fn write_pci_u16(&self, address: PciAddress, offset: u16, value: u16);
2950-
fn write_pci_u32(&self, address: PciAddress, offset: u16, value: u32);
2951-
2952-
/// Returns a monotonically-increasing value of nanoseconds.
2953-
fn nanos_since_boot(&self) -> u64;
2954-
2955-
/// Stall for at least the given number of **microseconds**. An implementation should not relinquish control of
2956-
/// the processor during the stall, and for this reason, firmwares should not stall for periods of more than
2957-
/// 100 microseconds.
2958-
fn stall(&self, microseconds: u64);
2959-
2960-
/// Sleep for at least the given number of **milliseconds**. An implementation may round to the closest sleep
2961-
/// time supported, and should relinquish the processor.
2962-
fn sleep(&self, milliseconds: u64);
2963-
2964-
fn create_mutex(&self) -> Handle;
2965-
2966-
/// Acquire the mutex referred to by the given handle. `timeout` is a millisecond timeout value
2967-
/// with the following meaning:
2968-
/// - `0` - try to acquire the mutex once, in a non-blocking manner. If the mutex cannot be
2969-
/// acquired immediately, return `Err(AmlError::MutexAcquireTimeout)`
2970-
/// - `1-0xfffe` - try to acquire the mutex for at least `timeout` milliseconds.
2971-
/// - `0xffff` - try to acquire the mutex indefinitely. Should not return `MutexAcquireTimeout`.
2972-
///
2973-
/// AML mutexes are **reentrant** - that is, a thread may acquire the same mutex more than once
2974-
/// without causing a deadlock.
2975-
fn acquire(&self, mutex: Handle, timeout: u16) -> Result<(), AmlError>;
2976-
fn release(&self, mutex: Handle);
2977-
2978-
fn breakpoint(&self) {}
2979-
2980-
fn handle_debug(&self, _object: &Object) {}
2981-
2982-
fn handle_fatal_error(&self, fatal_type: u8, fatal_code: u32, fatal_arg: u64) {
2983-
panic!(
2984-
"Fatal error while executing AML (encountered DefFatalOp). fatal_type = {}, fatal_code = {}, fatal_arg = {}",
2985-
fatal_type, fatal_code, fatal_arg
2986-
);
2987-
}
2988-
}
2989-
2990-
#[cfg(test)]
2991-
mod tests {
2992-
use super::*;
2993-
use core::str::FromStr;
2994-
2995-
struct TestHandler;
2996-
#[rustfmt::skip]
2997-
impl Handler for TestHandler {
2998-
fn read_u8(&self, _address: usize) -> u8 {0}
2999-
fn read_u16(&self, _address: usize) -> u16 {0}
3000-
fn read_u32(&self, _address: usize) -> u32 {0}
3001-
fn read_u64(&self, _address: usize) -> u64 {0}
3002-
fn write_u8(&self, _address: usize, _value: u8) {}
3003-
fn write_u16(&self, _address: usize, _value: u16) {}
3004-
fn write_u32(&self, _address: usize, _value: u32) {}
3005-
fn write_u64(&self, _address: usize, _value: u64) {}
3006-
fn read_io_u8(&self, _port: u16) -> u8 {0}
3007-
fn read_io_u16(&self, _port: u16) -> u16 {0}
3008-
fn read_io_u32(&self, _port: u16) -> u32 {0}
3009-
fn write_io_u8(&self, _port: u16, _value: u8) {}
3010-
fn write_io_u16(&self, _port: u16, _value: u16) {}
3011-
fn write_io_u32(&self, _port: u16, _value: u32) {}
3012-
fn read_pci_u8(&self, _address: PciAddress, _offset: u16) -> u8 {0}
3013-
fn read_pci_u16(&self, _address: PciAddress, _offset: u16) -> u16 {0}
3014-
fn read_pci_u32(&self, _address: PciAddress, _offset: u16) -> u32 {0}
3015-
fn write_pci_u8(&self, _address: PciAddress, _offset: u16, _value: u8) {}
3016-
fn write_pci_u16(&self, _address: PciAddress, _offset: u16, _value: u16) {}
3017-
fn write_pci_u32(&self, _address: PciAddress, _offset: u16, _value: u32) {}
3018-
fn nanos_since_boot(&self) -> u64 {0}
3019-
fn stall(&self, _microseconds: u64) {}
3020-
fn sleep(&self, _milliseconds: u64) {}
3021-
fn create_mutex(&self) -> Handle { Handle(0) }
3022-
fn acquire(&self, _mutex: Handle, _timeout: u16) -> Result<(), AmlError> { Ok(()) }
3023-
fn release(&self, _mutex: Handle) {}
3024-
}
3025-
3026-
#[test]
3027-
fn verify_interpreter_send_sync() {
3028-
fn test_send_sync<T: Send + Sync>() {}
3029-
test_send_sync::<Interpreter<TestHandler>>();
3030-
}
3031-
3032-
#[test]
3033-
fn add_op() {
3034-
let interpreter = Interpreter::new(TestHandler, 2);
3035-
// AddOp 0x0e 0x06 => Local2
3036-
interpreter.load_table(&[0x72, 0x0b, 0x0e, 0x00, 0x0a, 0x06, 0x62]).unwrap();
3037-
// AddOp 0x0e (AddOp 0x01 0x03 => Local1) => Local1
3038-
interpreter.load_table(&[0x72, 0x0a, 0x0e, 0x72, 0x0a, 0x01, 0x0a, 0x03, 0x61, 0x61]).unwrap();
3039-
}
3040-
3041-
#[test]
3042-
fn names() {
3043-
assert_eq!(
3044-
unsafe { MethodContext::new_from_table(b"\\\x2eABC_DEF_\0") }.namestring(),
3045-
Ok(AmlName::from_str("\\ABC.DEF").unwrap())
3046-
);
3047-
}
3048-
}

0 commit comments

Comments
 (0)