@@ -23,6 +23,7 @@ pub mod resource;
23
23
24
24
pub use pci_types:: PciAddress ;
25
25
26
+ use crate :: { AcpiError , AcpiHandler , AcpiTables , AmlTable , sdt:: SdtHeader } ;
26
27
use alloc:: {
27
28
boxed:: Box ,
28
29
collections:: btree_map:: BTreeMap ,
@@ -32,7 +33,7 @@ use alloc::{
32
33
vec:: Vec ,
33
34
} ;
34
35
use bit_field:: BitField ;
35
- use core:: { mem, str:: FromStr } ;
36
+ use core:: { mem, slice , str:: FromStr } ;
36
37
use log:: { info, trace, warn} ;
37
38
use namespace:: { AmlName , Namespace , NamespaceLevelKind } ;
38
39
use object:: {
@@ -70,8 +71,8 @@ impl<H> Interpreter<H>
70
71
where
71
72
H : Handler ,
72
73
{
73
- // TODO: new_from_tables helper that does `new` and then loads the DSDT + any SSDTs
74
-
74
+ /// Construct a new `Interpreter`. This does not load any tables - if you have an `AcpiTables`
75
+ /// already, use [`Interpreter::new_from_tables`] instead.
75
76
pub fn new ( handler : H , dsdt_revision : u8 ) -> Interpreter < H > {
76
77
info ! ( "Initializing AML interpreter v{}" , env!( "CARGO_PKG_VERSION" ) ) ;
77
78
Interpreter {
83
84
}
84
85
}
85
86
87
+ /// Construct a new `Interpreter` with the given set of ACPI tables. This will automatically
88
+ /// load the DSDT and any SSDTs in the supplied [`AcpiTables`].
89
+ // TODO: maybe merge handler types? Maybe make one a supertrait of the other?
90
+ pub fn new_from_tables < AH : AcpiHandler > (
91
+ acpi_handler : AH ,
92
+ aml_handler : H ,
93
+ tables : & AcpiTables < AH > ,
94
+ ) -> Result < Interpreter < H > , AcpiError > {
95
+ fn load_table < H : Handler , AH : AcpiHandler > (
96
+ interpreter : & Interpreter < H > ,
97
+ acpi_handler : & AH ,
98
+ table : AmlTable ,
99
+ ) -> Result < ( ) , AcpiError > {
100
+ let mapping = unsafe {
101
+ acpi_handler. map_physical_region :: < SdtHeader > ( table. phys_address , table. length as usize )
102
+ } ;
103
+ let stream = unsafe {
104
+ slice:: from_raw_parts (
105
+ mapping. virtual_start ( ) . as_ptr ( ) . byte_add ( mem:: size_of :: < SdtHeader > ( ) ) as * const u8 ,
106
+ table. length as usize - mem:: size_of :: < SdtHeader > ( ) ,
107
+ )
108
+ } ;
109
+ interpreter. load_table ( stream) . map_err ( |err| AcpiError :: Aml ( err) ) ?;
110
+ Ok ( ( ) )
111
+ }
112
+
113
+ let dsdt = tables. dsdt ( ) ?;
114
+ let interpreter = Interpreter :: new ( aml_handler, dsdt. revision ) ;
115
+ load_table ( & interpreter, & acpi_handler, dsdt) ?;
116
+
117
+ for ssdt in tables. ssdts ( ) {
118
+ load_table ( & interpreter, & acpi_handler, ssdt) ?;
119
+ }
120
+
121
+ Ok ( interpreter)
122
+ }
123
+
124
+ /// Load the supplied byte stream as an AML table. This should be only the encoded AML stream -
125
+ /// not the header at the start of a table. If you've used [`Interpreter::new_from_tables`],
126
+ /// you'll likely not need to load any tables manually.
86
127
pub fn load_table ( & self , stream : & [ u8 ] ) -> Result < ( ) , AmlError > {
87
128
let context = unsafe { MethodContext :: new_from_table ( stream) } ;
88
129
self . do_execute_method ( context) ?;
93
134
/// not a method, the object will instead be returned - this is useful for objects that can
94
135
/// either be defined directly, or through a method (e.g. a `_CRS` object).
95
136
pub fn invoke_method ( & self , path : AmlName , args : Vec < Arc < Object > > ) -> Result < Arc < Object > , AmlError > {
96
- info ! ( "Invoking AML method: {}" , path) ;
137
+ trace ! ( "Invoking AML method: {}" , path) ;
97
138
98
139
let object = self . namespace . lock ( ) . get ( path. clone ( ) ) ?. clone ( ) ;
99
140
match object. typ ( ) {
0 commit comments