@@ -18,9 +18,15 @@ pub mod op_region;
18
18
pub mod pci_routing;
19
19
pub mod resource;
20
20
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
+ } ;
24
30
use alloc:: {
25
31
boxed:: Box ,
26
32
collections:: btree_map:: BTreeMap ,
@@ -29,7 +35,7 @@ use alloc::{
29
35
vec:: Vec ,
30
36
} ;
31
37
use bit_field:: BitField ;
32
- use core:: { mem, slice, str:: FromStr } ;
38
+ use core:: { mem, slice, str:: FromStr , sync :: atomic :: Ordering } ;
33
39
use log:: { info, trace, warn} ;
34
40
use namespace:: { AmlName , Namespace , NamespaceLevelKind } ;
35
41
use object:: {
@@ -46,6 +52,7 @@ use object::{
46
52
WrappedObject ,
47
53
} ;
48
54
use op_region:: { OpRegion , RegionHandler , RegionSpace } ;
55
+ use pci_types:: PciAddress ;
49
56
use spinning_top:: Spinlock ;
50
57
51
58
/// `Interpreter` implements a virtual machine for the dynamic AML bytecode. It can be used by a
61
68
context_stack : Spinlock < Vec < MethodContext > > ,
62
69
dsdt_revision : u8 ,
63
70
region_handlers : Spinlock < BTreeMap < RegionSpace , Box < dyn RegionHandler > > > ,
71
+
64
72
global_lock_mutex : Handle ,
73
+ facs : PhysicalMapping < H , Facs > ,
65
74
}
66
75
67
76
unsafe impl < H > Send for Interpreter < H > where H : Handler + Send { }
76
85
{
77
86
/// Construct a new `Interpreter`. This does not load any tables - if you have an `AcpiTables`
78
87
/// 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 > {
80
89
info ! ( "Initializing AML interpreter v{}" , env!( "CARGO_PKG_VERSION" ) ) ;
81
90
82
91
let global_lock_mutex = handler. create_mutex ( ) ;
@@ -89,23 +98,17 @@ where
89
98
dsdt_revision,
90
99
region_handlers : Spinlock :: new ( BTreeMap :: new ( ) ) ,
91
100
global_lock_mutex,
101
+ facs,
92
102
}
93
103
}
94
104
95
105
/// Construct a new `Interpreter` with the given set of ACPI tables. This will automatically
96
106
/// 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
+ } ;
109
112
let stream = unsafe {
110
113
slice:: from_raw_parts (
111
114
mapping. virtual_start . as_ptr ( ) . byte_add ( mem:: size_of :: < SdtHeader > ( ) ) as * const u8 ,
@@ -116,12 +119,17 @@ where
116
119
Ok ( ( ) )
117
120
}
118
121
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
+
119
127
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) ?;
122
130
123
131
for ssdt in tables. ssdts ( ) {
124
- load_table ( & interpreter, & mapper , ssdt) ?;
132
+ load_table ( & interpreter, ssdt) ?;
125
133
}
126
134
127
135
Ok ( interpreter)
@@ -2905,144 +2913,3 @@ pub enum AmlError {
2905
2913
PrtInvalidSource ,
2906
2914
PrtNoEntry ,
2907
2915
}
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