diff --git a/src/acpi/aml/dataobj.rs b/src/acpi/aml/dataobj.rs deleted file mode 100644 index 32f8bf1a9ef1338a8777884dfa7b9bc67540acc6..0000000000000000000000000000000000000000 --- a/src/acpi/aml/dataobj.rs +++ /dev/null @@ -1,187 +0,0 @@ -use alloc::vec::Vec; -use alloc::string::String; - -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<u8> = 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/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs deleted file mode 100644 index 332e5fbb75c389123b142f7f6f2a30e027848ff1..0000000000000000000000000000000000000000 --- a/src/acpi/aml/mod.rs +++ /dev/null @@ -1,57 +0,0 @@ -//! # AML -//! Code to parse and execute AML tables - -use alloc::string::String; -use alloc::vec::Vec; -use core::str::FromStr; - -use super::sdt::Sdt; - -#[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(sdt: &Sdt) -> Result<Vec<String>, AmlError> { - parse_aml_with_scope(sdt, String::from_str("\\").unwrap()) -} - -pub fn parse_aml_with_scope(sdt: &Sdt, scope: String) -> Result<Vec<String>, AmlError> { - let data = sdt.data(); - let mut ctx = AmlExecutionContext::new(scope); - - parse_term_list(data, &mut ctx)?; - - Ok(ctx.namespace_delta) -} - -pub fn is_aml_table(sdt: &Sdt) -> bool { - if &sdt.signature == b"DSDT" || &sdt.signature == b"SSDT" { - true - } else { - false - } -} diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs deleted file mode 100644 index 2482fb75c9ed927f7f6f63e63b497f11be52da9c..0000000000000000000000000000000000000000 --- a/src/acpi/aml/namedobj.rs +++ /dev/null @@ -1,1045 +0,0 @@ -use alloc::boxed::Box; -use alloc::string::String; -use alloc::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()?, - bank_register: bank_name.val.get_as_string()?, - 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.scope.clone(), name.val)?; - - ctx.add_to_namespace(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.scope.clone(), name.val)?; - - ctx.add_to_namespace(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.scope.clone(), name.val)?; - - ctx.add_to_namespace(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.scope.clone(), name.val)?; - - let _ = ctx.add_to_namespace(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.scope.clone(), name.val)?; - - ctx.add_to_namespace(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.scope.clone(), name.val)?; - - ctx.add_to_namespace(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.scope.clone(), name.val)?; - - ctx.add_to_namespace(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.scope.clone(), name.val)?; - ctx.add_to_namespace(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.scope.clone(), name.val)?; - let mut local_ctx = AmlExecutionContext::new(local_scope_string.clone()); - - 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(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.scope.clone(), name.val)?; - ctx.add_to_namespace(local_scope_string, AmlValue::OperationRegion(OperationRegion { - region: 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()?); - - 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()?, - data_selector: data_name.val.get_as_string()? - }; - - 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.scope.clone(), AmlValue::String(field.val.name.clone()))?; - - ctx.add_to_namespace(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<AmlParseTypeGeneric<NamedField>, 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<AmlParseTypeGeneric<usize>, 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<AmlParseTypeGeneric<AccessField>, 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()?), - 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.scope.clone(), name.val)?; - ctx.add_to_namespace(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.scope.clone(), name.val)?; - ctx.add_to_namespace(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.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(local_scope_string.clone()); - parse_object_list(&data[5 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - - ctx.add_to_namespace(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.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(local_scope_string.clone()); - parse_object_list(&data[8 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - - 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(), - 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.scope.clone(), name.val)?; - - 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(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.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(local_scope_string, obj)?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 3 + object_name.len - }) -} diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs deleted file mode 100644 index fef3b20cf3a239f90d5f22ef30875ec395729b23..0000000000000000000000000000000000000000 --- a/src/acpi/aml/namespace.rs +++ /dev/null @@ -1,490 +0,0 @@ -use alloc::boxed::Box; -use alloc::string::String; -use alloc::string::ToString; -use alloc::vec::Vec; -use alloc::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::{SdtSignature, get_signature_from_index, get_index_from_signature}; - -#[derive(Clone, Debug)] -pub enum FieldSelector { - Region(String), - Bank { - region: String, - bank_register: String, - bank_selector: Box<AmlValue> - }, - Index { - index_selector: String, - data_selector: String - } -} - -#[derive(Clone, Debug)] -pub enum ObjectReference { - ArgObj(u8), - LocalObj(u8), - Object(String), - Index(Box<AmlValue>, Box<AmlValue>) -} - -#[derive(Clone, Debug)] -pub struct Method { - pub arg_count: u8, - pub serialized: bool, - pub sync_level: u8, - pub term_list: Vec<u8> -} - -#[derive(Clone, Debug)] -pub struct BufferField { - pub source_buf: Box<AmlValue>, - pub index: Box<AmlValue>, - pub length: Box<AmlValue> -} - -#[derive(Clone, Debug)] -pub struct FieldUnit { - pub selector: FieldSelector, - pub connection: Box<AmlValue>, - pub flags: FieldFlags, - pub offset: usize, - pub length: usize -} - -#[derive(Clone, Debug)] -pub struct Device { - pub obj_list: Vec<String>, - pub notify_methods: BTreeMap<u8, Vec<fn()>> -} - -#[derive(Clone, Debug)] -pub struct ThermalZone { - pub obj_list: Vec<String>, - pub notify_methods: BTreeMap<u8, Vec<fn()>> -} - -#[derive(Clone, Debug)] -pub struct Processor { - pub proc_id: u8, - pub p_blk: Option<u32>, - pub obj_list: Vec<String>, - pub notify_methods: BTreeMap<u8, Vec<fn()>> -} - -#[derive(Clone, Debug)] -pub struct OperationRegion { - pub region: RegionSpace, - pub offset: Box<AmlValue>, - pub len: Box<AmlValue>, - pub accessor: Accessor, - pub accessed_by: Option<u64> -} - -#[derive(Clone, Debug)] -pub struct PowerResource { - pub system_level: u8, - pub resource_order: u16, - pub obj_list: Vec<String> -} - -#[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<u8>), - BufferField(BufferField), - DDBHandle((Vec<String>, SdtSignature)), - DebugObject, - Device(Device), - Event(u64), - FieldUnit(FieldUnit), - Integer(u64), - IntegerConstant(u64), - Method(Method), - Mutex((u8, Option<u64>)), - ObjectReference(ObjectReference), - OperationRegion(OperationRegion), - Package(Vec<AmlValue>), - String(String), - PowerResource(PowerResource), - Processor(Processor), - RawDataBuffer(Vec<u8>), - 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, t: AmlValue) -> Result<AmlValue, AmlError> { - 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()?)), - AmlValue::BufferField(_) => Ok(AmlValue::BufferField(self.get_as_buffer_field()?)), - AmlValue::DDBHandle(_) => Ok(AmlValue::DDBHandle(self.get_as_ddb_handle()?)), - 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()?)), - 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()?)), - 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) -> Result<Vec<u8>, AmlError> { - match *self { - AmlValue::Buffer(ref b) => Ok(b.clone()), - AmlValue::Integer(ref i) => { - let mut v: Vec<u8> = 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()?; - let idx = b.index.get_as_integer()? as usize; - let len = b.length.get_as_integer()? 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) -> Result<BufferField, AmlError> { - match *self { - AmlValue::BufferField(ref b) => Ok(b.clone()), - _ => { - let raw_buf = self.get_as_buffer()?; - 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) -> Result<(Vec<String>, SdtSignature), AmlError> { - match *self { - AmlValue::DDBHandle(ref v) => Ok(v.clone()), - AmlValue::Integer(i) => if let Some(sig) = get_signature_from_index(i as usize) { - Ok((vec!(), sig)) - } else { - Err(AmlError::AmlValueError) - }, - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_device(&self) -> Result<Device, AmlError> { - match *self { - AmlValue::Device(ref s) => Ok(s.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_event(&self) -> Result<u64, AmlError> { - match *self { - AmlValue::Event(ref e) => Ok(e.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_field_unit(&self) -> Result<FieldUnit, AmlError> { - match *self { - AmlValue::FieldUnit(ref e) => Ok(e.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_integer(&self) -> Result<u64, AmlError> { - 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()?; - 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) = get_index_from_signature(v.1.clone()) { - 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<u64, AmlError> { - match *self { - AmlValue::IntegerConstant(ref i) => Ok(i.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_method(&self) -> Result<Method, AmlError> { - match *self { - AmlValue::Method(ref m) => Ok(m.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_mutex(&self) -> Result<(u8, Option<u64>), AmlError> { - match *self { - AmlValue::Mutex(ref m) => Ok(m.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_object_reference(&self) -> Result<ObjectReference, AmlError> { - match *self { - AmlValue::ObjectReference(ref m) => Ok(m.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - /* - pub fn get_as_operation_region(&self) -> Result<OperationRegion, AmlError> { - match *self { - AmlValue::OperationRegion(ref p) => Ok(p.clone()), - _ => Err(AmlError::AmlValueError) - } - } - */ - - pub fn get_as_package(&self) -> Result<Vec<AmlValue>, AmlError> { - match *self { - AmlValue::Package(ref p) => Ok(p.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_string(&self) -> Result<String, AmlError> { - 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()?; - Ok(String::from_utf8(b).expect("Invalid UTF-8")) - }, - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_power_resource(&self) -> Result<PowerResource, AmlError> { - match *self { - AmlValue::PowerResource(ref p) => Ok(p.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_processor(&self) -> Result<Processor, AmlError> { - match *self { - AmlValue::Processor(ref p) => Ok(p.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_raw_data_buffer(&self) -> Result<Vec<u8>, AmlError> { - match *self { - AmlValue::RawDataBuffer(ref p) => Ok(p.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_thermal_zone(&self) -> Result<ThermalZone, AmlError> { - match *self { - AmlValue::ThermalZone(ref p) => Ok(p.clone()), - _ => Err(AmlError::AmlValueError) - } - } -} - -impl Method { - pub fn execute(&self, scope: String, parameters: Vec<AmlValue>) -> AmlValue { - let mut ctx = AmlExecutionContext::new(scope); - ctx.init_arg_vars(parameters); - - let _ = parse_term_list(&self.term_list[..], &mut ctx); - ctx.clean_namespace(); - - match ctx.state { - ExecutionState::RETURN(v) => v, - _ => AmlValue::IntegerConstant(0) - } - } -} - -pub fn get_namespace_string(current: String, modifier_v: AmlValue) -> Result<String, AmlError> { - let mut modifier = modifier_v.get_as_string()?; - - 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/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs deleted file mode 100644 index 77fa1406b08bfbf5fe7b2801820621cb02049026..0000000000000000000000000000000000000000 --- a/src/acpi/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.scope.clone(), source_name.val)?; - let local_alias_string = get_namespace_string(ctx.scope.clone(), alias_name.val)?; - - ctx.add_to_namespace(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.scope.clone(), name.val)?; - - ctx.add_to_namespace(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.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/src/acpi/aml/namestring.rs b/src/acpi/aml/namestring.rs deleted file mode 100644 index 3cc823891a20c8063f8f5ea6726fa5e30d650e9b..0000000000000000000000000000000000000000 --- a/src/acpi/aml/namestring.rs +++ /dev/null @@ -1,226 +0,0 @@ -use alloc::vec::Vec; -use alloc::string::String; - -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<u8> = 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<u8>, usize), AmlError> { - parser_opcode!(data, 0x00); - Ok((vec!(), 1 )) -} - -pub fn parse_name_seg(data: &[u8]) -> Result<(Vec<u8>, 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<u8>, usize), AmlError> { - parser_opcode!(data, 0x2E); - - let mut characters: Vec<u8> = 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<u8>, 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<u8> = 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/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs deleted file mode 100644 index b1046e233afe888fb26b4c65015767d826486e3d..0000000000000000000000000000000000000000 --- a/src/acpi/aml/parser.rs +++ /dev/null @@ -1,552 +0,0 @@ -use alloc::string::String; -use alloc::collections::BTreeMap; -use alloc::vec::Vec; -use alloc::boxed::Box; - -use spin::RwLockWriteGuard; - -use super::namespace::{ AmlValue, ObjectReference }; -use super::AmlError; - -use crate::acpi::ACPI_TABLE; - -pub type ParseResult = Result<AmlParseType, AmlError>; -pub type AmlParseType = AmlParseTypeGeneric<AmlValue>; - -pub struct AmlParseTypeGeneric<T> { - pub val: T, - pub len: usize -} - -pub enum ExecutionState { - EXECUTING, - CONTINUE, - BREAK, - RETURN(AmlValue) -} - -pub struct AmlExecutionContext { - pub scope: String, - pub local_vars: [AmlValue; 8], - pub arg_vars: [AmlValue; 8], - pub state: ExecutionState, - pub namespace_delta: Vec<String>, - pub ctx_id: u64, - pub sync_level: u8 -} - -impl AmlExecutionContext { - pub fn new(scope: String) -> AmlExecutionContext { - let mut idptr = ACPI_TABLE.next_ctx.write(); - let id: u64 = *idptr; - - *idptr += 1; - - AmlExecutionContext { - scope: 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 - } - } - - pub fn wait_for_event(&mut self, event_ptr: AmlValue) -> Result<bool, AmlError> { - let mut namespace_ptr = self.prelock(); - 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, event_ptr: AmlValue) -> Result<(), AmlError> { - let mut namespace_ptr = self.prelock(); - 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, mutex_ptr: AmlValue) -> Result<(), AmlError> { - let id = self.ctx_id; - - let mut namespace_ptr = self.prelock(); - 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, mutex_ptr: AmlValue) -> Result<bool, AmlError> { - let id = self.ctx_id; - - let mut namespace_ptr = self.prelock(); - 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, name: String, value: AmlValue) -> Result<(), AmlError> { - let mut namespace = ACPI_TABLE.namespace.write(); - - 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) { - let mut namespace = ACPI_TABLE.namespace.write(); - - 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<AmlValue>) { - 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(&mut self) -> RwLockWriteGuard<'static, Option<BTreeMap<String, AmlValue>>> { - ACPI_TABLE.namespace.write() - } - - fn modify_local_obj(&mut self, local: usize, value: AmlValue) -> Result<(), AmlError> { - self.local_vars[local] = value.get_as_type(self.local_vars[local].clone())?; - Ok(()) - } - - fn modify_object(&mut self, name: String, value: AmlValue) -> Result<(), AmlError> { - if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() { - 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(coercion_obj)?); - Ok(()) - } else { - Err(AmlError::AmlHardFatal) - } - } - - fn modify_index_final(&mut self, name: String, value: AmlValue, indices: Vec<u64>) -> Result<(), AmlError> { - if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() { - let mut obj = if let Some(s) = namespace.get(&name) { - s.clone() - } else { - return Err(AmlError::AmlValueError); - }; - - obj = self.modify_index_core(obj, value, indices)?; - - namespace.insert(name, obj); - Ok(()) - } else { - Err(AmlError::AmlValueError) - } - } - - fn modify_index_core(&mut self, obj: AmlValue, value: AmlValue, indices: Vec<u64>) -> Result<AmlValue, AmlError> { - 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()? 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()? 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()?; - - let _ = self.modify(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(p[indices[0] as usize].clone(), value, indices[1..].to_vec())?; - } - - Ok(AmlValue::Package(p)) - }, - _ => Err(AmlError::AmlValueError) - } - } - - pub fn modify_index(&mut self, name: AmlValue, value: AmlValue, indices: Vec<u64>) -> Result<(), AmlError>{ - match name { - AmlValue::ObjectReference(r) => match r { - ObjectReference::Object(s) => self.modify_index_final(s, value, indices), - ObjectReference::Index(c, v) => { - let mut indices = indices.clone(); - indices.push(v.get_as_integer()?); - - self.modify_index(*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(v, value, indices)?; - - Ok(()) - } - }, - _ => Err(AmlError::AmlValueError) - } - } - - pub fn modify(&mut self, 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(i as usize, value), - ObjectReference::Object(s) => self.modify_object(s, value), - ObjectReference::Index(c, v) => self.modify_index(*c, value, vec!(v.get_as_integer()?)) - }, - AmlValue::String(s) => self.modify_object(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, name: String, value: AmlValue) -> Result<(), AmlError> { - if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() { - namespace.insert(name, value); - Ok(()) - } else { - Err(AmlError::AmlHardFatal) - } - } - - pub fn copy(&mut self, 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(s, value), - ObjectReference::Index(c, v) => self.modify_index(*c, value, vec!(v.get_as_integer()?)) - }, - AmlValue::String(s) => self.copy_object(s, value), - _ => Err(AmlError::AmlValueError) - } - } - - fn get_index_final(&self, name: String, indices: Vec<u64>) -> Result<AmlValue, AmlError> { - if let Some(ref namespace) = *ACPI_TABLE.namespace.read() { - let obj = if let Some(s) = namespace.get(&name) { - s.clone() - } else { - return Err(AmlError::AmlValueError); - }; - - self.get_index_core(obj, indices) - } else { - Err(AmlError::AmlValueError) - } - } - - fn get_index_core(&self, obj: AmlValue, indices: Vec<u64>) -> Result<AmlValue, AmlError> { - 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()?; - - Ok(AmlValue::Integer(b.source_buf.get_as_buffer()?[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(p[indices[0] as usize].clone(), indices[1..].to_vec()) - } - }, - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_index(&self, name: AmlValue, indices: Vec<u64>) -> Result<AmlValue, AmlError>{ - match name { - AmlValue::ObjectReference(r) => match r { - ObjectReference::Object(s) => self.get_index_final(s, indices), - ObjectReference::Index(c, v) => { - let mut indices = indices.clone(); - indices.push(v.get_as_integer()?); - - self.get_index(*c, indices) - }, - ObjectReference::ArgObj(_) => Err(AmlError::AmlValueError), - ObjectReference::LocalObj(i) => { - let v = self.local_vars[i as usize].clone(); - self.get_index_core(v, indices) - } - }, - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get(&self, name: AmlValue) -> Result<AmlValue, AmlError> { - Ok(match name { - AmlValue::ObjectReference(r) => match r { - ObjectReference::ArgObj(i) => self.arg_vars[i as usize].clone(), - ObjectReference::LocalObj(i) => self.local_vars[i as usize].clone(), - ObjectReference::Object(ref s) => if let Some(ref namespace) = *ACPI_TABLE.namespace.read() { - if let Some(o) = namespace.get(s) { - o.clone() - } else { - AmlValue::None - } - } else { AmlValue::None }, - ObjectReference::Index(c, v) => self.get_index(*c, vec!(v.get_as_integer()?))?, - }, - AmlValue::String(ref s) => if let Some(ref namespace) = *ACPI_TABLE.namespace.read() { - if let Some(o) = namespace.get(s) { - o.clone() - } else { - AmlValue::None - } - } else { AmlValue::None }, - _ => AmlValue::None - }) - } -} diff --git a/src/acpi/aml/parsermacros.rs b/src/acpi/aml/parsermacros.rs deleted file mode 100644 index 31a23386ffc232dbc87b74d8b5b6a8005db25563..0000000000000000000000000000000000000000 --- a/src/acpi/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/src/acpi/aml/pkglength.rs b/src/acpi/aml/pkglength.rs deleted file mode 100644 index 7b511f9b449259fcdd62b201150da1a782fc63df..0000000000000000000000000000000000000000 --- a/src/acpi/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/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs deleted file mode 100644 index cd8e1033abfb59b2520156d6d991678934628f8b..0000000000000000000000000000000000000000 --- a/src/acpi/aml/termlist.rs +++ /dev/null @@ -1,174 +0,0 @@ -use alloc::vec::Vec; - -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(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<AmlValue> = 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(get_namespace_string(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/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs deleted file mode 100644 index 28b86cac441fe8b3154cf7e6b2c9a32e6ec3a470..0000000000000000000000000000000000000000 --- a/src/acpi/aml/type1opcode.rs +++ /dev/null @@ -1,472 +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::time::monotonic; - -use crate::acpi::{Sdt, load_table, get_sdt_signature}; -use super::{parse_aml_table, is_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(name.val)?.get_as_buffer()?; - let sdt = unsafe { &*(tbl.as_ptr() as *const Sdt) }; - - if is_aml_table(sdt) { - load_table(get_sdt_signature(sdt)); - let delta = parse_aml_table(sdt)?; - let _ = ctx.modify(ddb_handle_object.val, AmlValue::DDBHandle((delta, get_sdt_signature(sdt)))); - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + name.len + ddb_handle_object.len - }) - } else { - 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()? 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 - }) -} - -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(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(object.val.clone())?.get_as_event()?; - - let _ = ctx.modify(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(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()?; - - 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()?; - - 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(object.val)?.get_as_ddb_handle()?; - let mut namespace = ctx.prelock(); - - 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()? > 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()? == 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/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs deleted file mode 100644 index 5c37652a689ddc373fdeb8c31983ea15bb10c226..0000000000000000000000000000000000000000 --- a/src/acpi/aml/type2opcode.rs +++ /dev/null @@ -1,1779 +0,0 @@ -use alloc::boxed::Box; -use alloc::string::String; -use alloc::vec::Vec; - -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::time::monotonic; -use crate::acpi::SDT_POINTERS; - -#[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()? 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<AmlValue> = 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()?)), - 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()? 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(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(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(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: Brief sleep here - } 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(); - let value = AmlValue::Integer(ctx.get(obj.val.clone())?.get_as_integer()? + 1); - let _ = ctx.modify(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(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()? > 0 && rhs.val.get_as_integer()? > 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()? == rhs.val.get_as_integer()? { 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()? > rhs.val.get_as_integer()? { 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()? < rhs.val.get_as_integer()? { 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()? == 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()? > 0 || rhs.val.get_as_integer()? > 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()?); - 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()? { - string.push_str(&format!("{:X}", b)); - } - - AmlValue::String(string) - }, - _ => return Err(AmlError::AmlValueError) - }; - - let _ = ctx.modify(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()?); - let _ = ctx.modify(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()?; - let mut result = 0; - - while i != 0 { - result <<= 4; - result += i % 10; - i /= 10; - } - - let result = AmlValue::Integer(result); - let _ = ctx.modify(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()?); - 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()? { - string.push_str(&format!("{}", b)); - } - - AmlValue::String(string) - }, - _ => return Err(AmlError::AmlValueError) - }; - - let _ = ctx.modify(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()?); - - let _ = ctx.modify(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()?; - let mut string = match String::from_utf8(buf) { - Ok(s) => s, - Err(_) => return Err(AmlError::AmlValueError) - }; - - string.truncate(length.val.get_as_integer()? as usize); - let res = AmlValue::String(string); - - let _ = ctx.modify(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()? - rhs.val.get_as_integer()?); - - let _ = ctx.modify(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(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(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()? | rhs.val.get_as_integer()?); - - let _ = ctx.modify(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()? >> rhs.val.get_as_integer()?); - - let _ = ctx.modify(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()? << rhs.val.get_as_integer()?); - - let _ = ctx.modify(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()? + rhs.val.get_as_integer()?); - - let _ = ctx.modify(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()? & rhs.val.get_as_integer()?); - - let _ = ctx.modify(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()? ^ rhs.val.get_as_integer()?); - - let _ = ctx.modify(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()?.clone(); - let mut buf2 = rhs.val.get_as_buffer()?.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(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()?; - - let (seconds, nanoseconds) = monotonic(); - let starting_time_ns = nanoseconds + (seconds * 1_000_000_000); - - loop { - match ctx.wait_for_event(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 { - // TODO: Brief sleep here - } 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: 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(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(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(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()?); - - let mut first = lhs.val.get_as_buffer()?.clone(); - let mut second = j.get_as_buffer()?.clone(); - - first.append(&mut second); - - AmlValue::Buffer(first) - }, - AmlValue::String(s) => { - let t = if let Ok(t) = rhs.val.get_as_string() { - 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() { - c.clone() - } else { - AmlValue::String(rhs.val.get_type_string()).get_as_buffer()?.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() { - second - } else { - rhs.val.get_type_string() - }; - - AmlValue::String(format!("{}{}", first, second)) - } - }; - - ctx.modify(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(); - let value = AmlValue::Integer(ctx.get(obj.val.clone())?.get_as_integer()? - 1); - let _ = ctx.modify(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()?; - let denominator = rhs.val.get_as_integer()?; - - let remainder = numerator % denominator; - let quotient = (numerator - remainder) / denominator; - - let _ = ctx.modify(target_remainder.val, AmlValue::Integer(remainder)); - let _ = ctx.modify(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()?; - - 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(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()?; - - 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(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)?; - - if let Some(ref ptrs) = *(SDT_POINTERS.read()) { - let sig_str = unsafe { - let sig = *(signature.val.get_as_string()?.as_bytes().as_ptr() as *const [u8; 4]); - String::from_utf8(sig.to_vec()).expect("Error converting signature to string") - }; - let oem_str = unsafe { - *(oem_id.val.get_as_string()?.as_bytes().as_ptr() as *const [u8; 6]) - }; - let oem_table_str = unsafe { - *(oem_table_id.val.get_as_string()?.as_bytes().as_ptr() as *const [u8; 8]) - }; - - let sdt_signature = (sig_str, oem_str, oem_table_str); - - let sdt = ptrs.get(&sdt_signature); - - if let Some(sdt) = sdt { - let hdl = parse_aml_with_scope(sdt, root_path.val.get_as_string()?)?; - let _ = ctx.modify(parameter_path.val, parameter_data.val); - - return Ok(AmlParseType { - val: AmlValue::DDBHandle((hdl, sdt_signature)), - len: 2 + signature.len + oem_id.len + oem_table_id.len + root_path.len + parameter_path.len + parameter_data.len - }); - } - } - - Ok(AmlParseType { - val: AmlValue::IntegerConstant(0), - len: 2 + signature.len + oem_id.len + oem_table_id.len + root_path.len + parameter_path.len + parameter_data.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()? as usize; - - match first_operand.val { - AmlValue::Integer(i) => { - let j = second_operand.val.get_as_integer()?; - - while idx < pkg.len() { - let val = if let Ok(v) = pkg[idx].get_as_integer() { 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()?; - - while idx < pkg.len() { - let val = if let Ok(v) = pkg[idx].get_as_string() { 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()?; - let j = second_operand.val.get_as_buffer()?; - - while idx < pkg.len() { - let val = if let Ok(v) = pkg[idx].get_as_buffer() { 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()?; - 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(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()? as usize; - let mut len = length.val.get_as_integer()? 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.split_off(len).clear(); - } - - 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()?; - - 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(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()? == 0 { - return Err(AmlError::AmlValueError); - } - - let result = AmlValue::Integer(lhs.val.get_as_integer()? % rhs.val.get_as_integer()?); - - let _ = ctx.modify(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()? * rhs.val.get_as_integer()?); - - let _ = ctx.modify(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()? & rhs.val.get_as_integer()?)); - - let _ = ctx.modify(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()? | rhs.val.get_as_integer()?)); - - let _ = ctx.modify(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()?); - - let _ = ctx.modify(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/src/acpi/dmar/drhd.rs b/src/acpi/dmar/drhd.rs deleted file mode 100644 index 494917ef7bc1e815190eb4f9fe41d1212e06547a..0000000000000000000000000000000000000000 --- a/src/acpi/dmar/drhd.rs +++ /dev/null @@ -1,77 +0,0 @@ -#[repr(packed)] -pub struct DrhdFault { - pub sts: u32, - pub ctrl: u32, - pub data: u32, - pub addr: [u32; 2], - _rsv: [u64; 2], - pub log: u64, -} - -#[repr(packed)] -pub struct DrhdProtectedMemory { - pub en: u32, - pub low_base: u32, - pub low_limit: u32, - pub high_base: u64, - pub high_limit: u64, -} - -#[repr(packed)] -pub struct DrhdInvalidation { - pub queue_head: u64, - pub queue_tail: u64, - pub queue_addr: u64, - _rsv: u32, - pub cmpl_sts: u32, - pub cmpl_ctrl: u32, - pub cmpl_data: u32, - pub cmpl_addr: [u32; 2], -} - -#[repr(packed)] -pub struct DrhdPageRequest { - pub queue_head: u64, - pub queue_tail: u64, - pub queue_addr: u64, - _rsv: u32, - pub sts: u32, - pub ctrl: u32, - pub data: u32, - pub addr: [u32; 2], -} - -#[repr(packed)] -pub struct DrhdMtrrVariable { - pub base: u64, - pub mask: u64, -} - -#[repr(packed)] -pub struct DrhdMtrr { - pub cap: u64, - pub def_type: u64, - pub fixed: [u64; 11], - pub variable: [DrhdMtrrVariable; 10], -} - -#[repr(packed)] -pub struct Drhd { - pub version: u32, - _rsv: u32, - pub cap: u64, - pub ext_cap: u64, - pub gl_cmd: u32, - pub gl_sts: u32, - pub root_table: u64, - pub ctx_cmd: u64, - _rsv1: u32, - pub fault: DrhdFault, - _rsv2: u32, - pub pm: DrhdProtectedMemory, - pub invl: DrhdInvalidation, - _rsv3: u64, - pub intr_table: u64, - pub page_req: DrhdPageRequest, - pub mtrr: DrhdMtrr, -} diff --git a/src/acpi/dmar/mod.rs b/src/acpi/dmar/mod.rs deleted file mode 100644 index 8b107e2f0b9fc389948180b0ff3bdeff26662687..0000000000000000000000000000000000000000 --- a/src/acpi/dmar/mod.rs +++ /dev/null @@ -1,215 +0,0 @@ -use core::mem; - -use super::sdt::Sdt; -use self::drhd::Drhd; -use crate::memory::Frame; -use crate::paging::{ActivePageTable, PageFlags, PhysicalAddress}; - -use super::{find_sdt, load_table, get_sdt_signature}; - -pub mod drhd; - -/// The DMA Remapping Table -#[derive(Debug)] -pub struct Dmar { - sdt: &'static Sdt, - pub addr_width: u8, - pub flags: u8, - _rsv: [u8; 10], -} - -impl Dmar { - pub fn init(active_table: &mut ActivePageTable) { - let dmar_sdt = find_sdt("DMAR"); - let dmar = if dmar_sdt.len() == 1 { - load_table(get_sdt_signature(dmar_sdt[0])); - Dmar::new(dmar_sdt[0]) - } else { - println!("Unable to find DMAR"); - return; - }; - - if let Some(dmar) = dmar { - println!(" DMAR: {}: {}", dmar.addr_width, dmar.flags); - - for dmar_entry in dmar.iter() { - println!(" {:?}", dmar_entry); - match dmar_entry { - DmarEntry::Drhd(dmar_drhd) => { - let drhd = dmar_drhd.get(active_table); - - println!("VER: {:X}", {drhd.version}); - println!("CAP: {:X}", {drhd.cap}); - println!("EXT_CAP: {:X}", {drhd.ext_cap}); - println!("GCMD: {:X}", {drhd.gl_cmd}); - println!("GSTS: {:X}", {drhd.gl_sts}); - println!("RT: {:X}", {drhd.root_table}); - }, - _ => () - } - } - } - } - - pub fn new(sdt: &'static Sdt) -> Option<Dmar> { - if &sdt.signature == b"DMAR" && sdt.data_len() >= 12 { //Not valid if no local address and flags - let addr_width = unsafe { *(sdt.data_address() as *const u8) }; - let flags = unsafe { *(sdt.data_address() as *const u8).offset(1) }; - let rsv: [u8; 10] = unsafe { *((sdt.data_address() as *const u8).offset(2) as *const [u8; 10]) }; - - Some(Dmar { - sdt: sdt, - addr_width: addr_width, - flags: flags, - _rsv: rsv, - }) - } else { - None - } - } - - pub fn iter(&self) -> DmarIter { - DmarIter { - sdt: self.sdt, - i: 12 // Skip address width and flags - } - } -} - -/// DMAR DMA Remapping Hardware Unit Definition -// TODO: Implement iterator on DmarDrhd scope -#[derive(Clone, Copy, Debug)] -#[repr(packed)] -pub struct DmarDrhd { - kind: u16, - length: u16, - flags: u8, - _rsv: u8, - segment: u16, - base: u64, -} - -impl DmarDrhd { - pub fn get(&self, active_table: &mut ActivePageTable) -> &'static mut Drhd { - let result = active_table.identity_map(Frame::containing_address(PhysicalAddress::new(self.base as usize)), PageFlags::new().write(true)); - result.flush(); - unsafe { &mut *(self.base as *mut Drhd) } - } -} - -/// DMAR Reserved Memory Region Reporting -// TODO: Implement iterator on DmarRmrr scope -#[derive(Clone, Copy, Debug)] -#[repr(packed)] -pub struct DmarRmrr { - kind: u16, - length: u16, - _rsv: u16, - segment: u16, - base: u64, - limit: u64, -} - -/// DMAR Root Port ATS Capability Reporting -// TODO: Implement iterator on DmarAtsr scope -#[derive(Clone, Copy, Debug)] -#[repr(packed)] -pub struct DmarAtsr { - kind: u16, - length: u16, - flags: u8, - _rsv: u8, - segment: u16, -} - -/// DMAR Remapping Hardware Static Affinity -#[derive(Clone, Copy, Debug)] -#[repr(packed)] -pub struct DmarRhsa { - kind: u16, - length: u16, - _rsv: u32, - base: u64, - domain: u32, -} - -/// DMAR ACPI Name-space Device Declaration -// TODO: Implement iterator on DmarAndd object name -#[derive(Clone, Copy, Debug)] -#[repr(packed)] -pub struct DmarAndd { - kind: u16, - length: u16, - _rsv: [u8; 3], - acpi_dev: u8, -} - -/// DMAR Entries -#[derive(Debug)] -pub enum DmarEntry { - Drhd(&'static DmarDrhd), - InvalidDrhd(usize), - Rmrr(&'static DmarRmrr), - InvalidRmrr(usize), - Atsr(&'static DmarAtsr), - InvalidAtsr(usize), - Rhsa(&'static DmarRhsa), - InvalidRhsa(usize), - Andd(&'static DmarAndd), - InvalidAndd(usize), - Unknown(u16) -} - -pub struct DmarIter { - sdt: &'static Sdt, - i: usize -} - -impl Iterator for DmarIter { - type Item = DmarEntry; - fn next(&mut self) -> Option<Self::Item> { - if self.i + 4 <= self.sdt.data_len() { - let entry_type = unsafe { *((self.sdt.data_address() as *const u8).add(self.i) as *const u16) }; - let entry_len = unsafe { *((self.sdt.data_address() as *const u8).add(self.i + 2) as *const u16) } as usize; - - if self.i + entry_len <= self.sdt.data_len() { - let item = match entry_type { - 0 => if entry_len >= mem::size_of::<DmarDrhd>() { - DmarEntry::Drhd(unsafe { &*((self.sdt.data_address() + self.i) as *const DmarDrhd) }) - } else { - DmarEntry::InvalidDrhd(entry_len) - }, - 1 => if entry_len >= mem::size_of::<DmarRmrr>() { - DmarEntry::Rmrr(unsafe { &*((self.sdt.data_address() + self.i) as *const DmarRmrr) }) - } else { - DmarEntry::InvalidRmrr(entry_len) - }, - 2 => if entry_len >= mem::size_of::<DmarAtsr>() { - DmarEntry::Atsr(unsafe { &*((self.sdt.data_address() + self.i) as *const DmarAtsr) }) - } else { - DmarEntry::InvalidAtsr(entry_len) - }, - 3 => if entry_len == mem::size_of::<DmarRhsa>() { - DmarEntry::Rhsa(unsafe { &*((self.sdt.data_address() + self.i) as *const DmarRhsa) }) - } else { - DmarEntry::InvalidRhsa(entry_len) - }, - 4 => if entry_len >= mem::size_of::<DmarAndd>() { - DmarEntry::Andd(unsafe { &*((self.sdt.data_address() + self.i) as *const DmarAndd) }) - } else { - DmarEntry::InvalidAndd(entry_len) - }, - _ => DmarEntry::Unknown(entry_type) - }; - - self.i += entry_len; - - Some(item) - } else { - None - } - } else { - None - } - } -} diff --git a/src/acpi/fadt.rs b/src/acpi/fadt.rs deleted file mode 100644 index 4ee13e929e5293e2f915459f19af5793daddd7b5..0000000000000000000000000000000000000000 --- a/src/acpi/fadt.rs +++ /dev/null @@ -1,124 +0,0 @@ -use core::{mem, ptr}; - -use super::sdt::Sdt; -use super::{ACPI_TABLE, SDT_POINTERS, get_sdt, find_sdt, get_sdt_signature, load_table}; - -use crate::paging::ActivePageTable; - -#[repr(packed)] -#[derive(Clone, Copy, Debug)] -pub struct Fadt { - pub header: Sdt, - pub firmware_ctrl: u32, - pub dsdt: u32, - - // field used in ACPI 1.0; no longer in use, for compatibility only - reserved: u8, - - pub preferred_power_managament: u8, - pub sci_interrupt: u16, - pub smi_command_port: u32, - pub acpi_enable: u8, - pub acpi_disable: u8, - pub s4_bios_req: u8, - pub pstate_control: u8, - pub pm1a_event_block: u32, - pub pm1b_event_block: u32, - pub pm1a_control_block: u32, - pub pm1b_control_block: u32, - pub pm2_control_block: u32, - pub pm_timer_block: u32, - pub gpe0_block: u32, - pub gpe1_block: u32, - pub pm1_event_length: u8, - pub pm1_control_length: u8, - pub pm2_control_length: u8, - pub pm_timer_length: u8, - pub gpe0_ength: u8, - pub gpe1_length: u8, - pub gpe1_base: u8, - pub c_state_control: u8, - pub worst_c2_latency: u16, - pub worst_c3_latency: u16, - pub flush_size: u16, - pub flush_stride: u16, - pub duty_offset: u8, - pub duty_width: u8, - pub day_alarm: u8, - pub month_alarm: u8, - pub century: u8, - - // reserved in ACPI 1.0; used since ACPI 2.0+ - pub boot_architecture_flags: u16, - - reserved2: u8, - pub flags: u32, -} - -/* ACPI 2 structure -#[repr(packed)] -#[derive(Clone, Copy, Debug, Default)] -pub struct GenericAddressStructure { - address_space: u8, - bit_width: u8, - bit_offset: u8, - access_size: u8, - address: u64, -} - -{ - // 12 byte structure; see below for details - pub reset_reg: GenericAddressStructure, - - pub reset_value: u8, - reserved3: [u8; 3], - - // 64bit pointers - Available on ACPI 2.0+ - pub x_firmware_control: u64, - pub x_dsdt: u64, - - pub x_pm1a_event_block: GenericAddressStructure, - pub x_pm1b_event_block: GenericAddressStructure, - pub x_pm1a_control_block: GenericAddressStructure, - pub x_pm1b_control_block: GenericAddressStructure, - pub x_pm2_control_block: GenericAddressStructure, - pub x_pm_timer_block: GenericAddressStructure, - pub x_gpe0_block: GenericAddressStructure, - pub x_gpe1_block: GenericAddressStructure, -} -*/ - -impl Fadt { - pub fn new(sdt: &'static Sdt) -> Option<Fadt> { - if &sdt.signature == b"FACP" && sdt.length as usize >= mem::size_of::<Fadt>() { - Some(unsafe { ptr::read((sdt as *const Sdt) as *const Fadt) }) - } else { - None - } - } - - pub fn init(active_table: &mut ActivePageTable) { - let fadt_sdt = find_sdt("FACP"); - let fadt = if fadt_sdt.len() == 1 { - load_table(get_sdt_signature(fadt_sdt[0])); - Fadt::new(fadt_sdt[0]) - } else { - println!("Unable to find FADT"); - return; - }; - - if let Some(fadt) = fadt { - println!(" FACP: {:X}", {fadt.dsdt}); - - let dsdt_sdt = get_sdt(fadt.dsdt as usize, active_table); - - let signature = get_sdt_signature(dsdt_sdt); - if let Some(ref mut ptrs) = *(SDT_POINTERS.write()) { - ptrs.insert(signature, dsdt_sdt); - } - - let mut fadt_t = ACPI_TABLE.fadt.write(); - *fadt_t = Some(fadt); - } - } -} diff --git a/src/acpi/hpet.rs b/src/acpi/hpet.rs index 269fa601f6824bc096ef2f28fdab90255ac8db24..498a6681bb0f2b41396d64a4ddb867744bd5b24c 100644 --- a/src/acpi/hpet.rs +++ b/src/acpi/hpet.rs @@ -6,7 +6,7 @@ use crate::memory::Frame; use crate::paging::{ActivePageTable, PhysicalAddress, Page, PageFlags, VirtualAddress}; use super::sdt::Sdt; -use super::{ACPI_TABLE, find_sdt, load_table, get_sdt_signature}; +use super::{ACPI_TABLE, find_sdt}; #[repr(packed)] #[derive(Clone, Copy, Debug, Default)] @@ -38,7 +38,6 @@ impl Hpet { pub fn init(active_table: &mut ActivePageTable) { let hpet_sdt = find_sdt("HPET"); let hpet = if hpet_sdt.len() == 1 { - load_table(get_sdt_signature(hpet_sdt[0])); Hpet::new(hpet_sdt[0], active_table) } else { println!("Unable to find HPET"); diff --git a/src/acpi/madt.rs b/src/acpi/madt.rs index 031598cef9cbdf44f0b45074fe375aeb6b99f8c4..f6dabb65fe2fa75e5706084b07ef3fe5e6fdfdeb 100644 --- a/src/acpi/madt.rs +++ b/src/acpi/madt.rs @@ -4,7 +4,7 @@ use crate::memory::{allocate_frames, Frame}; use crate::paging::{ActivePageTable, Page, PageFlags, PhysicalAddress, VirtualAddress}; use super::sdt::Sdt; -use super::{find_sdt, load_table, get_sdt_signature}; +use super::find_sdt; use core::intrinsics::{atomic_load, atomic_store}; use core::sync::atomic::Ordering; @@ -31,7 +31,6 @@ impl Madt { pub fn init(active_table: &mut ActivePageTable) { let madt_sdt = find_sdt("APIC"); let madt = if madt_sdt.len() == 1 { - load_table(get_sdt_signature(madt_sdt[0])); Madt::new(madt_sdt[0]) } else { println!("Unable to find MADT"); diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index 13b6743ef02ae9eaf230255b286dae758a348e19..c75c78b4197387ba728b2ad5fd5bb68c717553ff 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -6,18 +6,12 @@ use alloc::string::String; use alloc::vec::Vec; use alloc::boxed::Box; -use syscall::io::{Io, Pio}; - -use spin::RwLock; - -use crate::stop::kstop; +use spin::{Once, RwLock}; use crate::log::info; use crate::memory::Frame; use crate::paging::{ActivePageTable, Page, PageFlags, PhysicalAddress, VirtualAddress}; -use self::dmar::Dmar; -use self::fadt::Fadt; use self::madt::Madt; use self::rsdt::Rsdt; use self::sdt::Sdt; @@ -26,16 +20,11 @@ use self::hpet::Hpet; use self::rxsdt::Rxsdt; use self::rsdp::RSDP; -use self::aml::{parse_aml_table, AmlError, AmlValue}; - pub mod hpet; -mod dmar; -mod fadt; pub mod madt; mod rsdt; pub mod sdt; mod xsdt; -pub mod aml; mod rxsdt; mod rsdp; @@ -67,48 +56,20 @@ pub fn get_sdt(sdt_address: usize, active_table: &mut ActivePageTable) -> &'stat sdt } -fn init_aml_table(sdt: &'static Sdt) { - match parse_aml_table(sdt) { - Ok(_) => println!(": Parsed"), - Err(AmlError::AmlParseError(e)) => println!(": {}", e), - Err(AmlError::AmlInvalidOpCode) => println!(": Invalid opcode"), - Err(AmlError::AmlValueError) => println!(": Type constraints or value bounds not met"), - Err(AmlError::AmlDeferredLoad) => println!(": Deferred load reached top level"), - Err(AmlError::AmlFatalError(_, _, _)) => { - println!(": Fatal error occurred"); - unsafe { kstop(); } - }, - Err(AmlError::AmlHardFatal) => { - println!(": Fatal error occurred"); - unsafe { kstop(); } +pub enum RxsdtEnum { + Rsdt(Rsdt), + Xsdt(Xsdt), +} +impl Rxsdt for RxsdtEnum { + fn iter(&self) -> Box<dyn Iterator<Item = usize>> { + match self { + Self::Rsdt(rsdt) => <Rsdt as Rxsdt>::iter(rsdt), + Self::Xsdt(xsdt) => <Xsdt as Rxsdt>::iter(xsdt), } } } -fn init_namespace() { - { - let mut namespace = ACPI_TABLE.namespace.write(); - *namespace = Some(BTreeMap::new()); - } - - let dsdt = find_sdt("DSDT"); - if dsdt.len() == 1 { - print!(" DSDT"); - load_table(get_sdt_signature(dsdt[0])); - init_aml_table(dsdt[0]); - } else { - println!("Unable to find DSDT"); - return; - }; - - let ssdts = find_sdt("SSDT"); - - for ssdt in ssdts { - print!(" SSDT"); - load_table(get_sdt_signature(ssdt)); - init_aml_table(ssdt); - } -} +pub static RXSDT_ENUM: Once<RxsdtEnum> = Once::new(); /// Parse the ACPI tables to gather CPU, interrupt, and timer information pub unsafe fn init(active_table: &mut ActivePageTable, already_supplied_rsdps: Option<(u64, u64)>) { @@ -117,11 +78,6 @@ pub unsafe fn init(active_table: &mut ActivePageTable, already_supplied_rsdps: O *sdt_ptrs = Some(BTreeMap::new()); } - { - let mut order = SDT_ORDER.write(); - *order = Some(vec!()); - } - // Search for RSDP if let Some(rsdp) = RSDP::get_rsdp(active_table, already_supplied_rsdps) { info!("RSDP: {:?}", rsdp); @@ -132,15 +88,40 @@ pub unsafe fn init(active_table: &mut ActivePageTable, already_supplied_rsdps: O } println!(":"); - let rxsdt: Box<dyn Rxsdt + Send + Sync> = if let Some(rsdt) = Rsdt::new(rxsdt) { - Box::new(rsdt) + let rxsdt = if let Some(rsdt) = Rsdt::new(rxsdt) { + let mut initialized = false; + + let rsdt = RXSDT_ENUM.call_once(|| { + initialized = true; + + RxsdtEnum::Rsdt(rsdt) + }); + + if !initialized { + log::error!("RXSDT_ENUM already initialized"); + } + + rsdt } else if let Some(xsdt) = Xsdt::new(rxsdt) { - Box::new(xsdt) + let mut initialized = false; + + let xsdt = RXSDT_ENUM.call_once(|| { + initialized = true; + + RxsdtEnum::Xsdt(xsdt) + }); + if !initialized { + log::error!("RXSDT_ENUM already initialized"); + } + + xsdt } else { println!("UNKNOWN RSDT OR XSDT SIGNATURE"); return; }; + // TODO: Don't touch ACPI tables in kernel? + rxsdt.map_all(active_table); for sdt_address in rxsdt.iter() { @@ -152,47 +133,19 @@ pub unsafe fn init(active_table: &mut ActivePageTable, already_supplied_rsdps: O } } - Fadt::init(active_table); + // TODO: Enumerate processors in userspace, and then provide an ACPI-independent interface + // to initialize enumerated processors to userspace? Madt::init(active_table); - Dmar::init(active_table); + // TODO: Let userspace setup HPET, and then provide an interface to specify which timer to + // use? Hpet::init(active_table); - init_namespace(); } else { println!("NO RSDP FOUND"); } } -pub fn set_global_s_state(state: u8) { - if state == 5 { - let fadt = ACPI_TABLE.fadt.read(); - - if let Some(ref fadt) = *fadt { - let port = fadt.pm1a_control_block as u16; - let mut val = 1 << 13; - - let namespace = ACPI_TABLE.namespace.read(); - - if let Some(ref namespace) = *namespace { - if let Some(s) = namespace.get("\\_S5") { - if let Ok(p) = s.get_as_package() { - let slp_typa = p[0].get_as_integer().expect("SLP_TYPa is not an integer"); - let slp_typb = p[1].get_as_integer().expect("SLP_TYPb is not an integer"); - - println!("Shutdown SLP_TYPa {:X}, SLP_TYPb {:X}", slp_typa, slp_typb); - val |= slp_typa as u16; - - println!("Shutdown with ACPI outw(0x{:X}, 0x{:X})", port, val); - Pio::<u16>::new(port).write(val); - } - } - } - } - } -} - pub type SdtSignature = (String, [u8; 6], [u8; 8]); pub static SDT_POINTERS: RwLock<Option<BTreeMap<SdtSignature, &'static Sdt>>> = RwLock::new(None); -pub static SDT_ORDER: RwLock<Option<Vec<SdtSignature>>> = RwLock::new(None); pub fn find_sdt(name: &str) -> Vec<&'static Sdt> { let mut sdts: Vec<&'static Sdt> = vec!(); @@ -213,51 +166,12 @@ pub fn get_sdt_signature(sdt: &'static Sdt) -> SdtSignature { (signature, sdt.oem_id, sdt.oem_table_id) } -pub fn load_table(signature: SdtSignature) { - let mut order = SDT_ORDER.write(); - - if let Some(ref mut o) = *order { - o.push(signature); - } -} - -pub fn get_signature_from_index(index: usize) -> Option<SdtSignature> { - if let Some(ref order) = *(SDT_ORDER.read()) { - if index < order.len() { - Some(order[index].clone()) - } else { - None - } - } else { - None - } -} - -pub fn get_index_from_signature(signature: SdtSignature) -> Option<usize> { - if let Some(ref order) = *(SDT_ORDER.read()) { - let mut i = order.len(); - while i > 0 { - i -= 1; - - if order[i] == signature { - return Some(i); - } - } - } - - None -} - pub struct Acpi { - pub fadt: RwLock<Option<Fadt>>, - pub namespace: RwLock<Option<BTreeMap<String, AmlValue>>>, pub hpet: RwLock<Option<Hpet>>, pub next_ctx: RwLock<u64>, } pub static ACPI_TABLE: Acpi = Acpi { - fadt: RwLock::new(None), - namespace: RwLock::new(None), hpet: RwLock::new(None), next_ctx: RwLock::new(0), }; diff --git a/src/acpi/rsdt.rs b/src/acpi/rsdt.rs index c2eb8c9e7daccd1d2b196190367a3f26ae9f854f..750c464714e5a91d357ac14a77a3a7b12181384a 100644 --- a/src/acpi/rsdt.rs +++ b/src/acpi/rsdt.rs @@ -1,3 +1,4 @@ +use core::convert::TryFrom; use core::mem; use alloc::boxed::Box; @@ -15,6 +16,14 @@ impl Rsdt { None } } + pub fn as_slice(&self) -> &[u8] { + let length = usize::try_from(self.0.length) + .expect("expected 32-bit length to fit within usize"); + + unsafe { + core::slice::from_raw_parts(self.0 as *const _ as *const u8, length) + } + } } impl Rxsdt for Rsdt { diff --git a/src/acpi/xsdt.rs b/src/acpi/xsdt.rs index 9f0d3633bdb918701c108e4e3225023385a07556..6dc69b663def68a6455e2abf283b4c57ec4d026d 100644 --- a/src/acpi/xsdt.rs +++ b/src/acpi/xsdt.rs @@ -1,3 +1,4 @@ +use core::convert::TryFrom; use core::mem; use alloc::boxed::Box; @@ -15,6 +16,14 @@ impl Xsdt { None } } + pub fn as_slice(&self) -> &[u8] { + let length = usize::try_from(self.0.length) + .expect("expected 32-bit length to fit within usize"); + + unsafe { + core::slice::from_raw_parts(self.0 as *const _ as *const u8, length) + } + } } impl Rxsdt for Xsdt { diff --git a/src/arch/x86_64/device/ioapic.rs b/src/arch/x86_64/device/ioapic.rs index 54ea18ab3999b440620c09c0e18b787fdc3fe157..e92d45216cc1a4d27b2143779b8b3ca03498f029 100644 --- a/src/arch/x86_64/device/ioapic.rs +++ b/src/arch/x86_64/device/ioapic.rs @@ -24,9 +24,6 @@ impl IoApicRegs { // offset 0x10 unsafe { self.pointer.offset(4) } } - fn read_ioregsel(&self) -> u32 { - unsafe { ptr::read_volatile::<u32>(self.ioregsel()) } - } fn write_ioregsel(&mut self, value: u32) { unsafe { ptr::write_volatile::<u32>(self.ioregsel() as *mut u32, value) } } @@ -356,7 +353,12 @@ pub unsafe fn init(active_table: &mut ActivePageTable) { irq::set_irq_method(irq::IrqMethod::Apic); // tell the firmware that we're using APIC rather than the default 8259 PIC. - #[cfg(feature = "acpi")] + + // FIXME: With ACPI moved to userspace, we should instead allow userspace to check whether the + // IOAPIC has been initialized, and then subsequently let some ACPI driver call the AML from + // userspace. + + /*#[cfg(feature = "acpi")] { let method = { let namespace_guard = crate::acpi::ACPI_TABLE.namespace.read(); @@ -369,7 +371,7 @@ pub unsafe fn init(active_table: &mut ActivePageTable) { if let Some(m) = method { m.execute("\\_PIC".into(), vec!(crate::acpi::aml::AmlValue::Integer(1))); } - } + }*/ } fn get_override(irq: u8) -> Option<&'static Override> { src_overrides().iter().find(|over| over.bus_irq == irq) diff --git a/src/arch/x86_64/stop.rs b/src/arch/x86_64/stop.rs index 1000866735389db8cbd61855cb47f5b9ff0a06e2..eadc8c3c4a237f146a92e6927fa024fc645571c2 100644 --- a/src/arch/x86_64/stop.rs +++ b/src/arch/x86_64/stop.rs @@ -1,5 +1,10 @@ #[cfg(feature = "acpi")] -use crate::acpi; +use crate::{ + context, + scheme::acpi, + time, +}; + use crate::syscall::io::{Io, Pio}; #[no_mangle] @@ -22,12 +27,47 @@ pub unsafe extern fn kreset() -> ! { unreachable!(); } +#[cfg(feature = "acpi")] +fn userspace_acpi_shutdown() { + log::info!("Notifying any potential ACPI driver"); + // Tell whatever driver that handles ACPI, that it should enter the S5 state (i.e. + // shutdown). + if ! acpi::register_kstop() { + // There was no context to switch to. + log::info!("No ACPI driver was alive to handle shutdown."); + return; + } + log::info!("Waiting one second for ACPI driver to run the shutdown sequence."); + let (initial_s, initial_ns) = time::monotonic(); + + // Since this driver is a userspace process, and we do not use any magic like directly + // context switching, we have to wait for the userspace driver to complete, with a timeout. + // + // We switch context, and wait for one second. + loop { + // TODO: Switch directly to whichever process is handling the kstop pipe. We would add an + // event flag like EVENT_DIRECT, which has already been suggested for IRQs. + // TODO: Waitpid with timeout? Because, what if the ACPI driver would crash? + let _ = unsafe { context::switch() }; + let (current_s, current_ns) = time::monotonic(); + + let diff_s = current_s - initial_s; + let diff_part_ns = current_ns - initial_ns; + let diff_ns = diff_s * 1_000_000_000 + diff_part_ns; + + if diff_ns > 1_000_000_000 { + log::info!("Timeout reached, thus falling back to other shutdown methods."); + return; + } + } +} + #[no_mangle] pub unsafe extern fn kstop() -> ! { - println!("kstop"); + log::info!("Running kstop()"); #[cfg(feature = "acpi")] - acpi::set_global_s_state(5); + userspace_acpi_shutdown(); // Magic shutdown code for bochs and qemu (older versions). for c in "Shutdown".bytes() { diff --git a/src/context/context.rs b/src/context/context.rs index 5d6b444356fe388b5acde6907bbaf10705b8a114..299e3032af8d779a0cc49fd9b9bf3a9bd090d643 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -34,7 +34,7 @@ pub enum Status { Runnable, Blocked, Stopped(usize), - Exited(usize) + Exited(usize), } #[derive(Copy, Clone, Debug)] diff --git a/src/lib.rs b/src/lib.rs index 1b4aa6962fc7f3dea86f5f44ddf8c07ba196cd97..9f141dd34c2b7af24e6ebe411f8c640a7d75e03a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,6 +46,7 @@ #![feature(asm)] // TODO: Relax requirements of most asm invocations #![cfg_attr(target_arch = "aarch64", feature(llvm_asm))] // TODO: Rewrite using asm! #![feature(concat_idents)] +#![feature(const_btree_new)] #![feature(const_fn)] #![feature(core_intrinsics)] #![feature(global_asm)] diff --git a/src/scheme/acpi.rs b/src/scheme/acpi.rs index e3351a78695a89a0fadd10a5a1bc9367d800e275..c56a581e0066f97f5abe11102514f1e871eb36fc 100644 --- a/src/scheme/acpi.rs +++ b/src/scheme/acpi.rs @@ -1,448 +1,290 @@ use core::convert::TryInto; -use core::fmt::Write; use core::str; use core::sync::atomic::{self, AtomicUsize}; +use alloc::boxed::Box; use alloc::collections::BTreeMap; -use alloc::vec::Vec; - -use syscall::data::Stat; -use syscall::error::{EACCES, EBADF, EBADFD, EINVAL, EIO, EISDIR, ENOENT, ENOTDIR}; -use syscall::flag::{O_ACCMODE, O_DIRECTORY, O_RDWR, O_STAT, O_WRONLY}; -use syscall::scheme::{calc_seek_offset_usize, Scheme}; -use syscall::{Error, Result}; -use syscall::{MODE_DIR, MODE_FILE}; - -use spin::{Mutex, RwLock}; - -use crate::acpi::sdt::Sdt; -use crate::acpi::SdtSignature; -use crate::paging::{ActivePageTable, TableKind}; - -#[derive(Clone, Copy)] -struct PhysSlice { - phys_ptr: usize, - len: usize, - /// These appear to be identity mapped, so this is technically not needed. - virt: usize, -} -/// A scheme used to access ACPI tables needed for some drivers to function (e.g. pcid with the -/// PCIe "MCFG" table). -/// -/// # Layout -/// * `/tables` -/// * _can be listed to retrieve the available tables_ -/// * e.g. MCFG-<OEM ID in hex>-<OEM TABLE ID in hex> -/// * _maybe_ the MADT, in case some userspace driver takes care of the I/O APIC. -/// * _perhaps_ some interface for e.g. power management. -pub struct AcpiScheme { - handles: RwLock<BTreeMap<usize, Mutex<Handle>>>, - tables: Vec<(SdtSignature, PhysSlice)>, - next_fd: AtomicUsize, -} +use spin::{Mutex, Once, RwLock}; + +use crate::acpi::{RXSDT_ENUM, RxsdtEnum}; +use crate::event; +use crate::scheme::SchemeId; +use crate::sync::WaitCondition; -const TOPLEVEL_DIR_CONTENTS: &[u8] = b"tables\n"; -const ALLOWED_TABLES: &[[u8; 4]] = &[*b"MCFG", *b"APIC"]; +use crate::syscall::data::Stat; +use crate::syscall::error::{EACCES, EBADF, EBADFD, EINTR, EINVAL, EISDIR, ENOENT, ENOTDIR, EROFS}; +use crate::syscall::flag::{ + EventFlags, EVENT_READ, + MODE_CHR, MODE_DIR, MODE_FILE, + O_ACCMODE, O_CREAT, O_DIRECTORY, O_EXCL, O_RDONLY, O_STAT, O_SYMLINK, + SEEK_SET, SEEK_CUR, SEEK_END, +}; +use crate::syscall::scheme::Scheme; +use crate::syscall::error::{Error, Result}; -// XXX: Why can't core also have something like std::io::Take? It's not even real I/O! -/// An internal wrapper struct that limits the number of bytes that can be fmt-written, in order to -/// properly return the length when reading directories etc. The bytes that cannot be written will -/// be discarded. -struct Take<'a> { - buf: &'a mut [u8], +/// A scheme used to access the RSDT or XSDT, which is needed for e.g. `acpid` to function. +pub struct AcpiScheme; + +struct Handle { offset: usize, + kind: HandleKind, + stat: bool, } - -impl Take<'_> { - pub fn write_to_buf<'a>(buf: &'a mut [u8]) -> Take<'a> { - Take { offset: 0, buf } - } - pub fn bytes_currently_written(&self) -> usize { - self.offset - } +#[derive(Eq, PartialEq)] +enum HandleKind { + TopLevel, + Rxsdt, + ShutdownPipe, } -impl<'a> core::fmt::Write for Take<'a> { - fn write_str(&mut self, string: &str) -> core::fmt::Result { - if self.offset > self.buf.len() { - return Ok(()); - } +static HANDLES: RwLock<BTreeMap<usize, Handle>> = RwLock::new(BTreeMap::new()); +static NEXT_FD: AtomicUsize = AtomicUsize::new(0); - let string_bytes = string.as_bytes(); - let max = core::cmp::min(string_bytes.len() + self.offset, self.buf.len()) - self.offset; - self.buf[self.offset..self.offset + max].copy_from_slice(&string_bytes[..max]); - self.offset += max; - Ok(()) - } -} +static DATA: Once<Box<[u8]>> = Once::new(); -enum Handle { - TopLevel(usize), // seek offset - Tables(usize), // seek offset +const TOPLEVEL_CONTENTS: &[u8] = b"rxsdt\nkstop\n"; - Table { - name: [u8; 4], - oem_id: [u8; 6], - oem_table_id: [u8; 8], +static KSTOP_WAITCOND: WaitCondition = WaitCondition::new(); +static KSTOP_FLAG: Mutex<bool> = Mutex::new(false); - offset: usize, // seek offset - }, -} +static SCHEME_ID: Once<SchemeId> = Once::new(); -impl AcpiScheme { - fn get_tables() -> Vec<(SdtSignature, PhysSlice)> { - let mut active_table = unsafe { ActivePageTable::new(TableKind::Kernel) }; - - let mut tables = Vec::new(); - - for allowed_tbl_name in ALLOWED_TABLES.iter() { - use crate::acpi::{find_sdt, get_sdt, get_sdt_signature}; - - // it appears that the SDTs are identity mapped, in which case we can just call get_sdt - // whenever we need to and use the slice as if it was physical. - - let table_name_str = - str::from_utf8(allowed_tbl_name).expect("ACPI table name wasn't correct UTF-8"); - - for sdt in find_sdt(table_name_str) { - let virt = - get_sdt(sdt as *const Sdt as usize, &mut active_table) as *const Sdt as usize; - let signature = get_sdt_signature(sdt); - let sdt_pointer = sdt as *const Sdt as usize; - let len = sdt.length as usize; - assert_eq!(virt, sdt_pointer); - tables.push(( - signature, - PhysSlice { - phys_ptr: sdt_pointer, - len, - virt, - }, - )); - } - } - tables - } - pub fn new() -> Self { - Self { - handles: RwLock::new(BTreeMap::new()), - tables: Self::get_tables(), - next_fd: AtomicUsize::new(0), +pub fn register_kstop() -> bool { + *KSTOP_FLAG.lock() = true; + let mut waiters_awoken = KSTOP_WAITCOND.notify(); + + if let Some(&acpi_scheme) = SCHEME_ID.r#try() { + let handles = HANDLES.read(); + + for (&fd, _) in handles.iter().filter(|(_, handle)| handle.kind == HandleKind::ShutdownPipe) { + event::trigger(acpi_scheme, fd, EVENT_READ); + waiters_awoken += 1; } + } else { + log::error!("Calling register_kstop before kernel ACPI scheme was initialized"); } - fn lookup_signature_index( - &self, - name: [u8; 4], - oem_id: [u8; 6], - oem_table_id: [u8; 8], - ) -> Option<usize> { - self.tables - .iter() - .position(|((sig_name, sig_oem_id, sig_oem_table_id), _)| { - sig_name.as_bytes() == &name - && sig_oem_id == &oem_id - && sig_oem_table_id == &oem_table_id - }) - } - fn lookup_signature( - &self, - name: [u8; 4], - oem_id: [u8; 6], - oem_table_id: [u8; 8], - ) -> Option<PhysSlice> { - Some(self.tables[self.lookup_signature_index(name, oem_id, oem_table_id)?].1) + + if waiters_awoken == 0 { + log::error!("No userspace ACPI handler was notified when trying to shutdown. This is bad."); + // Let the kernel shutdown without ACPI. + return false; } + + // TODO: Context switch directly to the waiting context, to avoid annoying timeouts. + true } -fn parse_table_filename(filename: &[u8]) -> Option<([u8; 4], [u8; 6], [u8; 8])> { - // the table identifier takes the form: - // 1. a four byte table name, like 'APIC' (MADT) or 'MCFG'. - // 2. a dash followed by 12 hexadecimal digits (6 bytes when decoded) composing the OEM ID. - // 3. another dash followed by 16 hex digits (8 bytes), composing the OEM Table ID. - // hence, the table is 4 + 1 + 12 + 1 + 16 = 34 bytes long. - if filename.len() != 34 { - return None; - } - let mut table_identifier = [0u8; 34]; - table_identifier.copy_from_slice(filename); +impl AcpiScheme { + pub fn new(id: SchemeId) -> Self { + // NOTE: This __must__ be called from the main kernel context, while initializing all + // schemes. If it is called by any other context, then all ACPI data will probably not even + // be mapped. - let table_name = &table_identifier[..4]; - if table_identifier[4] != b'-' { - return None; - } - let oem_id_hex = &table_identifier[5..17]; - if table_identifier[17] != b'-' { - return None; - } - let oem_table_id_hex = &table_identifier[18..34]; + let mut data_init = false; + let mut id_init = false; - let oem_id_hex_str = str::from_utf8(oem_id_hex).ok()?; - let oem_table_id_hex_str = str::from_utf8(oem_table_id_hex).ok()?; + DATA.call_once(|| { + data_init = true; - let mut oem_id = [0u8; 6]; + let rsdt_or_xsdt = RXSDT_ENUM + .r#try() + .expect("expected RXSDT_ENUM to be initialized before AcpiScheme"); - for index in 0..oem_id.len() { - oem_id[index] = u8::from_str_radix(&oem_id_hex_str[index * 2..(index + 1) * 2], 16).ok()?; - } + let table = match rsdt_or_xsdt { + RxsdtEnum::Rsdt(rsdt) => rsdt.as_slice(), + RxsdtEnum::Xsdt(xsdt) => xsdt.as_slice(), + }; - let mut oem_table_id = [0u8; 8]; + Box::from(table) + }); + SCHEME_ID.call_once(|| { + id_init = true; - for index in 0..oem_table_id.len() { - oem_table_id[index] = - u8::from_str_radix(&oem_table_id_hex_str[index * 2..(index + 1) * 2], 16).ok()?; - } + id + }); - Some((table_name.try_into().unwrap(), oem_id, oem_table_id)) -} -fn serialize_table_filename( - buffer: &mut [u8], - (table_name, oem_id, oem_table_id): ([u8; 4], [u8; 6], [u8; 8]), -) -> usize { - let mut wrapper = Take::write_to_buf(buffer); - write!( - wrapper, - "{}-", - str::from_utf8(&table_name).expect("Acpi table id wasn't valid UTF-8") - ) - .unwrap(); - for b in &oem_id { - write!(wrapper, "{:2x}", b).unwrap(); - } - write!(wrapper, "-").unwrap(); - for b in &oem_table_id { - write!(wrapper, "{:2x}", b).unwrap(); + if !data_init || !id_init { + log::error!("AcpiScheme::init called multiple times"); + } + + Self } - wrapper.bytes_currently_written() } impl Scheme for AcpiScheme { fn open(&self, path: &str, flags: usize, opener_uid: u32, _opener_gid: u32) -> Result<usize> { + let path = path.trim_start_matches('/'); + if opener_uid != 0 { return Err(Error::new(EACCES)); } - - let path_str = path.trim_start_matches('/'); - - // TODO: Use some kind of component iterator. - - let new_handle = if path_str.starts_with("tables") { - let subpath = (&path_str[6..]).trim_start_matches('/'); - - if subpath.is_empty() { - // List of ACPI tables - if (flags & O_DIRECTORY == 0 && flags & O_STAT == 0) - || (flags & O_ACCMODE == O_WRONLY || flags & O_ACCMODE == O_RDWR) - { + if flags & O_CREAT == O_CREAT { + return Err(Error::new(EROFS)); + } + if flags & O_EXCL == O_EXCL || flags & O_SYMLINK == O_SYMLINK { + return Err(Error::new(EINVAL)); + } + if flags & O_ACCMODE != O_RDONLY && flags & O_STAT != O_STAT { + return Err(Error::new(EROFS)); + } + let handle_kind = match path { + "" => { + if flags & O_DIRECTORY != O_DIRECTORY && flags & O_STAT != O_STAT { return Err(Error::new(EISDIR)); } - Handle::Tables(0) - } else { - if flags & O_DIRECTORY != 0 && flags & O_STAT == 0 { + + HandleKind::TopLevel + } + "rxsdt" => { + if flags & O_DIRECTORY == O_DIRECTORY && flags & O_STAT != O_STAT { return Err(Error::new(ENOTDIR)); } - if flags & O_ACCMODE == O_WRONLY || flags & O_ACCMODE == O_RDWR { - return Err(Error::new(EINVAL)); - } - let (name, oem_id, oem_table_id) = - parse_table_filename(subpath.as_bytes()).ok_or(Error::new(ENOENT))?; - - if self - .lookup_signature_index(name, oem_id, oem_table_id) - .is_none() - { - return Err(Error::new(ENOENT)); - } - Handle::Table { - name, - oem_id, - oem_table_id, - offset: 0, - } + HandleKind::Rxsdt } - } else if path.is_empty() { - // Top-level - if (flags & O_DIRECTORY == 0 && flags & O_STAT == 0) - || (flags & O_ACCMODE == O_WRONLY || flags & O_ACCMODE == O_RDWR) - { - return Err(Error::new(EISDIR)); + "kstop" => { + if flags & O_DIRECTORY == O_DIRECTORY && flags & O_STAT != O_STAT { + return Err(Error::new(ENOTDIR)); + } + HandleKind::ShutdownPipe } - Handle::TopLevel(0) - } else { - return Err(Error::new(ENOENT)); + _ => return Err(Error::new(ENOENT)), }; - let new_fd = self.next_fd.fetch_add(1, atomic::Ordering::SeqCst); - self.handles.write().insert(new_fd, Mutex::new(new_handle)); - Ok(new_fd) - } - fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> { - let handles_guard = self.handles.read(); - let handle = handles_guard.get(&id).ok_or(Error::new(EBADF))?.lock(); - - Ok(match &*handle { - &Handle::TopLevel(_) => { - let path = b"acpi:"; - let max = core::cmp::min(buf.len(), path.len()); - buf[..max].copy_from_slice(&path[..]); - max - } - &Handle::Tables(_) => { - let path = b"acpi:tables"; - let max = core::cmp::min(buf.len(), path.len()); - buf[..max].copy_from_slice(&path[..]); - max - } - &Handle::Table { - name, - oem_id, - oem_table_id, - .. - } => { - let base_path = b"acpi:tables/"; - let base_max = core::cmp::min(buf.len(), base_path.len()); - buf[..base_max].copy_from_slice(&base_path[..]); - serialize_table_filename(&mut buf[base_max..], (name, oem_id, oem_table_id)) - } - }) + + let fd = NEXT_FD.fetch_add(1, atomic::Ordering::Relaxed); + let mut handles_guard = HANDLES.write(); + + let _ = handles_guard.insert(fd, Handle { + offset: 0, + kind: handle_kind, + stat: flags & O_STAT == O_STAT, + }); + + Ok(fd) } fn fstat(&self, id: usize, stat: &mut Stat) -> Result<usize> { - let handles_guard = self.handles.read(); - let handle = handles_guard.get(&id).ok_or(Error::new(EBADF))?.lock(); + let handles = HANDLES.read(); + let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - match &*handle { - &Handle::TopLevel(_) => { - stat.st_mode = MODE_DIR; - stat.st_size = TOPLEVEL_DIR_CONTENTS.len() as u64; + match handle.kind { + HandleKind::Rxsdt => { + let data = DATA.r#try().ok_or(Error::new(EBADFD))?; + + stat.st_mode = MODE_FILE; + stat.st_size = data.len().try_into().unwrap_or(u64::max_value()); } - &Handle::Tables(_) => { + HandleKind::TopLevel => { stat.st_mode = MODE_DIR; - stat.st_size = (self.tables.len() * 35) as u64; // fixed size of 34 bytes for the file names, plus a newline + stat.st_size = TOPLEVEL_CONTENTS.len().try_into().unwrap_or(u64::max_value()); } - &Handle::Table { - name, - oem_id, - oem_table_id, - .. - } => { - let len = self - .lookup_signature(name, oem_id, oem_table_id) - .ok_or(Error::new(EBADFD))? - .len; - - stat.st_mode = MODE_FILE; - stat.st_size = len as u64; + HandleKind::ShutdownPipe => { + stat.st_mode = MODE_CHR; + stat.st_size = 1; } } + Ok(0) } fn seek(&self, id: usize, pos: isize, whence: usize) -> Result<isize> { - let handles_guard = self.handles.read(); - let mut handle = handles_guard.get(&id).ok_or(Error::new(EBADF))?.lock(); - - let (cur_offset, length) = match &*handle { - &Handle::TopLevel(offset) => (offset, TOPLEVEL_DIR_CONTENTS.len()), - &Handle::Tables(offset) => (offset, (self.tables.len() * 35)), - &Handle::Table { - name, - oem_id, - oem_table_id, - offset, - } => ( - offset, - self.lookup_signature(name, oem_id, oem_table_id) - .ok_or(Error::new(EBADFD))? - .len, - ), - }; - let new_offset = calc_seek_offset_usize(cur_offset, pos, whence, length)?; - match &mut *handle { - &mut Handle::Table { ref mut offset, .. } - | &mut Handle::Tables(ref mut offset) - | &mut Handle::TopLevel(ref mut offset) => *offset = new_offset as usize, + let mut handles = HANDLES.write(); + let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + + if handle.stat { + return Err(Error::new(EBADF)); } - Ok(new_offset) - } - fn read(&self, id: usize, mut buf: &mut [u8]) -> Result<usize> { - let handles_guard = self.handles.read(); - let mut handle = handles_guard.get(&id).ok_or(Error::new(EBADF))?.lock(); - - match &mut *handle { - &mut Handle::TopLevel(ref mut offset) => { - let max_bytes_to_read = core::cmp::min(buf.len(), TOPLEVEL_DIR_CONTENTS.len()); - let bytes_to_read = core::cmp::max(max_bytes_to_read, *offset) - *offset; - buf[..bytes_to_read] - .copy_from_slice(&TOPLEVEL_DIR_CONTENTS[*offset..*offset + bytes_to_read]); - *offset += bytes_to_read; - Ok(bytes_to_read) + + let file_len = match handle.kind { + HandleKind::Rxsdt => DATA.r#try().ok_or(Error::new(EBADFD))?.len(), + HandleKind::ShutdownPipe => 1, + HandleKind::TopLevel => TOPLEVEL_CONTENTS.len(), + }; + + let new_offset = match whence { + SEEK_SET => pos as usize, + SEEK_CUR => if pos < 0 { + handle.offset.checked_sub((-pos) as usize).ok_or(Error::new(EINVAL))? + } else { + handle.offset.saturating_add(pos as usize) } - &mut Handle::Tables(ref mut offset) => { - if *offset >= self.tables.len() * 35 { - return Ok(0); - } - // one really good thing with fixed size filenames, is that no index has to be - // stored anywhere! - let base_table_index = *offset / 35; - let mut bytes_to_skip = *offset % 35; - let mut bytes_read = 0; - - for index in base_table_index..self.tables.len() { - let &(ref name_string, oem_id, oem_table_id) = &self.tables[index].0; - let signature = ( - name_string.as_bytes().try_into().or(Err(Error::new(EIO)))?, - oem_id, - oem_table_id, - ); - - let mut src_buf = [0u8; 35]; - serialize_table_filename(&mut src_buf[..34], signature); - src_buf[34] = b'\n'; - - let max_bytes_to_read = core::cmp::min(buf.len(), src_buf.len()); - let bytes_to_read = - core::cmp::max(max_bytes_to_read, bytes_to_skip) - bytes_to_skip; - buf[..bytes_to_read].copy_from_slice(&src_buf[..bytes_to_read]); - bytes_read += bytes_to_read; - bytes_to_skip = 0; - buf = &mut buf[bytes_to_read..]; - } - *offset += bytes_read; - Ok(bytes_read) + SEEK_END => if pos < 0 { + file_len.checked_sub((-pos) as usize).ok_or(Error::new(EINVAL))? + } else { + file_len } - &mut Handle::Table { - name, - oem_id, - oem_table_id, - ref mut offset, - } => { - let index = self - .lookup_signature_index(name, oem_id, oem_table_id) - .ok_or(Error::new(EBADFD))?; - let ( - _, - PhysSlice { - phys_ptr, - len, - virt: old_virt, + _ => return Err(Error::new(EINVAL)), + }; + + handle.offset = new_offset; + + Ok(new_offset as isize) + } + fn read(&self, id: usize, dst_buf: &mut [u8]) -> Result<usize> { + let mut handles = HANDLES.write(); + let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + + if handle.stat { + return Err(Error::new(EBADF)); + } + + let data = match handle.kind { + HandleKind::ShutdownPipe => { + let dst_byte = match dst_buf.first_mut() { + None => return Ok(0), + Some(dst) => if handle.offset >= 1 { + return Ok(0) + } else { + dst }, - ) = self.tables[index]; - assert_eq!(phys_ptr, old_virt); - let new_virt = - crate::acpi::get_sdt(phys_ptr, unsafe { &mut ActivePageTable::new(TableKind::Kernel) }) - as *const Sdt as usize; - - let table_contents = - unsafe { core::slice::from_raw_parts(new_virt as *const u8, len) }; - - let max_bytes_to_read = core::cmp::min(buf.len(), table_contents.len()); - let bytes_to_read = core::cmp::max(max_bytes_to_read, *offset) - *offset; - buf[..bytes_to_read] - .copy_from_slice(&table_contents[*offset..*offset + bytes_to_read]); - *offset += bytes_to_read; - Ok(bytes_to_read) + }; + + loop { + let flag_guard = KSTOP_FLAG.lock(); + + if *flag_guard { + break; + } else if ! KSTOP_WAITCOND.wait(flag_guard, "waiting for kstop") { + return Err(Error::new(EINTR)); + } + } + + *dst_byte = 0x42; + handle.offset = 1; + return Ok(1); } + HandleKind::Rxsdt => DATA.r#try().ok_or(Error::new(EBADFD))?, + HandleKind::TopLevel => TOPLEVEL_CONTENTS, + }; + + let src_offset = core::cmp::min(handle.offset, data.len()); + let src_buf = data + .get(src_offset..) + .expect("expected data to be at least data.len() bytes long"); + + let bytes_to_copy = core::cmp::min(dst_buf.len(), src_buf.len()); + + dst_buf[..bytes_to_copy].copy_from_slice(&src_buf[..bytes_to_copy]); + handle.offset += bytes_to_copy; + + Ok(bytes_to_copy) + } + // TODO + fn fevent(&self, id: usize, _flags: EventFlags) -> Result<EventFlags> { + let handles = HANDLES.read(); + let handle = handles.get(&id).ok_or(Error::new(EBADF))?; + + if handle.stat { + return Err(Error::new(EBADF)); } + + Ok(EventFlags::empty()) } fn write(&self, _id: usize, _buf: &[u8]) -> Result<usize> { Err(Error::new(EBADF)) } + fn close(&self, id: usize) -> Result<usize> { + if HANDLES.write().remove(&id).is_none() { + return Err(Error::new(EBADF)); + } + Ok(0) + } } diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs index ebb49aa1c348f6a3399a12e1160066b084c93cd8..74405b0f431dfce230407dc2ae3d8fc291640589 100644 --- a/src/scheme/mod.rs +++ b/src/scheme/mod.rs @@ -162,7 +162,7 @@ impl SchemeList { // These schemes should only be available on the root #[cfg(all(feature = "acpi", target_arch = "x86_64"))] { - self.insert(ns, "acpi", |_| Arc::new(AcpiScheme::new())).unwrap(); + self.insert(ns, "kernel/acpi", |scheme_id| Arc::new(AcpiScheme::new(scheme_id))).unwrap(); } self.insert(ns, "debug", |scheme_id| Arc::new(DebugScheme::new(scheme_id))).unwrap(); self.insert(ns, "initfs", |_| Arc::new(InitFsScheme::new())).unwrap(); diff --git a/src/sync/wait_condition.rs b/src/sync/wait_condition.rs index 2865bd35a12c4e3b1378ab09dae64eeea5d00361..8f6566ec7bc1362c09be6c05a4328e9388c3e970 100644 --- a/src/sync/wait_condition.rs +++ b/src/sync/wait_condition.rs @@ -10,7 +10,7 @@ pub struct WaitCondition { } impl WaitCondition { - pub fn new() -> WaitCondition { + pub const fn new() -> WaitCondition { WaitCondition { contexts: Mutex::new(Vec::new()) } diff --git a/src/syscall/process.rs b/src/syscall/process.rs index db2d2bd65be0b44091e8443ded13d7cb1b6951ad..2667ae78b47166810b5a07121b40d0fbd9439b26 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -1148,6 +1148,22 @@ pub fn exit(status: usize) -> ! { context.id }; + // TODO: Find a better way to implement this, perhaps when the init process calls exit. + if pid == ContextId::from(1) { + println!("Main kernel thread exited with status {:X}", status); + + extern { + fn kreset() -> !; + fn kstop() -> !; + } + + if status == SIGTERM { + unsafe { kreset(); } + } else { + unsafe { kstop(); } + } + } + // Files must be closed while context is valid so that messages can be passed for (_fd, file_opt) in close_files.drain(..).enumerate() { if let Some(file) = file_opt { @@ -1214,21 +1230,6 @@ pub fn exit(status: usize) -> ! { // Alert any tracers waiting of this process ptrace::close_tracee(pid); - - if pid == ContextId::from(1) { - println!("Main kernel thread exited with status {:X}", status); - - extern { - fn kreset() -> !; - fn kstop() -> !; - } - - if status == SIGTERM { - unsafe { kreset(); } - } else { - unsafe { kstop(); } - } - } } let _ = unsafe { context::switch() };