123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807 |
- #![no_std]
- #![feature(decl_macro, type_ascription, box_syntax, bool_to_option)]
- extern crate alloc;
- #[cfg(test)]
- extern crate std;
- #[cfg(test)]
- mod test_utils;
- pub(crate) mod expression;
- pub(crate) mod misc;
- pub(crate) mod name_object;
- pub(crate) mod namespace;
- pub(crate) mod opcode;
- pub(crate) mod parser;
- pub mod pci_routing;
- pub(crate) mod pkg_length;
- pub mod resource;
- pub(crate) mod statement;
- pub(crate) mod term_object;
- pub mod value;
- pub use crate::{namespace::*, value::AmlValue};
- use alloc::{boxed::Box, string::ToString};
- use core::mem;
- use log::{error, warn};
- use misc::{ArgNum, LocalNum};
- use name_object::Target;
- use parser::{Parser, Propagate};
- use pkg_length::PkgLength;
- use term_object::term_list;
- use value::{AmlType, Args};
- pub const AML_INTERPRETER_REVISION: u64 = 0;
- #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
- pub enum DebugVerbosity {
-
- None,
-
- Scopes,
-
- AllScopes,
-
- All,
- }
- struct MethodContext {
-
-
- locals: [Option<AmlValue>; 8],
-
-
- args: Args,
- }
- impl MethodContext {
- fn new(args: Args) -> MethodContext {
-
-
- const NONE_BUT_CONST: Option<AmlValue> = None;
- MethodContext { locals: [NONE_BUT_CONST; 8], args }
- }
- }
- pub struct AmlContext {
-
-
- handler: Box<dyn Handler>,
- pub namespace: Namespace,
- method_context: Option<MethodContext>,
-
- current_scope: AmlName,
- scope_indent: usize,
- debug_verbosity: DebugVerbosity,
- }
- impl AmlContext {
-
-
- pub fn new(handler: Box<dyn Handler>, debug_verbosity: DebugVerbosity) -> AmlContext {
- let mut context = AmlContext {
- handler,
- namespace: Namespace::new(),
- method_context: None,
- current_scope: AmlName::root(),
- scope_indent: 0,
- debug_verbosity,
- };
- context.add_predefined_objects();
- context
- }
- pub fn parse_table(&mut self, stream: &[u8]) -> Result<(), AmlError> {
- if stream.len() == 0 {
- return Err(AmlError::UnexpectedEndOfStream);
- }
- let table_length = PkgLength::from_raw_length(stream, stream.len() as u32).unwrap();
- match term_object::term_list(table_length).parse(stream, self) {
- Ok(_) => Ok(()),
- Err((_, _, Propagate::Err(err))) => {
- error!("Failed to parse AML stream. Err = {:?}", err);
- Err(err)
- }
- Err((_, _, other)) => {
- error!("AML table evaluated to unexpected result: {:?}", other);
- Err(AmlError::MalformedStream)
- }
- }
- }
-
- pub fn invoke_method(&mut self, path: &AmlName, args: Args) -> Result<AmlValue, AmlError> {
- use value::MethodCode;
- match self.namespace.get_by_path(path)?.clone() {
- AmlValue::Method { flags, code } => {
-
- let old_context = mem::replace(&mut self.method_context, Some(MethodContext::new(args)));
- let old_scope = mem::replace(&mut self.current_scope, path.clone());
-
- self.namespace.add_level(path.clone(), LevelType::MethodLocals)?;
- let return_value = match code {
- MethodCode::Aml(ref code) => {
- match term_list(PkgLength::from_raw_length(code, code.len() as u32).unwrap())
- .parse(code, self)
- {
-
- Ok(_) => Ok(AmlValue::Integer(0)),
- Err((_, _, Propagate::Return(result))) => Ok(result),
- Err((_, _, Propagate::Break)) => Err(AmlError::BreakInInvalidPosition),
- Err((_, _, Propagate::Continue)) => Err(AmlError::ContinueInInvalidPosition),
- Err((_, _, Propagate::Err(err))) => {
- error!("Failed to execute control method: {:?}", err);
- Err(err)
- }
- }
- }
- MethodCode::Native(ref method) => match (method)(self) {
- Ok(result) => Ok(result),
- Err(err) => {
- error!("Failed to execute control method: {:?}", err);
- Err(err)
- }
- },
- };
-
-
-
- self.namespace.remove_level(path.clone())?;
-
- self.method_context = old_context;
- self.current_scope = old_scope;
- return_value
- }
-
- value => Ok(value),
- }
- }
-
- pub fn initialize_objects(&mut self) -> Result<(), AmlError> {
- use name_object::NameSeg;
- use value::StatusObject;
-
- match self.invoke_method(&AmlName::from_str("\\_SB._INI").unwrap(), Args::default()) {
- Ok(_) => (),
- Err(AmlError::ValueDoesNotExist(_)) => (),
- Err(err) => return Err(err),
- }
-
- self.namespace.clone().traverse(|path, level: &NamespaceLevel| match level.typ {
- LevelType::Device => {
- let status = if level.values.contains_key(&NameSeg::from_str("_STA").unwrap()) {
- self.invoke_method(&AmlName::from_str("_STA").unwrap().resolve(&path)?, Args::default())?
- .as_status()?
- } else {
- StatusObject::default()
- };
-
- if status.present && level.values.contains_key(&NameSeg::from_str("_INI").unwrap()) {
- log::info!("Invoking _INI at level: {}", path);
- self.invoke_method(&AmlName::from_str("_INI").unwrap().resolve(&path)?, Args::default())?;
- }
-
- Ok(status.present || status.functional)
- }
- LevelType::Scope => Ok(true),
-
- LevelType::Processor => Ok(false),
- LevelType::PowerResource => Ok(false),
- LevelType::ThermalZone => Ok(false),
- LevelType::MethodLocals => Ok(false),
- })?;
- Ok(())
- }
- pub(crate) fn read_target(&self, target: &Target) -> Result<&AmlValue, AmlError> {
- match target {
- Target::Null => todo!(),
- Target::Name(name) => {
- let (_, handle) = self.namespace.search(name, &self.current_scope)?;
- self.namespace.get(handle)
- }
- Target::Debug => todo!(),
- Target::Arg(arg) => self.current_arg(*arg),
- Target::Local(local) => self.local(*local),
- }
- }
-
- pub(crate) fn current_arg(&self, arg: ArgNum) -> Result<&AmlValue, AmlError> {
- self.method_context.as_ref().ok_or(AmlError::NotExecutingControlMethod)?.args.arg(arg)
- }
-
- pub(crate) fn local(&self, local: LocalNum) -> Result<&AmlValue, AmlError> {
- if let None = self.method_context {
- return Err(AmlError::NotExecutingControlMethod);
- }
- if local > 7 {
- return Err(AmlError::InvalidLocalAccess(local));
- }
- self.method_context.as_ref().unwrap().locals[local as usize]
- .as_ref()
- .ok_or(AmlError::InvalidLocalAccess(local))
- }
-
-
-
-
- pub(crate) fn store(&mut self, target: Target, value: AmlValue) -> Result<AmlValue, AmlError> {
- match target {
- Target::Name(ref path) => {
- let (_, handle) = self.namespace.search(path, &self.current_scope)?;
- match self.namespace.get(handle).unwrap().type_of() {
- AmlType::FieldUnit => {
- let mut field = self.namespace.get(handle).unwrap().clone();
- field.write_field(value, self)?;
- field.read_field(self)
- }
- AmlType::BufferField => {
- let mut buffer_field = self.namespace.get(handle).unwrap().clone();
- buffer_field.write_buffer_field(value.clone(), self)?;
- Ok(value)
- }
- typ => {
- *self.namespace.get_mut(handle)? = value.as_type(typ, self)?;
- Ok(self.namespace.get(handle)?.clone())
- }
- }
- }
- Target::Debug => {
-
- unimplemented!()
- }
- Target::Arg(arg_num) => {
- if let None = self.method_context {
- return Err(AmlError::NotExecutingControlMethod);
- }
-
-
- self.method_context.as_mut().unwrap().args.store_arg(arg_num, value.clone())?;
- Ok(value)
- }
- Target::Local(local_num) => {
- if let None = self.method_context {
- return Err(AmlError::NotExecutingControlMethod);
- }
-
- self.method_context.as_mut().unwrap().locals[local_num as usize] = Some(value.clone());
- Ok(value)
- }
- Target::Null => Ok(value),
- }
- }
-
-
- pub(crate) fn read_region(&self, region_handle: AmlHandle, offset: u64, length: u64) -> Result<u64, AmlError> {
- use bit_field::BitField;
- use core::convert::TryInto;
- use value::RegionSpace;
- let (region_space, region_base, region_length, parent_device) = {
- if let AmlValue::OpRegion { region, offset, length, parent_device } =
- self.namespace.get(region_handle)?
- {
- (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(self.handler.read_u8(address) as u64),
- 16 => Ok(self.handler.read_u16(address) as u64),
- 32 => Ok(self.handler.read_u32(address) as u64),
- 64 => Ok(self.handler.read_u64(address)),
- _ => Err(AmlError::FieldInvalidAccessSize),
- }
- }
- RegionSpace::SystemIo => {
- let port = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
- match length {
- 8 => Ok(self.handler.read_io_u8(port) as u64),
- 16 => Ok(self.handler.read_io_u16(port) as u64),
- 32 => Ok(self.handler.read_io_u32(port) as u64),
- _ => Err(AmlError::FieldInvalidAccessSize),
- }
- }
- RegionSpace::PciConfig => {
-
- let parent_device = parent_device.as_ref().unwrap();
- let seg = match self.namespace.search(&AmlName::from_str("_SEG").unwrap(), parent_device) {
- Ok((_, handle)) => self
- .namespace
- .get(handle)?
- .as_integer(self)?
- .try_into()
- .map_err(|_| AmlError::FieldInvalidAddress)?,
- Err(AmlError::ValueDoesNotExist(_)) => 0,
- Err(err) => return Err(err),
- };
- let bbn = match self.namespace.search(&AmlName::from_str("_BBN").unwrap(), parent_device) {
- Ok((_, handle)) => self
- .namespace
- .get(handle)?
- .as_integer(self)?
- .try_into()
- .map_err(|_| AmlError::FieldInvalidAddress)?,
- Err(AmlError::ValueDoesNotExist(_)) => 0,
- Err(err) => return Err(err),
- };
- let adr = {
- let (_, handle) = self.namespace.search(&AmlName::from_str("_ADR").unwrap(), parent_device)?;
- self.namespace.get(handle)?.as_integer(self)?
- };
- let device = adr.get_bits(16..24) as u8;
- let function = adr.get_bits(0..8) as u8;
- let offset = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
- match length {
- 8 => Ok(self.handler.read_pci_u8(seg, bbn, device, function, offset) as u64),
- 16 => Ok(self.handler.read_pci_u16(seg, bbn, device, function, offset) as u64),
- 32 => Ok(self.handler.read_pci_u32(seg, bbn, device, function, offset) as u64),
- _ => Err(AmlError::FieldInvalidAccessSize),
- }
- }
-
- _ => unimplemented!(),
- }
- }
- pub(crate) fn write_region(
- &mut self,
- region_handle: AmlHandle,
- offset: u64,
- length: u64,
- value: u64,
- ) -> Result<(), AmlError> {
- use bit_field::BitField;
- use core::convert::TryInto;
- use value::RegionSpace;
- let (region_space, region_base, region_length, parent_device) = {
- if let AmlValue::OpRegion { region, offset, length, parent_device } =
- self.namespace.get(region_handle)?
- {
- (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(self.handler.write_u8(address, value as u8)),
- 16 => Ok(self.handler.write_u16(address, value as u16)),
- 32 => Ok(self.handler.write_u32(address, value as u32)),
- 64 => Ok(self.handler.write_u64(address, value)),
- _ => Err(AmlError::FieldInvalidAccessSize),
- }
- }
- RegionSpace::SystemIo => {
- let port = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
- match length {
- 8 => Ok(self.handler.write_io_u8(port, value as u8)),
- 16 => Ok(self.handler.write_io_u16(port, value as u16)),
- 32 => Ok(self.handler.write_io_u32(port, value as u32)),
- _ => Err(AmlError::FieldInvalidAccessSize),
- }
- }
- RegionSpace::PciConfig => {
-
- let parent_device = parent_device.as_ref().unwrap();
- let seg = match self.namespace.search(&AmlName::from_str("_SEG").unwrap(), parent_device) {
- Ok((_, handle)) => self
- .namespace
- .get(handle)?
- .as_integer(self)?
- .try_into()
- .map_err(|_| AmlError::FieldInvalidAddress)?,
- Err(AmlError::ValueDoesNotExist(_)) => 0,
- Err(err) => return Err(err),
- };
- let bbn = match self.namespace.search(&AmlName::from_str("_BBN").unwrap(), parent_device) {
- Ok((_, handle)) => self
- .namespace
- .get(handle)?
- .as_integer(self)?
- .try_into()
- .map_err(|_| AmlError::FieldInvalidAddress)?,
- Err(AmlError::ValueDoesNotExist(_)) => 0,
- Err(err) => return Err(err),
- };
- let adr = {
- let (_, handle) = self.namespace.search(&AmlName::from_str("_ADR").unwrap(), parent_device)?;
- self.namespace.get(handle)?.as_integer(self)?
- };
- let device = adr.get_bits(16..24) as u8;
- let function = adr.get_bits(0..8) as u8;
- let offset = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
- match length {
- 8 => Ok(self.handler.write_pci_u8(seg, bbn, device, function, offset, value as u8)),
- 16 => Ok(self.handler.write_pci_u16(seg, bbn, device, function, offset, value as u16)),
- 32 => Ok(self.handler.write_pci_u32(seg, bbn, device, function, offset, value as u32)),
- _ => Err(AmlError::FieldInvalidAccessSize),
- }
- }
-
- _ => unimplemented!(),
- }
- }
- fn add_predefined_objects(&mut self) {
-
- self.namespace.add_level(AmlName::from_str("\\_GPE").unwrap(), LevelType::Scope).unwrap();
- self.namespace.add_level(AmlName::from_str("\\_SB").unwrap(), LevelType::Scope).unwrap();
- self.namespace.add_level(AmlName::from_str("\\_SI").unwrap(), LevelType::Scope).unwrap();
- self.namespace.add_level(AmlName::from_str("\\_PR").unwrap(), LevelType::Scope).unwrap();
- self.namespace.add_level(AmlName::from_str("\\_TZ").unwrap(), LevelType::Scope).unwrap();
-
- self.namespace
- .add_value(AmlName::from_str("\\_OS").unwrap(), AmlValue::String("Microsoft Windows NT".to_string()))
- .unwrap();
-
- self.namespace
- .add_value(
- AmlName::from_str("\\_OSI").unwrap(),
- AmlValue::native_method(1, false, 0, |context| {
- Ok(match context.current_arg(0)?.as_string(context)?.as_str() {
- "Windows 2000" => true,
- "Windows 2001" => true,
- "Windows 2001 SP1" => true,
- "Windows 2001 SP2" => true,
- "Windows 2001.1" => true,
- "Windows 2001.1 SP1" => true,
- "Windows 2006" => true,
- "Windows 2006 SP1" => true,
- "Windows 2006 SP2" => true,
- "Windows 2006.1" => true,
- "Windows 2009" => true,
- "Windows 2012" => true,
- "Windows 2013" => true,
- "Windows 2015" => true,
- "Windows 2016" => true,
- "Windows 2017" => true,
- "Windows 2017.2" => true,
- "Windows 2018" => true,
- "Windows 2018.2" => true,
- "Windows 2019" => true,
- "Darwin" => true,
- "Linux" => {
-
-
- warn!("ACPI evaluated `_OSI(\"Linux\")`. This is a bug. Reporting no support.");
- false
- }
- "Extended Address Space Descriptor" => true,
-
- "Module Device" => false,
- "3.0 Thermal Model" => true,
- "3.0 _SCP Extensions" => true,
-
- "Processor Aggregator Device" => false,
- _ => false,
- }
- .then_some(AmlValue::ones())
- .unwrap_or(AmlValue::zero()))
- }),
- )
- .unwrap();
-
- self.namespace.add_value(AmlName::from_str("\\_REV").unwrap(), AmlValue::Integer(2)).unwrap();
- }
- }
- pub trait Handler: Send + Sync {
- fn read_u8(&self, address: usize) -> u8;
- fn read_u16(&self, address: usize) -> u16;
- fn read_u32(&self, address: usize) -> u32;
- fn read_u64(&self, address: usize) -> u64;
- fn write_u8(&mut self, address: usize, value: u8);
- fn write_u16(&mut self, address: usize, value: u16);
- fn write_u32(&mut self, address: usize, value: u32);
- fn write_u64(&mut self, address: usize, value: u64);
- fn read_io_u8(&self, port: u16) -> u8;
- fn read_io_u16(&self, port: u16) -> u16;
- fn read_io_u32(&self, port: u16) -> u32;
- fn write_io_u8(&self, port: u16, value: u8);
- fn write_io_u16(&self, port: u16, value: u16);
- fn write_io_u32(&self, port: u16, value: u32);
- fn read_pci_u8(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16) -> u8;
- fn read_pci_u16(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16) -> u16;
- fn read_pci_u32(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16) -> u32;
- fn write_pci_u8(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16, value: u8);
- fn write_pci_u16(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16, value: u16);
- fn write_pci_u32(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16, value: u32);
- fn handle_fatal_error(&self, fatal_type: u8, fatal_code: u32, fatal_arg: u64) {
- panic!("Fatal error while executing AML (encountered DefFatal op). fatal_type = {:?}, fatal_code = {:?}, fatal_arg = {:?}", fatal_type, fatal_code, fatal_arg);
- }
- }
- #[derive(Clone, PartialEq, Eq, Debug)]
- pub enum AmlError {
-
- UnexpectedEndOfStream,
- UnexpectedByte(u8),
-
- MalformedStream,
- InvalidNameSeg,
- InvalidPkgLength,
- InvalidFieldFlags,
- UnterminatedStringConstant,
- InvalidStringConstant,
- InvalidRegionSpace(u8),
-
- MalformedPackage,
-
- MalformedBuffer,
-
-
-
- WrongParser,
-
- FatalError,
-
- EmptyNamesAreInvalid,
-
-
-
- InvalidNormalizedName(AmlName),
- RootHasNoParent,
-
-
-
- LevelDoesNotExist(AmlName),
- ValueDoesNotExist(AmlName),
-
- NameCollision(AmlName),
- TriedToRemoveRootNamespace,
-
-
-
- NotExecutingControlMethod,
-
-
- InvalidArgAccess(ArgNum),
-
- InvalidLocalAccess(LocalNum),
-
- TooManyArgs,
-
- BreakInInvalidPosition,
-
- ContinueInInvalidPosition,
-
- PrtInvalidAddress,
- PrtInvalidPin,
- PrtInvalidSource,
- PrtInvalidGsi,
-
- PrtNoEntry,
-
- ReservedResourceType,
- ResourceDescriptorTooShort,
- ResourceDescriptorTooLong,
- UnexpectedResourceType,
-
- IncompatibleValueConversion {
- current: AmlType,
- target: AmlType,
- },
- InvalidStatusObject,
- InvalidShiftLeft,
- InvalidShiftRight,
- FieldRegionIsNotOpRegion,
- FieldInvalidAddress,
- FieldInvalidAccessSize,
- TypeCannotBeCompared(AmlType),
-
- TypeCannotBeSliced(AmlType),
- TypeCannotBeWrittenToBufferField(AmlType),
- BufferFieldIndexesOutOfBounds,
- }
- #[cfg(test)]
- mod tests {
- use super::*;
- #[test]
- fn test_send_sync() {
-
- fn test_send_sync<T: Send + Sync>() {}
- test_send_sync::<AmlContext>();
- }
- }
|