Files
RedBear-OS/src/acpi/aml/namedobj.rs
T

1011 lines
38 KiB
Rust

use alloc::boxed::Box;
use collections::string::String;
use collections::vec::Vec;
use core::str::FromStr;
use collections::btree_map::BTreeMap;
use super::{AmlInternalError, AmlExecutable, AmlValue, get_namespace_string};
use super::namespace::FieldSelector;
use super::namestring::{parse_name_string, parse_name_seg};
use super::termlist::{parse_term_arg, parse_term_list, parse_object_list, TermArg, TermObj, Object};
use super::pkglength::parse_pkg_length;
use super::type2opcode::{parse_def_buffer, DefBuffer};
#[derive(Debug, Clone)]
pub enum NamedObj {
DefBankField {
region_name: String,
bank_name: String,
bank_value: TermArg,
flags: FieldFlags,
field_list: Vec<FieldElement>
},
DefCreateBitField {
name: String,
source_buf: TermArg,
bit_index: TermArg
},
DefCreateByteField {
name: String,
source_buf: TermArg,
byte_index: TermArg
},
DefCreateWordField {
name: String,
source_buf: TermArg,
byte_index: TermArg
},
DefCreateDWordField {
name: String,
source_buf: TermArg,
byte_index: TermArg
},
DefCreateQWordField {
name: String,
source_buf: TermArg,
byte_index: TermArg
},
DefCreateField {
name: String,
source_buf: TermArg,
bit_index: TermArg,
num_bits: TermArg
},
DefDataRegion {
name: String,
signature: TermArg,
oem_id: TermArg,
oem_table_id: TermArg
},
DefDevice {
name: String,
obj_list: Vec<Object>
},
DefEvent {
name: String
},
DefOpRegion {
name: String,
region: RegionSpace,
offset: TermArg,
len: TermArg
},
DefField {
name: String,
flags: FieldFlags,
field_list: Vec<FieldElement>
},
DefIndexField {
idx_name: String,
data_name: String,
flags: FieldFlags,
field_list: Vec<FieldElement>
},
DefMethod {
name: String,
method: Method
},
DefMutex {
name: String,
sync_level: u8
},
DefPowerRes {
name: String,
system_level: u8,
resource_order: u16,
obj_list: Vec<Object>
},
DefProcessor {
name: String,
proc_id: u8,
p_blk_addr: u32,
p_blk_len: u8,
obj_list: Vec<Object>
},
DefThermalZone {
name: String,
obj_list: Vec<Object>
},
DeferredLoad(Vec<u8>)
}
#[derive(Debug, Clone)]
pub struct Method {
arg_count: u8,
serialized: bool,
sync_level: u8,
term_list: Vec<TermObj>
}
impl AmlExecutable for NamedObj {
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
match *self {
NamedObj::DefBankField { ref region_name, ref bank_name, ref bank_value, ref flags, ref field_list } => {
let mut offset: usize = 0;
let bank_val = if let Some(b) = bank_value.execute(namespace, scope.clone()) {
Box::new(b)
} else {
return None;
};
for f in field_list {
match *f {
FieldElement::ReservedField { length } => offset += length,
FieldElement::NamedField { name: ref field_name, length } => {
let local_scope_string = get_namespace_string(scope.clone(),
field_name.clone());
namespace.insert(local_scope_string, AmlValue::FieldUnit {
selector: FieldSelector::Bank {
region: region_name.clone(),
bank_selector: bank_val.clone()
},
flags: flags.clone(),
offset: offset.clone(),
length: length.clone()
});
offset += length;
},
_ => ()
}
}
},
NamedObj::DefIndexField { ref idx_name, ref data_name, ref flags, ref field_list } => {
let mut offset: usize = 0;
for f in field_list {
match *f {
FieldElement::ReservedField { length } => offset += length,
FieldElement::NamedField { name: ref field_name, length } => {
let local_scope_string = get_namespace_string(scope.clone(),
field_name.clone());
namespace.insert(local_scope_string, AmlValue::FieldUnit {
selector: FieldSelector::Index {
index_selector: idx_name.clone(),
data_selector: data_name.clone()
},
flags: flags.clone(),
offset: offset.clone(),
length: length.clone()
});
offset += length;
},
_ => ()
}
}
},
NamedObj::DefCreateBitField { ref name, ref source_buf, ref bit_index } => {
let local_scope_string = get_namespace_string(scope.clone(), name.clone());
let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) {
Some(r) => Box::new(r),
_ => return None
};
let resolved_index = match bit_index.execute(namespace, scope.clone()) {
Some(r) => Box::new(r),
_ => return None
};
namespace.insert(local_scope_string, AmlValue::BufferField {
source_buf: resolved_source_buf,
index: resolved_index,
length: Box::new(AmlValue::IntegerConstant(1))
});
},
NamedObj::DefCreateByteField { ref name, ref source_buf, ref byte_index } => {
let local_scope_string = get_namespace_string(scope.clone(), name.clone());
let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) {
Some(r) => Box::new(r),
_ => return None
};
let resolved_index = match byte_index.execute(namespace, scope.clone()) {
Some(r) => Box::new(r),
_ => return None
};
namespace.insert(local_scope_string, AmlValue::BufferField {
source_buf: resolved_source_buf,
index: resolved_index,
length: Box::new(AmlValue::IntegerConstant(8))
});
},
NamedObj::DefCreateWordField { ref name, ref source_buf, ref byte_index } => {
let local_scope_string = get_namespace_string(scope.clone(), name.clone());
let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) {
Some(r) => Box::new(r),
_ => return None
};
let resolved_index = match byte_index.execute(namespace, scope.clone()) {
Some(r) => Box::new(r),
_ => return None
};
namespace.insert(local_scope_string, AmlValue::BufferField {
source_buf: resolved_source_buf,
index: resolved_index,
length: Box::new(AmlValue::IntegerConstant(16))
});
},
NamedObj::DefCreateDWordField { ref name, ref source_buf, ref byte_index } => {
let local_scope_string = get_namespace_string(scope.clone(), name.clone());
let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) {
Some(r) => Box::new(r),
_ => return None
};
let resolved_index = match byte_index.execute(namespace, scope.clone()) {
Some(r) => Box::new(r),
_ => return None
};
namespace.insert(local_scope_string, AmlValue::BufferField {
source_buf: resolved_source_buf,
index: resolved_index,
length: Box::new(AmlValue::IntegerConstant(32))
});
},
NamedObj::DefCreateQWordField { ref name, ref source_buf, ref byte_index } => {
let local_scope_string = get_namespace_string(scope.clone(), name.clone());
let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) {
Some(r) => Box::new(r),
_ => return None
};
let resolved_index = match byte_index.execute(namespace, scope.clone()) {
Some(r) => Box::new(r),
_ => return None
};
namespace.insert(local_scope_string, AmlValue::BufferField {
source_buf: resolved_source_buf,
index: resolved_index,
length: Box::new(AmlValue::IntegerConstant(64))
});
},
NamedObj::DefCreateField { ref name, ref source_buf, ref bit_index, ref num_bits } => {
let local_scope_string = get_namespace_string(scope.clone(), name.clone());
let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) {
Some(r) => Box::new(r),
_ => return None
};
let resolved_index = match bit_index.execute(namespace, scope.clone()) {
Some(r) => Box::new(r),
_ => return None
};
let resolved_length = match num_bits.execute(namespace, scope.clone()) {
Some(r) => Box::new(r),
_ => return None
};
namespace.insert(local_scope_string, AmlValue::BufferField {
source_buf: resolved_source_buf,
index: resolved_index,
length: resolved_length
});
},
NamedObj::DefDataRegion { ref name, ref signature, ref oem_id, ref oem_table_id } => {
let local_scope_string = get_namespace_string(scope.clone(), name.clone());
namespace.insert(local_scope_string, AmlValue::OperationRegion {
region: RegionSpace::SystemMemory,
offset: Box::new(AmlValue::IntegerConstant(0)),
len: Box::new(AmlValue::IntegerConstant(0))
});
},
NamedObj::DefOpRegion { ref name, ref region, ref offset, ref len } => {
let local_scope_string = get_namespace_string(scope.clone(), name.clone());
let resolved_offset = match offset.execute(namespace, scope.clone()) {
Some(r) => r,
_ => return None
};
let resolved_len = match len.execute(namespace, scope.clone()) {
Some(r) => r,
_ => return None
};
namespace.insert(local_scope_string, AmlValue::OperationRegion {
region: *region,
offset: Box::new(resolved_offset),
len: Box::new(resolved_len)
});
},
NamedObj::DefField { ref name, ref flags, ref field_list } => {
let mut offset: usize = 0;
for f in field_list {
match *f {
FieldElement::ReservedField { length } => offset += length,
FieldElement::NamedField { name: ref field_name, length } => {
let local_scope_string = get_namespace_string(scope.clone(),
field_name.clone());
namespace.insert(local_scope_string, AmlValue::FieldUnit {
selector: FieldSelector::Region(name.clone()),
flags: flags.clone(),
offset: offset.clone(),
length: length.clone()
});
offset += length;
},
_ => ()
}
}
},
NamedObj::DefMethod { ref name, ref method } => {
let local_scope_string = get_namespace_string(scope.clone(), name.clone());
namespace.insert(local_scope_string, AmlValue::Method(method.clone()));
},
NamedObj::DefDevice { ref name, ref obj_list } => {
let local_scope_string = get_namespace_string(scope, name.clone());
let mut local_namespace = BTreeMap::new();
obj_list.execute(&mut local_namespace, String::new());
namespace.insert(local_scope_string, AmlValue::Device(local_namespace));
},
NamedObj::DefThermalZone { ref name, ref obj_list } => {
let local_scope_string = get_namespace_string(scope, name.clone());
let mut local_namespace = BTreeMap::new();
obj_list.execute(&mut local_namespace, String::new());
namespace.insert(local_scope_string, AmlValue::ThermalZone(local_namespace));
},
NamedObj::DefProcessor { ref name, proc_id, p_blk_addr, p_blk_len, ref obj_list } => {
let local_scope_string = get_namespace_string(scope, name.clone());
let mut local_namespace = BTreeMap::new();
obj_list.execute(&mut local_namespace, String::new());
namespace.insert(local_scope_string, AmlValue::Processor {
proc_id: proc_id,
p_blk: if p_blk_len > 0 { Some(p_blk_addr) } else { None },
obj_list: local_namespace
});
},
NamedObj::DefPowerRes { ref name, system_level, resource_order, ref obj_list } => {
let local_scope_string = get_namespace_string(scope, name.clone());
let mut local_namespace = BTreeMap::new();
obj_list.execute(&mut local_namespace, String::new());
namespace.insert(local_scope_string, AmlValue::PowerResource {
system_level,
resource_order,
obj_list: local_namespace
});
},
NamedObj::DefMutex { ref name, sync_level } => {
let local_scope_string = get_namespace_string(scope, name.clone());
namespace.insert(local_scope_string, AmlValue::Mutex(sync_level));
},
NamedObj::DefEvent { ref name } => {
let local_scope_string = get_namespace_string(scope, name.clone());
namespace.insert(local_scope_string, AmlValue::Event);
},
_ => ()
}
None
}
}
#[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
}
#[derive(Debug, Clone)]
pub enum UpdateRule {
Preserve,
WriteAsOnes,
WriteAsZeros
}
#[derive(Debug, Clone)]
pub enum FieldElement {
NamedField {
name: String,
length: usize
},
ReservedField {
length: usize
},
AccessField {
access_type: AccessType,
access_attrib: AccessAttrib
},
ConnectFieldNameString(String),
ConnectFieldBufferData(DefBuffer),
}
#[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]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_selector! {
data,
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_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(AmlInternalError::AmlInvalidOpCode)
}
fn parse_def_bank_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode_extended!(data, 0x87);
let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?;
let (region_name, region_name_len) = match parse_name_string(
&data[2 + pkg_length_len .. 2 + pkg_length]) {
Ok(res) => res,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)),
Err(e) => return Err(e)
};
let (bank_name, bank_name_len) = match parse_name_string(
&data[2 + pkg_length_len + region_name_len .. 2 + pkg_length]) {
Ok(res) => res,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)),
Err(e) => return Err(e)
};
let (bank_value, bank_value_len) = match parse_term_arg(
&data[2 + pkg_length_len + region_name_len .. 2 + pkg_length]) {
Ok(res) => res,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)),
Err(e) => return Err(e)
};
let flags_raw = data[2 + pkg_length_len + region_name_len + bank_name_len + bank_value_len];
let 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,
_ => return Err(AmlInternalError::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(AmlInternalError::AmlParseError("BankField - invalid update rule"))
}
};
let field_list = match parse_field_list(
&data[3 + pkg_length_len + region_name_len + bank_name_len + bank_value_len ..
2 + pkg_length]) {
Ok(p) => p,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)),
Err(e) => return Err(e)
};
Ok((NamedObj::DefBankField {region_name, bank_name, bank_value, flags, field_list},
2 + pkg_length))
}
fn parse_def_create_bit_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode!(data, 0x8D);
let (source_buf, source_buf_len) = parse_term_arg(&data[1..])?;
let (bit_index, bit_index_len) = parse_term_arg(&data[1 + source_buf_len..])?;
let (name, name_len) = parse_name_string(&data[1 + source_buf_len + bit_index_len..])?;
Ok((NamedObj::DefCreateBitField {name, source_buf, bit_index},
1 + source_buf_len + bit_index_len + name_len))
}
fn parse_def_create_byte_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode!(data, 0x8C);
let (source_buf, source_buf_len) = parse_term_arg(&data[1..])?;
let (byte_index, byte_index_len) = parse_term_arg(&data[1 + source_buf_len..])?;
let (name, name_len) = parse_name_string(&data[1 + source_buf_len + byte_index_len..])?;
Ok((NamedObj::DefCreateByteField {name, source_buf, byte_index},
1 + source_buf_len + byte_index_len + name_len))
}
fn parse_def_create_word_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode!(data, 0x8B);
let (source_buf, source_buf_len) = parse_term_arg(&data[1..])?;
let (byte_index, byte_index_len) = parse_term_arg(&data[1 + source_buf_len..])?;
let (name, name_len) = parse_name_string(&data[1 + source_buf_len + byte_index_len..])?;
Ok((NamedObj::DefCreateWordField {name, source_buf, byte_index},
1 + source_buf_len + byte_index_len + name_len))
}
fn parse_def_create_dword_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode!(data, 0x8A);
let (source_buf, source_buf_len) = parse_term_arg(&data[1..])?;
let (byte_index, byte_index_len) = parse_term_arg(&data[1 + source_buf_len..])?;
let (name, name_len) = parse_name_string(&data[1 + source_buf_len + byte_index_len..])?;
Ok((NamedObj::DefCreateDWordField {name, source_buf, byte_index},
1 + source_buf_len + byte_index_len + name_len))
}
fn parse_def_create_qword_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode!(data, 0x8F);
let (source_buf, source_buf_len) = parse_term_arg(&data[1..])?;
let (byte_index, byte_index_len) = parse_term_arg(&data[1 + source_buf_len..])?;
let (name, name_len) = parse_name_string(&data[1 + source_buf_len + byte_index_len..])?;
Ok((NamedObj::DefCreateQWordField {name, source_buf, byte_index},
1 + source_buf_len + byte_index_len + name_len))
}
fn parse_def_create_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode_extended!(data, 0x13);
let (source_buf, source_buf_len) = parse_term_arg(&data[2..])?;
let (bit_index, bit_index_len) = parse_term_arg(&data[2 + source_buf_len..])?;
let (num_bits, num_bits_len) = parse_term_arg(&data[2 + source_buf_len + bit_index_len..])?;
let (name, name_len) = parse_name_string(
&data[2 + source_buf_len + bit_index_len + num_bits_len..])?;
Ok((NamedObj::DefCreateField {name, source_buf, bit_index, num_bits},
2 + source_buf_len + bit_index_len + num_bits_len + name_len))
}
fn parse_def_data_region(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode_extended!(data, 0x88);
let (name, name_len) = parse_name_string(&data[2..])?;
let (signature, signature_len) = parse_term_arg(&data[2 + name_len..])?;
let (oem_id, oem_id_len) = parse_term_arg(&data[2 + name_len + signature_len..])?;
let (oem_table_id, oem_table_id_len) = parse_term_arg(
&data[2 + name_len + signature_len + oem_id_len..])?;
Ok((NamedObj::DefDataRegion {name, signature, oem_id, oem_table_id},
2 + name_len + signature_len + oem_id_len + oem_table_id_len))
}
fn parse_def_event(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode_extended!(data, 0x02);
let (name, name_len) = parse_name_string(&data[2..])?;
Ok((NamedObj::DefEvent {name}, 2 + name_len))
}
fn parse_def_device(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode_extended!(data, 0x82);
let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?;
let (name, name_len) = match parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length]) {
Ok(p) => p,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)),
Err(e) => return Err(e)
};
let obj_list = match parse_object_list(&data[2 + pkg_length_len + name_len .. 2 + pkg_length]) {
Ok(p) => p,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)),
Err(e) => return Err(e)
};
Ok((NamedObj::DefDevice {name, obj_list}, 2 + pkg_length_len))
}
fn parse_def_op_region(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode_extended!(data, 0x80);
let (name, name_len) = parse_name_string(&data[2..])?;
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(AmlInternalError::AmlParseError("OpRegion - invalid region"))
};
let (offset, offset_len) = parse_term_arg(&data[3 + name_len..])?;
let (len, len_len) = parse_term_arg(&data[3 + name_len + offset_len..])?;
Ok((NamedObj::DefOpRegion {name, region, offset, len}, 3 + name_len + offset_len + len_len))
}
fn parse_def_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode_extended!(data, 0x81);
let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?;
let (name, name_len) = match parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length]) {
Ok(p) => p,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)),
Err(e) => return Err(e)
};
let flags_raw = data[2 + pkg_length_len + name_len];
let 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,
_ => return Err(AmlInternalError::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(AmlInternalError::AmlParseError("Field - Invalid update rule"))
}
};
let field_list = match parse_field_list(&data[3 + pkg_length_len + name_len .. 2 + pkg_length]) {
Ok(p) => p,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)),
Err(e) => return Err(e)
};
Ok((NamedObj::DefField {name, flags, field_list}, 2 + pkg_length))
}
fn parse_def_index_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode_extended!(data, 0x86);
let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?;
let (idx_name, idx_name_len) = match parse_name_string(
&data[2 + pkg_length_len .. 2 + pkg_length]) {
Ok(p) => p,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)),
Err(e) => return Err(e)
};
let (data_name, data_name_len) = match parse_name_string(
&data[2 + pkg_length_len + idx_name_len .. 2 + pkg_length]) {
Ok(p) => p,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)),
Err(e) => return Err(e)
};
let flags_raw = data[2 + pkg_length_len + idx_name_len + data_name_len];
let 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,
_ => return Err(AmlInternalError::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(AmlInternalError::AmlParseError("IndexField - Invalid update rule"))
}
};
let field_list = match parse_field_list(
&data[3 + pkg_length_len + idx_name_len + data_name_len .. 2 + pkg_length]) {
Ok(p) => p,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)),
Err(e) => return Err(e)
};
Ok((NamedObj::DefIndexField {idx_name, data_name, flags, field_list}, 2 + pkg_length))
}
fn parse_field_list(data: &[u8]) -> Result<Vec<FieldElement>, AmlInternalError> {
let mut terms: Vec<FieldElement> = vec!();
let mut current_offset: usize = 0;
while current_offset < data.len() {
let (res, len) = match parse_field_element(&data[current_offset..]) {
Ok(r) => r,
Err(AmlInternalError::AmlInvalidOpCode) =>
return Err(AmlInternalError::AmlParseError("FieldList - no valid field")),
Err(e) => return Err(e)
};
terms.push(res);
current_offset += len;
}
Ok(terms)
}
fn parse_field_element(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalError> {
parser_selector! {
data,
parse_named_field,
parse_reserved_field,
parse_access_field,
parse_connect_field
};
Err(AmlInternalError::AmlInvalidOpCode)
}
fn parse_named_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalError> {
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(AmlInternalError::AmlParseError("NamedField - invalid name"))
};
let (length, length_len) = parse_pkg_length(&data[4..])?;
Ok((FieldElement::NamedField {name, length}, 4 + length_len))
}
fn parse_reserved_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalError> {
parser_opcode!(data, 0x00);
let (length, length_len) = parse_pkg_length(&data[1..])?;
Ok((FieldElement::ReservedField {length}, 1 + length_len))
}
fn parse_access_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalError> {
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,
_ => return Err(AmlInternalError::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(AmlInternalError::AmlParseError("AccessField - Invalid access attrib"))
},
1 => AccessAttrib::AttribBytes(data[2]),
2 => AccessAttrib::AttribRawBytes(data[2]),
3 => AccessAttrib::AttribRawProcessBytes(data[2]),
_ => return Err(AmlInternalError::AmlParseError("AccessField - Invalid access attrib"))
// This should never happen but the compiler bitches if I don't cover this
};
return Ok((FieldElement::AccessField {access_type, access_attrib}, if data[0] == 0x01 {
3 as usize
} else {
4 as usize
}))
}
fn parse_connect_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalError> {
parser_opcode!(data, 0x02);
match parse_def_buffer(&data[1..]) {
Ok((buf, buf_len)) => return Ok((FieldElement::ConnectFieldBufferData(buf), buf_len + 1)),
Err(AmlInternalError::AmlInvalidOpCode) => (),
Err(e) => return Err(e)
}
match parse_name_string(&data[1..]) {
Ok((name, name_len)) => Ok((FieldElement::ConnectFieldNameString(name), name_len + 1)),
Err(AmlInternalError::AmlInvalidOpCode) => Err(AmlInternalError::AmlParseError("ConnectField - unable to match field")),
Err(e) => Err(e)
}
}
fn parse_def_method(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode!(data, 0x14);
let (pkg_len, pkg_len_len) = parse_pkg_length(&data[1..])?;
let (name, name_len) = match parse_name_string(&data[1 + pkg_len_len..]) {
Ok(p) => p,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 1 + pkg_len].to_vec()), 1 + pkg_len)),
Err(e) => return Err(e)
};
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 = match parse_term_list(&data[2 + pkg_len_len + name_len .. 1 + pkg_len]) {
Ok(p) => p,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 1 + pkg_len].to_vec()), 1 + pkg_len)),
Err(e) => return Err(e)
};
Ok((NamedObj::DefMethod {
name: name,
method: Method {
arg_count,
serialized,
sync_level,
term_list
}
}, pkg_len + 1))
}
fn parse_def_mutex(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode_extended!(data, 0x01);
let (name, name_len) = match parse_name_string(&data[2 ..]) {
Ok(p) => p,
Err(e) => return Err(e),
};
let flags = data[2 + name_len];
let sync_level = flags & 0x0F;
Ok((NamedObj::DefMutex {name, sync_level}, name_len + 3))
}
fn parse_def_power_res(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode_extended!(data, 0x84);
let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?;
let (name, name_len) = match parse_name_string(&data[2 + pkg_len_len..]) {
Ok(p) => p,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)),
Err(e) => return Err(e)
};
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 obj_list = match parse_object_list(&data[5 + pkg_len_len + name_len .. 2 + pkg_len]) {
Ok(p) => p,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)),
Err(e) => return Err(e)
};
Ok((NamedObj::DefPowerRes {name, system_level, resource_order, obj_list}, 2 + pkg_len))
}
fn parse_def_processor(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode_extended!(data, 0x83);
let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?;
let (name, name_len) = match parse_name_string(&data[2 + pkg_len_len..]) {
Ok(p) => p,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)),
Err(e) => return Err(e)
};
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 obj_list = match parse_object_list(&data[8 + pkg_len_len + name_len .. 2 + pkg_len]) {
Ok(p) => p,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)),
Err(e) => return Err(e)
};
Ok((NamedObj::DefProcessor {name, proc_id, p_blk_addr, p_blk_len, obj_list}, 2 + pkg_len))
}
fn parse_def_thermal_zone(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> {
parser_opcode_extended!(data, 0x85);
let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?;
let (name, name_len) = match parse_name_string(&data[2 + pkg_len_len..]) {
Ok(p) => p,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)),
Err(e) => return Err(e)
};
let obj_list = match parse_object_list(&data[2 + pkg_len_len + name_len .. 2 + pkg_len]) {
Ok(p) => p,
Err(AmlInternalError::AmlDeferredLoad) =>
return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)),
Err(e) => return Err(e)
};
Ok((NamedObj::DefThermalZone {name, obj_list}, 2 + pkg_len))
}