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