@@ -18,9 +18,15 @@ pub mod op_region;
1818pub mod pci_routing;
1919pub 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+ } ;
2430use alloc:: {
2531 boxed:: Box ,
2632 collections:: btree_map:: BTreeMap ,
@@ -29,7 +35,7 @@ use alloc::{
2935 vec:: Vec ,
3036} ;
3137use bit_field:: BitField ;
32- use core:: { mem, slice, str:: FromStr } ;
38+ use core:: { mem, slice, str:: FromStr , sync :: atomic :: Ordering } ;
3339use log:: { info, trace, warn} ;
3440use namespace:: { AmlName , Namespace , NamespaceLevelKind } ;
3541use object:: {
@@ -46,6 +52,7 @@ use object::{
4652 WrappedObject ,
4753} ;
4854use op_region:: { OpRegion , RegionHandler , RegionSpace } ;
55+ use pci_types:: PciAddress ;
4956use spinning_top:: Spinlock ;
5057
5158/// `Interpreter` implements a virtual machine for the dynamic AML bytecode. It can be used by a
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
6776unsafe impl < H > Send for Interpreter < H > where H : Handler + Send { }
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"\\ \x2e ABC_DEF_\0 " ) } . namestring( ) ,
3045- Ok ( AmlName :: from_str( "\\ ABC.DEF" ) . unwrap( ) )
3046- ) ;
3047- }
3048- }
0 commit comments