Procházet zdrojové kódy

Support reads from buffer fields, implicitly converting to integer or buffer

Isaac Woods před 3 roky
rodič
revize
fb1bc5870a
3 změnil soubory, kde provedl 31 přidání a 2 odebrání
  1. 1 0
      aml/src/lib.rs
  2. 1 1
      aml/src/resource.rs
  3. 29 1
      aml/src/value.rs

+ 1 - 0
aml/src/lib.rs

@@ -791,6 +791,7 @@ pub enum AmlError {
     /// Produced when the `Mid` operator is applied to a value of a type other than `Buffer` or `String`.
     TypeCannotBeSliced(AmlType),
     TypeCannotBeWrittenToBufferField(AmlType),
+    BufferFieldIndexesOutOfBounds,
 }
 
 #[cfg(test)]

+ 1 - 1
aml/src/resource.rs

@@ -22,7 +22,7 @@ pub enum Resource {
 pub fn resource_descriptor_list(descriptor: &AmlValue) -> Result<Vec<Resource>, AmlError> {
     if let AmlValue::Buffer(bytes) = descriptor {
         let mut descriptors = Vec::new();
-        let mut buffer_data = bytes.lock();
+        let buffer_data = bytes.lock();
         let mut bytes = buffer_data.as_slice();
 
         while bytes.len() > 0 {

+ 29 - 1
aml/src/value.rs

@@ -295,10 +295,11 @@ impl AmlValue {
             }
 
             /*
-             * Read from a field. This can return either a `Buffer` or an `Integer`, so we make sure to call
+             * Read from a field or buffer field. These can return either a `Buffer` or an `Integer`, so we make sure to call
              * `as_integer` on the result.
              */
             AmlValue::Field { .. } => self.read_field(context)?.as_integer(context),
+            AmlValue::BufferField { .. } => self.read_buffer_field(context)?.as_integer(context),
 
             _ => Err(AmlError::IncompatibleValueConversion { current: self.type_of(), target: AmlType::Integer }),
         }
@@ -309,6 +310,7 @@ impl AmlValue {
             AmlValue::Buffer(ref bytes) => Ok(bytes.clone()),
             // TODO: implement conversion of String and Integer to Buffer
             AmlValue::Field { .. } => self.read_field(context)?.as_buffer(context),
+            AmlValue::BufferField { .. } => self.read_buffer_field(context)?.as_buffer(context),
             _ => Err(AmlError::IncompatibleValueConversion { current: self.type_of(), target: AmlType::Buffer }),
         }
     }
@@ -501,6 +503,32 @@ impl AmlValue {
         }
     }
 
+    pub fn read_buffer_field(&self, context: &AmlContext) -> Result<AmlValue, AmlError> {
+        use bitvec::view::BitView;
+
+        if let AmlValue::BufferField { buffer_data, offset, length } = self {
+            let offset = *offset as usize;
+            let length = *length as usize;
+            let inner_data = buffer_data.lock();
+
+            if (offset + length) > (inner_data.len() * 8) {
+                return Err(AmlError::BufferFieldIndexesOutOfBounds);
+            }
+
+            let bitslice = inner_data.view_bits::<bitvec::order::Lsb0>();
+            let bits = &bitslice[offset..(offset + length)];
+            if length > 64 {
+                Ok(AmlValue::Buffer(Arc::new(spinning_top::Spinlock::new(bits.as_raw_slice().to_vec()))))
+            } else {
+                let mut value = 0u64;
+                value.view_bits_mut::<bitvec::order::Lsb0>()[0..length].clone_from_bitslice(bits);
+                Ok(AmlValue::Integer(value))
+            }
+        } else {
+            Err(AmlError::IncompatibleValueConversion { current: self.type_of(), target: AmlType::BufferField })
+        }
+    }
+
     pub fn write_buffer_field(&mut self, value: AmlValue, context: &mut AmlContext) -> Result<(), AmlError> {
         use bitvec::view::BitView;