Ver Fonte

Only read from field if update rule is Preserve

Isaac Woods há 4 anos atrás
pai
commit
e54158ee01
1 ficheiros alterados com 15 adições e 13 exclusões
  1. 15 13
      aml/src/value.rs

+ 15 - 13
aml/src/value.rs

@@ -336,12 +336,20 @@ impl AmlValue {
 
     pub fn write_field(&mut self, value: AmlValue, context: &mut AmlContext) -> Result<(), AmlError> {
         /*
-         * TODO:
-         * If we need to preserve the field's value, we'll need the contents of the field before we write it. To
-         * appease the borrow-checker, this is done before we destructure the field for now, but it would be more
-         * efficient if we could only do this if the field's update rule is Preserve.
+         * If the field's update rule is `Preserve`, we need to read the initial value of the field, so we can
+         * overwrite the correct bits. We destructure the field to do the actual write, so we read from it if
+         * needed here, otherwise the borrow-checker doesn't understand.
          */
-        let field_value = self.read_field(context)?.as_integer(context)?;
+        let field_update_rule = if let AmlValue::Field { region, flags, offset, length } = self {
+            flags.field_update_rule()?
+        } else {
+            return Err(AmlError::IncompatibleValueConversion);
+        };
+        let mut field_value = match field_update_rule {
+            FieldUpdateRule::Preserve => self.read_field(context)?.as_integer(context)?,
+            FieldUpdateRule::WriteAsOnes => 0xffffffff_ffffffff,
+            FieldUpdateRule::WriteAsZeros => 0x0,
+        };
 
         if let AmlValue::Field { region, flags, offset, length } = self {
             let maximum_access_size = {
@@ -370,14 +378,8 @@ impl AmlValue {
              */
             let access_size = u64::max(minimum_access_size, length.next_power_of_two());
 
-            let mut value_to_write = match flags.field_update_rule()? {
-                FieldUpdateRule::Preserve => field_value,
-                FieldUpdateRule::WriteAsOnes => 0xffffffff_ffffffff,
-                FieldUpdateRule::WriteAsZeros => 0x0,
-            };
-            value_to_write.set_bits(0..(*length as usize), value.as_integer(context)?);
-
-            context.write_region(*region, *offset, access_size, value_to_write)
+            field_value.set_bits(0..(*length as usize), value.as_integer(context)?);
+            context.write_region(*region, *offset, access_size, field_value)
         } else {
             Err(AmlError::IncompatibleValueConversion)
         }