From 328a89c224fb74c6494e31fae48e62ec80313228 Mon Sep 17 00:00:00 2001
From: Connor Wood <connorwood71@gmail.com>
Date: Thu, 10 Aug 2017 14:28:30 +0200
Subject: [PATCH] Completed context modify, aside from BufferFields and nested
 Indexes

---
 src/acpi/aml/parser.rs | 119 +++++++++++++++++++++++++----------------
 1 file changed, 73 insertions(+), 46 deletions(-)

diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs
index 2cc907cd..b5251d5c 100644
--- a/src/acpi/aml/parser.rs
+++ b/src/acpi/aml/parser.rs
@@ -283,63 +283,90 @@ impl AmlExecutionContext {
         ACPI_TABLE.namespace.write()
     }
 
+    fn modify_local_obj(&mut self, local: usize, value: AmlValue) -> Result<(), AmlError> {
+        self.local_vars[local] = value;
+        Ok(())
+    }
+
+    fn modify_object(&mut self, name: String, value: AmlValue) -> Result<(), AmlError> {
+        if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() {
+            namespace.insert(name, value);
+            Ok(())
+        } else {
+            Err(AmlError::AmlHardFatal)
+        }
+    }
+
+    fn modify_index_final(&mut self, name: String, value: AmlValue, indices: Vec<u64>) -> Result<(), AmlError> {
+        if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() {
+            let obj = if let Some(s) = namespace.get(&name) {
+                s.clone()
+            } else {
+                return Err(AmlError::AmlValueError);
+            };
+            
+            match obj {
+                AmlValue::String(ref string) => {
+                    if indices.len() != 1 {
+                        return Err(AmlError::AmlValueError);
+                    }
+                    
+                    let mut bytes = string.clone().into_bytes();
+                    bytes[indices[0] as usize] = value.get_as_integer()? as u8;
+                    
+                    let string = String::from_utf8(bytes).unwrap();
+                    namespace.insert(name, AmlValue::String(string));
+                },
+                AmlValue::Buffer(ref b) => {
+                    if indices.len() != 1 {
+                        return Err(AmlError::AmlValueError);
+                    }
+                    
+                    let mut b = b.clone();
+                    b[indices[0] as usize] = value.get_as_integer()? as u8;
+                    
+                    namespace.insert(name, AmlValue::Buffer(b));
+                },
+                AmlValue::Package(ref p) => {
+                    // TODO: Nested references need to be handled here
+                    if indices.len() < 0 {
+                        return Err(AmlError::AmlValueError);
+                    }
+                    
+                    let mut p = p.clone();
+//                    let ref mut current = p;
+                    
+                    p[indices[0] as usize] = value;
+                    
+                    namespace.insert(name, AmlValue::Package(p));
+                },
+                _ => return Err(AmlError::AmlValueError)
+            }
+        }
+
+        Ok(())
+    }
+
     pub fn modify(&mut self, name: AmlValue, value: AmlValue) -> Result<(), AmlError> {
         match name {
             AmlValue::ObjectReference(r) => match r {
-                ObjectReference::ArgObj(_) => return Err(AmlError::AmlValueError),
-                ObjectReference::LocalObj(i) => self.local_vars[i as usize] = value,
-                ObjectReference::Object(s) => if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() {
-                    namespace.insert(s, value);
-                },
+                ObjectReference::ArgObj(_) => Err(AmlError::AmlValueError),
+                ObjectReference::LocalObj(i) => self.modify_local_obj(i as usize, value),
+                ObjectReference::Object(s) => self.modify_object(s, value),
                 ObjectReference::Index(c, v) => {
-                    let idx = v.get_as_integer()? as usize;
+                    let idx = v.get_as_integer()?;
                     match *c {
                         AmlValue::ObjectReference(r) => match r {
-                            ObjectReference::Object(s) => {
-                                if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() {
-                                    let obj = if let Some(s) = namespace.get(&s) {
-                                        s.clone()
-                                    } else {
-                                        return Err(AmlError::AmlValueError);
-                                    };
-                                    
-                                    match obj {
-                                        AmlValue::String(ref string) => {
-                                            let mut bytes = string.clone().into_bytes();
-                                            bytes[idx] = value.get_as_integer()? as u8;
-                                            
-                                            let string = String::from_utf8(bytes).unwrap();
-                                            namespace.insert(s, AmlValue::String(string));
-                                        },
-                                        AmlValue::Buffer(ref b) => {
-                                            let mut b = b.clone();
-                                            b[idx] = value.get_as_integer()? as u8;
-
-                                            namespace.insert(s, AmlValue::Buffer(b));
-                                        },
-                                        AmlValue::Package(ref p) => {
-                                            let mut p = p.clone();
-                                            p[idx] = value;
-
-                                            namespace.insert(s, AmlValue::Package(p));
-                                        },
-                                        _ => return Err(AmlError::AmlValueError)
-                                    }
-                                }
-                            },
-                            _ => return Err(AmlError::AmlValueError)
+                            ObjectReference::Object(s) => self.modify_index_final(s, value, vec!(idx)),
+                            _ => Err(AmlError::AmlValueError)
                         },
-                        _ => return Err(AmlError::AmlValueError)
+                        _ => Err(AmlError::AmlValueError)
                     }
                 }
             },
-            AmlValue::String(s) => if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() {
-                namespace.insert(s, value);
-            },
-            _ => return Err(AmlError::AmlValueError)
+            AmlValue::String(s) => self.modify_object(s, value),
+            _ => Err(AmlError::AmlValueError)
         }
-
-        Ok(())
     }
 
     pub fn get(&self, name: AmlValue) -> Result<AmlValue, AmlError> {
-- 
GitLab