@@ -23,7 +23,17 @@ use bit_field::BitField;
23
23
use core:: { mem, str:: FromStr } ;
24
24
use log:: { info, trace, warn} ;
25
25
use namespace:: { AmlName , Namespace , NamespaceLevelKind } ;
26
- use object:: { FieldFlags , FieldUnit , FieldUnitKind , MethodFlags , Object , ObjectType , ReferenceKind } ;
26
+ use object:: {
27
+ DeviceStatus ,
28
+ FieldFlags ,
29
+ FieldUnit ,
30
+ FieldUnitKind ,
31
+ FieldUpdateRule ,
32
+ MethodFlags ,
33
+ Object ,
34
+ ObjectType ,
35
+ ReferenceKind ,
36
+ } ;
27
37
use op_region:: { OpRegion , RegionHandler , RegionSpace } ;
28
38
use spinning_top:: Spinlock ;
29
39
@@ -109,6 +119,85 @@ where
109
119
handlers. insert ( space, Box :: new ( handler) ) ;
110
120
}
111
121
122
+ /// Initialize the namespace - this should be called after all tables have been loaded and
123
+ /// operation region handlers registered. Specifically, it will call relevant `_STA`, `_INI`,
124
+ /// and `_REG` methods.
125
+ pub fn initialize_namespace ( & self ) {
126
+ /*
127
+ * This should match the initialization order of ACPICA and uACPI.
128
+ */
129
+ if let Err ( err) = self . invoke_method_if_present ( AmlName :: from_str ( "\\ _INI" ) . unwrap ( ) , vec ! [ ] ) {
130
+ warn ! ( "Invoking \\ _INI failed: {:?}" , err) ;
131
+ }
132
+ if let Err ( err) = self . invoke_method_if_present ( AmlName :: from_str ( "\\ _SB._INI" ) . unwrap ( ) , vec ! [ ] ) {
133
+ warn ! ( "Invoking \\ _SB._INI failed: {:?}" , err) ;
134
+ }
135
+
136
+ // TODO: run all _REGs for globally-installed handlers (this might need more bookkeeping)
137
+
138
+ /*
139
+ * We can now initialize each device in the namespace. For each device, we evaluate `_STA`,
140
+ * which indicates if the device is present and functional. If this method does not exist,
141
+ * we assume the device should be initialized.
142
+ *
143
+ * We then evaluate `_INI` for the device. This can dynamically populate objects such as
144
+ * `_ADR`, `_CID`, `_HID`, `_SUN`, and `_UID`, and so is necessary before further
145
+ * operation.
146
+ */
147
+ let mut num_devices_initialized = 0 ;
148
+ /*
149
+ * TODO
150
+ * We clone a copy of the namespace here to traverse while executing all the `_STA` and
151
+ * `_INI` objects. Avoiding this would be good, but is not easy, as we need
152
+ * potentially-mutable access while executing all of the methods.
153
+ */
154
+ let mut namespace = self . namespace . lock ( ) . clone ( ) ;
155
+ let init_status = namespace. traverse ( |path, level| {
156
+ match level. kind {
157
+ NamespaceLevelKind :: Device
158
+ | NamespaceLevelKind :: Processor
159
+ | NamespaceLevelKind :: ThermalZone
160
+ | NamespaceLevelKind :: PowerResource => {
161
+ let should_initialize = match self
162
+ . invoke_method_if_present ( AmlName :: from_str ( "_STA" ) . unwrap ( ) . resolve ( path) ?, vec ! [ ] )
163
+ {
164
+ Ok ( Some ( result) ) => {
165
+ let Object :: Integer ( result) = * result else { panic ! ( ) } ;
166
+ let status = DeviceStatus ( result) ;
167
+ status. present ( ) && status. functioning ( )
168
+ }
169
+ Ok ( None ) => true ,
170
+ Err ( err) => {
171
+ warn ! ( "Failed to evaluate _STA for device {}: {:?}" , path, err) ;
172
+ false
173
+ }
174
+ } ;
175
+
176
+ if should_initialize {
177
+ num_devices_initialized += 1 ;
178
+ if let Err ( err) = self
179
+ . invoke_method_if_present ( AmlName :: from_str ( "_INI" ) . unwrap ( ) . resolve ( path) ?, vec ! [ ] )
180
+ {
181
+ warn ! ( "Failed to evaluate _INI for device {}: {:?}" , path, err) ;
182
+ }
183
+ Ok ( true )
184
+ } else {
185
+ /*
186
+ * If this device should not be initialized, don't initialize it's children.
187
+ */
188
+ Ok ( false )
189
+ }
190
+ }
191
+ _ => Ok ( true ) ,
192
+ }
193
+ } ) ;
194
+ if let Err ( err) = init_status {
195
+ warn ! ( "Error while traversing namespace for devices: {:?}" , err) ;
196
+ }
197
+
198
+ info ! ( "Initialized {} devices" , num_devices_initialized) ;
199
+ }
200
+
112
201
fn do_execute_method ( & self , mut context : MethodContext ) -> Result < Arc < Object > , AmlError > {
113
202
/*
114
203
* This is the main loop that executes operations. Every op is handled at the top-level of
@@ -2529,6 +2618,7 @@ pub trait Handler: Send + Sync {
2529
2618
/// without causing a deadlock.
2530
2619
fn acquire ( & self , mutex : Handle , timeout : u16 ) -> Result < ( ) , AmlError > ;
2531
2620
fn release ( & self , mutex : Handle ) ;
2621
+
2532
2622
fn breakpoint ( & self ) { }
2533
2623
2534
2624
fn handle_debug ( & self , _object : & Object ) { }
0 commit comments