Prechádzať zdrojové kódy

Implement DefStore for Names

More work needed to support storing into the debug object, locals, and args
Isaac Woods 5 rokov pred
rodič
commit
390ee97a4f

+ 9 - 0
aml_parser/src/namespace.rs

@@ -87,6 +87,15 @@ impl Namespace {
         self.get(handle).map_err(|_| AmlError::ObjectDoesNotExist(path.as_string()))
     }
 
+    pub fn get_mut(&mut self, handle: AmlHandle) -> Result<&mut AmlValue, AmlError> {
+        self.object_map.get_mut(&handle).ok_or(AmlError::HandleDoesNotExist(handle))
+    }
+
+    pub fn get_by_path_mut(&mut self, path: &AmlName) -> Result<&mut AmlValue, AmlError> {
+        let handle = *self.name_map.get(path).ok_or(AmlError::ObjectDoesNotExist(path.as_string()))?;
+        self.get_mut(handle).map_err(|_| AmlError::ObjectDoesNotExist(path.as_string()))
+    }
+
     /// Search for an object at the given path of the namespace, applying the search rules
     /// described in §5.3 of the ACPI specification, if they are applicable. Returns the handle of
     /// the first valid object, if found.

+ 1 - 0
aml_parser/src/opcode.rs

@@ -43,6 +43,7 @@ pub const DEF_RETURN_OP: u8 = 0xa4;
  * Type 2 opcodes
  */
 pub const DEF_L_EQUAL_OP: u8 = 0x93;
+pub const DEF_STORE_OP: u8 = 0x70;
 
 /*
  * Miscellaneous objects

+ 49 - 3
aml_parser/src/type2.rs

@@ -1,7 +1,7 @@
 use crate::{
-    name_object::name_string,
+    name_object::{name_string, super_name, Target},
     opcode::{self, opcode},
-    parser::{choice, comment_scope_verbose, try_with_context, ParseResult, Parser},
+    parser::{choice, comment_scope, comment_scope_verbose, id, try_with_context, Parser},
     term_object::term_arg,
     value::AmlValue,
     AmlError,
@@ -24,7 +24,7 @@ where
      *                DefSubtract | DefTimer | DefToBCD | DefToBuffer | DefToDecimalString |
      *                DefToHexString | DefToInteger | DefToString | DefWait | DefXOr | MethodInvocation
      */
-    comment_scope_verbose("Type2Opcode", choice!(def_l_equal(), method_invocation()))
+    comment_scope_verbose("Type2Opcode", choice!(def_l_equal(), def_store(), method_invocation()))
 }
 
 fn def_l_equal<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
@@ -45,6 +45,52 @@ where
         .map(|((), result)| Ok(result))
 }
 
+fn def_store<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
+where
+    'c: 'a,
+{
+    /*
+     * DefStore := 0x70 TermArg SuperName
+     *
+     * Implicit conversion is only applied when the destination target is a `Name` - not when we
+     * are storing into a method local or argument (these stores are semantically identical to
+     * CopyObject). We must also make sure to return a copy of the data that is in the destination
+     * after the store (as opposed to the data we think we put into it), because some stores can
+     * alter the data during the store.
+     */
+    opcode(opcode::DEF_STORE_OP)
+        .then(comment_scope("DefStore", term_arg().then(super_name())))
+        .map_with_context(|((), (value, target)), context| {
+            match target {
+                Target::Name(ref path) => {
+                    let handle =
+                        try_with_context!(context, context.namespace.search(path, &context.current_scope));
+                    let desired_type = context.namespace.get(handle).unwrap().type_of();
+                    let converted_object = try_with_context!(context, value.as_type(desired_type));
+
+                    *try_with_context!(context, context.namespace.get_mut(handle)) =
+                        AmlValue::Name(box converted_object);
+                    (Ok(context.namespace.get(handle).unwrap().clone()), context)
+                }
+
+                Target::Debug => {
+                    // TODO
+                    unimplemented!()
+                }
+
+                Target::Arg(arg_num) => {
+                    // TODO
+                    unimplemented!()
+                }
+
+                Target::Local(local_num) => {
+                    // TODO
+                    unimplemented!()
+                }
+            }
+        })
+}
+
 fn method_invocation<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
 where
     'c: 'a,