From 41ce7fdf1f96cf8cfe254981976ddf20f6cf61b4 Mon Sep 17 00:00:00 2001
From: Connor Wood <connorwood71@gmail.com>
Date: Sun, 30 Jul 2017 11:23:32 +0300
Subject: [PATCH] Implemented much of ctx::modify and ctx::get

---
 src/acpi/aml/parser.rs      | 90 ++++++++++++++++++++++++++++++++-----
 src/acpi/aml/termlist.rs    |  2 +-
 src/acpi/aml/type1opcode.rs |  6 +--
 src/acpi/aml/type2opcode.rs | 12 ++---
 4 files changed, 88 insertions(+), 22 deletions(-)

diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs
index 1cfc6e08..2cc907cd 100644
--- a/src/acpi/aml/parser.rs
+++ b/src/acpi/aml/parser.rs
@@ -283,29 +283,95 @@ impl AmlExecutionContext {
         ACPI_TABLE.namespace.write()
     }
 
-    pub fn modify(&mut self, name: AmlValue, value: AmlValue) {
-        // TODO: throw errors
-        // TODO: return DRO
+    pub fn modify(&mut self, name: AmlValue, value: AmlValue) -> Result<(), AmlError> {
         match name {
-            AmlValue::None => (),
             AmlValue::ObjectReference(r) => match r {
-                ObjectReference::ArgObj(_) => (),
+                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::Index(c, v) => {
+                    let idx = v.get_as_integer()? as usize;
+                    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)
+                        },
+                        _ => return Err(AmlError::AmlValueError)
+                    }
+                }
             },
-            _ => ()
+            AmlValue::String(s) => if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() {
+                namespace.insert(s, value);
+            },
+            _ => return Err(AmlError::AmlValueError)
         }
+
+        Ok(())
     }
 
-    pub fn get(&self, name: AmlValue) -> AmlValue {
-        match name {
-            AmlValue::None => AmlValue::None,
+    pub fn get(&self, name: AmlValue) -> Result<AmlValue, AmlError> {
+        Ok(match name {
             AmlValue::ObjectReference(r) => match r {
                 ObjectReference::ArgObj(i) => self.arg_vars[i as usize].clone(),
                 ObjectReference::LocalObj(i) => self.local_vars[i as usize].clone(),
-                _ => AmlValue::None
+                ObjectReference::Object(ref s) => if let Some(ref namespace) = *ACPI_TABLE.namespace.read() {
+                    if let Some(o) = namespace.get(s) {
+                        o.clone()
+                    } else {
+                        AmlValue::None
+                    }
+                } else { AmlValue::None },
+                ObjectReference::Index(c, v) => if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() {
+                    let idx = v.get_as_integer()? as usize;
+                    match *c {
+                        AmlValue::Package(p) => p[idx].clone(),
+                        _ => AmlValue::None
+                    }
+                } else {
+                    AmlValue::None
+                }
             },
+            AmlValue::String(ref s) => if let Some(ref namespace) = *ACPI_TABLE.namespace.read() {
+                if let Some(o) = namespace.get(s) {
+                    o.clone()
+                } else {
+                    AmlValue::None
+                }
+            } else { AmlValue::None },
             _ => AmlValue::None
-        }
+        })
     }
 }
diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs
index 8087c44b..262f7312 100644
--- a/src/acpi/aml/termlist.rs
+++ b/src/acpi/aml/termlist.rs
@@ -125,7 +125,7 @@ pub fn parse_method_invocation(data: &[u8],
     }
     
     let name = parse_name_string(data, ctx)?;
-    let method = ctx.get(name.val.clone());
+    let method = ctx.get(name.val.clone())?;
 
     let method = match method {
         AmlValue::None => return Err(AmlError::AmlDeferredLoad),
diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs
index bf6f7d60..2ea0482b 100644
--- a/src/acpi/aml/type1opcode.rs
+++ b/src/acpi/aml/type1opcode.rs
@@ -151,7 +151,7 @@ fn parse_def_load(data: &[u8],
     let name = parse_name_string(&data[2..], ctx)?;
     let ddb_handle_object = parse_super_name(&data[2 + name.len..], ctx)?;
 
-    let tbl = ctx.get(name.val).get_as_buffer()?;
+    let tbl = ctx.get(name.val)?.get_as_buffer()?;
     let sdt = unsafe { &*(tbl.as_ptr() as *const Sdt) };
 
     if is_aml_table(sdt) {
@@ -223,7 +223,7 @@ fn parse_def_reset(data: &[u8],
     parser_opcode_extended!(data, 0x26);
 
     let object = parse_super_name(&data[2..], ctx)?;
-    ctx.get(object.val.clone()).get_as_event()?;
+    ctx.get(object.val.clone())?.get_as_event()?;
 
     ctx.modify(object.val.clone(), AmlValue::Event(0));
 
@@ -333,7 +333,7 @@ fn parse_def_unload(data: &[u8],
 
     let object = parse_super_name(&data[2..], ctx)?;
 
-    let delta = ctx.get(object.val).get_as_ddb_handle()?;
+    let delta = ctx.get(object.val)?.get_as_ddb_handle()?;
     let mut namespace = ctx.prelock();
 
     if let Some(ref mut ns) = *namespace {
diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs
index d0a6c323..20dc7566 100644
--- a/src/acpi/aml/type2opcode.rs
+++ b/src/acpi/aml/type2opcode.rs
@@ -271,7 +271,7 @@ fn parse_def_ref_of(data: &[u8],
     let obj = parse_super_name(&data[1..], ctx)?;
     let res = match obj.val {
         AmlValue::String(ref s) => {
-            match ctx.get(AmlValue::String(s.clone())) {
+            match ctx.get(AmlValue::String(s.clone()))? {
                 AmlValue::None => return Err(AmlError::AmlValueError),
                 _ => ObjectReference::Object(s.clone())
             }
@@ -299,7 +299,7 @@ fn parse_def_deref_of(data: &[u8],
     parser_opcode!(data, 0x83);
 
     let obj = parse_term_arg(&data[1..], ctx)?;
-    let res = ctx.get(obj.val);
+    let res = ctx.get(obj.val)?;
 
     match res {
         AmlValue::None => Err(AmlError::AmlValueError),
@@ -368,7 +368,7 @@ fn parse_def_increment(data: &[u8],
     let obj = parse_super_name(&data[1..], ctx)?;
     
     let mut namespace = ctx.prelock();
-    let value = AmlValue::Integer(ctx.get(obj.val.clone()).get_as_integer()? + 1);
+    let value = AmlValue::Integer(ctx.get(obj.val.clone())?.get_as_integer()? + 1);
     ctx.modify(obj.val, value.clone());
     
     Ok(AmlParseType {
@@ -773,7 +773,7 @@ fn parse_def_size_of(data: &[u8],
     parser_opcode!(data, 0x87);
 
     let name = parse_super_name(&data[1..], ctx)?;
-    let obj = ctx.get(name.val);
+    let obj = ctx.get(name.val)?;
 
     let res = match obj {
         AmlValue::Buffer(ref v) => v.len(),
@@ -1053,7 +1053,7 @@ fn parse_def_cond_ref_of(data: &[u8],
 
     let res = match obj.val {
         AmlValue::String(ref s) => {
-            match ctx.get(AmlValue::String(s.clone())) {
+            match ctx.get(AmlValue::String(s.clone()))? {
                 AmlValue::None => return Ok(AmlParseType {
                     val: AmlValue::Integer(0),
                     len: 1 + obj.len + target.len
@@ -1135,7 +1135,7 @@ fn parse_def_decrement(data: &[u8],
     let obj = parse_super_name(&data[1..], ctx)?;
     
     let mut namespace = ctx.prelock();
-    let value = AmlValue::Integer(ctx.get(obj.val.clone()).get_as_integer()? - 1);
+    let value = AmlValue::Integer(ctx.get(obj.val.clone())?.get_as_integer()? - 1);
     ctx.modify(obj.val, value.clone());
     
     Ok(AmlParseType {
-- 
GitLab