@@ -23,7 +23,17 @@ use bit_field::BitField;
2323use core:: { mem, str:: FromStr } ;
2424use log:: { info, trace, warn} ;
2525use 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+ } ;
2737use op_region:: { OpRegion , RegionHandler , RegionSpace } ;
2838use spinning_top:: Spinlock ;
2939
@@ -109,6 +119,85 @@ where
109119 handlers. insert ( space, Box :: new ( handler) ) ;
110120 }
111121
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+
112201 fn do_execute_method ( & self , mut context : MethodContext ) -> Result < Arc < Object > , AmlError > {
113202 /*
114203 * 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 {
25292618 /// without causing a deadlock.
25302619 fn acquire ( & self , mutex : Handle , timeout : u16 ) -> Result < ( ) , AmlError > ;
25312620 fn release ( & self , mutex : Handle ) ;
2621+
25322622 fn breakpoint ( & self ) { }
25332623
25342624 fn handle_debug ( & self , _object : & Object ) { }
0 commit comments