123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- use crate::{misc::ArgNum, AmlContext, AmlError, AmlHandle, AmlName};
- use alloc::{string::String, vec::Vec};
- use bit_field::BitField;
- use core::convert::TryInto;
- #[derive(Clone, Copy, PartialEq, Eq, Debug)]
- pub enum RegionSpace {
- SystemMemory,
- SystemIo,
- PciConfig,
- EmbeddedControl,
- SMBus,
- SystemCmos,
- PciBarTarget,
- IPMI,
- GeneralPurposeIo,
- GenericSerialBus,
- OemDefined(u8),
- }
- #[derive(Clone, Copy, PartialEq, Eq, Debug)]
- pub enum FieldAccessType {
- Any,
- Byte,
- Word,
- DWord,
- QWord,
- Buffer,
- Reserved,
- }
- #[derive(Clone, Copy, PartialEq, Eq, Debug)]
- pub enum FieldUpdateRule {
- Preserve,
- WriteAsOnes,
- WriteAsZeros,
- }
- #[derive(Clone, Copy, PartialEq, Eq, Debug)]
- pub struct FieldFlags(u8);
- impl FieldFlags {
- pub fn new(value: u8) -> FieldFlags {
- FieldFlags(value)
- }
- pub fn access_type(&self) -> Result<FieldAccessType, AmlError> {
- match self.0.get_bits(0..4) {
- 0 => Ok(FieldAccessType::Any),
- 1 => Ok(FieldAccessType::Byte),
- 2 => Ok(FieldAccessType::Word),
- 3 => Ok(FieldAccessType::DWord),
- 4 => Ok(FieldAccessType::QWord),
- 5 => Ok(FieldAccessType::Buffer),
- _ => Err(AmlError::InvalidFieldFlags),
- }
- }
- pub fn lock_rule(&self) -> bool {
- self.0.get_bit(4)
- }
- pub fn field_update_rule(&self) -> Result<FieldUpdateRule, AmlError> {
- match self.0.get_bits(5..7) {
- 0 => Ok(FieldUpdateRule::Preserve),
- 1 => Ok(FieldUpdateRule::WriteAsOnes),
- 2 => Ok(FieldUpdateRule::WriteAsZeros),
- _ => Err(AmlError::InvalidFieldFlags),
- }
- }
- }
- #[derive(Clone, Copy, PartialEq, Eq, Debug)]
- pub struct MethodFlags(u8);
- impl MethodFlags {
- pub fn new(value: u8) -> MethodFlags {
- MethodFlags(value)
- }
- pub fn arg_count(&self) -> u8 {
- self.0.get_bits(0..3)
- }
- pub fn serialize(&self) -> bool {
- self.0.get_bit(3)
- }
- pub fn sync_level(&self) -> u8 {
- self.0.get_bits(4..8)
- }
- }
- #[derive(Clone, Copy, PartialEq, Eq, Debug)]
- pub struct StatusObject {
-
-
-
- present: bool,
-
-
- enabled: bool,
- show_in_ui: bool,
- functioning: bool,
-
- battery_present: bool,
- }
- impl Default for StatusObject {
- fn default() -> Self {
- StatusObject { present: true, enabled: true, show_in_ui: true, functioning: true, battery_present: true }
- }
- }
- #[derive(Clone, Copy, PartialEq, Eq, Debug)]
- pub enum AmlType {
- Uninitialized,
- Buffer,
- BufferField,
-
- DdbHandle,
- DebugObject,
- Event,
- FieldUnit,
- Integer,
- Method,
- Mutex,
- ObjReference,
- OpRegion,
- Package,
- PowerResource,
- Processor,
- RawDataBuffer,
- String,
- ThermalZone,
- }
- #[derive(Clone, PartialEq, Eq, Debug)]
- pub enum AmlValue {
- Boolean(bool),
- Integer(u64),
- String(String),
-
-
-
- OpRegion {
- region: RegionSpace,
- offset: u64,
- length: u64,
- parent_device: Option<AmlName>,
- },
-
- Field {
- region: AmlHandle,
- flags: FieldFlags,
- offset: u64,
- length: u64,
- },
- Method {
- flags: MethodFlags,
- code: Vec<u8>,
- },
- Buffer {
- bytes: Vec<u8>,
- size: u64,
- },
- Processor {
- id: u8,
- pblk_address: u32,
- pblk_len: u8,
- },
- Mutex {
- sync_level: u8,
- },
- Package(Vec<AmlValue>),
- }
- impl AmlValue {
-
- pub fn type_of(&self) -> AmlType {
- match self {
- AmlValue::Boolean(_) => AmlType::Integer,
- AmlValue::Integer(_) => AmlType::Integer,
- AmlValue::String(_) => AmlType::String,
- AmlValue::OpRegion { .. } => AmlType::OpRegion,
- AmlValue::Field { .. } => AmlType::FieldUnit,
- AmlValue::Method { .. } => AmlType::Method,
- AmlValue::Buffer { .. } => AmlType::Buffer,
- AmlValue::Processor { .. } => AmlType::Processor,
- AmlValue::Mutex { .. } => AmlType::Mutex,
- AmlValue::Package(_) => AmlType::Package,
- }
- }
- pub fn as_bool(&self) -> Result<bool, AmlError> {
- match self {
- AmlValue::Boolean(value) => Ok(*value),
- AmlValue::Integer(value) => Ok(*value != 0),
- _ => Err(AmlError::IncompatibleValueConversion),
- }
- }
- pub fn as_integer(&self, context: &AmlContext) -> Result<u64, AmlError> {
- match self {
- AmlValue::Integer(value) => Ok(*value),
- AmlValue::Buffer { ref bytes, .. } => {
-
- let bytes = if bytes.len() > 8 { &bytes[0..8] } else { bytes };
- Ok(bytes.iter().rev().fold(0: u64, |mut i, &popped| {
- i <<= 8;
- i += popped as u64;
- i
- }))
- }
-
- AmlValue::Field { .. } => self.read_field(context)?.as_integer(context),
- _ => Err(AmlError::IncompatibleValueConversion),
- }
- }
-
-
-
- pub fn as_status(&self) -> Result<StatusObject, AmlError> {
- match self {
- AmlValue::Integer(value) => {
-
- if value.get_bits(5..64) != 0 {
- return Err(AmlError::InvalidStatusObject);
- }
- Ok(StatusObject {
- present: value.get_bit(0),
- enabled: value.get_bit(1),
- show_in_ui: value.get_bit(2),
- functioning: value.get_bit(3),
- battery_present: value.get_bit(4),
- })
- }
- _ => Err(AmlError::InvalidStatusObject),
- }
- }
-
-
-
-
-
-
-
-
-
-
-
- pub fn as_type(&self, desired_type: AmlType, context: &AmlContext) -> Result<AmlValue, AmlError> {
-
- let our_type = self.type_of();
-
- if our_type == desired_type {
- return Ok(self.clone());
- }
-
- match desired_type {
- AmlType::Integer => self.as_integer(context).map(|value| AmlValue::Integer(value)),
- _ => Err(AmlError::IncompatibleValueConversion),
- }
- }
-
-
- pub fn read_field(&self, context: &AmlContext) -> Result<AmlValue, AmlError> {
- if let AmlValue::Field { region, flags, offset, length } = self {
- let (region_space, region_base, region_length, parent_device) = {
- if let AmlValue::OpRegion { region, offset, length, parent_device } =
- context.namespace.get(*region)?
- {
- (region, offset, length, parent_device)
- } else {
- return Err(AmlError::FieldRegionIsNotOpRegion);
- }
- };
- match region_space {
- RegionSpace::SystemMemory => {
- let address = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
- match length {
- 8 => Ok(AmlValue::Integer(context.handler.read_u8(address) as u64)),
- 16 => Ok(AmlValue::Integer(context.handler.read_u16(address) as u64)),
- 32 => Ok(AmlValue::Integer(context.handler.read_u32(address) as u64)),
- 64 => Ok(AmlValue::Integer(context.handler.read_u64(address))),
- _ => Err(AmlError::FieldInvalidAccessSize),
- }
- }
- RegionSpace::SystemIo => {
- let port = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
- match length {
- 8 => Ok(AmlValue::Integer(context.handler.read_io_u8(port) as u64)),
- 16 => Ok(AmlValue::Integer(context.handler.read_io_u16(port) as u64)),
- 32 => Ok(AmlValue::Integer(context.handler.read_io_u32(port) as u64)),
- _ => Err(AmlError::FieldInvalidAccessSize),
- }
- }
-
- _ => unimplemented!(),
- }
- } else {
- Err(AmlError::IncompatibleValueConversion)
- }
- }
- }
- #[derive(Clone, Debug, Default)]
- pub struct Args {
- pub arg_0: Option<AmlValue>,
- pub arg_1: Option<AmlValue>,
- pub arg_2: Option<AmlValue>,
- pub arg_3: Option<AmlValue>,
- pub arg_4: Option<AmlValue>,
- pub arg_5: Option<AmlValue>,
- pub arg_6: Option<AmlValue>,
- }
- impl Args {
- pub fn from_list(mut list: Vec<AmlValue>) -> Args {
- assert!(list.len() <= 7);
- list.reverse();
- Args {
- arg_0: list.pop(),
- arg_1: list.pop(),
- arg_2: list.pop(),
- arg_3: list.pop(),
- arg_4: list.pop(),
- arg_5: list.pop(),
- arg_6: list.pop(),
- }
- }
-
-
-
-
- pub fn arg(&self, num: ArgNum) -> Result<&AmlValue, AmlError> {
- match num {
- 0 => self.arg_0.as_ref().ok_or(AmlError::InvalidArgAccess(num)),
- 1 => self.arg_1.as_ref().ok_or(AmlError::InvalidArgAccess(num)),
- 2 => self.arg_2.as_ref().ok_or(AmlError::InvalidArgAccess(num)),
- 3 => self.arg_3.as_ref().ok_or(AmlError::InvalidArgAccess(num)),
- 4 => self.arg_4.as_ref().ok_or(AmlError::InvalidArgAccess(num)),
- 5 => self.arg_5.as_ref().ok_or(AmlError::InvalidArgAccess(num)),
- 6 => self.arg_6.as_ref().ok_or(AmlError::InvalidArgAccess(num)),
- _ => Err(AmlError::InvalidArgAccess(num)),
- }
- }
- }
|