Sfoglia il codice sorgente

Parse DefMethod

This just extracts the information needed to add it to the namespace and
progress with the parse. It does not actually parse the contents of the
method, as this only needs to be done if we want to execute it.
Isaac Woods 5 anni fa
parent
commit
206de53042

+ 0 - 1
aml_parser/src/lib.rs

@@ -50,7 +50,6 @@ impl AmlContext {
             return Err(AmlError::UnexpectedEndOfStream);
             return Err(AmlError::UnexpectedEndOfStream);
         }
         }
 
 
-
         let table_length = PkgLength::from_raw_length(stream, stream.len() as u32) as PkgLength;
         let table_length = PkgLength::from_raw_length(stream, stream.len() as u32) as PkgLength;
         match term_object::term_list(table_length).parse(stream, self) {
         match term_object::term_list(table_length).parse(stream, self) {
             Ok(_) => Ok(()),
             Ok(_) => Ok(()),

+ 14 - 4
aml_parser/src/parser.rs

@@ -1,4 +1,4 @@
-use crate::{AmlContext, AmlError};
+use crate::{pkg_length::PkgLength, AmlContext, AmlError};
 use alloc::vec::Vec;
 use alloc::vec::Vec;
 use core::marker::PhantomData;
 use core::marker::PhantomData;
 use log::trace;
 use log::trace;
@@ -138,20 +138,30 @@ where
     }
     }
 }
 }
 
 
-pub fn take_n<'a, 'c>(n: usize) -> impl Parser<'a, 'c, &'a [u8]>
+pub fn take_n<'a, 'c>(n: u32) -> impl Parser<'a, 'c, &'a [u8]>
 where
 where
     'c: 'a,
     'c: 'a,
 {
 {
     move |input: &'a [u8], context| {
     move |input: &'a [u8], context| {
-        if input.len() < n {
+        if (input.len() as u32) < n {
             return Err((input, context, AmlError::UnexpectedEndOfStream));
             return Err((input, context, AmlError::UnexpectedEndOfStream));
         }
         }
 
 
-        let (result, new_input) = input.split_at(n);
+        let (result, new_input) = input.split_at(n as usize);
         Ok((new_input, context, result))
         Ok((new_input, context, result))
     }
     }
 }
 }
 
 
+pub fn take_to_end_of_pkglength<'a, 'c>(length: PkgLength) -> impl Parser<'a, 'c, &'a [u8]>
+where
+    'c: 'a,
+{
+    move |input: &'a [u8], context| {
+        let bytes_to_take = (input.len() as u32) - length.end_offset;
+        take_n(bytes_to_take).parse(input, context)
+    }
+}
+
 // TODO: can we use const generics (e.g. [R; N]) to avoid allocating?
 // TODO: can we use const generics (e.g. [R; N]) to avoid allocating?
 pub fn n_of<'a, 'c, P, R>(parser: P, n: usize) -> impl Parser<'a, 'c, Vec<R>>
 pub fn n_of<'a, 'c, P, R>(parser: P, n: usize) -> impl Parser<'a, 'c, Vec<R>>
 where
 where

+ 1 - 1
aml_parser/src/pkg_length.rs

@@ -64,7 +64,7 @@ where
         }
         }
 
 
         let (new_input, context, length): (&[u8], &mut AmlContext, u32) =
         let (new_input, context, length): (&[u8], &mut AmlContext, u32) =
-            match take_n(byte_count as usize).parse(new_input, context) {
+            match take_n(byte_count as u32).parse(new_input, context) {
                 Ok((new_input, context, bytes)) => {
                 Ok((new_input, context, bytes)) => {
                     let initial_length = u32::from(lead_byte.get_bits(0..4));
                     let initial_length = u32::from(lead_byte.get_bits(0..4));
                     (
                     (

+ 61 - 3
aml_parser/src/term_object.rs

@@ -1,7 +1,17 @@
 use crate::{
 use crate::{
     name_object::{name_seg, name_string},
     name_object::{name_seg, name_string},
     opcode::{self, ext_opcode, opcode},
     opcode::{self, ext_opcode, opcode},
-    parser::{choice, comment_scope, take, take_u16, take_u32, take_u64, ParseResult, Parser},
+    parser::{
+        choice,
+        comment_scope,
+        take,
+        take_to_end_of_pkglength,
+        take_u16,
+        take_u32,
+        take_u64,
+        ParseResult,
+        Parser,
+    },
     pkg_length::{pkg_length, PkgLength},
     pkg_length::{pkg_length, PkgLength},
     value::{AmlValue, FieldFlags},
     value::{AmlValue, FieldFlags},
     AmlContext,
     AmlContext,
@@ -30,7 +40,6 @@ where
     }
     }
 }
 }
 
 
-// TODO: maybe return `AmlValue` on success
 pub fn term_object<'a, 'c>() -> impl Parser<'a, 'c, ()>
 pub fn term_object<'a, 'c>() -> impl Parser<'a, 'c, ()>
 where
 where
     'c: 'a,
     'c: 'a,
@@ -39,7 +48,23 @@ where
      * TermObj := NamespaceModifierObj | NamedObj | Type1Opcode | Type2Opcode
      * TermObj := NamespaceModifierObj | NamedObj | Type1Opcode | Type2Opcode
      * NamespaceModifierObj := DefAlias | DefName | DefScope
      * NamespaceModifierObj := DefAlias | DefName | DefScope
      */
      */
-    comment_scope("TermObj", choice!(def_scope(), def_op_region(), def_field()))
+    comment_scope("TermObj", choice!(def_scope(), named_obj()))
+}
+
+pub fn named_obj<'a, 'c>() -> impl Parser<'a, 'c, ()>
+where
+    'c: 'a,
+{
+    /*
+     * NamedObj := DefBankField | DefCreateBitField | DefCreateByteField | DefCreateDWordField |
+     *             DefCreateField | DefCreateQWordField | DefCreateWordField | DefDataRegion |
+     *             DefExternal | DefOpRegion | DefPowerRes | DefProcessor | DefThermalZone |
+     *             DefMethod | DefMutex
+     *
+     * XXX: DefMethod and DefMutex (at least) are not included in any rule in the AML grammar,
+     * but are defined in the NamedObj section so we assume they're part of NamedObj
+     */
+    comment_scope("NamedObj", choice!(def_op_region(), def_field(), def_method()))
 }
 }
 
 
 pub fn def_scope<'a, 'c>() -> impl Parser<'a, 'c, ()>
 pub fn def_scope<'a, 'c>() -> impl Parser<'a, 'c, ()>
@@ -174,6 +199,39 @@ where
     choice!(reserved_field, access_field, named_field)
     choice!(reserved_field, access_field, named_field)
 }
 }
 
 
+pub fn def_method<'a, 'c>() -> impl Parser<'a, 'c, ()>
+where
+    'c: 'a,
+{
+    /*
+     * DefMethod := 0x14 PkgLength NameString MethodFlags TermList
+     * MethodFlags := ByteData (where bits 0-2: ArgCount (0 to 7)
+     *                                bit 3: SerializeFlag (0 = Not Serialized, 1 = Serialized)
+     *                                bits 4-7: SyncLevel (0x00 to 0x0f))
+     */
+    opcode(opcode::METHOD_OP)
+        .then(comment_scope(
+            "DefMethod",
+            pkg_length()
+                .then(name_string())
+                .then(take())
+                .feed(|((length, name), flags)| {
+                    take_to_end_of_pkglength(length).map(move |code| (name.clone(), flags, code))
+                })
+                .map_with_context(|(name, flags, code), context| {
+                    // TODO: put it in the namespace
+                    trace!(
+                        "Method with name {} with flags {:#b}, length = {}",
+                        name,
+                        flags,
+                        code.len()
+                    );
+                    ((), context)
+                }),
+        ))
+        .discard_result()
+}
+
 pub fn term_arg<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
 pub fn term_arg<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
 where
 where
     'c: 'a,
     'c: 'a,

+ 22 - 0
aml_parser/src/value.rs

@@ -68,6 +68,28 @@ impl FieldFlags {
         }
         }
     }
     }
 }
 }
+
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub struct MethodFlags(u8);
+
+impl MethodFlags {
+    pub fn new(value: u8) -> MethodFlags {
+        MethodFlags(value)
+    }
+
+    pub fn arg_count(&self) -> u8 {
+        self.0.get_bits(0..3)
+    }
+
+    pub fn serialize(&self) -> bool {
+        self.0.get_bit(3)
+    }
+
+    pub fn sync_level(&self) -> u8 {
+        self.0.get_bits(4..8)
+    }
+}
+
 #[derive(Clone, PartialEq, Eq, Debug)]
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub enum AmlValue {
 pub enum AmlValue {
     Integer(u64),
     Integer(u64),