浏览代码

Start work on object initialization

This is a way from being finished, but will travserse the namespace and
initialize the hardware. This uses a bunch of AML we don't currently
implement on QEMU, so will stay unfinished until we can get through QEMU's
_STA objects.
Isaac Woods 4 年之前
父节点
当前提交
77eec36828
共有 1 个文件被更改,包括 56 次插入0 次删除
  1. 56 0
      aml/src/lib.rs

+ 56 - 0
aml/src/lib.rs

@@ -238,6 +238,62 @@ impl AmlContext {
         }
     }
 
+    pub fn initialize_objects(&mut self) -> Result<(), AmlError> {
+        use name_object::NameSeg;
+        use namespace::NamespaceLevel;
+        use value::StatusObject;
+
+        /*
+         * TODO:
+         *    - unconditionally execute `\_SB._INI`, if it exists
+         *    - traverse namespace, looking for devices
+         *    - if `_STA` is present, evaluate it. If not, assume device is present and functional.
+         *    - if device is present, evaluate `_INI` if it exists
+         *    - if device is present, or isn't present but is functional, traverse it's children for more devices
+         */
+        /*
+         * If `\_SB._INI` exists, we unconditionally execute it at the beginning of device initialization.
+         */
+        match self.invoke_method(&AmlName::from_str("\\_SB._INI").unwrap(), Args::default()) {
+            Ok(_) => (),
+            Err(AmlError::ValueDoesNotExist(_)) => (),
+            Err(err) => return Err(err),
+        }
+
+        /*
+         * Next, we traverse the namespace, looking for devices.
+         *
+         * XXX: we clone the namespace here, which obviously drives up heap burden quite a bit (not as much as you
+         * might first expect though - we're only duplicating the level data structure, not all the objects). The
+         * issue here is that we need to access the namespace during traversal (e.g. to invoke a method), which the
+         * borrow checker really doesn't like. A better solution could be a iterator-like traversal system that
+         * keeps track of the namespace without keeping it borrowed. This works for now.
+         */
+        self.namespace.clone().traverse(|path, level: &NamespaceLevel| match level.typ {
+            LevelType::Device => {
+                let sta = if level.values.contains_key(&NameSeg::from_str("_STA").unwrap()) {
+                    self.invoke_method(&AmlName::from_str("_STA").unwrap().resolve(&path)?, Args::default())?
+                        .as_status()?
+                } else {
+                    StatusObject::default()
+                };
+
+                // TODO: if this object is present, evaluate _INI if it exists
+
+                // TODO: can devices contain other devices?
+                Ok(true)
+            }
+
+            LevelType::Scope => Ok(true),
+
+            // TODO: can either of these contain devices?
+            LevelType::Processor => Ok(false),
+            LevelType::MethodLocals => Ok(false),
+        })?;
+
+        Ok(())
+    }
+
     pub(crate) fn current_arg(&self, arg: ArgNum) -> Result<&AmlValue, AmlError> {
         self.current_args.as_ref().ok_or(AmlError::InvalidArgAccess(0xff))?.arg(arg)
     }