Browse Source

Parse String constants in ComputationalData

Isaac Woods 5 years ago
parent
commit
b63cedb5df
3 changed files with 29 additions and 2 deletions
  1. 2 0
      aml_parser/src/lib.rs
  2. 25 2
      aml_parser/src/term_object.rs
  3. 2 0
      aml_parser/src/value.rs

+ 2 - 0
aml_parser/src/lib.rs

@@ -33,6 +33,8 @@ pub enum AmlError {
     UnexpectedByte(u8),
     InvalidNameSeg([u8; 4]),
     InvalidFieldFlags,
+    UnterminatedStringConstant,
+    InvalidStringConstant,
 }
 
 #[derive(Debug)]

+ 25 - 2
aml_parser/src/term_object.rs

@@ -364,8 +364,25 @@ where
      * RevisionOp := ExtOpPrefix(0x5b) 0x30
      */
     let const_parser = |input: &'a [u8], context: &'c mut AmlContext| {
-        let (new_input, context, op) = take().parse(input, context)?;
+        let string_parser = |input: &'a [u8], context| -> ParseResult<'a, 'c, AmlValue> {
+            /*
+             * Using `position` isn't very efficient here, but is probably fine because the
+             * strings are usually quite short.
+             */
+            let nul_position = match input.iter().position(|&c| c == b'\0') {
+                Some(position) => position,
+                None => return Err((input, context, AmlError::UnterminatedStringConstant)),
+            };
+
+            let string = String::from(match str::from_utf8(&input[0..nul_position]) {
+                Ok(string) => string,
+                Err(_) => return Err((input, context, AmlError::InvalidStringConstant)),
+            });
 
+            Ok((&input[(nul_position + 1)..], context, AmlValue::String(string)))
+        };
+
+        let (new_input, context, op) = take().parse(input, context)?;
         match op {
             opcode::BYTE_CONST => {
                 take().map(|value| Ok(AmlValue::Integer(value as u64))).parse(new_input, context)
@@ -379,7 +396,7 @@ where
             opcode::QWORD_CONST => {
                 take_u64().map(|value| Ok(AmlValue::Integer(value))).parse(new_input, context)
             }
-            // TODO: implement String
+            opcode::STRING_PREFIX => string_parser.parse(new_input, context),
             opcode::ZERO_OP => Ok((new_input, context, AmlValue::Integer(0))),
             opcode::ONE_OP => Ok((new_input, context, AmlValue::Integer(1))),
             opcode::ONES_OP => Ok((new_input, context, AmlValue::Integer(u64::max_value()))),
@@ -447,5 +464,11 @@ mod test {
             AmlValue::Integer(0xde6700ff651235f3),
             &[0x28]
         );
+        check_ok!(
+            computational_data()
+                .parse(&[0x0d, b'A', b'B', b'C', b'D', b'\0', 0xff, 0xf5], &mut context),
+            AmlValue::String(String::from("ABCD")),
+            &[0xff, 0xf5]
+        );
     }
 }

+ 2 - 0
aml_parser/src/value.rs

@@ -1,4 +1,5 @@
 use crate::AmlError;
+use alloc::{collections::BTreeMap, string::String, vec::Vec};
 use bit_field::BitField;
 
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
@@ -93,5 +94,6 @@ impl MethodFlags {
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub enum AmlValue {
     Integer(u64),
+    String(String),
     Field { flags: FieldFlags, offset: u64, length: u64 },
 }