From f4564d6caf43bf51eb1908d565bb56530d30b852 Mon Sep 17 00:00:00 2001 From: Ron Williams Date: Sun, 22 Jan 2023 19:42:41 -0800 Subject: [PATCH] switch to aml crate, implement acpi:/symbols --- acpid/Cargo.toml | 2 + acpid/src/acpi.rs | 349 +++++- acpid/src/aml/dataobj.rs | 184 --- acpid/src/aml/mod.rs | 144 --- acpid/src/aml/namedobj.rs | 1043 ---------------- acpid/src/aml/namespace.rs | 490 -------- acpid/src/aml/namespacemodifier.rs | 106 -- acpid/src/aml/namestring.rs | 223 ---- acpid/src/aml/parser.rs | 557 --------- acpid/src/aml/parsermacros.rs | 52 - acpid/src/aml/pkglength.rs | 25 - acpid/src/aml/termlist.rs | 172 --- acpid/src/aml/type1opcode.rs | 477 -------- acpid/src/aml/type2opcode.rs | 1784 ---------------------------- acpid/src/main.rs | 19 +- acpid/src/scheme.rs | 68 +- 16 files changed, 401 insertions(+), 5294 deletions(-) delete mode 100644 acpid/src/aml/dataobj.rs delete mode 100644 acpid/src/aml/mod.rs delete mode 100644 acpid/src/aml/namedobj.rs delete mode 100644 acpid/src/aml/namespace.rs delete mode 100644 acpid/src/aml/namespacemodifier.rs delete mode 100644 acpid/src/aml/namestring.rs delete mode 100644 acpid/src/aml/parser.rs delete mode 100644 acpid/src/aml/parsermacros.rs delete mode 100644 acpid/src/aml/pkglength.rs delete mode 100644 acpid/src/aml/termlist.rs delete mode 100644 acpid/src/aml/type1opcode.rs delete mode 100644 acpid/src/aml/type2opcode.rs diff --git a/acpid/Cargo.toml b/acpid/Cargo.toml index ccabe47a7b..451f0daeec 100644 --- a/acpid/Cargo.toml +++ b/acpid/Cargo.toml @@ -16,3 +16,5 @@ redox-daemon = "0.1" redox-log = "0.1.1" redox_syscall = "0.3" thiserror = "1" +aml = "0.16.2" +rustc-hash = "1.1.0" diff --git a/acpid/src/acpi.rs b/acpid/src/acpi.rs index 1fc4260578..b8879f1262 100644 --- a/acpid/src/acpi.rs +++ b/acpid/src/acpi.rs @@ -1,4 +1,4 @@ -use std::collections::BTreeMap; +use rustc_hash::FxHashSet; use std::convert::{TryFrom, TryInto}; use std::ops::Deref; use std::sync::Arc; @@ -6,10 +6,13 @@ use std::{fmt, mem}; use syscall::flag::PhysmapFlags; +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +use syscall::io::{Io, Pio}; + use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard}; use thiserror::Error; -use super::aml::AmlValue; +use aml::{AmlContext, AmlName}; pub mod dmar; use self::dmar::Dmar; @@ -219,14 +222,29 @@ impl fmt::Debug for Sdt { pub struct Dsdt(Sdt); pub struct Ssdt(Sdt); + +#[derive(Debug, Error)] +pub enum SymbolListError { + #[error("Aml Internal Error")] + AmlInternalError, +} + +pub struct AmlSymbols { + pub symbols_str: String, + symbols_hash: FxHashSet, +} + pub struct AcpiContext { tables: Vec, dsdt: Option, fadt: Option, - // TODO: Remove Option. This is not kernel code, and not static, but we still need to replace - // every match where namespace{,_mut}() are used. - namespace: RwLock>>, + // the aml parser + aml_context: RwLock, + + // Use to cache the symbols list, which doesn't change very often + // Set it to None if the ACPI tables change e.g. due to PnP + aml_symbols: RwLock>, // TODO: The kernel ACPI code seemed to use load_table quite ubiquitously, however ACPI 5.1 // states that DDBHandles can only be obtained when loading XSDT-pointed tables. So, we'll @@ -236,6 +254,7 @@ pub struct AcpiContext { pub next_ctx: RwLock, } + impl AcpiContext { pub fn init(rxsdt_physaddrs: impl Iterator) -> Self { let tables = rxsdt_physaddrs.map(|physaddr| { @@ -243,7 +262,7 @@ impl AcpiContext { .try_into() .expect("expected ACPI addresses to be compatible with the current word size"); - log::debug!("TABLE AT {:#>08X}", physaddr); + log::trace!("TABLE AT {:#>08X}", physaddr); Sdt::load_from_physical(physaddr) .expect("failed to load physical SDT") @@ -253,7 +272,10 @@ impl AcpiContext { tables, dsdt: None, fadt: None, - namespace: RwLock::new(Some(BTreeMap::new())), + + aml_context: RwLock::new(AmlContext::new(Box::new(AmlPhysMemHandler), aml::DebugVerbosity::None)), + aml_symbols: RwLock::new(None), + next_ctx: RwLock::new(0), sdt_order: RwLock::new(Vec::new()), @@ -266,10 +288,28 @@ impl AcpiContext { Fadt::init(&mut this); //TODO (hangs on real hardware): Dmar::init(&this); - crate::aml::init_namespace(&this); + if let Some(mut parser) = this.aml_context.try_write() { + if let Some(dsdt) = this.dsdt() { + match parser.parse_table(dsdt.aml()) { + Ok(_) => log::trace!("Parsed DSDT"), + Err(e) => { + log::error!("DSDT: {:?}", e); + } + } + } else { + log::error!("No DSDT for aml parsing"); + } - for (path, _) in this.namespace.get_mut().as_mut().unwrap().iter() { - log::trace!("ACPI NS: {}", path); + for ssdt in this.ssdts() { + match parser.parse_table(ssdt.aml()) { + Ok(_) => log::trace!("Parsed SSDT"), + Err(e) => { + log::error!("SSDT: {:?}", e); + } + } + } + } else { + log::error!("Failed to obtain aml_context"); } this @@ -296,12 +336,6 @@ impl AcpiContext { pub fn take_single_sdt(&self, signature: [u8; 4]) -> Option { self.find_single_sdt_pos(signature).map(|pos| self.tables[pos].clone()) } - pub fn namespace(&self) -> RwLockReadGuard<'_, Option>> { - self.namespace.read() - } - pub fn namespace_mut(&self) -> RwLockWriteGuard<'_, Option>> { - self.namespace.write() - } pub fn fadt(&self) -> Option<&Fadt> { self.fadt.as_ref() } @@ -320,6 +354,204 @@ impl AcpiContext { pub fn new_index(&self, signature: &SdtSignature) { self.sdt_order.write().push(Some(*signature)); } + fn aml_context(&self) -> RwLockReadGuard<'_, AmlContext>{ + self.aml_context.read() + } + fn aml_context_mut(&self) -> RwLockWriteGuard<'_, AmlContext> { + self.aml_context.write() + } + pub fn aml_lookup(&self, symbol: &str) -> Option { + let aml_name = match AmlName::from_str(symbol) { + Ok(aml_name) => aml_name, + Err(error) => { + log::error!("Lookup failed to convert name to AmlName {}, {:?}", symbol, error); + return None; + } + }; + + // Check the cache first + if let Ok(symbols_option) = self.aml_symbols() { + if let Some(symbols) = symbols_option.as_ref() { + if symbols.symbols_hash.contains(symbol) { + log::trace!("Found symbol in cache, {}", symbol); + return Some(aml_name); + } + } + } + + // Symbol does not exactly match cache, allow lookup using namespace rules + let aml_ctx = self.aml_context(); + let root = aml::AmlName::root(); + if aml_ctx.namespace.get_by_path(&aml_name).is_ok() + || aml_ctx.namespace.search_for_level(&aml_name, &root).is_ok() + { + Some(aml_name) + } else { + log::trace!("Lookup did not find {}", aml_name); + None + } + } + + pub fn aml_symbols(&self) -> Result>, SymbolListError> { + // Some private functions for building the symbol name correctly and efficiently + fn level_name(level_aml_name: &aml::AmlName) -> String { + let mut name = level_aml_name.as_string(); + // remove unnecessary underscores + while let Some(index) = name.find("_.") { + name.remove(index); + } + while name.len() > 0 && &name[name.len() - 1..] == "_" { + name.pop(); + } + name.shrink_to_fit(); + name + } + fn child_symbol(level_name: &str, value_name: &str) -> String { + let mut name = String::with_capacity(level_name.len() + 1 + value_name.len()); + name.push_str(level_name); + name.push('.'); + name.push_str(value_name.trim_end_matches('_')); + name.shrink_to_fit(); + name + } + fn root_symbol(value_name: &str) -> String { + let mut name = String::with_capacity(1 + value_name.len()); + name.push('\\'); + name.push_str(value_name.trim_end_matches('_')); + name.shrink_to_fit(); + name + } + + // return the cached value if it exists + let symbols = self.aml_symbols.read(); + if symbols.is_some() { + return Ok(symbols); + } + // free the read lock + drop(symbols); + + // List has not been initialized, we have to build it + log::trace!("Creating symbols list"); + + let mut symbols_str: String = String::with_capacity(30000); + + let mut symbols_hash: FxHashSet = FxHashSet::default(); + + // Get write lock because traverse requires mut + let mut aml_ctx = self.aml_context_mut(); + + let root = aml::AmlName::root(); + let traverse = aml_ctx.namespace.traverse(| level_aml_name, level | { + let level_is_root = level_aml_name.eq(&root); + let level_name = level_name(level_aml_name); + for (name, _handle) in level.values.iter() { + // Create the name of the symbol as "\levelname.symbolname" + let symbol = if level_is_root { + root_symbol(name.as_str()) + } else { + child_symbol(&level_name, name.as_str()) + }; + symbols_str.push_str(&symbol); + symbols_str.push('\n'); + symbols_hash.insert(symbol); + } + Ok(true) + }); + + match traverse { + Err(error) => { + log::error!("Traverse failed, {:?}", error); + return Err(SymbolListError::AmlInternalError); + } + _ => {} + } + + symbols_str.shrink_to_fit(); + + // Cache the new list + log::trace!("Updating symbols list"); + + let mut write_guarded_symbols = self.aml_symbols.write(); + *write_guarded_symbols = Some(AmlSymbols { symbols_str, symbols_hash }); + + // return the cached value + Ok(RwLockWriteGuard::downgrade(write_guarded_symbols)) + } + + /// Discard any cached symbols list. To be called if the AML namespace changes. + /// The caller must have at least a Read Lock on the aml context to ensure + /// the cached list is not out of sync with the namespace. + pub fn aml_symbols_reset(&self) { + let mut symbols = self.aml_symbols.write(); + *symbols = None; + } + + /// Set Power State + /// See https://uefi.org/sites/default/files/resources/ACPI_6_1.pdf + /// - search for PM1a + /// See https://forum.osdev.org/viewtopic.php?t=16990 for practical details + pub fn set_global_s_state(&self, state: u8) { + if state != 5 { + return; + } + let fadt = match self.fadt() { + Some(fadt) => fadt, + None => { + log::error!("Cannot set global S-state due to missing FADT."); + return; + } + }; + + let port = fadt.pm1a_control_block as u16; + let mut val = 1 << 13; + + let aml_ctx = self.aml_context(); + + let s5_aml_name = match aml::AmlName::from_str("\\_S5") { + Ok(aml_name) => aml_name, + Err(error) => { log::error!("Could not build AmlName for \\_S5, {:?}", error); return; } + }; + + let s5 = match aml_ctx.namespace.get_by_path(&s5_aml_name) { + Ok(s5) => s5, + Err(error) => { log::error!("Cannot set S-state, missing \\_S5, {:?}", error); return; } + }; + + let package = match s5 { + aml::AmlValue::Package(package) => package, + _ => { log::error!("Cannot set S-state, \\_S5 is not a package"); return; } + }; + + let slp_typa = match package[0] { + aml::AmlValue::Integer(i) => i, + _ => { log::error!("typa is not an Integer"); return; } + }; + let slp_typb = match package[1] { + aml::AmlValue::Integer(i) => i, + _ => { log::error!("typb is not an Integer"); return; } + }; + + log::trace!("Shutdown SLP_TYPa {:X}, SLP_TYPb {:X}", slp_typa, slp_typb); + val |= slp_typa as u16; + + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + log::warn!("Shutdown with ACPI outw(0x{:X}, 0x{:X})", port, val); + Pio::::new(port).write(val); + } + + // TODO: Handle SLP_TYPb + + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + log::error!("Cannot shutdown with ACPI outw(0x{:X}, 0x{:X}) on this architecture", port, val); + } + + loop { + core::hint::spin_loop(); + } + } + } #[repr(packed)] @@ -539,3 +771,88 @@ impl AmlContainingTable for Ssdt { &*self.0 } } + +struct AmlPhysMemHandler; + +impl aml::Handler for AmlPhysMemHandler { + fn read_u8(&self, _address: usize) -> u8 { + log::error!("read u8 {:X}", _address); + 0 + } + fn read_u16(&self, _address: usize) -> u16 { + log::error!("read u16 {:X}", _address); + 0 + } + fn read_u32(&self, _address: usize) -> u32 { + log::error!("read u32 {:X}", _address); + 0 + } + fn read_u64(&self, _address: usize) -> u64 { + log::error!("read u64 {:X}", _address); + 0 + } + + fn write_u8(&mut self, _address: usize, _value: u8) { + log::error!("write u8 {:X}", _address); + } + fn write_u16(&mut self, _address: usize, _value: u16) { + log::error!("write u16 {:X}", _address); + } + fn write_u32(&mut self, _address: usize, _value: u32) { + log::error!("write u32 {:X}", _address); + } + fn write_u64(&mut self, _address: usize, _value: u64) { + log::error!("write u64 {:X}", _address); + } + + fn read_io_u8(&self, _port: u16) -> u8 { + log::error!("read io u8 {:X}", _port); + + 0 + } + fn read_io_u16(&self, _port: u16) -> u16 { + log::error!("read io u16 {:X}", _port); + + 0 + } + fn read_io_u32(&self, _port: u16) -> u32 { + log::error!("read io u32 {:X}", _port); + + 0 + } + + fn write_io_u8(&self, _port: u16, _value: u8) { + log::error!("write io u8 {:X}", _port); + } + fn write_io_u16(&self, _port: u16, _value: u16) { + log::error!("write io u16 {:X}", _port); + } + fn write_io_u32(&self, _port: u16, _value: u32) { + log::error!("write io u32 {:X}", _port); + } + + fn read_pci_u8(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16) -> u8 { + log::error!("read pci u8 {:X}", _device); + + 0 + } + fn read_pci_u16(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16) -> u16 { + log::error!("read pci u8 {:X}", _device); + + 0 + } + fn read_pci_u32(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16) -> u32 { + log::error!("read pci u8 {:X}", _device); + + 0 + } + fn write_pci_u8(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16, _value: u8) { + log::error!("write pci u8 {:X}", _device); + } + fn write_pci_u16(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16, _value: u16) { + log::error!("write pci u8 {:X}", _device); + } + fn write_pci_u32(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16, _value: u32) { + log::error!("write pci u8 {:X}", _device); + } +} diff --git a/acpid/src/aml/dataobj.rs b/acpid/src/aml/dataobj.rs deleted file mode 100644 index 6e4ab1da73..0000000000 --- a/acpid/src/aml/dataobj.rs +++ /dev/null @@ -1,184 +0,0 @@ -use super::AmlError; -use super::parser::{ AmlParseType, ParseResult, AmlExecutionContext, ExecutionState }; -use super::namespace::{ AmlValue, ObjectReference }; - -use super::type2opcode::{parse_def_buffer, parse_def_package, parse_def_var_package}; -use super::termlist::parse_term_arg; -use super::namestring::parse_super_name; - -pub fn parse_data_obj(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_selector! { - data, ctx, - parse_computational_data, - parse_def_package, - parse_def_var_package - }; - - Err(AmlError::AmlInvalidOpCode) -} - -pub fn parse_data_ref_obj(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_selector! { - data, ctx, - parse_data_obj, - parse_term_arg - }; - - match parse_super_name(data, ctx) { - Ok(res) => match res.val { - AmlValue::String(s) => Ok(AmlParseType { - val: AmlValue::ObjectReference(ObjectReference::Object(s)), - len: res.len - }), - _ => Ok(res) - }, - Err(e) => Err(e) - } -} - -pub fn parse_arg_obj(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - match data[0] { - 0x68 ..= 0x6E => Ok(AmlParseType { - val: AmlValue::ObjectReference(ObjectReference::ArgObj(data[0] - 0x68)), - len: 1 as usize - }), - _ => Err(AmlError::AmlInvalidOpCode) - } -} - -pub fn parse_local_obj(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - match data[0] { - 0x68 ..= 0x6E => Ok(AmlParseType { - val: AmlValue::ObjectReference(ObjectReference::LocalObj(data[0] - 0x60)), - len: 1 as usize - }), - _ => Err(AmlError::AmlInvalidOpCode) - } -} - -fn parse_computational_data(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - match data[0] { - 0x0A => Ok(AmlParseType { - val: AmlValue::Integer(data[1] as u64), - len: 2 as usize - }), - 0x0B => { - let res = (data[1] as u16) + - ((data[2] as u16) << 8); - - Ok(AmlParseType { - val: AmlValue::Integer(res as u64), - len: 3 as usize - }) - }, - 0x0C => { - let res = (data[1] as u32) + - ((data[2] as u32) << 8) + - ((data[3] as u32) << 16) + - ((data[4] as u32) << 24); - - Ok(AmlParseType { - val: AmlValue::Integer(res as u64), - len: 5 as usize - }) - }, - 0x0D => { - let mut cur_ptr: usize = 1; - let mut cur_string: Vec = vec!(); - - while data[cur_ptr] != 0x00 { - cur_string.push(data[cur_ptr]); - cur_ptr += 1; - } - - match String::from_utf8(cur_string) { - Ok(s) => Ok(AmlParseType { - val: AmlValue::String(s.clone()), - len: s.clone().len() + 2 - }), - Err(_) => Err(AmlError::AmlParseError("String data - invalid string")) - } - }, - 0x0E => { - let res = (data[1] as u64) + - ((data[2] as u64) << 8) + - ((data[3] as u64) << 16) + - ((data[4] as u64) << 24) + - ((data[5] as u64) << 32) + - ((data[6] as u64) << 40) + - ((data[7] as u64) << 48) + - ((data[8] as u64) << 56); - - Ok(AmlParseType { - val: AmlValue::Integer(res as u64), - len: 9 as usize - }) - }, - 0x00 => Ok(AmlParseType { - val: AmlValue::IntegerConstant(0 as u64), - len: 1 as usize - }), - 0x01 => Ok(AmlParseType { - val: AmlValue::IntegerConstant(1 as u64), - len: 1 as usize - }), - 0x5B => if data[1] == 0x30 { - Ok(AmlParseType { - val: AmlValue::IntegerConstant(2017_0630 as u64), - len: 2 as usize - }) - } else { - Err(AmlError::AmlInvalidOpCode) - }, - 0xFF => Ok(AmlParseType { - val: AmlValue::IntegerConstant(0xFFFF_FFFF_FFFF_FFFF), - len: 1 as usize - }), - _ => parse_def_buffer(data, ctx) - } -} diff --git a/acpid/src/aml/mod.rs b/acpid/src/aml/mod.rs deleted file mode 100644 index 39f4c1c9e6..0000000000 --- a/acpid/src/aml/mod.rs +++ /dev/null @@ -1,144 +0,0 @@ -//! # AML -//! -//! Code to parse and execute ACPI Machine Language tables. - -use std::collections::HashMap; - -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -use syscall::io::{Io, Pio}; - -use crate::acpi::{AcpiContext, AmlContainingTable, Sdt, SdtHeader}; - -#[macro_use] -mod parsermacros; - -mod namespace; -mod termlist; -mod namespacemodifier; -mod pkglength; -mod namestring; -mod namedobj; -mod dataobj; -mod type1opcode; -mod type2opcode; -mod parser; - -use self::parser::AmlExecutionContext; -use self::termlist::parse_term_list; -pub use self::namespace::AmlValue; - -#[derive(Debug)] -pub enum AmlError { - AmlParseError(&'static str), - AmlInvalidOpCode, - AmlValueError, - AmlDeferredLoad, - AmlFatalError(u8, u16, AmlValue), - AmlHardFatal -} - -pub fn parse_aml_table(acpi_ctx: &AcpiContext, sdt: impl AmlContainingTable) -> Result, AmlError> { - parse_aml_with_scope(acpi_ctx, sdt, "\\".to_owned()) -} - -pub fn parse_aml_with_scope(acpi_ctx: &AcpiContext, sdt: impl AmlContainingTable, scope: String) -> Result, AmlError> { - let data = sdt.aml(); - let mut ctx = AmlExecutionContext::new(acpi_ctx, scope); - - parse_term_list(data, &mut ctx)?; - - Ok(ctx.namespace_delta) -} - -fn init_aml_table(acpi_ctx: &AcpiContext, sdt: impl AmlContainingTable) { - match parse_aml_table(acpi_ctx, &sdt) { - Ok(_) => log::debug!("Table {} parsed successfully", sdt.header().signature()), - Err(AmlError::AmlParseError(e)) => log::error!("Table {} got parse error: {}", sdt.header().signature(), e), - Err(AmlError::AmlInvalidOpCode) => log::error!("Table {} got invalid opcode", sdt.header().signature()), - Err(AmlError::AmlValueError) => log::error!("For table {}: type constraints or value bounds not met", sdt.header().signature()), - Err(AmlError::AmlDeferredLoad) => log::error!("For table {}: deferred load reached top level", sdt.header().signature()), - Err(AmlError::AmlFatalError(ty, code, val)) => { - log::error!("Fatal error occurred for table {}: type={}, code={}, val={:?}", sdt.header().signature(), ty, code, val); - return; - }, - Err(AmlError::AmlHardFatal) => { - log::error!("Hard fatal error occurred for table {}", sdt.header().signature()); - return; - } - } -} -pub fn init_namespace(context: &AcpiContext) { - let dsdt = context.dsdt().expect("could not find any DSDT"); - - log::debug!("Found DSDT."); - init_aml_table(context, dsdt); - - let ssdts = context.ssdts(); - - for ssdt in ssdts { - print!("Found SSDT."); - init_aml_table(context, ssdt); - } -} - -pub fn set_global_s_state(context: &AcpiContext, state: u8) { - if state != 5 { - return; - } - let fadt = match context.fadt() { - Some(fadt) => fadt, - None => { - log::error!("Cannot set global S-state due to missing FADT."); - return; - } - }; - - let port = fadt.pm1a_control_block as u16; - let mut val = 1 << 13; - - let namespace_guard = context.namespace(); - - let namespace = match &*namespace_guard { - Some(namespace) => namespace, - None => { - log::error!("Cannot set global S-state due to missing ACPI namespace"); - return; - } - }; - - let s5 = match namespace.get("\\_S5") { - Some(s5) => s5, - None => { - log::error!("Cannot set global S-state due to missing \\_S5"); - return; - } - }; - let p = match s5.get_as_package() { - Ok(package) => package, - Err(error) => { - log::error!("Cannot set global S-state due to \\_S5 not being a package: {:?}", error); - return; - } - }; - - let slp_typa = p[0].get_as_integer(context).expect("SLP_TYPa is not an integer"); - let slp_typb = p[1].get_as_integer(context).expect("SLP_TYPb is not an integer"); - - log::info!("Shutdown SLP_TYPa {:X}, SLP_TYPb {:X}", slp_typa, slp_typb); - val |= slp_typa as u16; - - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - { - log::info!("Shutdown with ACPI outw(0x{:X}, 0x{:X})", port, val); - Pio::::new(port).write(val); - } - - #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] - { - log::error!("Cannot shutdown with ACPI outw(0x{:X}, 0x{:X}) on this architecture", port, val); - } - - loop { - core::hint::spin_loop(); - } -} diff --git a/acpid/src/aml/namedobj.rs b/acpid/src/aml/namedobj.rs deleted file mode 100644 index 40659b2c77..0000000000 --- a/acpid/src/aml/namedobj.rs +++ /dev/null @@ -1,1043 +0,0 @@ -use std::collections::BTreeMap; - -use super::AmlError; -use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext, ExecutionState }; -use super::namespace::{AmlValue, FieldSelector, Method, get_namespace_string, - Accessor, BufferField, FieldUnit, Processor, PowerResource, OperationRegion, - Device, ThermalZone}; -use super::namestring::{parse_name_string, parse_name_seg}; -use super::termlist::{parse_term_arg, parse_object_list}; -use super::pkglength::parse_pkg_length; -use super::type2opcode::parse_def_buffer; - -#[derive(Debug, Copy, Clone)] -pub enum RegionSpace { - SystemMemory, - SystemIO, - PCIConfig, - EmbeddedControl, - SMBus, - SystemCMOS, - PciBarTarget, - IPMI, - GeneralPurposeIO, - GenericSerialBus, - UserDefined(u8) -} - -#[derive(Debug, Clone)] -pub struct FieldFlags { - access_type: AccessType, - lock_rule: bool, - update_rule: UpdateRule -} - -#[derive(Debug, Clone)] -pub enum AccessType { - AnyAcc, - ByteAcc, - WordAcc, - DWordAcc, - QWordAcc, - BufferAcc(AccessAttrib) -} - -#[derive(Debug, Clone)] -pub enum UpdateRule { - Preserve, - WriteAsOnes, - WriteAsZeros -} - -#[derive(Debug, Clone)] -pub struct NamedField { - name: String, - length: usize -} - -#[derive(Debug, Clone)] -pub struct AccessField { - access_type: AccessType, - access_attrib: AccessAttrib -} - -#[derive(Debug, Clone)] -pub enum AccessAttrib { - AttribBytes(u8), - AttribRawBytes(u8), - AttribRawProcessBytes(u8), - AttribQuick, - AttribSendReceive, - AttribByte, - AttribWord, - AttribBlock, - AttribProcessCall, - AttribBlockProcessCall -} - -pub fn parse_named_obj(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_selector! { - data, ctx, - parse_def_bank_field, - parse_def_create_bit_field, - parse_def_create_byte_field, - parse_def_create_word_field, - parse_def_create_dword_field, - parse_def_create_qword_field, - parse_def_create_field, - parse_def_data_region, - parse_def_event, - parse_def_external, - parse_def_device, - parse_def_op_region, - parse_def_field, - parse_def_index_field, - parse_def_method, - parse_def_mutex, - parse_def_power_res, - parse_def_processor, - parse_def_thermal_zone - }; - - Err(AmlError::AmlInvalidOpCode) -} - -fn parse_def_bank_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 3 { - return Err(AmlError::AmlParseError("DefBankField - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x87); - - let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let data = &data[2 + pkg_length_len .. 2 + pkg_length]; - - let region_name = parse_name_string(data, ctx)?; - let bank_name = parse_name_string(&data[2 + pkg_length_len + region_name.len .. 2 + pkg_length], ctx)?; - - let bank_value = parse_term_arg(&data[2 + pkg_length_len + region_name.len .. 2 + pkg_length], ctx)?; - - let flags_raw = data[2 + pkg_length_len + region_name.len + bank_name.len + bank_value.len]; - let mut flags = FieldFlags { - access_type: match flags_raw & 0x0F { - 0 => AccessType::AnyAcc, - 1 => AccessType::ByteAcc, - 2 => AccessType::WordAcc, - 3 => AccessType::DWordAcc, - 4 => AccessType::QWordAcc, - 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), - _ => return Err(AmlError::AmlParseError("BankField - invalid access type")) - }, - lock_rule: (flags_raw & 0x10) == 0x10, - update_rule: match (flags_raw & 0x60) >> 5 { - 0 => UpdateRule::Preserve, - 1 => UpdateRule::WriteAsOnes, - 2 => UpdateRule::WriteAsZeros, - _ => return Err(AmlError::AmlParseError("BankField - invalid update rule")) - } - }; - - let selector = FieldSelector::Bank { - region: region_name.val.get_as_string(ctx.acpi_context())?, - bank_register: bank_name.val.get_as_string(ctx.acpi_context())?, - bank_selector: Box::new(bank_value.val) - }; - - parse_field_list(&data[3 + pkg_length_len + region_name.len + bank_name.len + bank_value.len .. - 2 + pkg_length], ctx, selector, &mut flags)?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + pkg_length - }) -} - -fn parse_def_create_bit_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 2 { - return Err(AmlError::AmlParseError("DefCreateBitField - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x8D); - - let source_buf = parse_term_arg(&data[2..], ctx)?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; - let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val)?; - - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, AmlValue::BufferField(BufferField { - source_buf: Box::new(source_buf.val), - index: Box::new(bit_index.val), - length: Box::new(AmlValue::IntegerConstant(1)) - }))?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + name.len + source_buf.len + bit_index.len - }) -} - -fn parse_def_create_byte_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 2 { - return Err(AmlError::AmlParseError("DefCreateByteField - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x8C); - - let source_buf = parse_term_arg(&data[2..], ctx)?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; - let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val)?; - - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, AmlValue::BufferField(BufferField { - source_buf: Box::new(source_buf.val), - index: Box::new(bit_index.val), - length: Box::new(AmlValue::IntegerConstant(8)) - }))?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + name.len + source_buf.len + bit_index.len - }) -} - -fn parse_def_create_word_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 2 { - return Err(AmlError::AmlParseError("DefCreateWordField - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x8B); - - let source_buf = parse_term_arg(&data[2..], ctx)?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; - let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val)?; - - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, AmlValue::BufferField(BufferField { - source_buf: Box::new(source_buf.val), - index: Box::new(bit_index.val), - length: Box::new(AmlValue::IntegerConstant(16)) - }))?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + name.len + source_buf.len + bit_index.len - }) -} - -fn parse_def_create_dword_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 2 { - return Err(AmlError::AmlParseError("DefCreateDwordField - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x8A); - - let source_buf = parse_term_arg(&data[2..], ctx)?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; - let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val)?; - - let _ = ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, AmlValue::BufferField(BufferField { - source_buf: Box::new(source_buf.val), - index: Box::new(bit_index.val), - length: Box::new(AmlValue::IntegerConstant(32)) - })); - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + name.len + source_buf.len + bit_index.len - }) -} - -fn parse_def_create_qword_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 2 { - return Err(AmlError::AmlParseError("DefCreateQwordField - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x8F); - - let source_buf = parse_term_arg(&data[2..], ctx)?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; - let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val)?; - - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, AmlValue::BufferField(BufferField { - source_buf: Box::new(source_buf.val), - index: Box::new(bit_index.val), - length: Box::new(AmlValue::IntegerConstant(64)) - }))?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + name.len + source_buf.len + bit_index.len - }) -} - -fn parse_def_create_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 2 { - return Err(AmlError::AmlParseError("DefCreateField - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x13); - - let source_buf = parse_term_arg(&data[2..], ctx)?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; - let num_bits = parse_term_arg(&data[2 + source_buf.len + bit_index.len..], ctx)?; - let name = parse_name_string(&data[2 + source_buf.len + bit_index.len + num_bits.len..], ctx)?; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val)?; - - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, AmlValue::BufferField(BufferField { - source_buf: Box::new(source_buf.val), - index: Box::new(bit_index.val), - length: Box::new(num_bits.val) - }))?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + name.len + source_buf.len + bit_index.len + num_bits.len - }) -} - -fn parse_def_data_region(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 2 { - return Err(AmlError::AmlParseError("DefDataRegion - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - // TODO: Find the actual offset and length, once table mapping is implemented - parser_opcode_extended!(data, 0x88); - - let name = parse_name_string(&data[2..], ctx)?; - let signature = parse_term_arg(&data[2 + name.len..], ctx)?; - let oem_id = parse_term_arg(&data[2 + name.len + signature.len..], ctx)?; - let oem_table_id = parse_term_arg(&data[2 + name.len + signature.len + oem_id.len..], ctx)?; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val)?; - - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, AmlValue::OperationRegion(OperationRegion { - region: RegionSpace::SystemMemory, - offset: Box::new(AmlValue::IntegerConstant(0)), - len: Box::new(AmlValue::IntegerConstant(0)), - accessor: Accessor { - read: |_x| 0 as u64, - write: |_x, _y| () - }, - accessed_by: None - }))?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + name.len + signature.len + oem_id.len + oem_table_id.len - }) -} - -fn parse_def_event(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 2 { - return Err(AmlError::AmlParseError("DefEvent - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x02); - - let name = parse_name_string(&data[2..], ctx)?; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val)?; - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, AmlValue::Event(0))?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + name.len - }) -} - -fn parse_def_device(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 2 { - return Err(AmlError::AmlParseError("DefDevice - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - // TODO: How to handle local context deferreds - parser_opcode_extended!(data, 0x82); - - let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], ctx)?; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val)?; - let mut local_ctx = AmlExecutionContext::new(ctx.acpi_context(), local_scope_string.clone()); - - parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_ctx)?; - - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, AmlValue::Device(Device { - obj_list: local_ctx.namespace_delta.clone(), - notify_methods: BTreeMap::new() - }))?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + pkg_length - }) -} - -fn parse_def_op_region(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 3 { - return Err(AmlError::AmlParseError("DefOpRegion - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x80); - - let name = parse_name_string(&data[2..], ctx)?; - let region = match data[2 + name.len] { - 0x00 => RegionSpace::SystemMemory, - 0x01 => RegionSpace::SystemIO, - 0x02 => RegionSpace::PCIConfig, - 0x03 => RegionSpace::EmbeddedControl, - 0x04 => RegionSpace::SMBus, - 0x05 => RegionSpace::SystemCMOS, - 0x06 => RegionSpace::PciBarTarget, - 0x07 => RegionSpace::IPMI, - 0x08 => RegionSpace::GeneralPurposeIO, - 0x09 => RegionSpace::GenericSerialBus, - 0x80 ..= 0xFF => RegionSpace::UserDefined(data[2 + name.len]), - _ => return Err(AmlError::AmlParseError("OpRegion - invalid region")) - }; - - let offset = parse_term_arg(&data[3 + name.len..], ctx)?; - let len = parse_term_arg(&data[3 + name.len + offset.len..], ctx)?; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val)?; - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, AmlValue::OperationRegion(OperationRegion { - region, - offset: Box::new(offset.val), - len: Box::new(len.val), - accessor: Accessor { - read: |_x| 0 as u64, - write: |_x, _y| () - }, - accessed_by: None - }))?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 3 + name.len + offset.len + len.len - }) -} - -fn parse_def_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 3 { - return Err(AmlError::AmlParseError("DefField - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x81); - - let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], ctx)?; - - let flags_raw = data[2 + pkg_length_len + name.len]; - let mut flags = FieldFlags { - access_type: match flags_raw & 0x0F { - 0 => AccessType::AnyAcc, - 1 => AccessType::ByteAcc, - 2 => AccessType::WordAcc, - 3 => AccessType::DWordAcc, - 4 => AccessType::QWordAcc, - 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), - _ => return Err(AmlError::AmlParseError("Field - Invalid access type")) - }, - lock_rule: (flags_raw & 0x10) == 0x10, - update_rule: match (flags_raw & 0x60) >> 5 { - 0 => UpdateRule::Preserve, - 1 => UpdateRule::WriteAsOnes, - 2 => UpdateRule::WriteAsZeros, - _ => return Err(AmlError::AmlParseError("Field - Invalid update rule")) - } - }; - - let selector = FieldSelector::Region(name.val.get_as_string(ctx.acpi_context())?); - - parse_field_list(&data[3 + pkg_length_len + name.len .. 2 + pkg_length], ctx, selector, &mut flags)?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + pkg_length - }) -} - -fn parse_def_index_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 3 { - return Err(AmlError::AmlParseError("DefIndexField - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x86); - - let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let idx_name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], ctx)?; - let data_name = parse_name_string(&data[2 + pkg_length_len + idx_name.len .. 2 + pkg_length], ctx)?; - - let flags_raw = data[2 + pkg_length_len + idx_name.len + data_name.len]; - let mut flags = FieldFlags { - access_type: match flags_raw & 0x0F { - 0 => AccessType::AnyAcc, - 1 => AccessType::ByteAcc, - 2 => AccessType::WordAcc, - 3 => AccessType::DWordAcc, - 4 => AccessType::QWordAcc, - 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), - _ => return Err(AmlError::AmlParseError("IndexField - Invalid access type")) - }, - lock_rule: (flags_raw & 0x10) == 0x10, - update_rule: match (flags_raw & 0x60) >> 5 { - 0 => UpdateRule::Preserve, - 1 => UpdateRule::WriteAsOnes, - 2 => UpdateRule::WriteAsZeros, - _ => return Err(AmlError::AmlParseError("IndexField - Invalid update rule")) - } - }; - - let selector = FieldSelector::Index { - index_selector: idx_name.val.get_as_string(ctx.acpi_context())?, - data_selector: data_name.val.get_as_string(ctx.acpi_context())? - }; - - parse_field_list(&data[3 + pkg_length_len + idx_name.len + data_name.len .. 2 + pkg_length], - ctx, selector, &mut flags)?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + pkg_length - }) -} - -fn parse_field_list(data: &[u8], - ctx: &mut AmlExecutionContext, - selector: FieldSelector, - flags: &mut FieldFlags) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - let mut current_offset: usize = 0; - let mut field_offset: usize = 0; - let mut connection = AmlValue::Uninitialized; - - while current_offset < data.len() { - let res = parse_field_element(&data[current_offset..], ctx, selector.clone(), &mut connection, flags, &mut field_offset)?; - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - current_offset += res.len; - } - - Ok(AmlParseType { - val: AmlValue::None, - len: data.len() - }) -} - -fn parse_field_element(data: &[u8], - ctx: &mut AmlExecutionContext, - selector: FieldSelector, - connection: &mut AmlValue, - flags: &mut FieldFlags, - offset: &mut usize) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - let length = if let Ok(field) = parse_named_field(data, ctx) { - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), AmlValue::String(field.val.name.clone()))?; - - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, AmlValue::FieldUnit(FieldUnit { - selector: selector.clone(), - connection: Box::new(connection.clone()), - flags: flags.clone(), - offset: offset.clone(), - length: field.val.length - }))?; - - *offset += field.val.length; - field.len - } else if let Ok(field) = parse_reserved_field(data, ctx) { - *offset += field.val; - field.len - } else if let Ok(field) = parse_access_field(data, ctx) { - match field.val.access_type { - AccessType::BufferAcc(_) => - flags.access_type = AccessType::BufferAcc(field.val.access_attrib.clone()), - ref a => flags.access_type = a.clone() - } - - field.len - } else if let Ok(field) = parse_connect_field(data, ctx) { - *connection = field.val.clone(); - field.len - } else { - return Err(AmlError::AmlInvalidOpCode); - }; - - Ok(AmlParseType { - val: AmlValue::None, - len: length - }) -} - -fn parse_named_field(data: &[u8], _ctx: &mut AmlExecutionContext) -> Result, AmlError> { - if data.len() < 4 { - return Err(AmlError::AmlParseError("NamedField - data truncated")) - } - - let (name_seg, name_seg_len) = parse_name_seg(&data[0..4])?; - let name = match String::from_utf8(name_seg) { - Ok(s) => s, - Err(_) => return Err(AmlError::AmlParseError("NamedField - invalid name")) - }; - let (length, length_len) = parse_pkg_length(&data[4..])?; - - Ok(AmlParseTypeGeneric { - val: NamedField { name, length }, - len: name_seg_len + length_len - }) -} - -fn parse_reserved_field(data: &[u8], _ctx: &mut AmlExecutionContext) -> Result, AmlError> { - if data.len() < 1 { - return Err(AmlError::AmlParseError("ReservedField - data truncated")) - } - - parser_opcode!(data, 0x00); - - let (length, length_len) = parse_pkg_length(&data[1..])?; - Ok(AmlParseTypeGeneric { - val: length, - len: 1 + length_len - }) -} - -fn parse_access_field(data: &[u8], _ctx: &mut AmlExecutionContext) -> Result, AmlError> { - if data.len() < 3 { - return Err(AmlError::AmlParseError("AccessField - data truncated")) - } - - parser_opcode!(data, 0x01, 0x03); - - let flags_raw = data[1]; - let access_type = match flags_raw & 0x0F { - 0 => AccessType::AnyAcc, - 1 => AccessType::ByteAcc, - 2 => AccessType::WordAcc, - 3 => AccessType::DWordAcc, - 4 => AccessType::QWordAcc, - 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), - _ => return Err(AmlError::AmlParseError("AccessField - Invalid access type")) - }; - - let access_attrib = match (flags_raw & 0xC0) >> 6 { - 0 => match data[2] { - 0x02 => AccessAttrib::AttribQuick, - 0x04 => AccessAttrib::AttribSendReceive, - 0x06 => AccessAttrib::AttribByte, - 0x08 => AccessAttrib::AttribWord, - 0x0A => AccessAttrib::AttribBlock, - 0x0B => AccessAttrib::AttribBytes(data[3]), - 0x0C => AccessAttrib::AttribProcessCall, - 0x0D => AccessAttrib::AttribBlockProcessCall, - 0x0E => AccessAttrib::AttribRawBytes(data[3]), - 0x0F => AccessAttrib::AttribRawProcessBytes(data[3]), - _ => return Err(AmlError::AmlParseError("AccessField - Invalid access attrib")) - }, - 1 => AccessAttrib::AttribBytes(data[2]), - 2 => AccessAttrib::AttribRawBytes(data[2]), - 3 => AccessAttrib::AttribRawProcessBytes(data[2]), - _ => return Err(AmlError::AmlParseError("AccessField - Invalid access attrib")) - // This should never happen but the compiler bitches if I don't cover this - }; - - Ok(AmlParseTypeGeneric { - val: AccessField { access_type, access_attrib }, - len: if data[0] == 0x01 { - 3 as usize - } else { - 4 as usize - } - }) -} - -fn parse_connect_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 1 { - return Err(AmlError::AmlParseError("ConnectField - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x02); - - if let Ok(e) = parse_def_buffer(&data[1..], ctx) { - Ok(AmlParseType { - val: e.val, - len: e.len + 1 - }) - } else { - let name = parse_name_string(&data[1..], ctx)?; - Ok(AmlParseType { - val: AmlValue::Alias(name.val.get_as_string(ctx.acpi_context())?), - len: name.len + 1 - }) - } -} - -fn parse_def_method(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 1 { - return Err(AmlError::AmlParseError("DefMethod - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x14); - - let (pkg_len, pkg_len_len) = parse_pkg_length(&data[1..])?; - let name = parse_name_string(&data[1 + pkg_len_len..], ctx)?; - let flags = data[1 + pkg_len_len + name.len]; - - let arg_count = flags & 0x07; - let serialized = (flags & 0x08) == 0x08; - let sync_level = flags & 0xF0 >> 4; - - let term_list = &data[2 + pkg_len_len + name.len .. 1 + pkg_len]; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val)?; - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, AmlValue::Method(Method { - arg_count, - serialized, - sync_level, - term_list: term_list.to_vec() - }))?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 1 + pkg_len - }) -} - -fn parse_def_mutex(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 1 { - return Err(AmlError::AmlParseError("DefMutex - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x01); - - let name = parse_name_string(&data[2 ..], ctx)?; - let flags = data[2 + name.len]; - let sync_level = flags & 0x0F; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val)?; - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, AmlValue::Mutex((sync_level, None)))?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 3 + name.len - }) -} - -fn parse_def_power_res(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 5 { - return Err(AmlError::AmlParseError("DefPowerRes - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - // TODO: How to handle local context deferreds - parser_opcode_extended!(data, 0x84); - - let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; - let name = parse_name_string(&data[2 + pkg_len_len..], ctx)?; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val)?; - - let system_level = data[2 + pkg_len_len + name.len]; - let resource_order: u16 = (data[3 + pkg_len_len + name.len] as u16) + - ((data[4 + pkg_len_len + name.len] as u16) << 8); - - let mut local_ctx = AmlExecutionContext::new(ctx.acpi_context(), local_scope_string.clone()); - parse_object_list(&data[5 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, AmlValue::PowerResource(PowerResource { - system_level, - resource_order, - obj_list: local_ctx.namespace_delta.clone() - }))?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + pkg_len - }) -} - -fn parse_def_processor(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 8 { - return Err(AmlError::AmlParseError("DefProcessor - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x83); - - let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; - let name = parse_name_string(&data[2 + pkg_len_len..], ctx)?; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val)?; - - let proc_id = data[2 + pkg_len_len + name.len]; - let p_blk_addr: u32 = (data[3 + pkg_len_len + name.len] as u32) + - ((data[4 + pkg_len_len + name.len] as u32) << 8) + - ((data[5 + pkg_len_len + name.len] as u32) << 16) + - ((data[6 + pkg_len_len + name.len] as u32) << 24); - let p_blk_len = data[7 + pkg_len_len + name.len]; - - let mut local_ctx = AmlExecutionContext::new(ctx.acpi_context(), local_scope_string.clone()); - parse_object_list(&data[8 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, AmlValue::Processor(Processor { - proc_id, - p_blk: if p_blk_len > 0 { Some(p_blk_addr) } else { None }, - obj_list: local_ctx.namespace_delta.clone(), - notify_methods: BTreeMap::new() - }))?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + pkg_len - }) -} - -fn parse_def_thermal_zone(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 2 { - return Err(AmlError::AmlParseError("DefThermalZone - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x85); - - let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; - let name = parse_name_string(&data[2 + pkg_len_len .. 2 + pkg_len], ctx)?; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val)?; - - let mut local_ctx = AmlExecutionContext::new(ctx.acpi_context(), local_scope_string.clone()); - parse_object_list(&data[2 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, AmlValue::ThermalZone(ThermalZone { - obj_list: local_ctx.namespace_delta.clone(), - notify_methods: BTreeMap::new() - }))?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + pkg_len - }) -} - -fn parse_def_external(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if data.len() < 2 { - return Err(AmlError::AmlParseError("DefExternal - data truncated")) - } - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x15); - - let object_name = parse_name_string(&data[1..], ctx)?; - let object_type = data[1 + object_name.len]; - let argument_count = data[2 + object_name.len]; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), object_name.val)?; - - let obj = match object_type { - 8 => AmlValue::Method(Method { - arg_count: argument_count, - serialized: false, - sync_level: 0, - term_list: vec!() - }), - _ => AmlValue::Uninitialized - }; - - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, obj)?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 3 + object_name.len - }) -} diff --git a/acpid/src/aml/namespace.rs b/acpid/src/aml/namespace.rs deleted file mode 100644 index 4dfd18516f..0000000000 --- a/acpid/src/aml/namespace.rs +++ /dev/null @@ -1,490 +0,0 @@ -use std::collections::BTreeMap; - -use core::fmt::Debug; -use core::str::FromStr; - -use super::termlist::parse_term_list; -use super::namedobj::{ RegionSpace, FieldFlags }; -use super::parser::{AmlExecutionContext, ExecutionState}; -use super::AmlError; - -use crate::acpi::{AcpiContext, SdtSignature}; - -#[derive(Clone, Debug)] -pub enum FieldSelector { - Region(String), - Bank { - region: String, - bank_register: String, - bank_selector: Box - }, - Index { - index_selector: String, - data_selector: String - } -} - -#[derive(Clone, Debug)] -pub enum ObjectReference { - ArgObj(u8), - LocalObj(u8), - Object(String), - Index(Box, Box) -} - -#[derive(Clone, Debug)] -pub struct Method { - pub arg_count: u8, - pub serialized: bool, - pub sync_level: u8, - pub term_list: Vec -} - -#[derive(Clone, Debug)] -pub struct BufferField { - pub source_buf: Box, - pub index: Box, - pub length: Box -} - -#[derive(Clone, Debug)] -pub struct FieldUnit { - pub selector: FieldSelector, - pub connection: Box, - pub flags: FieldFlags, - pub offset: usize, - pub length: usize -} - -#[derive(Clone, Debug)] -pub struct Device { - pub obj_list: Vec, - pub notify_methods: BTreeMap> -} - -#[derive(Clone, Debug)] -pub struct ThermalZone { - pub obj_list: Vec, - pub notify_methods: BTreeMap> -} - -#[derive(Clone, Debug)] -pub struct Processor { - pub proc_id: u8, - pub p_blk: Option, - pub obj_list: Vec, - pub notify_methods: BTreeMap> -} - -#[derive(Clone, Debug)] -pub struct OperationRegion { - pub region: RegionSpace, - pub offset: Box, - pub len: Box, - pub accessor: Accessor, - pub accessed_by: Option -} - -#[derive(Clone, Debug)] -pub struct PowerResource { - pub system_level: u8, - pub resource_order: u16, - pub obj_list: Vec -} - -#[derive(Debug)] -pub struct Accessor { - pub read: fn(usize) -> u64, - pub write: fn(usize, u64) -} - -impl Clone for Accessor { - fn clone(&self) -> Accessor { - Accessor { - read: (*self).read, - write: (*self).write - } - } -} - -#[derive(Clone, Debug)] -pub enum AmlValue { - None, - Uninitialized, - Alias(String), - Buffer(Vec), - BufferField(BufferField), - DDBHandle((Vec, SdtSignature)), - DebugObject, - Device(Device), - Event(u64), - FieldUnit(FieldUnit), - Integer(u64), - IntegerConstant(u64), - Method(Method), - Mutex((u8, Option)), - ObjectReference(ObjectReference), - OperationRegion(OperationRegion), - Package(Vec), - String(String), - PowerResource(PowerResource), - Processor(Processor), - - #[allow(dead_code)] - RawDataBuffer(Vec), - - ThermalZone(ThermalZone) -} - -impl AmlValue { - pub fn get_type_string(&self) -> String { - match *self { - AmlValue::Uninitialized => String::from_str("[Uninitialized Object]").unwrap(), - AmlValue::Integer(_) => String::from_str("[Integer]").unwrap(), - AmlValue::String(_) => String::from_str("[String]").unwrap(), - AmlValue::Buffer(_) => String::from_str("[Buffer]").unwrap(), - AmlValue::Package(_) => String::from_str("[Package]").unwrap(), - AmlValue::FieldUnit(_) => String::from_str("[Field]").unwrap(), - AmlValue::Device(_) => String::from_str("[Device]").unwrap(), - AmlValue::Event(_) => String::from_str("[Event]").unwrap(), - AmlValue::Method(_) => String::from_str("[Control Method]").unwrap(), - AmlValue::Mutex(_) => String::from_str("[Mutex]").unwrap(), - AmlValue::OperationRegion(_) => String::from_str("[Operation Region]").unwrap(), - AmlValue::PowerResource(_) => String::from_str("[Power Resource]").unwrap(), - AmlValue::Processor(_) => String::from_str("[Processor]").unwrap(), - AmlValue::ThermalZone(_) => String::from_str("[Thermal Zone]").unwrap(), - AmlValue::BufferField(_) => String::from_str("[Buffer Field]").unwrap(), - AmlValue::DDBHandle(_) => String::from_str("[DDB Handle]").unwrap(), - AmlValue::DebugObject => String::from_str("[Debug Object]").unwrap(), - _ => String::new() - } - } - - pub fn get_as_type(&self, ctx: &AcpiContext, t: AmlValue) -> Result { - match t { - AmlValue::None => Ok(AmlValue::None), - AmlValue::Uninitialized => Ok(self.clone()), - AmlValue::Alias(_) => match *self { - AmlValue::Alias(_) => Ok(self.clone()), - _ => Err(AmlError::AmlValueError) - }, - AmlValue::Buffer(_) => Ok(AmlValue::Buffer(self.get_as_buffer(ctx)?)), - AmlValue::BufferField(_) => Ok(AmlValue::BufferField(self.get_as_buffer_field(ctx)?)), - AmlValue::DDBHandle(_) => Ok(AmlValue::DDBHandle(self.get_as_ddb_handle(ctx)?)), - AmlValue::DebugObject => match *self { - AmlValue::DebugObject => Ok(self.clone()), - _ => Err(AmlError::AmlValueError) - }, - AmlValue::Device(_) => Ok(AmlValue::Device(self.get_as_device()?)), - AmlValue::Event(_) => Ok(AmlValue::Event(self.get_as_event()?)), - AmlValue::FieldUnit(_) => Ok(AmlValue::FieldUnit(self.get_as_field_unit()?)), - AmlValue::Integer(_) => Ok(AmlValue::Integer(self.get_as_integer(ctx)?)), - AmlValue::IntegerConstant(_) => Ok(AmlValue::IntegerConstant(self.get_as_integer_constant()?)), - AmlValue::Method(_) => Ok(AmlValue::Method(self.get_as_method()?)), - AmlValue::Mutex(_) => Ok(AmlValue::Mutex(self.get_as_mutex()?)), - AmlValue::ObjectReference(_) => Ok(AmlValue::ObjectReference(self.get_as_object_reference()?)), - AmlValue::OperationRegion(_) => match *self { - AmlValue::OperationRegion(_) => Ok(self.clone()), - _ => Err(AmlError::AmlValueError) - }, - AmlValue::Package(_) => Ok(AmlValue::Package(self.get_as_package()?)), - AmlValue::String(_) => Ok(AmlValue::String(self.get_as_string(ctx)?)), - AmlValue::PowerResource(_) => Ok(AmlValue::PowerResource(self.get_as_power_resource()?)), - AmlValue::Processor(_) => Ok(AmlValue::Processor(self.get_as_processor()?)), - AmlValue::RawDataBuffer(_) => Ok(AmlValue::RawDataBuffer(self.get_as_raw_data_buffer()?)), - AmlValue::ThermalZone(_) => Ok(AmlValue::ThermalZone(self.get_as_thermal_zone()?)) - } - } - - pub fn get_as_buffer(&self, ctx: &AcpiContext) -> Result, AmlError> { - match *self { - AmlValue::Buffer(ref b) => Ok(b.clone()), - AmlValue::Integer(ref i) => { - let mut v: Vec = vec!(); - let mut i = i.clone(); - - while i != 0 { - v.push((i & 0xFF) as u8); - i >>= 8; - } - - while v.len() < 8 { - v.push(0); - } - - Ok(v) - }, - AmlValue::String(ref s) => { - Ok(s.clone().into_bytes()) - }, - AmlValue::BufferField(ref b) => { - let buf = b.source_buf.get_as_buffer(ctx)?; - let idx = b.index.get_as_integer(ctx)? as usize; - let len = b.length.get_as_integer(ctx)? as usize; - - if idx + len > buf.len() { - return Err(AmlError::AmlValueError); - } - - Ok(buf[idx .. idx + len].to_vec()) - }, - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_buffer_field(&self, acpi_ctx: &AcpiContext) -> Result { - match *self { - AmlValue::BufferField(ref b) => Ok(b.clone()), - _ => { - let raw_buf = self.get_as_buffer(acpi_ctx)?; - let buf = Box::new(AmlValue::Buffer(raw_buf.clone())); - let idx = Box::new(AmlValue::IntegerConstant(0)); - let len = Box::new(AmlValue::Integer(raw_buf.len() as u64)); - - Ok(BufferField { - source_buf: buf, - index: idx, - length: len - }) - } - } - } - - pub fn get_as_ddb_handle(&self, acpi_ctx: &AcpiContext) -> Result<(Vec, SdtSignature), AmlError> { - match *self { - AmlValue::DDBHandle(ref v) => Ok(v.clone()), - AmlValue::Integer(i) => if let Some(sig) = acpi_ctx.get_signature_from_index(i as usize) { - Ok((vec!(), sig)) - } else { - log::error!("AmlValueError in get_as_ddb_handle integer"); - Err(AmlError::AmlValueError) - }, - _ => { log::error!("AmlValueError in get_as_ddb_handle other"); Err(AmlError::AmlValueError) } - } - } - - pub fn get_as_device(&self) -> Result { - match *self { - AmlValue::Device(ref s) => Ok(s.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_event(&self) -> Result { - match *self { - AmlValue::Event(ref e) => Ok(e.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_field_unit(&self) -> Result { - match *self { - AmlValue::FieldUnit(ref e) => Ok(e.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_integer(&self, acpi_ctx: &AcpiContext) -> Result { - match *self { - AmlValue::IntegerConstant(ref i) => Ok(i.clone()), - AmlValue::Integer(ref i) => Ok(i.clone()), - AmlValue::Buffer(ref b) => { - let mut b = b.clone(); - if b.len() > 8 { - return Err(AmlError::AmlValueError); - } - - let mut i: u64 = 0; - - while b.len() > 0 { - i <<= 8; - i += b.pop().expect("Won't happen") as u64; - } - - Ok(i) - }, - AmlValue::BufferField(_) => { - let mut b = self.get_as_buffer(acpi_ctx)?; - if b.len() > 8 { - return Err(AmlError::AmlValueError); - } - - let mut i: u64 = 0; - - while b.len() > 0 { - i <<= 8; - i += b.pop().expect("Won't happen") as u64; - } - - Ok(i) - }, - AmlValue::DDBHandle(ref v) => if let Some(idx) = acpi_ctx.get_index_from_signature(&v.1) { - Ok(idx as u64) - } else { - Err(AmlError::AmlValueError) - }, - AmlValue::String(ref s) => { - let s = s.clone()[0..8].to_string().to_uppercase(); - let mut i: u64 = 0; - - for c in s.chars() { - if !c.is_digit(16) { - break; - } - - i <<= 8; - i += c.to_digit(16).unwrap() as u64; - } - - Ok(i) - }, - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_integer_constant(&self) -> Result { - match *self { - AmlValue::IntegerConstant(ref i) => Ok(i.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_method(&self) -> Result { - match *self { - AmlValue::Method(ref m) => Ok(m.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_mutex(&self) -> Result<(u8, Option), AmlError> { - match *self { - AmlValue::Mutex(ref m) => Ok(m.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_object_reference(&self) -> Result { - match *self { - AmlValue::ObjectReference(ref m) => Ok(m.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - /* - pub fn get_as_operation_region(&self) -> Result { - match *self { - AmlValue::OperationRegion(ref p) => Ok(p.clone()), - _ => Err(AmlError::AmlValueError) - } - } - */ - - pub fn get_as_package(&self) -> Result, AmlError> { - match *self { - AmlValue::Package(ref p) => Ok(p.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_string(&self, ctx: &AcpiContext) -> Result { - match *self { - AmlValue::String(ref s) => Ok(s.clone()), - AmlValue::Integer(ref i) => Ok(format!("{:X}", i)), - AmlValue::IntegerConstant(ref i) => Ok(format!("{:X}", i)), - AmlValue::Buffer(ref b) => Ok(String::from_utf8(b.clone()).expect("Invalid UTF-8")), - AmlValue::BufferField(_) => { - let b = self.get_as_buffer(ctx)?; - Ok(String::from_utf8(b).expect("Invalid UTF-8")) - }, - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_power_resource(&self) -> Result { - match *self { - AmlValue::PowerResource(ref p) => Ok(p.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_processor(&self) -> Result { - match *self { - AmlValue::Processor(ref p) => Ok(p.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_raw_data_buffer(&self) -> Result, AmlError> { - match *self { - AmlValue::RawDataBuffer(ref p) => Ok(p.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_thermal_zone(&self) -> Result { - match *self { - AmlValue::ThermalZone(ref p) => Ok(p.clone()), - _ => Err(AmlError::AmlValueError) - } - } -} - -impl Method { - pub fn execute(&self, acpi_ctx: &AcpiContext, scope: String, parameters: Vec) -> AmlValue { - let mut ctx = AmlExecutionContext::new(acpi_ctx, scope); - ctx.init_arg_vars(parameters); - - let _ = parse_term_list(&self.term_list[..], &mut ctx); - ctx.clean_namespace(acpi_ctx); - - match ctx.state { - ExecutionState::RETURN(v) => v, - _ => AmlValue::IntegerConstant(0) - } - } -} - -pub fn get_namespace_string(ctx: &AcpiContext, current: String, modifier_v: AmlValue) -> Result { - let mut modifier = modifier_v.get_as_string(ctx)?; - - if current.len() == 0 { - return Ok(modifier); - } - - if modifier.len() == 0 { - return Ok(current); - } - - if modifier.starts_with("\\") { - return Ok(modifier); - } - - let mut namespace = current.clone(); - - if modifier.starts_with("^") { - while modifier.starts_with("^") { - modifier = modifier[1..].to_string(); - - if namespace.ends_with("\\") { - return Err(AmlError::AmlValueError); - } - - loop { - if namespace.ends_with(".") { - namespace.pop(); - break; - } - - if namespace.pop() == None { - return Err(AmlError::AmlValueError); - } - } - } - } - - if !namespace.ends_with("\\") { - namespace.push('.'); - } - - Ok(namespace + &modifier) -} diff --git a/acpid/src/aml/namespacemodifier.rs b/acpid/src/aml/namespacemodifier.rs deleted file mode 100644 index 3c3a31465c..0000000000 --- a/acpid/src/aml/namespacemodifier.rs +++ /dev/null @@ -1,106 +0,0 @@ -use super::AmlError; -use super::parser::{AmlParseType, ParseResult, AmlExecutionContext, ExecutionState}; -use super::namespace::{AmlValue, get_namespace_string}; -use super::pkglength::parse_pkg_length; -use super::namestring::parse_name_string; -use super::termlist::parse_term_list; -use super::dataobj::parse_data_ref_obj; - -pub fn parse_namespace_modifier(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_selector! { - data, ctx, - parse_alias_op, - parse_scope_op, - parse_name_op - }; - - Err(AmlError::AmlInvalidOpCode) -} - -fn parse_alias_op(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x06); - - let source_name = parse_name_string(&data[1..], ctx)?; - let alias_name = parse_name_string(&data[1 + source_name.len..], ctx)?; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), source_name.val)?; - let local_alias_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), alias_name.val)?; - - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, AmlValue::Alias(local_alias_string))?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 1 + source_name.len + alias_name.len - }) -} - -fn parse_name_op(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x08); - - let name = parse_name_string(&data[1..], ctx)?; - let data_ref_obj = parse_data_ref_obj(&data[1 + name.len..], ctx)?; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val)?; - - ctx.add_to_namespace(ctx.acpi_context(), local_scope_string, data_ref_obj.val)?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 1 + name.len + data_ref_obj.len - }) -} - -fn parse_scope_op(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x10); - - let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let name = parse_name_string(&data[1 + pkg_length_len..], ctx)?; - - let local_scope_string = get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val.clone())?; - let containing_scope_string = ctx.scope.clone(); - - ctx.scope = local_scope_string; - parse_term_list(&data[1 + pkg_length_len + name.len .. 1 + pkg_length], ctx)?; - ctx.scope = containing_scope_string; - - Ok(AmlParseType { - val: AmlValue::None, - len: 1 + pkg_length - }) -} diff --git a/acpid/src/aml/namestring.rs b/acpid/src/aml/namestring.rs deleted file mode 100644 index dd3eb88a33..0000000000 --- a/acpid/src/aml/namestring.rs +++ /dev/null @@ -1,223 +0,0 @@ -use super::AmlError; -use super::parser::{AmlParseType, ParseResult, AmlExecutionContext, ExecutionState}; -use super::namespace::AmlValue; -use super::dataobj::{parse_arg_obj, parse_local_obj}; -use super::type2opcode::parse_type6_opcode; - -pub fn parse_name_string(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - let mut characters: Vec = vec!(); - let mut starting_index: usize = 0; - - if data[0] == 0x5C { - characters.push(data[0]); - starting_index = 1; - } else if data[0] == 0x5E { - while data[starting_index] == 0x5E { - characters.push(data[starting_index]); - starting_index += 1; - } - } - - let sel = |data| { - parser_selector_simple! { - data, - parse_dual_name_path, - parse_multi_name_path, - parse_null_name, - parse_name_seg - }; - - Err(AmlError::AmlInvalidOpCode) - }; - let (mut chr, len) = sel(&data[starting_index..])?; - characters.append(&mut chr); - - let name_string = String::from_utf8(characters); - - match name_string { - Ok(s) => Ok(AmlParseType { - val: AmlValue::String(s.clone()), - len: len + starting_index - }), - Err(_) => Err(AmlError::AmlParseError("Namestring - Name is invalid")) - } -} - -fn parse_null_name(data: &[u8]) -> Result<(Vec, usize), AmlError> { - parser_opcode!(data, 0x00); - Ok((vec!(), 1 )) -} - -pub fn parse_name_seg(data: &[u8]) -> Result<(Vec, usize), AmlError> { - match data[0] { - 0x41 ..= 0x5A | 0x5F => (), - _ => return Err(AmlError::AmlInvalidOpCode) - } - - match data[1] { - 0x30 ..= 0x39 | 0x41 ..= 0x5A | 0x5F => (), - _ => return Err(AmlError::AmlInvalidOpCode) - } - - match data[2] { - 0x30 ..= 0x39 | 0x41 ..= 0x5A | 0x5F => (), - _ => return Err(AmlError::AmlInvalidOpCode) - } - - match data[3] { - 0x30 ..= 0x39 | 0x41 ..= 0x5A | 0x5F => (), - _ => return Err(AmlError::AmlInvalidOpCode) - } - - let mut name_seg = vec!(data[0], data[1], data[2], data[3]); - while *(name_seg.last().unwrap()) == 0x5F { - name_seg.pop(); - } - - Ok((name_seg, 4)) -} - -fn parse_dual_name_path(data: &[u8]) -> Result<(Vec, usize), AmlError> { - parser_opcode!(data, 0x2E); - - let mut characters: Vec = vec!(); - let mut dual_len: usize = 1; - - match parse_name_seg(&data[1..5]) { - Ok((mut v, len)) => { - characters.append(&mut v); - dual_len += len; - }, - Err(e) => return Err(e) - } - - characters.push(0x2E); - - match parse_name_seg(&data[5..9]) { - Ok((mut v, len)) => { - characters.append(&mut v); - dual_len += len; - }, - Err(e) => return Err(e) - } - - Ok((characters, dual_len)) -} - -fn parse_multi_name_path(data: &[u8]) -> Result<(Vec, usize), AmlError> { - parser_opcode!(data, 0x2F); - - let seg_count = data[1]; - if seg_count == 0x00 { - return Err(AmlError::AmlParseError("MultiName Path - can't have zero name segments")); - } - - let mut current_seg = 0; - let mut characters: Vec = vec!(); - let mut multi_len: usize = 2; - - while current_seg < seg_count { - match parse_name_seg(&data[(current_seg as usize * 4) + 2 ..]) { - Ok((mut v, len)) => { - characters.append(&mut v); - multi_len += len; - }, - Err(e) => return Err(e) - } - - characters.push(0x2E); - - current_seg += 1; - } - - characters.pop(); - - Ok((characters, multi_len)) -} - -pub fn parse_super_name(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_selector! { - data, ctx, - parse_simple_name, - parse_type6_opcode, - parse_debug_obj - }; - - Err(AmlError::AmlInvalidOpCode) -} - -fn parse_debug_obj(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x31); - - Ok(AmlParseType { - val: AmlValue::DebugObject, - len: 2 - }) -} - -pub fn parse_simple_name(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_selector! { - data, ctx, - parse_name_string, - parse_arg_obj, - parse_local_obj - }; - - Err(AmlError::AmlInvalidOpCode) -} - -pub fn parse_target(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - if data[0] == 0x00 { - Ok(AmlParseType { - val: AmlValue::None, - len: 1 - }) - } else { - parse_super_name(data, ctx) - } -} diff --git a/acpid/src/aml/parser.rs b/acpid/src/aml/parser.rs deleted file mode 100644 index 3902453ebe..0000000000 --- a/acpid/src/aml/parser.rs +++ /dev/null @@ -1,557 +0,0 @@ -use std::collections::BTreeMap; - -use parking_lot::RwLockWriteGuard; - -use super::namespace::{AmlValue, ObjectReference}; -use super::AmlError; - -use crate::acpi::AcpiContext; - -pub type ParseResult = Result; -pub type AmlParseType = AmlParseTypeGeneric; - -#[derive(Debug)] -pub struct AmlParseTypeGeneric { - pub val: T, - pub len: usize -} - -pub enum ExecutionState { - EXECUTING, - CONTINUE, - BREAK, - RETURN(AmlValue) -} - -pub struct AmlExecutionContext<'a> { - pub scope: String, - pub local_vars: [AmlValue; 8], - pub arg_vars: [AmlValue; 8], - pub state: ExecutionState, - pub namespace_delta: Vec, - pub ctx_id: u64, - pub sync_level: u8, - - pub acpi_context: &'a AcpiContext, -} - -impl<'a> AmlExecutionContext<'a> { - pub fn new(acpi_context: &'a AcpiContext, scope: String) -> AmlExecutionContext<'_> { - let mut idptr = acpi_context.next_ctx.write(); - let id: u64 = *idptr; - - *idptr += 1; - - AmlExecutionContext { - scope, - local_vars: [AmlValue::Uninitialized, - AmlValue::Uninitialized, - AmlValue::Uninitialized, - AmlValue::Uninitialized, - AmlValue::Uninitialized, - AmlValue::Uninitialized, - AmlValue::Uninitialized, - AmlValue::Uninitialized], - arg_vars: [AmlValue::Uninitialized, - AmlValue::Uninitialized, - AmlValue::Uninitialized, - AmlValue::Uninitialized, - AmlValue::Uninitialized, - AmlValue::Uninitialized, - AmlValue::Uninitialized, - AmlValue::Uninitialized], - state: ExecutionState::EXECUTING, - namespace_delta: vec!(), - ctx_id: id, - sync_level: 0, - - acpi_context, - } - } - pub fn acpi_context(&self) -> &'a AcpiContext { - self.acpi_context - } - - pub fn wait_for_event(&mut self, ctx: &AcpiContext, event_ptr: AmlValue) -> Result { - let mut namespace_ptr = self.prelock(ctx); - let namespace = match *namespace_ptr { - Some(ref mut n) => n, - None => return Err(AmlError::AmlHardFatal) - }; - - let mutex_idx = match event_ptr { - AmlValue::String(ref s) => s.clone(), - AmlValue::ObjectReference(ref o) => match *o { - ObjectReference::Object(ref s) => s.clone(), - _ => return Err(AmlError::AmlValueError) - }, - _ => return Err(AmlError::AmlValueError) - }; - - let mutex = match namespace.get(&mutex_idx) { - Some(s) => s.clone(), - None => return Err(AmlError::AmlValueError) - }; - - match mutex { - AmlValue::Event(count) => { - if count > 0 { - namespace.insert(mutex_idx, AmlValue::Event(count - 1)); - return Ok(true); - } - }, - _ => return Err(AmlError::AmlValueError) - } - - Ok(false) - } - - pub fn signal_event(&mut self, ctx: &AcpiContext, event_ptr: AmlValue) -> Result<(), AmlError> { - let mut namespace_ptr = self.prelock(ctx); - let namespace = match *namespace_ptr { - Some(ref mut n) => n, - None => return Err(AmlError::AmlHardFatal) - }; - - - let mutex_idx = match event_ptr { - AmlValue::String(ref s) => s.clone(), - AmlValue::ObjectReference(ref o) => match *o { - ObjectReference::Object(ref s) => s.clone(), - _ => return Err(AmlError::AmlValueError) - }, - _ => return Err(AmlError::AmlValueError) - }; - - let mutex = match namespace.get(&mutex_idx) { - Some(s) => s.clone(), - None => return Err(AmlError::AmlValueError) - }; - - match mutex { - AmlValue::Event(count) => { - namespace.insert(mutex_idx, AmlValue::Event(count + 1)); - }, - _ => return Err(AmlError::AmlValueError) - } - - Ok(()) - } - - pub fn release_mutex(&mut self, ctx: &AcpiContext, mutex_ptr: AmlValue) -> Result<(), AmlError> { - let id = self.ctx_id; - - let mut namespace_ptr = self.prelock(ctx); - let namespace = match *namespace_ptr { - Some(ref mut n) => n, - None => return Err(AmlError::AmlHardFatal) - }; - - let mutex_idx = match mutex_ptr { - AmlValue::String(ref s) => s.clone(), - AmlValue::ObjectReference(ref o) => match *o { - ObjectReference::Object(ref s) => s.clone(), - _ => return Err(AmlError::AmlValueError) - }, - _ => return Err(AmlError::AmlValueError) - }; - - let mutex = match namespace.get(&mutex_idx) { - Some(s) => s.clone(), - None => return Err(AmlError::AmlValueError) - }; - - match mutex { - AmlValue::Mutex((sync_level, owner)) => { - if let Some(o) = owner { - if o == id { - if sync_level == self.sync_level { - namespace.insert(mutex_idx, AmlValue::Mutex((sync_level, None))); - return Ok(()); - } else { - return Err(AmlError::AmlValueError); - } - } else { - return Err(AmlError::AmlHardFatal); - } - } - }, - AmlValue::OperationRegion(ref region) => { - if let Some(o) = region.accessed_by { - if o == id { - let mut new_region = region.clone(); - new_region.accessed_by = None; - - namespace.insert(mutex_idx, AmlValue::OperationRegion(new_region)); - return Ok(()); - } else { - return Err(AmlError::AmlHardFatal); - } - } - }, - _ => return Err(AmlError::AmlValueError) - } - - Ok(()) - } - - pub fn acquire_mutex(&mut self, ctx: &AcpiContext, mutex_ptr: AmlValue) -> Result { - let id = self.ctx_id; - - let mut namespace_ptr = self.prelock(ctx); - let namespace = match *namespace_ptr { - Some(ref mut n) => n, - None => return Err(AmlError::AmlHardFatal) - }; - let mutex_idx = match mutex_ptr { - AmlValue::String(ref s) => s.clone(), - AmlValue::ObjectReference(ref o) => match *o { - ObjectReference::Object(ref s) => s.clone(), - _ => return Err(AmlError::AmlValueError) - }, - _ => return Err(AmlError::AmlValueError) - }; - - let mutex = match namespace.get(&mutex_idx) { - Some(s) => s.clone(), - None => return Err(AmlError::AmlValueError) - }; - - match mutex { - AmlValue::Mutex((sync_level, owner)) => { - if owner == None { - if sync_level < self.sync_level { - return Err(AmlError::AmlValueError); - } - - namespace.insert(mutex_idx, AmlValue::Mutex((sync_level, Some(id)))); - self.sync_level = sync_level; - - return Ok(true); - } - }, - AmlValue::OperationRegion(ref o) => { - if o.accessed_by == None { - let mut new_region = o.clone(); - new_region.accessed_by = Some(id); - - namespace.insert(mutex_idx, AmlValue::OperationRegion(new_region)); - return Ok(true); - } - }, - _ => return Err(AmlError::AmlValueError) - } - - Ok(false) - } - - pub fn add_to_namespace(&mut self, ctx: &AcpiContext, name: String, value: AmlValue) -> Result<(), AmlError> { - let mut namespace = ctx.namespace_mut(); - - if let Some(ref mut namespace) = *namespace { - if let Some(obj) = namespace.get(&name) { - match *obj { - AmlValue::Uninitialized => (), - AmlValue::Method(ref m) => { - if m.term_list.len() != 0 { - return Err(AmlError::AmlValueError); - } - }, - _ => return Err(AmlError::AmlValueError) - } - } - - self.namespace_delta.push(name.clone()); - namespace.insert(name, value); - - Ok(()) - } else { - Err(AmlError::AmlValueError) - } - } - - pub fn clean_namespace(&mut self, ctx: &AcpiContext) { - let mut namespace = ctx.namespace_mut(); - - if let Some(ref mut namespace) = *namespace { - for k in &self.namespace_delta { - namespace.remove(k); - } - } - } - - pub fn init_arg_vars(&mut self, parameters: Vec) { - if parameters.len() > 8 { - return; - } - - let mut cur = 0; - while cur < parameters.len() { - self.arg_vars[cur] = parameters[cur].clone(); - cur += 1; - } - } - - pub fn prelock<'ctx>(&mut self, ctx: &'ctx AcpiContext) -> RwLockWriteGuard<'ctx, Option>> { - ctx.namespace_mut() - } - - fn modify_local_obj(&mut self, ctx: &AcpiContext, local: usize, value: AmlValue) -> Result<(), AmlError> { - self.local_vars[local] = value.get_as_type(ctx, self.local_vars[local].clone())?; - Ok(()) - } - - fn modify_object(&mut self, ctx: &AcpiContext, name: String, value: AmlValue) -> Result<(), AmlError> { - if let Some(ref mut namespace) = *ctx.namespace_mut() { - let coercion_obj = { - let obj = namespace.get(&name); - - if let Some(o) = obj { - o.clone() - } else { - AmlValue::Uninitialized - } - }; - - namespace.insert(name, value.get_as_type(ctx, coercion_obj)?); - Ok(()) - } else { - Err(AmlError::AmlHardFatal) - } - } - - fn modify_index_final(&mut self, ctx: &AcpiContext, name: String, value: AmlValue, indices: Vec) -> Result<(), AmlError> { - if let Some(ref mut namespace) = *ctx.namespace_mut() { - let mut obj = if let Some(s) = namespace.get(&name) { - s.clone() - } else { - return Err(AmlError::AmlValueError); - }; - - obj = self.modify_index_core(ctx, obj, value, indices)?; - - namespace.insert(name, obj); - Ok(()) - } else { - Err(AmlError::AmlValueError) - } - } - - fn modify_index_core(&mut self, ctx: &AcpiContext, obj: AmlValue, value: AmlValue, indices: Vec) -> Result { - 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(ctx)? as u8; - - let string = String::from_utf8(bytes).unwrap(); - - Ok(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(ctx)? as u8; - - Ok(AmlValue::Buffer(b)) - }, - AmlValue::BufferField(ref b) => { - if indices.len() != 1 { - return Err(AmlError::AmlValueError); - } - - let mut idx = indices[0]; - idx += b.index.get_as_integer(ctx)?; - - let _ = self.modify(ctx, AmlValue::ObjectReference(ObjectReference::Index(b.source_buf.clone(), Box::new(AmlValue::Integer(idx.clone())))), value); - - Ok(AmlValue::BufferField(b.clone())) - }, - AmlValue::Package(ref p) => { - if indices.len() == 0 { - return Err(AmlError::AmlValueError); - } - - let mut p = p.clone(); - - if indices.len() == 1 { - p[indices[0] as usize] = value; - } else { - p[indices[0] as usize] = self.modify_index_core(ctx, p[indices[0] as usize].clone(), value, indices[1..].to_vec())?; - } - - Ok(AmlValue::Package(p)) - }, - _ => Err(AmlError::AmlValueError) - } - } - - pub fn modify_index(&mut self, ctx: &AcpiContext, name: AmlValue, value: AmlValue, indices: Vec) -> Result<(), AmlError>{ - match name { - AmlValue::ObjectReference(r) => match r { - ObjectReference::Object(s) => self.modify_index_final(ctx, s, value, indices), - ObjectReference::Index(c, v) => { - let mut indices = indices.clone(); - indices.push(v.get_as_integer(ctx)?); - - self.modify_index(ctx, *c, value, indices) - }, - ObjectReference::ArgObj(_) => Err(AmlError::AmlValueError), - ObjectReference::LocalObj(i) => { - let v = self.local_vars[i as usize].clone(); - self.local_vars[i as usize] = self.modify_index_core(ctx, v, value, indices)?; - - Ok(()) - } - }, - _ => Err(AmlError::AmlValueError) - } - } - - pub fn modify(&mut self, ctx: &AcpiContext, name: AmlValue, value: AmlValue) -> Result<(), AmlError> { - match name { - AmlValue::ObjectReference(r) => match r { - ObjectReference::ArgObj(_) => Err(AmlError::AmlValueError), - ObjectReference::LocalObj(i) => self.modify_local_obj(ctx, i as usize, value), - ObjectReference::Object(s) => self.modify_object(ctx, s, value), - ObjectReference::Index(c, v) => self.modify_index(ctx, *c, value, vec!(v.get_as_integer(ctx)?)) - }, - AmlValue::String(s) => self.modify_object(ctx, s, value), - _ => Err(AmlError::AmlValueError) - } - } - - fn copy_local_obj(&mut self, local: usize, value: AmlValue) -> Result<(), AmlError> { - self.local_vars[local] = value; - Ok(()) - } - - fn copy_object(&mut self, ctx: &AcpiContext, name: String, value: AmlValue) -> Result<(), AmlError> { - if let Some(ref mut namespace) = *ctx.namespace_mut() { - namespace.insert(name, value); - Ok(()) - } else { - Err(AmlError::AmlHardFatal) - } - } - - pub fn copy(&mut self, ctx: &AcpiContext, name: AmlValue, value: AmlValue) -> Result<(), AmlError> { - match name { - AmlValue::ObjectReference(r) => match r { - ObjectReference::ArgObj(_) => Err(AmlError::AmlValueError), - ObjectReference::LocalObj(i) => self.copy_local_obj(i as usize, value), - ObjectReference::Object(s) => self.copy_object(ctx, s, value), - ObjectReference::Index(c, v) => self.modify_index(ctx, *c, value, vec!(v.get_as_integer(ctx)?)) - }, - AmlValue::String(s) => self.copy_object(ctx, s, value), - _ => Err(AmlError::AmlValueError) - } - } - - fn get_index_final(&self, ctx: &AcpiContext, name: String, indices: Vec) -> Result { - if let Some(ref namespace) = *ctx.namespace() { - let obj = if let Some(s) = namespace.get(&name) { - s.clone() - } else { - return Err(AmlError::AmlValueError); - }; - - self.get_index_core(ctx, obj, indices) - } else { - Err(AmlError::AmlValueError) - } - } - - fn get_index_core(&self, ctx: &AcpiContext, obj: AmlValue, indices: Vec) -> Result { - match obj { - AmlValue::String(ref string) => { - if indices.len() != 1 { - return Err(AmlError::AmlValueError); - } - - let bytes = string.clone().into_bytes(); - Ok(AmlValue::Integer(bytes[indices[0] as usize] as u64)) - }, - AmlValue::Buffer(ref b) => { - if indices.len() != 1 { - return Err(AmlError::AmlValueError); - } - - Ok(AmlValue::Integer(b[indices[0] as usize] as u64)) - }, - AmlValue::BufferField(ref b) => { - if indices.len() != 1 { - return Err(AmlError::AmlValueError); - } - - let mut idx = indices[0]; - idx += b.index.get_as_integer(ctx)?; - - Ok(AmlValue::Integer(b.source_buf.get_as_buffer(ctx, )?[idx as usize] as u64)) - }, - AmlValue::Package(ref p) => { - if indices.len() == 0 { - return Err(AmlError::AmlValueError); - } - - if indices.len() == 1 { - Ok(p[indices[0] as usize].clone()) - } else { - self.get_index_core(ctx, p[indices[0] as usize].clone(), indices[1..].to_vec()) - } - }, - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_index(&self, ctx: &AcpiContext, name: AmlValue, indices: Vec) -> Result{ - match name { - AmlValue::ObjectReference(r) => match r { - ObjectReference::Object(s) => self.get_index_final(ctx, s, indices), - ObjectReference::Index(c, v) => { - let mut indices = indices.clone(); - indices.push(v.get_as_integer(ctx)?); - - self.get_index(ctx, *c, indices) - }, - ObjectReference::ArgObj(_) => Err(AmlError::AmlValueError), - ObjectReference::LocalObj(i) => { - let v = self.local_vars[i as usize].clone(); - self.get_index_core(ctx, v, indices) - } - }, - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get(&self, ctx: &AcpiContext, name: AmlValue) -> Result { - 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(), - ObjectReference::Object(ref s) => if let Some(ref namespace) = *ctx.namespace() { - if let Some(o) = namespace.get(s) { - o.clone() - } else { - AmlValue::None - } - } else { AmlValue::None }, - ObjectReference::Index(c, v) => self.get_index(ctx, *c, vec!(v.get_as_integer(ctx)?))?, - }, - AmlValue::String(ref s) => if let Some(ref namespace) = *ctx.namespace() { - if let Some(o) = namespace.get(s) { - o.clone() - } else { - AmlValue::None - } - } else { AmlValue::None }, - _ => AmlValue::None - }) - } -} diff --git a/acpid/src/aml/parsermacros.rs b/acpid/src/aml/parsermacros.rs deleted file mode 100644 index 31a23386ff..0000000000 --- a/acpid/src/aml/parsermacros.rs +++ /dev/null @@ -1,52 +0,0 @@ -#[macro_export] -macro_rules! parser_selector { - {$data:expr, $ctx:expr, $func:expr} => { - match $func($data, $ctx) { - Ok(res) => return Ok(res), - Err(AmlError::AmlInvalidOpCode) => (), - Err(e) => return Err(e) - } - }; - {$data:expr, $ctx:expr, $func:expr, $($funcs:expr),+} => { - parser_selector! {$data, $ctx, $func}; - parser_selector! {$data, $ctx, $($funcs),*}; - }; -} - -#[macro_export] -macro_rules! parser_selector_simple { - {$data:expr, $func:expr} => { - match $func($data) { - Ok(res) => return Ok(res), - Err(AmlError::AmlInvalidOpCode) => (), - Err(e) => return Err(e) - } - }; - {$data:expr, $func:expr, $($funcs:expr),+} => { - parser_selector_simple! {$data, $func}; - parser_selector_simple! {$data, $($funcs),*}; - }; -} - -#[macro_export] -macro_rules! parser_opcode { - ($data:expr, $opcode:expr) => { - if $data[0] != $opcode { - return Err(AmlError::AmlInvalidOpCode); - } - }; - ($data:expr, $opcode:expr, $alternate_opcode:expr) => { - if $data[0] != $opcode && $data[0] != $alternate_opcode { - return Err(AmlError::AmlInvalidOpCode); - } - }; -} - -#[macro_export] -macro_rules! parser_opcode_extended { - ($data:expr, $opcode:expr) => { - if $data[0] != 0x5B || $data[1] != $opcode { - return Err(AmlError::AmlInvalidOpCode); - } - }; -} diff --git a/acpid/src/aml/pkglength.rs b/acpid/src/aml/pkglength.rs deleted file mode 100644 index 7b511f9b44..0000000000 --- a/acpid/src/aml/pkglength.rs +++ /dev/null @@ -1,25 +0,0 @@ -use super::AmlError; - -pub fn parse_pkg_length(data: &[u8]) -> Result<(usize, usize), AmlError> { - let lead_byte = data[0]; - let count_bytes: usize = (lead_byte >> 6) as usize; - - if count_bytes == 0 { - return Ok(((lead_byte & 0x3F) as usize, 1 as usize)); - } - - let upper_two = (lead_byte >> 4) & 0x03; - if upper_two != 0 { - return Err(AmlError::AmlParseError("Invalid package length")); - } - - let mut current_byte = 0; - let mut pkg_len: usize = (lead_byte & 0x0F) as usize; - - while current_byte < count_bytes { - pkg_len += (data[1 + current_byte] as u32 * 16 * (256 as u32).pow(current_byte as u32)) as usize; - current_byte += 1; - } - - Ok((pkg_len, count_bytes + 1)) -} diff --git a/acpid/src/aml/termlist.rs b/acpid/src/aml/termlist.rs deleted file mode 100644 index 036036f1eb..0000000000 --- a/acpid/src/aml/termlist.rs +++ /dev/null @@ -1,172 +0,0 @@ -use super::AmlError; -use super::parser::{ AmlParseType, ParseResult, AmlExecutionContext, ExecutionState }; -use super::namespace::{AmlValue, get_namespace_string}; -use super::namespacemodifier::parse_namespace_modifier; -use super::namedobj::parse_named_obj; -use super::dataobj::{parse_data_obj, parse_arg_obj, parse_local_obj}; -use super::type1opcode::parse_type1_opcode; -use super::type2opcode::parse_type2_opcode; -use super::namestring::parse_name_string; - -pub fn parse_term_list(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - let mut current_offset: usize = 0; - - while current_offset < data.len() { - let res = parse_term_obj(&data[current_offset..], ctx)?; - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: data.len() - }) - } - - current_offset += res.len; - } - - Ok(AmlParseType { - val: AmlValue::None, - len: data.len() - }) -} - -pub fn parse_term_arg(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_selector! { - data, ctx, - parse_local_obj, - parse_data_obj, - parse_arg_obj, - parse_type2_opcode - }; - - Err(AmlError::AmlInvalidOpCode) -} - -pub fn parse_object_list(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - let mut current_offset: usize = 0; - - while current_offset < data.len() { - let res = parse_object(&data[current_offset..], ctx)?; - - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: data.len() - }) - } - - current_offset += res.len; - } - - Ok(AmlParseType { - val: AmlValue::None, - len: data.len() - }) -} - -fn parse_object(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_selector! { - data, ctx, - parse_namespace_modifier, - parse_named_obj - }; - - Err(AmlError::AmlInvalidOpCode) -} - -pub fn parse_method_invocation(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - let name = parse_name_string(data, ctx)?; - let method = ctx.get(ctx.acpi_context(), name.val.clone())?; - - let method = match method { - AmlValue::None => return Err(AmlError::AmlDeferredLoad), - _ => method.get_as_method()? - }; - - let mut cur = 0; - let mut params: Vec = vec!(); - - let mut current_offset = name.len; - - while cur < method.arg_count { - let res = parse_term_arg(&data[current_offset..], ctx)?; - - current_offset += res.len; - cur += 1; - - params.push(res.val); - } - - Ok(AmlParseType { - val: method.execute(ctx.acpi_context(), get_namespace_string(ctx.acpi_context(), ctx.scope.clone(), name.val)?, params), - len: current_offset - }) -} - -fn parse_term_obj(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_selector! { - data, ctx, - parse_namespace_modifier, - parse_named_obj, - parse_type1_opcode, - parse_type2_opcode - }; - - Err(AmlError::AmlInvalidOpCode) -} diff --git a/acpid/src/aml/type1opcode.rs b/acpid/src/aml/type1opcode.rs deleted file mode 100644 index b89d939cb3..0000000000 --- a/acpid/src/aml/type1opcode.rs +++ /dev/null @@ -1,477 +0,0 @@ -use super::AmlError; -use super::parser::{AmlParseType, ParseResult, AmlExecutionContext, ExecutionState}; -use super::namespace::AmlValue; -use super::pkglength::parse_pkg_length; -use super::termlist::{parse_term_arg, parse_term_list}; -use super::namestring::{parse_name_string, parse_super_name}; - -use crate::monotonic; - -use crate::acpi::PossibleAmlTables; -use super::parse_aml_table; - -pub fn parse_type1_opcode(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_selector! { - data, ctx, - parse_def_break, - parse_def_breakpoint, - parse_def_continue, - parse_def_noop, - parse_def_fatal, - parse_def_if_else, - parse_def_load, - parse_def_notify, - parse_def_release, - parse_def_reset, - parse_def_signal, - parse_def_sleep, - parse_def_stall, - parse_def_return, - parse_def_unload, - parse_def_while - }; - - Err(AmlError::AmlInvalidOpCode) -} - -fn parse_def_break(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0xA5); - ctx.state = ExecutionState::BREAK; - - Ok(AmlParseType { - val: AmlValue::None, - len: 1 as usize - }) -} - -fn parse_def_breakpoint(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0xCC); - - Ok(AmlParseType { - val: AmlValue::None, - len: 1 as usize - }) -} - -fn parse_def_continue(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x9F); - ctx.state = ExecutionState::CONTINUE; - - Ok(AmlParseType { - val: AmlValue::None, - len: 1 as usize - }) -} - -fn parse_def_noop(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0xA3); - - Ok(AmlParseType { - val: AmlValue::None, - len: 1 as usize - }) -} - -fn parse_def_fatal(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x32); - - let fatal_type = data[2]; - let fatal_code: u16 = (data[3] as u16) + ((data[4] as u16) << 8); - let fatal_arg = parse_term_arg(&data[5..], ctx)?; - - Err(AmlError::AmlFatalError(fatal_type, fatal_code, fatal_arg.val)) -} - -fn parse_def_load(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x20); - - let name = parse_name_string(&data[2..], ctx)?; - let ddb_handle_object = parse_super_name(&data[2 + name.len..], ctx)?; - - let tbl = ctx.get(ctx.acpi_context(), name.val)?.get_as_buffer(ctx.acpi_context())?; - - let table = crate::acpi::Sdt::new(tbl.into()).map_err(|error| { - log::error!("Failed to parse def_load ACPI table: {}", error); - AmlError::AmlValueError - })?; - - if let Some(aml_sdt) = PossibleAmlTables::try_new(table.clone()) { - ctx.acpi_context().new_index(&table.signature()); - let delta = parse_aml_table(ctx.acpi_context(), aml_sdt)?; - let _ = ctx.modify(ctx.acpi_context(), ddb_handle_object.val, AmlValue::DDBHandle((delta, table.signature()))); - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + name.len + ddb_handle_object.len - }) - } else { - log::error!("Loaded table is not for AML"); - Err(AmlError::AmlValueError) - } -} - -fn parse_def_notify(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x86); - - let object = parse_super_name(&data[1..], ctx)?; - let value = parse_term_arg(&data[1 + object.len..], ctx)?; - - let number = value.val.get_as_integer(ctx.acpi_context())? as u8; - - match ctx.get(ctx.acpi_context(), object.val)? { - AmlValue::Device(d) => { - if let Some(methods) = d.notify_methods.get(&number) { - for method in methods { - method(); - } - } - }, - AmlValue::Processor(d) => { - if let Some(methods) = d.notify_methods.get(&number) { - for method in methods { - method(); - } - } - }, - AmlValue::ThermalZone(d) => { - if let Some(methods) = d.notify_methods.get(&number) { - for method in methods { - method(); - } - } - }, - _ => return Err(AmlError::AmlValueError) - } - - Ok(AmlParseType { - val: AmlValue::None, - len: 1 + object.len + value.len - }) -} - -fn parse_def_release(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x27); - - let obj = parse_super_name(&data[2..], ctx)?; - let _ = ctx.release_mutex(ctx.acpi_context(), obj.val); - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + obj.len - }) -} - -fn parse_def_reset(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x26); - - let object = parse_super_name(&data[2..], ctx)?; - ctx.get(ctx.acpi_context(), object.val.clone())?.get_as_event()?; - - let _ = ctx.modify(ctx.acpi_context(), object.val.clone(), AmlValue::Event(0)); - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + object.len - }) -} - -fn parse_def_signal(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x24); - let object = parse_super_name(&data[2..], ctx)?; - - ctx.signal_event(ctx.acpi_context(), object.val)?; - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + object.len - }) -} - -fn parse_def_sleep(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x22); - - let time = parse_term_arg(&data[2..], ctx)?; - let timeout = time.val.get_as_integer(ctx.acpi_context())?; - - let (seconds, nanoseconds) = monotonic(); - let starting_time_ns = nanoseconds + (seconds * 1_000_000_000); - - loop { - let (seconds, nanoseconds) = monotonic(); - let current_time_ns = nanoseconds + (seconds * 1_000_000_000); - - if current_time_ns - starting_time_ns > timeout as u64 * 1_000_000 { - break; - } - } - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + time.len - }) -} - -fn parse_def_stall(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x21); - - let time = parse_term_arg(&data[2..], ctx)?; - let timeout = time.val.get_as_integer(ctx.acpi_context())?; - - let (seconds, nanoseconds) = monotonic(); - let starting_time_ns = nanoseconds + (seconds * 1_000_000_000); - - loop { - let (seconds, nanoseconds) = monotonic(); - let current_time_ns = nanoseconds + (seconds * 1_000_000_000); - - if current_time_ns - starting_time_ns > timeout as u64 * 1000 { - break; - } - } - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + time.len - }) -} - -fn parse_def_unload(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x2A); - - let object = parse_super_name(&data[2..], ctx)?; - - let delta = ctx.get(ctx.acpi_context(), object.val)?.get_as_ddb_handle(ctx.acpi_context())?; - let mut namespace = ctx.prelock(ctx.acpi_context()); - - if let Some(ref mut ns) = *namespace { - for o in delta.0 { - ns.remove(&o); - } - } - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + object.len - }) -} - -fn parse_def_if_else(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0xA0); - - let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let if_condition = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], ctx)?; - - let (else_length, else_length_len) = if data.len() > 1 + pkg_length && data[1 + pkg_length] == 0xA1 { - parse_pkg_length(&data[2 + pkg_length..])? - } else { - (0 as usize, 0 as usize) - }; - - if if_condition.val.get_as_integer(ctx.acpi_context())? > 0 { - parse_term_list(&data[1 + pkg_length_len + if_condition.len .. 1 + pkg_length], ctx)?; - } else if else_length > 0 { - parse_term_list(&data[2 + pkg_length + else_length_len .. 2 + pkg_length + else_length], ctx)?; - } - - Ok(AmlParseType { - val: AmlValue::None, - len: 1 + pkg_length + if else_length > 0 { 1 + else_length } else { 0 } - }) -} - -fn parse_def_while(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0xA2); - - let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - - loop { - let predicate = parse_term_arg(&data[1 + pkg_length_len..], ctx)?; - if predicate.val.get_as_integer(ctx.acpi_context())? == 0 { - break; - } - - parse_term_list(&data[1 + pkg_length_len + predicate.len .. 1 + pkg_length], ctx)?; - - match ctx.state { - ExecutionState::EXECUTING => (), - ExecutionState::BREAK => { - ctx.state = ExecutionState::EXECUTING; - break; - }, - ExecutionState::CONTINUE => ctx.state = ExecutionState::EXECUTING, - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - } - - Ok(AmlParseType { - val: AmlValue::None, - len: 1 + pkg_length - }) -} - -fn parse_def_return(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0xA4); - - let arg_object = parse_term_arg(&data[1..], ctx)?; - ctx.state = ExecutionState::RETURN(arg_object.val); - - Ok(AmlParseType { - val: AmlValue::None, - len: 1 + arg_object.len - }) -} diff --git a/acpid/src/aml/type2opcode.rs b/acpid/src/aml/type2opcode.rs deleted file mode 100644 index 60d02bb717..0000000000 --- a/acpid/src/aml/type2opcode.rs +++ /dev/null @@ -1,1784 +0,0 @@ -use std::convert::TryFrom; - -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; -use super::termlist::{parse_term_arg, parse_method_invocation}; -use super::namestring::{parse_super_name, parse_target, parse_name_string, parse_simple_name}; -use super::dataobj::parse_data_ref_obj; - -use crate::monotonic; -use crate::acpi::{PossibleAmlTables, SdtSignature}; - -#[derive(Debug, Clone)] -pub enum MatchOpcode { - MTR, - MEQ, - MLE, - MLT, - MGE, - MGT -} - -pub fn parse_type2_opcode(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_selector! { - data, ctx, - parse_def_increment, - parse_def_acquire, - parse_def_wait, - parse_def_land, - parse_def_lequal, - parse_def_lgreater, - parse_def_lless, - parse_def_lnot, - parse_def_lor, - parse_def_size_of, - parse_def_store, - parse_def_subtract, - parse_def_to_buffer, - parse_def_to_hex_string, - parse_def_to_bcd, - parse_def_to_decimal_string, - parse_def_to_integer, - parse_def_to_string, - parse_def_add, - parse_def_xor, - parse_def_shift_left, - parse_def_shift_right, - parse_def_mod, - parse_def_and, - parse_def_or, - parse_def_concat_res, - parse_def_concat, - parse_def_cond_ref_of, - parse_def_copy_object, - parse_def_decrement, - parse_def_divide, - parse_def_find_set_left_bit, - parse_def_find_set_right_bit, - parse_def_from_bcd, - parse_def_load_table, - parse_def_match, - parse_def_mid, - parse_def_multiply, - parse_def_nand, - parse_def_nor, - parse_def_not, - parse_def_timer, - parse_def_buffer, - parse_def_package, - parse_def_var_package, - parse_def_object_type, - parse_def_deref_of, - parse_def_ref_of, - parse_def_index, - parse_method_invocation - }; - - Err(AmlError::AmlInvalidOpCode) -} - -pub fn parse_type6_opcode(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_selector! { - data, ctx, - parse_def_deref_of, - parse_def_ref_of, - parse_def_index, - parse_method_invocation - }; - - Err(AmlError::AmlInvalidOpCode) -} - -pub fn parse_def_object_type(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x8E); - parser_selector! { - data, ctx, - parse_super_name, - parse_def_ref_of, - parse_def_deref_of, - parse_def_index - } - - Err(AmlError::AmlInvalidOpCode) -} - -pub fn parse_def_package(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - // TODO: Handle deferred loads in here - parser_opcode!(data, 0x12); - - let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let numelements = data[1 + pkg_length_len] as usize; - let mut elements = parse_package_elements_list(&data[2 + pkg_length_len .. 1 + pkg_length], ctx)?.val.get_as_package()?; - - if elements.len() > numelements { - elements = elements[0 .. numelements].to_vec(); - } else if numelements > elements.len() { - for _ in 0..numelements - elements.len() { - elements.push(AmlValue::Uninitialized); - } - } - - Ok(AmlParseType { - val: AmlValue::Package(elements), - len: 1 + pkg_length - }) -} - -pub fn parse_def_var_package(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - // TODO: Handle deferred loads in here - parser_opcode!(data, 0x13); - - let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let num_elements = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], ctx)?; - let mut elements = parse_package_elements_list(&data[1 + pkg_length_len + num_elements.len .. - 1 + pkg_length], ctx)?.val.get_as_package()?; - - let numelements = num_elements.val.get_as_integer(ctx.acpi_context())? as usize; - - if elements.len() > numelements { - elements = elements[0 .. numelements].to_vec(); - } else if numelements > elements.len() { - for _ in 0..numelements - elements.len() { - elements.push(AmlValue::Uninitialized); - } - } - - Ok(AmlParseType { - val: AmlValue::Package(elements), - len: 1 + pkg_length - }) -} - -fn parse_package_elements_list(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - let mut current_offset: usize = 0; - let mut elements: Vec = vec!(); - - while current_offset < data.len() { - let dro = if let Ok(e) = parse_data_ref_obj(&data[current_offset..], ctx) { - e - } else { - let d = parse_name_string(&data[current_offset..], ctx)?; - AmlParseType { - val: AmlValue::ObjectReference(ObjectReference::Object(d.val.get_as_string(ctx.acpi_context())?)), - len: d.len - } - }; - - elements.push(dro.val); - current_offset += dro.len; - } - - Ok(AmlParseType { - val: AmlValue::Package(elements), - len: data.len() - }) -} - -pub fn parse_def_buffer(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x11); - - let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let buffer_size = parse_term_arg(&data[1 + pkg_length_len..], ctx)?; - let mut byte_list = data[1 + pkg_length_len + buffer_size.len .. 1 + pkg_length].to_vec().clone(); - - byte_list.truncate(buffer_size.val.get_as_integer(ctx.acpi_context())? as usize); - - Ok(AmlParseType { - val: AmlValue::Buffer(byte_list), - len: 1 + pkg_length - }) -} - -fn parse_def_ref_of(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x71); - - let obj = parse_super_name(&data[1..], ctx)?; - let res = match obj.val { - AmlValue::String(ref s) => { - match ctx.get(ctx.acpi_context(), AmlValue::String(s.clone()))? { - AmlValue::None => return Err(AmlError::AmlValueError), - _ => ObjectReference::Object(s.clone()) - } - }, - AmlValue::ObjectReference(ref o) => o.clone(), - _ => return Err(AmlError::AmlValueError) - }; - - Ok(AmlParseType { - val: AmlValue::ObjectReference(res), - len: 1 + obj.len - }) -} - -fn parse_def_deref_of(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x83); - - let obj = parse_term_arg(&data[1..], ctx)?; - let res = ctx.get(ctx.acpi_context(), obj.val)?; - - match res { - AmlValue::None => Err(AmlError::AmlValueError), - _ => Ok(AmlParseType { - val: res, - len: 1 + obj.len - }) - } -} - -fn parse_def_acquire(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x23); - - let obj = parse_super_name(&data[1..], ctx)?; - let timeout = (data[2 + obj.len] as u16) + ((data[3 + obj.len] as u16) << 8); - - let (seconds, nanoseconds) = monotonic(); - let starting_time_ns = nanoseconds + (seconds * 1_000_000_000); - - loop { - match ctx.acquire_mutex(ctx.acpi_context(), obj.val.clone()) { - Err(e) => return Err(e), - Ok(b) => if b { - return Ok(AmlParseType { - val: AmlValue::Integer(0), - len: 4 + obj.len - }); - } else if timeout == 0xFFFF { - // TODO: How long should be sleep be? - let _ = syscall::sched_yield(); - } else { - let (seconds, nanoseconds) = monotonic(); - let current_time_ns = nanoseconds + (seconds * 1_000_000_000); - - if current_time_ns - starting_time_ns > timeout as u64 * 1_000_000 { - return Ok(AmlParseType { - val: AmlValue::Integer(1), - len: 4 + obj.len - }); - } - } - } - } -} - -fn parse_def_increment(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x75); - - let obj = parse_super_name(&data[1..], ctx)?; - - let _namespace = ctx.prelock(ctx.acpi_context()); - let value = AmlValue::Integer(ctx.get(ctx.acpi_context(), obj.val.clone())?.get_as_integer(ctx.acpi_context())? + 1); - let _ = ctx.modify(ctx.acpi_context(), obj.val, value.clone()); - - Ok(AmlParseType { - val: value, - len: 1 + obj.len - }) -} - -fn parse_def_index(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x88); - - let obj = parse_term_arg(&data[1..], ctx)?; - let idx = parse_term_arg(&data[1 + obj.len..], ctx)?; - let target = parse_target(&data[1 + obj.len + idx.len..], ctx)?; - - let reference = AmlValue::ObjectReference(ObjectReference::Index(Box::new(obj.val), Box::new(idx.val))); - let _ = ctx.modify(ctx.acpi_context(), target.val, reference.clone()); - - Ok(AmlParseType { - val: reference, - len: 1 + obj.len + idx.len + target.len - }) -} - -fn parse_def_land(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x90); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - - let result = if lhs.val.get_as_integer(ctx.acpi_context())? > 0 && rhs.val.get_as_integer(ctx.acpi_context())? > 0 { 1 } else { 0 }; - - Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), - len: 1 + lhs.len + rhs.len - }) -} - -fn parse_def_lequal(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x93); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - - let result = if lhs.val.get_as_integer(ctx.acpi_context())? == rhs.val.get_as_integer(ctx.acpi_context())? { 1 } else { 0 }; - - Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), - len: 1 + lhs.len + rhs.len - }) -} - -fn parse_def_lgreater(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x94); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - - let result = if lhs.val.get_as_integer(ctx.acpi_context())? > rhs.val.get_as_integer(ctx.acpi_context())? { 1 } else { 0 }; - - Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), - len: 1 + lhs.len + rhs.len - }) -} - -fn parse_def_lless(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x95); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - - let result = if lhs.val.get_as_integer(ctx.acpi_context())? < rhs.val.get_as_integer(ctx.acpi_context())? { 1 } else { 0 }; - - Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), - len: 1 + lhs.len + rhs.len - }) -} - -fn parse_def_lnot(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x92); - - let operand = parse_term_arg(&data[1..], ctx)?; - let result = if operand.val.get_as_integer(ctx.acpi_context())? == 0 { 1 } else { 0 }; - - Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), - len: 1 + operand.len - }) -} - -fn parse_def_lor(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x91); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - - let result = if lhs.val.get_as_integer(ctx.acpi_context())? > 0 || rhs.val.get_as_integer(ctx.acpi_context())? > 0 { 1 } else { 0 }; - - Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), - len: 1 + lhs.len + rhs.len - }) -} - -fn parse_def_to_hex_string(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x98); - - let operand = parse_term_arg(&data[2..], ctx)?; - let target = parse_target(&data[2 + operand.len..], ctx)?; - - let res = match operand.val { - AmlValue::Integer(_) => { - let result: String = format!("{:X}", operand.val.get_as_integer(ctx.acpi_context())?); - AmlValue::String(result) - }, - AmlValue::String(s) => AmlValue::String(s), - AmlValue::Buffer(_) => { - let mut string: String = String::new(); - - for b in operand.val.get_as_buffer(ctx.acpi_context())? { - string.push_str(&format!("{:X}", b)); - } - - AmlValue::String(string) - }, - _ => return Err(AmlError::AmlValueError) - }; - - let _ = ctx.modify(ctx.acpi_context(), target.val, res.clone()); - - Ok(AmlParseType { - val: res, - len: 1 + operand.len + target.len - }) -} - -fn parse_def_to_buffer(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x96); - - let operand = parse_term_arg(&data[2..], ctx)?; - let target = parse_target(&data[2 + operand.len..], ctx)?; - - let res = AmlValue::Buffer(operand.val.get_as_buffer(ctx.acpi_context())?); - let _ = ctx.modify(ctx.acpi_context(), target.val, res.clone()); - - Ok(AmlParseType { - val: res, - len: 1 + operand.len + target.len - }) -} - -fn parse_def_to_bcd(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x29); - - let operand = parse_term_arg(&data[2..], ctx)?; - let target = parse_target(&data[2 + operand.len..], ctx)?; - - let mut i = operand.val.get_as_integer(ctx.acpi_context())?; - let mut result = 0; - - while i != 0 { - result <<= 4; - result += i % 10; - i /= 10; - } - - let result = AmlValue::Integer(result); - let _ = ctx.modify(ctx.acpi_context(), target.val, result.clone()); - - Ok(AmlParseType { - val: result, - len: 1 + operand.len + target.len - }) -} - -fn parse_def_to_decimal_string(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x97); - - let operand = parse_term_arg(&data[2..], ctx)?; - let target = parse_target(&data[2 + operand.len..], ctx)?; - let res = match operand.val { - AmlValue::Integer(_) => { - let result: String = format!("{}", operand.val.get_as_integer(ctx.acpi_context())?); - AmlValue::String(result) - }, - AmlValue::String(s) => AmlValue::String(s), - AmlValue::Buffer(_) => { - let mut string: String = String::new(); - - for b in operand.val.get_as_buffer(ctx.acpi_context())? { - string.push_str(&format!("{}", b)); - } - - AmlValue::String(string) - }, - _ => return Err(AmlError::AmlValueError) - }; - - let _ = ctx.modify(ctx.acpi_context(), target.val, res.clone()); - - Ok(AmlParseType { - val: res, - len: 1 + operand.len + target.len - }) -} - -fn parse_def_to_integer(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x99); - - let operand = parse_term_arg(&data[2..], ctx)?; - let target = parse_target(&data[2 + operand.len..], ctx)?; - - let res = AmlValue::Integer(operand.val.get_as_integer(ctx.acpi_context())?); - - let _ = ctx.modify(ctx.acpi_context(), target.val, res.clone()); - - Ok(AmlParseType { - val: res, - len: 1 + operand.len + target.len - }) -} - -fn parse_def_to_string(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x9C); - - let operand = parse_term_arg(&data[1..], ctx)?; - let length = parse_term_arg(&data[1 + operand.len..], ctx)?; - let target = parse_target(&data[1 + operand.len + length.len..], ctx)?; - - let buf = operand.val.get_as_buffer(ctx.acpi_context())?; - let mut string = match String::from_utf8(buf) { - Ok(s) => s, - Err(_) => return Err(AmlError::AmlValueError) - }; - - string.truncate(length.val.get_as_integer(ctx.acpi_context())? as usize); - let res = AmlValue::String(string); - - let _ = ctx.modify(ctx.acpi_context(), target.val, res.clone()); - - Ok(AmlParseType { - val: res, - len: 1 + operand.len + length.len + target.len - }) -} - -fn parse_def_subtract(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x74); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - - let result = AmlValue::Integer(lhs.val.get_as_integer(ctx.acpi_context())? - rhs.val.get_as_integer(ctx.acpi_context())?); - - let _ = ctx.modify(ctx.acpi_context(), target.val, result.clone()); - - Ok(AmlParseType { - val: result, - len: 1 + lhs.len + rhs.len + target.len - }) -} - -fn parse_def_size_of(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x87); - - let name = parse_super_name(&data[1..], ctx)?; - let obj = ctx.get(ctx.acpi_context(), name.val)?; - - let res = match obj { - AmlValue::Buffer(ref v) => v.len(), - AmlValue::String(ref s) => s.len(), - AmlValue::Package(ref p) => p.len(), - _ => return Err(AmlError::AmlValueError) - }; - - Ok(AmlParseType { - val: AmlValue::Integer(res as u64), - len: 1 + name.len - }) -} - -fn parse_def_store(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x70); - - let operand = parse_term_arg(&data[1..], ctx)?; - let target = parse_super_name(&data[1 + operand.len..], ctx)?; - - let _ = ctx.modify(ctx.acpi_context(), target.val.clone(), operand.val); - - Ok(AmlParseType { - val: target.val, - len: 1 + operand.len + target.len - }) -} - -fn parse_def_or(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x7D); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - - let result = AmlValue::Integer(lhs.val.get_as_integer(ctx.acpi_context())? | rhs.val.get_as_integer(ctx.acpi_context())?); - - let _ = ctx.modify(ctx.acpi_context(), target.val, result.clone()); - - Ok(AmlParseType { - val: result, - len: 1 + lhs.len + rhs.len + target.len - }) -} - -fn parse_def_shift_left(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x79); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - - let result = AmlValue::Integer(lhs.val.get_as_integer(ctx.acpi_context())? >> rhs.val.get_as_integer(ctx.acpi_context())?); - - let _ = ctx.modify(ctx.acpi_context(), target.val, result.clone()); - - Ok(AmlParseType { - val: result, - len: 1 + lhs.len + rhs.len + target.len - }) -} - -fn parse_def_shift_right(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x7A); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - - let result = AmlValue::Integer(lhs.val.get_as_integer(ctx.acpi_context())? << rhs.val.get_as_integer(ctx.acpi_context())?); - - let _ = ctx.modify(ctx.acpi_context(), target.val, result.clone()); - - Ok(AmlParseType { - val: result, - len: 1 + lhs.len + rhs.len + target.len - }) -} - -fn parse_def_add(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x72); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - - let result = AmlValue::Integer(lhs.val.get_as_integer(ctx.acpi_context())? + rhs.val.get_as_integer(ctx.acpi_context())?); - - let _ = ctx.modify(ctx.acpi_context(), target.val, result.clone()); - - Ok(AmlParseType { - val: result, - len: 1 + lhs.len + rhs.len + target.len - }) -} - -fn parse_def_and(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x7B); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - - let result = AmlValue::Integer(lhs.val.get_as_integer(ctx.acpi_context())? & rhs.val.get_as_integer(ctx.acpi_context())?); - - let _ = ctx.modify(ctx.acpi_context(), target.val, result.clone()); - - Ok(AmlParseType { - val: result, - len: 1 + lhs.len + rhs.len + target.len - }) -} - -fn parse_def_xor(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x7F); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - - let result = AmlValue::Integer(lhs.val.get_as_integer(ctx.acpi_context())? ^ rhs.val.get_as_integer(ctx.acpi_context())?); - - let _ = ctx.modify(ctx.acpi_context(), target.val, result.clone()); - - Ok(AmlParseType { - val: result, - len: 1 + lhs.len + rhs.len + target.len - }) -} - -fn parse_def_concat_res(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x84); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - - let mut buf1 = lhs.val.get_as_buffer(ctx.acpi_context())?.clone(); - let mut buf2 = rhs.val.get_as_buffer(ctx.acpi_context())?.clone(); - - if buf1.len() == 1 || buf2.len() == 1 { - return Err(AmlError::AmlValueError); - } - - if buf1.len() >= 2 && buf1[buf1.len() - 2] == 0x79 { - buf1 = buf1[0..buf1.len() - 2].to_vec(); - } - - if buf2.len() >= 2 && buf2[buf2.len() - 2] == 0x79 { - buf2 = buf2[0..buf2.len() - 2].to_vec(); - } - - buf1.append(&mut buf2); - buf1.push(0x79); - - let mut checksum: u8 = 0; - let loopbuf = buf1.clone(); - for b in loopbuf { - checksum += b; - } - - checksum = (!checksum) + 1; - buf1.push(checksum); - - let res = AmlValue::Buffer(buf1); - ctx.modify(ctx.acpi_context(), target.val, res.clone())?; - - Ok(AmlParseType { - val: res, - len: 1 + lhs.len + rhs.len + target.len - }) -} - -fn parse_def_wait(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x25); - - let obj = parse_super_name(&data[2..], ctx)?; - let timeout_obj = parse_term_arg(&data[2 + obj.len..], ctx)?; - - let timeout = timeout_obj.val.get_as_integer(ctx.acpi_context())?; - - let (seconds, nanoseconds) = monotonic(); - let starting_time_ns = nanoseconds + (seconds * 1_000_000_000); - - loop { - match ctx.wait_for_event(ctx.acpi_context(), obj.val.clone()) { - Err(e) => return Err(e), - Ok(b) => if b { - return Ok(AmlParseType { - val: AmlValue::Integer(0), - len: 2 + obj.len + timeout_obj.len - }) - } else if timeout >= 0xFFFF { - let _ = syscall::sched_yield(); - } else { - let (seconds, nanoseconds) = crate::monotonic(); - let current_time_ns = nanoseconds + (seconds * 1_000_000_000); - - if current_time_ns - starting_time_ns > timeout as u64 * 1_000_000 { - return Ok(AmlParseType { - val: AmlValue::Integer(1), - len: 2 + obj.len + timeout_obj.len - }); - } - } - } - } -} - -fn parse_def_cond_ref_of(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x12); - - let obj = parse_super_name(&data[2..], ctx)?; - let target = parse_target(&data[2 + obj.len..], ctx)?; - - let res = match obj.val { - AmlValue::String(ref s) => { - match ctx.get(ctx.acpi_context(), AmlValue::String(s.clone()))? { - AmlValue::None => return Ok(AmlParseType { - val: AmlValue::Integer(0), - len: 1 + obj.len + target.len - }), - _ => ObjectReference::Object(s.clone()) - } - }, - AmlValue::ObjectReference(ref o) => o.clone(), - _ => return Err(AmlError::AmlValueError) - }; - - let _ = ctx.modify(ctx.acpi_context(), target.val, AmlValue::ObjectReference(res)); - - Ok(AmlParseType { - val: AmlValue::Integer(1), - len: 1 + obj.len + target.len - }) -} - -fn parse_def_copy_object(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - // TODO: Compute the result - // TODO: Store the result - parser_opcode!(data, 0x9D); - - let source = parse_term_arg(&data[1..], ctx)?; - let destination = parse_simple_name(&data[1 + source.len..], ctx)?; - - ctx.copy(ctx.acpi_context(), destination.val, source.val.clone())?; - - Ok(AmlParseType { - val: source.val, - len: 1 + source.len + destination.len - }) -} - -fn parse_def_concat(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x73); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - - let result = match lhs.val { - AmlValue::Integer(_i) => { - let j = AmlValue::Integer(rhs.val.get_as_integer(ctx.acpi_context())?); - - let mut first = lhs.val.get_as_buffer(ctx.acpi_context())?.clone(); - let mut second = j.get_as_buffer(ctx.acpi_context())?.clone(); - - first.append(&mut second); - - AmlValue::Buffer(first) - }, - AmlValue::String(s) => { - let t = if let Ok(t) = rhs.val.get_as_string(ctx.acpi_context()) { - t - } else { - rhs.val.get_type_string() - }; - - AmlValue::String(format!("{}{}", s, t)) - }, - AmlValue::Buffer(b) => { - let mut b = b.clone(); - let mut c = if let Ok(c) = rhs.val.get_as_buffer(ctx.acpi_context()) { - c.clone() - } else { - AmlValue::String(rhs.val.get_type_string()).get_as_buffer(ctx.acpi_context())?.clone() - }; - - b.append(&mut c); - - AmlValue::Buffer(b) - }, - _ => { - let first = lhs.val.get_type_string(); - let second = if let Ok(second) = rhs.val.get_as_string(ctx.acpi_context()) { - second - } else { - rhs.val.get_type_string() - }; - - AmlValue::String(format!("{}{}", first, second)) - } - }; - - ctx.modify(ctx.acpi_context(), target.val, result.clone())?; - - Ok(AmlParseType { - val: result, - len: 1 + lhs.len + rhs.len + target.len - }) -} - -fn parse_def_decrement(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x76); - - let obj = parse_super_name(&data[1..], ctx)?; - - let _namespace = ctx.prelock(ctx.acpi_context()); - let value = AmlValue::Integer(ctx.get(ctx.acpi_context(), obj.val.clone())?.get_as_integer(ctx.acpi_context())? - 1); - let _ = ctx.modify(ctx.acpi_context(), obj.val, value.clone()); - - Ok(AmlParseType { - val: value, - len: 1 + obj.len - }) -} - -fn parse_def_divide(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x78); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - let target_remainder = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let target_quotient = parse_target(&data[1 + lhs.len + rhs.len + target_remainder.len..], ctx)?; - - let numerator = lhs.val.get_as_integer(ctx.acpi_context())?; - let denominator = rhs.val.get_as_integer(ctx.acpi_context())?; - - let remainder = numerator % denominator; - let quotient = (numerator - remainder) / denominator; - - let _ = ctx.modify(ctx.acpi_context(), target_remainder.val, AmlValue::Integer(remainder)); - let _ = ctx.modify(ctx.acpi_context(), target_quotient.val, AmlValue::Integer(quotient)); - - Ok(AmlParseType { - val: AmlValue::Integer(quotient), - len: 1 + lhs.len + rhs.len + target_remainder.len + target_quotient.len - }) -} - -fn parse_def_find_set_left_bit(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x81); - - let operand = parse_term_arg(&data[2..], ctx)?; - let target = parse_target(&data[2 + operand.len..], ctx)?; - - let mut first_bit = 32; - let mut test = operand.val.get_as_integer(ctx.acpi_context())?; - - while first_bit > 0{ - if test & 0x8000_0000_0000_0000 > 0 { - break; - } - - test <<= 1; - first_bit -= 1; - } - - let result = AmlValue::Integer(first_bit); - let _ = ctx.modify(ctx.acpi_context(), target.val, result.clone()); - - Ok(AmlParseType { - val: result, - len: 1 + operand.len + target.len - }) -} - -fn parse_def_find_set_right_bit(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x82); - - let operand = parse_term_arg(&data[2..], ctx)?; - let target = parse_target(&data[2 + operand.len..], ctx)?; - - let mut first_bit = 1; - let mut test = operand.val.get_as_integer(ctx.acpi_context())?; - - while first_bit <= 32 { - if test & 1 > 0 { - break; - } - - test >>= 1; - first_bit += 1; - } - - if first_bit == 33 { - first_bit = 0; - } - - let result = AmlValue::Integer(first_bit); - let _ = ctx.modify(ctx.acpi_context(), target.val, result.clone()); - - Ok(AmlParseType { - val: result, - len: 1 + operand.len + target.len - }) -} - -fn parse_def_load_table(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - // TODO: Clean up - parser_opcode_extended!(data, 0x1F); - - let signature = parse_term_arg(&data[2..], ctx)?; - let oem_id = parse_term_arg(&data[2 + signature.len..], ctx)?; - let oem_table_id = parse_term_arg(&data[2 + signature.len + oem_id.len..], ctx)?; - let root_path = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len..], ctx)?; - 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 signature = { - <[u8; 4]>::try_from(&*signature.val.get_as_string(ctx.acpi_context())?.as_bytes()) - .expect("expected 'load table' def to have a signature that is 4 bytes long") - }; - let oem_id = { - <[u8; 6]>::try_from(&*oem_id.val.get_as_string(ctx.acpi_context())?.as_bytes()) - .expect("expected 'load table' def to have an OEM ID that is 6 bytes long") - }; - let oem_table_id = { - <[u8; 8]>::try_from(&*oem_table_id.val.get_as_string(ctx.acpi_context())?.as_bytes()) - .expect("expected 'load table' def to have an OEM table ID that is 8 bytes long") - }; - - let sdt_signature = SdtSignature { - signature, - oem_id, - oem_table_id, - }; - - let parse_len = 2 + signature.len() + oem_id.len() + oem_table_id.len() + root_path.len + parameter_path.len + parameter_data.len; - - let sdt = ctx.acpi_context().sdt_from_signature(&sdt_signature); - - Ok(if let Some(sdt) = sdt.and_then(|sdt| PossibleAmlTables::try_new(sdt.clone())) { - let hdl = parse_aml_with_scope(ctx.acpi_context(), sdt, root_path.val.get_as_string(ctx.acpi_context())?)?; - let _ = ctx.modify(ctx.acpi_context(), parameter_path.val, parameter_data.val); - - AmlParseType { - val: AmlValue::DDBHandle((hdl, sdt_signature)), - len: parse_len, - } - } else { - AmlParseType { - val: AmlValue::IntegerConstant(0), - len: parse_len, - } - }) -} - -fn parse_def_match(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x28); - - let search_pkg = parse_term_arg(&data[1..], ctx)?; - - let first_operation = match data[1 + search_pkg.len] { - 0 => MatchOpcode::MTR, - 1 => MatchOpcode::MEQ, - 2 => MatchOpcode::MLE, - 3 => MatchOpcode::MLT, - 4 => MatchOpcode::MGE, - 5 => MatchOpcode::MGT, - _ => return Err(AmlError::AmlParseError("DefMatch - Invalid Opcode")) - }; - let first_operand = parse_term_arg(&data[2 + search_pkg.len..], ctx)?; - - let second_operation = match data[2 + search_pkg.len + first_operand.len] { - 0 => MatchOpcode::MTR, - 1 => MatchOpcode::MEQ, - 2 => MatchOpcode::MLE, - 3 => MatchOpcode::MLT, - 4 => MatchOpcode::MGE, - 5 => MatchOpcode::MGT, - _ => return Err(AmlError::AmlParseError("DefMatch - Invalid Opcode")) - }; - let second_operand = parse_term_arg(&data[3 + search_pkg.len + first_operand.len..], ctx)?; - - let start_index = parse_term_arg(&data[3 + search_pkg.len + first_operand.len + second_operand.len..], ctx)?; - - let pkg = search_pkg.val.get_as_package()?; - let mut idx = start_index.val.get_as_integer(ctx.acpi_context())? as usize; - - match first_operand.val { - AmlValue::Integer(i) => { - let j = second_operand.val.get_as_integer(ctx.acpi_context())?; - - while idx < pkg.len() { - let val = if let Ok(v) = pkg[idx].get_as_integer(ctx.acpi_context()) { v } else { idx += 1; continue; }; - idx += 1; - - match first_operation { - MatchOpcode::MTR => (), - MatchOpcode::MEQ => if val != i { continue }, - MatchOpcode::MLE => if val > i { continue }, - MatchOpcode::MLT => if val >= i { continue }, - MatchOpcode::MGE => if val < i { continue }, - MatchOpcode::MGT => if val <= i { continue } - } - - match second_operation { - MatchOpcode::MTR => (), - MatchOpcode::MEQ => if val != j { continue }, - MatchOpcode::MLE => if val > j { continue }, - MatchOpcode::MLT => if val >= j { continue }, - MatchOpcode::MGE => if val < j { continue }, - MatchOpcode::MGT => if val <= j { continue } - } - - return Ok(AmlParseType { - val: AmlValue::Integer(idx as u64), - len: 3 + search_pkg.len + first_operand.len + second_operand.len + start_index.len - }) - } - }, - AmlValue::String(i) => { - let j = second_operand.val.get_as_string(ctx.acpi_context())?; - - while idx < pkg.len() { - let val = if let Ok(v) = pkg[idx].get_as_string(ctx.acpi_context()) { v } else { idx += 1; continue; }; - idx += 1; - - match first_operation { - MatchOpcode::MTR => (), - MatchOpcode::MEQ => if val != i { continue }, - MatchOpcode::MLE => if val > i { continue }, - MatchOpcode::MLT => if val >= i { continue }, - MatchOpcode::MGE => if val < i { continue }, - MatchOpcode::MGT => if val <= i { continue } - } - - match second_operation { - MatchOpcode::MTR => (), - MatchOpcode::MEQ => if val != j { continue }, - MatchOpcode::MLE => if val > j { continue }, - MatchOpcode::MLT => if val >= j { continue }, - MatchOpcode::MGE => if val < j { continue }, - MatchOpcode::MGT => if val <= j { continue } - } - - return Ok(AmlParseType { - val: AmlValue::Integer(idx as u64), - len: 3 + search_pkg.len + first_operand.len + second_operand.len + start_index.len - }) - } - }, - _ => { - let i = first_operand.val.get_as_buffer(ctx.acpi_context())?; - let j = second_operand.val.get_as_buffer(ctx.acpi_context())?; - - while idx < pkg.len() { - let val = if let Ok(v) = pkg[idx].get_as_buffer(ctx.acpi_context()) { v } else { idx += 1; continue; }; - idx += 1; - - match first_operation { - MatchOpcode::MTR => (), - MatchOpcode::MEQ => if val != i { continue }, - MatchOpcode::MLE => if val > i { continue }, - MatchOpcode::MLT => if val >= i { continue }, - MatchOpcode::MGE => if val < i { continue }, - MatchOpcode::MGT => if val <= i { continue } - } - - match second_operation { - MatchOpcode::MTR => (), - MatchOpcode::MEQ => if val != j { continue }, - MatchOpcode::MLE => if val > j { continue }, - MatchOpcode::MLT => if val >= j { continue }, - MatchOpcode::MGE => if val < j { continue }, - MatchOpcode::MGT => if val <= j { continue } - } - - return Ok(AmlParseType { - val: AmlValue::Integer(idx as u64), - len: 3 + search_pkg.len + first_operand.len + second_operand.len + start_index.len - }) - } - } - } - - Ok(AmlParseType { - val: AmlValue::IntegerConstant(0xFFFF_FFFF_FFFF_FFFF), - len: 3 + search_pkg.len + first_operand.len + second_operand.len + start_index.len - }) -} - -fn parse_def_from_bcd(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x28); - - let operand = parse_term_arg(&data[2..], ctx)?; - let target = parse_target(&data[2 + operand.len..], ctx)?; - - let mut i = operand.val.get_as_integer(ctx.acpi_context())?; - let mut result = 0; - - while i != 0 { - if i & 0x0F > 10 { - return Err(AmlError::AmlValueError); - } - - result *= 10; - result += i & 0x0F; - i >>= 4; - } - - let result = AmlValue::Integer(result); - - let _ = ctx.modify(ctx.acpi_context(), target.val, result.clone()); - - Ok(AmlParseType { - val: result, - len: 2 + operand.len + target.len - }) -} - -fn parse_def_mid(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x9E); - - let source = parse_term_arg(&data[1..], ctx)?; - let index = parse_term_arg(&data[1 + source.len..], ctx)?; - let length = parse_term_arg(&data[1 + source.len + index.len..], ctx)?; - let target = parse_target(&data[1 + source.len + index.len + length.len..], ctx)?; - - let idx = index.val.get_as_integer(ctx.acpi_context())? as usize; - let mut len = length.val.get_as_integer(ctx.acpi_context())? as usize; - - let result = match source.val { - AmlValue::String(s) => { - if idx > s.len() { - AmlValue::String(String::new()) - } else { - let mut res = s.clone().split_off(idx); - - if len < res.len() { - res.truncate(len); - } - - AmlValue::String(res) - } - }, - _ => { - // If it isn't a string already, treat it as a buffer. Must perform that check first, - // as Mid can operate on both strings and buffers, but a string can be cast as a buffer - // implicitly. - // Additionally, any type that can be converted to a buffer can also be converted to a - // string, so no information is lost - let b = source.val.get_as_buffer(ctx.acpi_context())?; - - if idx > b.len() { - AmlValue::Buffer(vec!()) - } else { - if idx + len > b.len() { - len = b.len() - idx; - } - - AmlValue::Buffer(b[idx .. idx + len].to_vec()) - } - } - }; - - let _ = ctx.modify(ctx.acpi_context(), target.val, result.clone()); - - Ok(AmlParseType { - val: result, - len: 1 + source.len + index.len + length.len + target.len - }) -} - -fn parse_def_mod(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x85); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - - if rhs.val.get_as_integer(ctx.acpi_context())? == 0 { - return Err(AmlError::AmlValueError); - } - - let result = AmlValue::Integer(lhs.val.get_as_integer(ctx.acpi_context())? % rhs.val.get_as_integer(ctx.acpi_context())?); - - let _ = ctx.modify(ctx.acpi_context(), target.val, result.clone()); - - Ok(AmlParseType { - val: result, - len: 1 + lhs.len + rhs.len + target.len - }) -} - -fn parse_def_multiply(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - // TODO: Handle overflow - parser_opcode!(data, 0x77); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - - let result = AmlValue::Integer(lhs.val.get_as_integer(ctx.acpi_context())? * rhs.val.get_as_integer(ctx.acpi_context())?); - - let _ = ctx.modify(ctx.acpi_context(), target.val, result.clone()); - - Ok(AmlParseType { - val: result, - len: 1 + lhs.len + rhs.len + target.len - }) -} - -fn parse_def_nand(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x7C); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - - let result = AmlValue::Integer(!(lhs.val.get_as_integer(ctx.acpi_context())? & rhs.val.get_as_integer(ctx.acpi_context())?)); - - let _ = ctx.modify(ctx.acpi_context(), target.val, result.clone()); - - Ok(AmlParseType { - val: result, - len: 1 + lhs.len + rhs.len + target.len - }) -} - -fn parse_def_nor(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x7E); - - let lhs = parse_term_arg(&data[1..], ctx)?; - let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - - let result = AmlValue::Integer(!(lhs.val.get_as_integer(ctx.acpi_context())? | rhs.val.get_as_integer(ctx.acpi_context())?)); - - let _ = ctx.modify(ctx.acpi_context(), target.val, result.clone()); - - Ok(AmlParseType { - val: result, - len: 1 + lhs.len + rhs.len + target.len - }) -} - -fn parse_def_not(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode!(data, 0x80); - - let operand = parse_term_arg(&data[1..], ctx)?; - let target = parse_target(&data[1 + operand.len..], ctx)?; - - let result = AmlValue::Integer(!operand.val.get_as_integer(ctx.acpi_context())?); - - let _ = ctx.modify(ctx.acpi_context(), target.val, result.clone()); - - Ok(AmlParseType { - val: result, - len: 1 + operand.len + target.len - }) -} - -fn parse_def_timer(data: &[u8], - ctx: &mut AmlExecutionContext) -> ParseResult { - match ctx.state { - ExecutionState::EXECUTING => (), - _ => return Ok(AmlParseType { - val: AmlValue::None, - len: 0 - }) - } - - parser_opcode_extended!(data, 0x33); - - let (seconds, nanoseconds) = monotonic(); - let monotonic_ns = nanoseconds + (seconds * 1_000_000_000); - - Ok(AmlParseType { - val: AmlValue::Integer(monotonic_ns), - len: 2 as usize - }) -} diff --git a/acpid/src/main.rs b/acpid/src/main.rs index 0247bb6fac..34bb3b0626 100644 --- a/acpid/src/main.rs +++ b/acpid/src/main.rs @@ -1,3 +1,5 @@ +#![feature(if_let_guard)] + use std::convert::TryFrom; use std::io::{self, prelude::*}; use std::fs::{File, OpenOptions}; @@ -13,11 +15,8 @@ use syscall::data::{Event, Packet}; use syscall::flag::{EventFlags, O_NONBLOCK}; mod acpi; -mod aml; mod scheme; -// TODO: Perhaps use the acpi and aml crates? - fn monotonic() -> (u64, u64) { use syscall::call::clock_gettime; use syscall::data::TimeSpec; @@ -38,8 +37,8 @@ fn setup_logging() -> Option<&'static RedoxLogger> { let mut logger = RedoxLogger::new() .with_output( OutputBuilder::stderr() - .with_filter(log::LevelFilter::Info) // limit global output to important info - .with_ansi_escape_codes() + .with_filter(log::LevelFilter::Warn) // limit global output to important info + // .with_ansi_escape_codes() .flush_on_newline(true) .build() ); @@ -48,9 +47,9 @@ fn setup_logging() -> Option<&'static RedoxLogger> { match OutputBuilder::in_redox_logging_scheme("misc", "acpi", "acpid.log") { Ok(b) => logger = logger.with_output( // TODO: Add a configuration file for this - b.with_filter(log::LevelFilter::Trace) + b.with_filter(log::LevelFilter::Warn) .flush_on_newline(true) - .with_ansi_escape_codes() + // .with_ansi_escape_codes() .build() ), Err(error) => eprintln!("Failed to create xhci.log: {}", error), @@ -59,8 +58,8 @@ fn setup_logging() -> Option<&'static RedoxLogger> { #[cfg(target_os = "redox")] match OutputBuilder::in_redox_logging_scheme("misc", "acpi", "acpid.ansi.log") { Ok(b) => logger = logger.with_output( - b.with_filter(log::LevelFilter::Trace) - .with_ansi_escape_codes() + b.with_filter(log::LevelFilter::Warn) + // .with_ansi_escape_codes() .flush_on_newline(true) .build() ), @@ -215,7 +214,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { drop(shutdown_pipe); drop(event_queue); - aml::set_global_s_state(&acpi_context, 5); + acpi_context.set_global_s_state(5); unreachable!("System should have shut down before this is entered"); } diff --git a/acpid/src/scheme.rs b/acpid/src/scheme.rs index 3aeafc41ec..788f7c92dd 100644 --- a/acpid/src/scheme.rs +++ b/acpid/src/scheme.rs @@ -1,38 +1,43 @@ use std::collections::BTreeMap; use std::convert::{TryFrom, TryInto}; +use parking_lot::RwLockReadGuard; use syscall::data::Stat; -use syscall::error::{EBADF, EBADFD, EINVAL, EISDIR, ENOENT, ENOTDIR, EOVERFLOW}; +use syscall::error::{EIO, EBADF, EBADFD, EINVAL, EISDIR, ENOENT, ENOTDIR, EOVERFLOW}; use syscall::error::{Error, Result}; use syscall::flag::{O_ACCMODE, O_DIRECTORY, O_RDONLY, O_STAT, O_SYMLINK}; use syscall::flag::{MODE_FILE, MODE_DIR, SEEK_CUR, SEEK_END, SEEK_SET}; use syscall::scheme::SchemeMut; -use crate::acpi::{AcpiContext, SdtSignature}; +use crate::acpi::{AcpiContext, SdtSignature, AmlSymbols}; pub struct AcpiScheme<'acpi> { ctx: &'acpi AcpiContext, - handles: BTreeMap, + handles: BTreeMap>, next_fd: usize, } -struct Handle { +struct Handle<'a> { offset: usize, - kind: HandleKind, + kind: HandleKind<'a>, stat: bool, } -enum HandleKind { +enum HandleKind<'a> { TopLevel, Tables, Table(SdtSignature), + Symbols(RwLockReadGuard<'a, Option>), + Symbol(aml::AmlName), } -impl HandleKind { +impl HandleKind<'_> { fn is_dir(&self) -> bool { match self { Self::TopLevel => true, Self::Tables => true, Self::Table(_) => false, + Self::Symbols(_) => true, + Self::Symbol(_) => false, } } fn len(&self, acpi_ctx: &AcpiContext) -> Result { @@ -40,6 +45,13 @@ impl HandleKind { Self::TopLevel => TOPLEVEL_CONTENTS.len(), Self::Tables => acpi_ctx.tables().len().checked_mul(TABLE_DENTRY_LENGTH).unwrap_or(usize::max_value()), Self::Table(signature) => acpi_ctx.sdt_from_signature(signature).ok_or(Error::new(EBADFD))?.length(), + Self::Symbols(symbols_option) => { + match symbols_option.as_ref() { + Some(symbols) => symbols.symbols_str.len(), + _ => 0, + } + }, + Self::Symbol(_) => 0, }) } } @@ -54,7 +66,7 @@ impl<'acpi> AcpiScheme<'acpi> { } } -const TOPLEVEL_CONTENTS: &[u8] = b"tables\n"; +const TOPLEVEL_CONTENTS: &[u8] = b"tables\nsymbols\n"; const TABLE_DENTRY_LENGTH: usize = 35; @@ -147,6 +159,20 @@ impl SchemeMut for AcpiScheme<'_> { HandleKind::Table(signature) } + ["symbols"] => if let Ok(symbols_option) = self.ctx.aml_symbols() { + HandleKind::Symbols(symbols_option) + } else { + return Err(Error::new(EIO)) + }, + + ["symbols", symbol] => { + if let Some(symbol) = self.ctx.aml_lookup(symbol) { + HandleKind::Symbol(symbol) + } else { + return Err(Error::new(ENOENT)); + } + } + _ => return Err(Error::new(ENOENT)), }; @@ -177,7 +203,7 @@ impl SchemeMut for AcpiScheme<'_> { } fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result { let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - + stat.st_size = handle.kind.len(self.ctx)?.try_into().unwrap_or(u64::max_value()); if handle.kind.is_dir() { @@ -223,7 +249,7 @@ impl SchemeMut for AcpiScheme<'_> { return Err(Error::new(EBADF)); } - let src_buf = match handle.kind { + let src_buf = match &handle.kind { HandleKind::TopLevel => TOPLEVEL_CONTENTS, HandleKind::Table(ref signature) => self.ctx.sdt_from_signature(signature).ok_or(Error::new(EBADFD))?.as_slice(), @@ -264,6 +290,26 @@ impl SchemeMut for AcpiScheme<'_> { return Ok(bytes_written); } + + HandleKind::Symbols(symbols_option) => { + match symbols_option.as_ref() { + Some(symbols) => { + let offset = std::cmp::min(symbols.symbols_str.len(), handle.offset); + let src_buf = &symbols.symbols_str.as_bytes()[offset..]; + + let to_copy = std::cmp::min(src_buf.len(), buf.len()); + buf[..to_copy].copy_from_slice(&src_buf[..to_copy]); + + handle.offset = handle.offset.checked_add(to_copy).ok_or(Error::new(EOVERFLOW))?; + + return Ok(to_copy); + } + _ => return Err(Error::new(EIO)), + } + } + + HandleKind::Symbol(_) => b"", + }; let offset = std::cmp::min(src_buf.len(), handle.offset); @@ -272,7 +318,7 @@ impl SchemeMut for AcpiScheme<'_> { let to_copy = std::cmp::min(src_buf.len(), buf.len()); buf[..to_copy].copy_from_slice(&src_buf[..to_copy]); - handle.offset += to_copy; + handle.offset = handle.offset.checked_add(to_copy).ok_or(Error::new(EOVERFLOW))?; Ok(to_copy) }