From c79eb0eeabd434b82bbf3084babe393625910e45 Mon Sep 17 00:00:00 2001
From: Connor Wood <connorwood71@gmail.com>
Date: Sun, 23 Jul 2017 13:42:30 +0100
Subject: [PATCH] Implemented table API in full

---
 src/acpi/aml/mod.rs         |  6 +++++-
 src/acpi/aml/namespace.rs   |  7 +++++++
 src/acpi/aml/type1opcode.rs | 11 +++++++++--
 src/acpi/aml/type2opcode.rs | 33 +++++++++++++++++++++++++++++----
 src/acpi/mod.rs             | 37 ++++++++++++++++++++++++++++---------
 src/acpi/rsdt.rs            | 10 +++++++---
 src/acpi/rxsdt.rs           | 28 ++++++++++++++++++++++++++++
 src/acpi/sdt.rs             |  4 ++++
 src/acpi/xsdt.rs            | 10 +++++++---
 src/lib.rs                  |  1 +
 10 files changed, 125 insertions(+), 22 deletions(-)
 create mode 100644 src/acpi/rxsdt.rs

diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs
index f943b54e..9ec105c6 100644
--- a/src/acpi/aml/mod.rs
+++ b/src/acpi/aml/mod.rs
@@ -36,8 +36,12 @@ pub enum AmlError {
 }
 
 pub fn parse_aml_table(sdt: &Sdt) -> Result<Vec<String>, AmlError> {
+    parse_aml_with_scope(sdt, String::from_str("\\").unwrap())
+}
+
+pub fn parse_aml_with_scope(sdt: &Sdt, scope: String) -> Result<Vec<String>, AmlError> {
     let data = sdt.data();
-    let mut ctx = AmlExecutionContext::new(String::from_str("\\").unwrap());
+    let mut ctx = AmlExecutionContext::new(scope);
     
     parse_term_list(data, &mut ctx)?;
 
diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs
index 641ddb5a..9c7f5645 100644
--- a/src/acpi/aml/namespace.rs
+++ b/src/acpi/aml/namespace.rs
@@ -113,6 +113,13 @@ impl AmlValue {
             _ => Err(AmlError::AmlValueError)
         }
     }
+
+    pub fn get_as_ddb_handle(&self) -> Result<Vec<String>, AmlError> {
+        match *self {
+            AmlValue::DDBHandle(ref v) => Ok(v.clone()),
+            _ => Err(AmlError::AmlValueError)
+        }
+    }
     
     pub fn get_as_string(&self) -> Result<String, AmlError> {
         match *self {
diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs
index eb57bc0a..638de9e4 100644
--- a/src/acpi/aml/type1opcode.rs
+++ b/src/acpi/aml/type1opcode.rs
@@ -363,12 +363,19 @@ fn parse_def_unload(data: &[u8],
         })
     }
     
-    // TODO: remove from namespace all values added when `object` was loaded
-    // TODO: globally synchronous (how?)
     parser_opcode_extended!(data, 0x2A);
 
     let object = parse_super_name(&data[2..], ctx)?;
 
+    let delta = ctx.get(object.val).get_as_ddb_handle()?;
+    let mut namespace = ctx.prelock();
+
+    if let Some(ref mut ns) = *namespace {
+        for o in delta {
+            ns.remove(&o);
+        }
+    }
+
     Ok(AmlParseType {
         val: AmlValue::None,
         len: 2 + object.len
diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs
index 00924de8..e445119d 100644
--- a/src/acpi/aml/type2opcode.rs
+++ b/src/acpi/aml/type2opcode.rs
@@ -2,7 +2,7 @@ use alloc::boxed::Box;
 use collections::string::String;
 use collections::vec::Vec;
 
-use super::AmlError;
+use super::{AmlError, parse_aml_with_scope};
 use super::parser::{AmlParseType, ParseResult, AmlExecutionContext, ExecutionState};
 use super::namespace::{AmlValue, ObjectReference};
 use super::pkglength::parse_pkg_length;
@@ -11,6 +11,7 @@ use super::namestring::{parse_super_name, parse_target, parse_name_string, parse
 use super::dataobj::parse_data_ref_obj;
 
 use time::monotonic;
+use acpi::ACPI_TABLE;
 
 #[derive(Debug, Clone)]
 pub enum MatchOpcode {
@@ -1263,8 +1264,6 @@ fn parse_def_load_table(data: &[u8],
         })
     }
     
-    // TODO: Compute the result
-    // TODO: Store the result, if appropriate
     // TODO: Clean up
     parser_opcode_extended!(data, 0x1F);
 
@@ -1275,8 +1274,34 @@ fn parse_def_load_table(data: &[u8],
     let parameter_path = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len + root_path.len..], ctx)?;
     let parameter_data = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len + root_path.len + parameter_path.len..], ctx)?;
 
+    let rxsdt_ptr = ACPI_TABLE.rxsdt.read();
+    
+    if let Some(ref rxsdt) = *rxsdt_ptr {
+        let sig_str = unsafe {
+            *(signature.val.get_as_string()?.as_bytes().as_ptr() as *const [u8; 4])
+        };
+        let oem_str = unsafe {
+            *(oem_id.val.get_as_string()?.as_bytes().as_ptr() as *const [u8; 6])
+        };
+        let oem_table_str = unsafe {
+            *(oem_table_id.val.get_as_string()?.as_bytes().as_ptr() as *const [u8; 8])
+        };
+        
+        let sdt = rxsdt.find(sig_str, oem_str, oem_table_str);
+        
+        if let Some(sdt) = sdt {
+            let hdl = parse_aml_with_scope(sdt, root_path.val.get_as_string()?)?;
+            ctx.modify(parameter_path.val, parameter_data.val);
+            
+            return Ok(AmlParseType {
+                val: AmlValue::DDBHandle(hdl),
+                len: 2 + signature.len + oem_id.len + oem_table_id.len + root_path.len + parameter_path.len + parameter_data.len
+            });
+        }
+    }
+
     Ok(AmlParseType {
-        val: AmlValue::Uninitialized,
+        val: AmlValue::IntegerConstant(0),
         len: 2 + signature.len + oem_id.len + oem_table_id.len + root_path.len + parameter_path.len + parameter_data.len
     })
 }
diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs
index ac19b5c9..cdd7e0aa 100644
--- a/src/acpi/mod.rs
+++ b/src/acpi/mod.rs
@@ -5,6 +5,7 @@ use core::intrinsics::{atomic_load, atomic_store};
 use core::sync::atomic::Ordering;
 use collections::btree_map::BTreeMap;
 use collections::string::String;
+use alloc::boxed::Box;
 
 use syscall::io::{Io, Pio};
 
@@ -25,6 +26,7 @@ use self::rsdt::Rsdt;
 use self::sdt::Sdt;
 use self::xsdt::Xsdt;
 use self::hpet::Hpet;
+use self::rxsdt::Rxsdt;
 
 use self::aml::{is_aml_table, parse_aml_table, AmlError, AmlValue};
 
@@ -36,6 +38,7 @@ mod rsdt;
 mod sdt;
 mod xsdt;
 mod aml;
+mod rxsdt;
 
 const TRAMPOLINE: usize = 0x7E00;
 const AP_STARTUP: usize = TRAMPOLINE + 512;
@@ -261,18 +264,32 @@ pub unsafe fn init(active_table: &mut ActivePageTable) {
             print!("{}", c as char);
         }
         println!(":");
-        if let Some(rsdt) = Rsdt::new(rxsdt) {
-            for sdt_address in rsdt.iter() {
-                let sdt = get_sdt(sdt_address, active_table);
-                parse_sdt(sdt, active_table);
-            }
+
+        let rxsdt: Box<Rxsdt + Send + Sync> = if let Some(rsdt) = Rsdt::new(rxsdt) {
+            Box::new(rsdt)
         } else if let Some(xsdt) = Xsdt::new(rxsdt) {
-            for sdt_address in xsdt.iter() {
-                let sdt = get_sdt(sdt_address, active_table);
-                parse_sdt(sdt, active_table);
-            }
+            Box::new(xsdt)
         } else {
             println!("UNKNOWN RSDT OR XSDT SIGNATURE");
+            return;
+        };
+
+        {
+            let mut rxsdt_ptr = ACPI_TABLE.rxsdt.write();
+            *rxsdt_ptr = Some(rxsdt);
+        }
+
+        {
+            let rxsdt_ptr = ACPI_TABLE.rxsdt.read();
+
+            if let Some(ref rxsdt) = *rxsdt_ptr {
+                rxsdt.map_all(active_table);
+                
+                for sdt_address in rxsdt.iter() {
+                    let sdt = unsafe { &*(sdt_address as *const Sdt) };
+                    parse_sdt(sdt, active_table);
+                }
+            }
         }
     } else {
         println!("NO RSDP FOUND");
@@ -321,6 +338,7 @@ pub fn set_global_s_state(state: u8) {
 }
 
 pub struct Acpi {
+    pub rxsdt: RwLock<Option<Box<Rxsdt + Send + Sync>>>,
     pub fadt: RwLock<Option<Fadt>>,
     pub namespace: RwLock<Option<BTreeMap<String, AmlValue>>>,
     pub hpet: RwLock<Option<Hpet>>,
@@ -328,6 +346,7 @@ pub struct Acpi {
 }
 
 pub static ACPI_TABLE: Acpi = Acpi {
+    rxsdt: RwLock::new(None),
     fadt: RwLock::new(None),
     namespace: RwLock::new(None),
     hpet: RwLock::new(None),
diff --git a/src/acpi/rsdt.rs b/src/acpi/rsdt.rs
index fa391c0c..7877a061 100644
--- a/src/acpi/rsdt.rs
+++ b/src/acpi/rsdt.rs
@@ -1,6 +1,8 @@
 use core::mem;
+use alloc::boxed::Box;
 
 use super::sdt::Sdt;
+use super::rxsdt::Rxsdt;
 
 #[derive(Debug)]
 pub struct Rsdt(&'static Sdt);
@@ -13,12 +15,14 @@ impl Rsdt {
             None
         }
     }
+}
 
-    pub fn iter(&self) -> RsdtIter {
-        RsdtIter {
+impl Rxsdt for Rsdt {
+    fn iter(&self) -> Box<Iterator<Item = usize>> {
+        Box::new(RsdtIter {
             sdt: self.0,
             i: 0
-        }
+        })
     }
 }
 
diff --git a/src/acpi/rxsdt.rs b/src/acpi/rxsdt.rs
new file mode 100644
index 00000000..8c7278be
--- /dev/null
+++ b/src/acpi/rxsdt.rs
@@ -0,0 +1,28 @@
+use alloc::boxed::Box;
+
+use paging::ActivePageTable;
+
+use super::sdt::Sdt;
+use super::get_sdt;
+
+pub trait Rxsdt {
+    fn iter(&self) -> Box<Iterator<Item = usize>>;
+
+    fn map_all(&self, active_table: &mut ActivePageTable) {
+        for sdt in self.iter() {
+            get_sdt(sdt, active_table);
+        }
+    }
+            
+    fn find(&self, signature: [u8; 4], oem_id: [u8; 6], oem_table_id: [u8; 8]) -> Option<&'static Sdt> {
+        for sdt in self.iter() {
+            let sdt = unsafe { &*(sdt as *const Sdt) };
+            
+            if sdt.match_pattern(signature, oem_id, oem_table_id) {
+                return Some(sdt);
+            }
+        }
+
+        return None;
+    }
+}
diff --git a/src/acpi/sdt.rs b/src/acpi/sdt.rs
index 1a7a4faf..67dee89b 100644
--- a/src/acpi/sdt.rs
+++ b/src/acpi/sdt.rs
@@ -35,4 +35,8 @@ impl Sdt {
     pub fn data(&self) -> &[u8] {
         unsafe { slice::from_raw_parts(self.data_address() as *const u8, self.data_len()) }
     }
+    
+    pub fn match_pattern(&self, signature: [u8; 4], oem_id: [u8; 6], oem_table_id: [u8; 8]) -> bool{
+        self.signature == signature && self.oem_id == oem_id && self.oem_table_id == oem_table_id
+    }
 }
diff --git a/src/acpi/xsdt.rs b/src/acpi/xsdt.rs
index 5ec60361..7339ce01 100644
--- a/src/acpi/xsdt.rs
+++ b/src/acpi/xsdt.rs
@@ -1,6 +1,8 @@
 use core::mem;
+use alloc::boxed::Box;
 
 use super::sdt::Sdt;
+use super::rxsdt::Rxsdt;
 
 #[derive(Debug)]
 pub struct Xsdt(&'static Sdt);
@@ -13,12 +15,14 @@ impl Xsdt {
             None
         }
     }
+}
 
-    pub fn iter(&self) -> XsdtIter {
-        XsdtIter {
+impl Rxsdt for Xsdt {
+    fn iter(&self) -> Box<Iterator<Item = usize>> {
+        Box::new(XsdtIter {
             sdt: self.0,
             i: 0
-        }
+        })
     }
 }
 
diff --git a/src/lib.rs b/src/lib.rs
index 533b9e47..4dc0c3f9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -19,6 +19,7 @@
 #![feature(never_type)]
 #![feature(thread_local)]
 #![feature(unique)]
+#![feature(conservative_impl_trait)]
 #![no_std]
 
 extern crate alloc_kernel as allocator;
-- 
GitLab