From 9f55367906dbf13492f4b05a5e678d70de14b0a9 Mon Sep 17 00:00:00 2001 From: Connor Wood <connorwood71@gmail.com> Date: Tue, 29 Aug 2017 17:29:07 +0100 Subject: [PATCH] Implemented notification API --- src/acpi/aml/namedobj.rs | 17 +++++++++++++---- src/acpi/aml/namespace.rs | 24 +++++++++++++++++++----- src/acpi/aml/type1opcode.rs | 28 +++++++++++++++++++++++++++- 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 1d2a8e5c..bd813a8e 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -1,10 +1,12 @@ use alloc::boxed::Box; use collections::string::String; +use collections::btree_map::BTreeMap; use super::AmlError; use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext, ExecutionState }; use super::namespace::{AmlValue, ObjectReference, FieldSelector, Method, get_namespace_string, - Accessor, BufferField, FieldUnit, Processor, PowerResource, OperationRegion}; + 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; @@ -428,7 +430,10 @@ fn parse_def_device(data: &[u8], parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_ctx)?; - ctx.add_to_namespace(local_scope_string, AmlValue::Device(local_ctx.namespace_delta.clone()))?; + ctx.add_to_namespace(local_scope_string, AmlValue::Device(Device { + obj_list: local_ctx.namespace_delta.clone(), + notify_methods: BTreeMap::new() + }))?; Ok(AmlParseType { val: AmlValue::None, @@ -893,7 +898,8 @@ fn parse_def_processor(data: &[u8], ctx.add_to_namespace(local_scope_string, AmlValue::Processor(Processor { proc_id: proc_id, p_blk: if p_blk_len > 0 { Some(p_blk_addr) } else { None }, - obj_list: local_ctx.namespace_delta.clone() + obj_list: local_ctx.namespace_delta.clone(), + notify_methods: BTreeMap::new() }))?; Ok(AmlParseType { @@ -922,7 +928,10 @@ fn parse_def_thermal_zone(data: &[u8], let mut local_ctx = AmlExecutionContext::new(local_scope_string.clone()); parse_object_list(&data[2 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - ctx.add_to_namespace(local_scope_string, AmlValue::ThermalZone(local_ctx.namespace_delta.clone()))?; + ctx.add_to_namespace(local_scope_string, AmlValue::ThermalZone(ThermalZone { + obj_list: local_ctx.namespace_delta.clone(), + notify_methods: BTreeMap::new() + }))?; Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 64f02abc..ca51fe54 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -2,6 +2,7 @@ use alloc::boxed::Box; use collections::string::String; use collections::string::ToString; use collections::vec::Vec; +use collections::btree_map::BTreeMap; use core::fmt::{Debug, Formatter, Error}; use core::str::FromStr; @@ -57,11 +58,24 @@ pub struct FieldUnit { pub length: usize } +#[derive(Clone)] +pub struct Device { + pub obj_list: Vec<String>, + pub notify_methods: BTreeMap<u8, Vec<fn()>> +} + +#[derive(Clone)] +pub struct ThermalZone { + pub obj_list: Vec<String>, + pub notify_methods: BTreeMap<u8, Vec<fn()>> +} + #[derive(Clone)] pub struct Processor { pub proc_id: u8, pub p_blk: Option<u32>, - pub obj_list: Vec<String> + pub obj_list: Vec<String>, + pub notify_methods: BTreeMap<u8, Vec<fn()>> } #[derive(Clone)] @@ -103,7 +117,7 @@ pub enum AmlValue { BufferField(BufferField), DDBHandle(Vec<String>), DebugObject, - Device(Vec<String>), + Device(Device), Event(u64), FieldUnit(FieldUnit), Integer(u64), @@ -117,7 +131,7 @@ pub enum AmlValue { PowerResource(PowerResource), Processor(Processor), RawDataBuffer(Vec<u8>), - ThermalZone(Vec<String>) + ThermalZone(ThermalZone) } impl Debug for AmlValue { @@ -246,7 +260,7 @@ impl AmlValue { } } - pub fn get_as_device(&self) -> Result<Vec<String>, AmlError> { + pub fn get_as_device(&self) -> Result<Device, AmlError> { match *self { AmlValue::Device(ref s) => Ok(s.clone()), _ => Err(AmlError::AmlValueError) @@ -397,7 +411,7 @@ impl AmlValue { } } - pub fn get_as_thermal_zone(&self) -> Result<Vec<String>, AmlError> { + pub fn get_as_thermal_zone(&self) -> Result<ThermalZone, AmlError> { match *self { AmlValue::ThermalZone(ref p) => Ok(p.clone()), _ => Err(AmlError::AmlValueError) diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index 2ea0482b..18e43bdf 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -177,12 +177,38 @@ fn parse_def_notify(data: &[u8], }) } - // TODO: This requires significantly more infrastructure from the OS itself, see 5.6.6 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()? as u8; + + match ctx.get(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 -- GitLab