lib.rs 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. //! `aml` is a pure-Rust AML (ACPI Machine Language) parser, used for parsing the DSDT and
  2. //! SSDT tables from ACPI. This crate can be used by kernels to gather information about the
  3. //! hardware, and invoke control methods to query and change the state of devices in a
  4. //! hardware-independent way.
  5. //!
  6. //! ### Using the library
  7. //! To use the library, you should create an `AmlContext` using `AmlContext::new()`, and then pass it tables
  8. //! containing AML (probably from the `acpi` crate), which you've mapped into the virtual address space. This will
  9. //! parse the table, populating the namespace with objects encoded by the AML. After this, you may unmap the memory
  10. //! the table was mapped into - all the information needed will be extracted and allocated on the heap.
  11. //!
  12. //! You can then access specific objects by name like so: e.g.
  13. //! ```ignore
  14. //! let my_aml_value = aml_context.lookup(&AmlName::from_str("\\_SB.PCI0.S08._ADR").unwrap());
  15. //! ```
  16. //!
  17. //! And invoke control methods like this: e.g.
  18. //! ```ignore
  19. //! let result = aml_context.invoke_method(&AmlName::from_str("\\_SB.HPET._CRS").unwrap(), value::Args::EMPTY);
  20. //! ```
  21. //!
  22. //! ### About the parser
  23. //! The parser is written using a set of custom parser combinators - the code can be confusing on
  24. //! first reading, but provides an extensible and type-safe way to write parsers. For an easy
  25. //! introduction to parser combinators and the foundations used for this library, I suggest reading
  26. //! [Bodil's fantastic blog post](https://bodil.lol/parser-combinators/).
  27. //!
  28. //! The actual combinators can be found in `parser.rs`. Various tricks are used to provide a nice
  29. //! API and work around limitations in the type system, such as the concrete types like
  30. //! `MapWithContext`.
  31. //!
  32. //! The actual parsers are then grouped into categories based loosely on the AML grammar sections in
  33. //! the ACPI spec. Most are written in terms of combinators, but some have to be written in a more
  34. //! imperitive style, either because they're clearer, or because we haven't yet found good
  35. //! combinator patterns to express the parse.
  36. #![no_std]
  37. #![feature(decl_macro)]
  38. extern crate alloc;
  39. #[cfg(test)]
  40. extern crate std;
  41. #[cfg(test)]
  42. mod test_utils;
  43. pub(crate) mod expression;
  44. pub(crate) mod misc;
  45. pub(crate) mod name_object;
  46. pub(crate) mod namespace;
  47. pub(crate) mod opcode;
  48. pub(crate) mod parser;
  49. pub mod pci_routing;
  50. pub(crate) mod pkg_length;
  51. pub mod resource;
  52. pub(crate) mod statement;
  53. pub(crate) mod term_object;
  54. pub mod value;
  55. pub use crate::{namespace::*, value::AmlValue};
  56. use alloc::{boxed::Box, string::ToString};
  57. use core::mem;
  58. use log::{error, warn};
  59. use misc::{ArgNum, LocalNum};
  60. use name_object::Target;
  61. use parser::{Parser, Propagate};
  62. use pkg_length::PkgLength;
  63. use term_object::term_list;
  64. use value::{AmlType, Args};
  65. /// AML has a `RevisionOp` operator that returns the "AML interpreter revision". It's not clear
  66. /// what this is actually used for, but this is ours.
  67. pub const AML_INTERPRETER_REVISION: u64 = 0;
  68. /// Describes how much debug information the parser should emit. Set the "maximum" expected verbosity in
  69. /// the context's `debug_verbosity` - everything will be printed that is less or equal in 'verbosity'.
  70. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
  71. pub enum DebugVerbosity {
  72. /// Print no debug information
  73. None,
  74. /// Print heads and tails when entering and leaving scopes of major objects, but not more minor ones.
  75. Scopes,
  76. /// Print heads and tails when entering and leaving scopes of all objects.
  77. AllScopes,
  78. /// Print heads and tails of all objects, and extra debug information as it's parsed.
  79. All,
  80. }
  81. #[derive(Debug)]
  82. struct MethodContext {
  83. /// AML local variables. These are used when we invoke a control method. A `None` value represents a null AML
  84. /// object.
  85. locals: [Option<AmlValue>; 8],
  86. /// If we're currently invoking a control method, this stores the arguments that were passed to
  87. /// it. It's `None` if we aren't invoking a method.
  88. args: Args,
  89. }
  90. impl MethodContext {
  91. fn new(args: Args) -> MethodContext {
  92. // XXX: this is required because `Option<AmlValue>` is not `Copy`, so it can't be used to initialize an
  93. // array, but consts can :(
  94. const NONE_BUT_CONST: Option<AmlValue> = None;
  95. MethodContext { locals: [NONE_BUT_CONST; 8], args }
  96. }
  97. }
  98. pub struct AmlContext {
  99. /// The `Handler` passed from the library user. This is stored as a boxed trait object simply to avoid having
  100. /// to add a lifetime and type parameter to `AmlContext`, as they would massively complicate the parser types.
  101. handler: Box<dyn Handler>,
  102. pub namespace: Namespace,
  103. method_context: Option<MethodContext>,
  104. /*
  105. * These track the state of the context while it's parsing an AML table.
  106. */
  107. current_scope: AmlName,
  108. scope_indent: usize,
  109. debug_verbosity: DebugVerbosity,
  110. }
  111. impl AmlContext {
  112. /// Creates a new `AmlContext` - the central type in managing the AML tables. Only one of these should be
  113. /// created, and it should be passed the DSDT and all SSDTs defined by the hardware.
  114. pub fn new(handler: Box<dyn Handler>, debug_verbosity: DebugVerbosity) -> AmlContext {
  115. let mut context = AmlContext {
  116. handler,
  117. namespace: Namespace::new(),
  118. method_context: None,
  119. current_scope: AmlName::root(),
  120. scope_indent: 0,
  121. debug_verbosity,
  122. };
  123. context.add_predefined_objects();
  124. context
  125. }
  126. pub fn parse_table(&mut self, stream: &[u8]) -> Result<(), AmlError> {
  127. if stream.len() == 0 {
  128. return Err(AmlError::UnexpectedEndOfStream);
  129. }
  130. let table_length = PkgLength::from_raw_length(stream, stream.len() as u32).unwrap();
  131. match term_object::term_list(table_length).parse(stream, self) {
  132. Ok(_) => Ok(()),
  133. Err((_, _, Propagate::Err(err))) => {
  134. error!("Failed to parse AML stream. Err = {:?}", err);
  135. Err(err)
  136. }
  137. Err((_, _, other)) => {
  138. error!("AML table evaluated to unexpected result: {:?}", other);
  139. Err(AmlError::MalformedStream)
  140. }
  141. }
  142. }
  143. // TODO: docs
  144. pub fn invoke_method(&mut self, path: &AmlName, args: Args) -> Result<AmlValue, AmlError> {
  145. use value::MethodCode;
  146. match self.namespace.get_by_path(path)?.clone() {
  147. AmlValue::Method { flags, code } => {
  148. /*
  149. * First, set up the state we expect to enter the method with, but clearing local
  150. * variables to "null" and setting the arguments. Save the current method state and scope, so if we're
  151. * already executing another control method, we resume into it correctly.
  152. */
  153. let old_context = mem::replace(&mut self.method_context, Some(MethodContext::new(args)));
  154. let old_scope = mem::replace(&mut self.current_scope, path.clone());
  155. /*
  156. * Create a namespace level to store local objects created by the invocation.
  157. */
  158. self.namespace.add_level(path.clone(), LevelType::MethodLocals)?;
  159. let return_value = match code {
  160. MethodCode::Aml(ref code) => {
  161. match term_list(PkgLength::from_raw_length(code, code.len() as u32).unwrap())
  162. .parse(code, self)
  163. {
  164. // If the method doesn't return a value, we implicitly return `0`
  165. Ok(_) => Ok(AmlValue::Integer(0)),
  166. Err((_, _, Propagate::Return(result))) => Ok(result),
  167. Err((_, _, Propagate::Break)) => Err(AmlError::BreakInInvalidPosition),
  168. Err((_, _, Propagate::Continue)) => Err(AmlError::ContinueInInvalidPosition),
  169. Err((_, _, Propagate::Err(err))) => {
  170. error!("Failed to execute control method: {:?}", err);
  171. Err(err)
  172. }
  173. }
  174. }
  175. MethodCode::Native(ref method) => match (method)(self) {
  176. Ok(result) => Ok(result),
  177. Err(err) => {
  178. error!("Failed to execute control method: {:?}", err);
  179. Err(err)
  180. }
  181. },
  182. };
  183. /*
  184. * Locally-created objects should be destroyed on method exit (see §5.5.2.3 of the ACPI spec). We do
  185. * this by simply removing the method's local object layer.
  186. */
  187. // TODO: this should also remove objects created by the method outside the method's scope, if they
  188. // weren't statically created. This is harder.
  189. self.namespace.remove_level(path.clone())?;
  190. /*
  191. * Restore the old state.
  192. */
  193. self.method_context = old_context;
  194. self.current_scope = old_scope;
  195. return_value
  196. }
  197. /*
  198. * AML can encode methods that don't require any computation simply as the value that would otherwise be
  199. * returned (e.g. a `_STA` object simply being an `AmlValue::Integer`, instead of a method that just
  200. * returns an integer).
  201. */
  202. value => Ok(value),
  203. }
  204. }
  205. // TODO: docs
  206. pub fn initialize_objects(&mut self) -> Result<(), AmlError> {
  207. use name_object::NameSeg;
  208. use value::StatusObject;
  209. /*
  210. * If `\_SB._INI` exists, we unconditionally execute it at the beginning of device initialization.
  211. */
  212. match self.invoke_method(&AmlName::from_str("\\_SB._INI").unwrap(), Args::default()) {
  213. Ok(_) => (),
  214. Err(AmlError::ValueDoesNotExist(_)) => (),
  215. Err(err) => return Err(err),
  216. }
  217. /*
  218. * Next, we traverse the namespace, looking for devices.
  219. *
  220. * XXX: we clone the namespace here, which obviously drives up heap burden quite a bit (not as much as you
  221. * might first expect though - we're only duplicating the level data structure, not all the objects). The
  222. * issue here is that we need to access the namespace during traversal (e.g. to invoke a method), which the
  223. * borrow checker really doesn't like. A better solution could be a iterator-like traversal system that
  224. * keeps track of the namespace without keeping it borrowed. This works for now.
  225. */
  226. self.namespace.clone().traverse(|path, level: &NamespaceLevel| match level.typ {
  227. LevelType::Device => {
  228. let status = if level.values.contains_key(&NameSeg::from_str("_STA").unwrap()) {
  229. self.invoke_method(&AmlName::from_str("_STA").unwrap().resolve(&path)?, Args::default())?
  230. .as_status()?
  231. } else {
  232. StatusObject::default()
  233. };
  234. /*
  235. * If the device is present and has an `_INI` method, invoke it.
  236. */
  237. if status.present && level.values.contains_key(&NameSeg::from_str("_INI").unwrap()) {
  238. log::info!("Invoking _INI at level: {}", path);
  239. self.invoke_method(&AmlName::from_str("_INI").unwrap().resolve(&path)?, Args::default())?;
  240. }
  241. /*
  242. * We traverse the children of this device if it's present, or isn't present but is functional.
  243. */
  244. Ok(status.present || status.functional)
  245. }
  246. LevelType::Scope => Ok(true),
  247. // TODO: can any of these contain devices?
  248. LevelType::Processor => Ok(false),
  249. LevelType::PowerResource => Ok(false),
  250. LevelType::ThermalZone => Ok(false),
  251. LevelType::MethodLocals => Ok(false),
  252. })?;
  253. Ok(())
  254. }
  255. pub(crate) fn read_target(&self, target: &Target) -> Result<&AmlValue, AmlError> {
  256. match target {
  257. Target::Null => todo!(),
  258. Target::Name(name) => {
  259. let (_, handle) = self.namespace.search(name, &self.current_scope)?;
  260. self.namespace.get(handle)
  261. }
  262. Target::Debug => todo!(),
  263. Target::Arg(arg) => self.current_arg(*arg),
  264. Target::Local(local) => self.local(*local),
  265. }
  266. }
  267. /// Get the value of an argument by its argument number. Can only be executed from inside a control method.
  268. pub(crate) fn current_arg(&self, arg: ArgNum) -> Result<&AmlValue, AmlError> {
  269. self.method_context.as_ref().ok_or(AmlError::NotExecutingControlMethod)?.args.arg(arg)
  270. }
  271. /// Get the current value of a local by its local number. Can only be executed from inside a control method.
  272. pub(crate) fn local(&self, local: LocalNum) -> Result<&AmlValue, AmlError> {
  273. if let None = self.method_context {
  274. return Err(AmlError::NotExecutingControlMethod);
  275. }
  276. if local > 7 {
  277. return Err(AmlError::InvalidLocalAccess(local));
  278. }
  279. self.method_context.as_ref().unwrap().locals[local as usize]
  280. .as_ref()
  281. .ok_or(AmlError::InvalidLocalAccess(local))
  282. }
  283. /// Perform a store into a `Target`, according to the rules specified by §19.3.5.8. This returns a value read
  284. /// out of the target, if neccessary, as values can be altered during a store in some circumstances. When
  285. /// required, this also performs required implicit conversions, otherwise stores are semantically equivalent to
  286. /// a `CopyObject`.
  287. pub(crate) fn store(&mut self, target: Target, value: AmlValue) -> Result<AmlValue, AmlError> {
  288. match target {
  289. Target::Name(ref path) => {
  290. let (_, handle) = self.namespace.search(path, &self.current_scope)?;
  291. match self.namespace.get(handle).unwrap().type_of() {
  292. AmlType::FieldUnit => {
  293. let mut field = self.namespace.get(handle).unwrap().clone();
  294. field.write_field(value, self)?;
  295. field.read_field(self)
  296. }
  297. AmlType::BufferField => {
  298. let mut buffer_field = self.namespace.get(handle).unwrap().clone();
  299. buffer_field.write_buffer_field(value.clone(), self)?;
  300. Ok(value)
  301. }
  302. typ => {
  303. *self.namespace.get_mut(handle)? = value.as_type(typ, self)?;
  304. Ok(self.namespace.get(handle)?.clone())
  305. }
  306. }
  307. }
  308. Target::Debug => {
  309. // TODO
  310. unimplemented!()
  311. }
  312. Target::Arg(arg_num) => {
  313. if let None = self.method_context {
  314. return Err(AmlError::NotExecutingControlMethod);
  315. }
  316. /*
  317. * Stores into `Arg` objects are simply copied with no conversion applied, unless the `Arg`
  318. * contains an Object Reference, in which case an automatic de-reference occurs and the object is
  319. * copied to the target of the Object Reference, instead of overwriting the `Arg.`
  320. */
  321. // TODO: implement behaviour for object references
  322. self.method_context.as_mut().unwrap().args.store_arg(arg_num, value.clone())?;
  323. Ok(value)
  324. }
  325. Target::Local(local_num) => {
  326. if let None = self.method_context {
  327. return Err(AmlError::NotExecutingControlMethod);
  328. }
  329. /*
  330. * Stores into `Local` objects are always simply copied into the destination with no conversion
  331. * applied, even if it contains an Object Reference.
  332. */
  333. self.method_context.as_mut().unwrap().locals[local_num as usize] = Some(value.clone());
  334. Ok(value)
  335. }
  336. Target::Null => Ok(value),
  337. }
  338. }
  339. /// Read from an operation-region, performing only standard-sized reads (supported powers-of-2 only. If a field
  340. /// is not one of these sizes, it may need to be masked, or multiple reads may need to be performed).
  341. pub(crate) fn read_region(&self, region_handle: AmlHandle, offset: u64, length: u64) -> Result<u64, AmlError> {
  342. use bit_field::BitField;
  343. use core::convert::TryInto;
  344. use value::RegionSpace;
  345. let (region_space, region_base, region_length, parent_device) = {
  346. if let AmlValue::OpRegion { region, offset, length, parent_device } =
  347. self.namespace.get(region_handle)?
  348. {
  349. (region, offset, length, parent_device)
  350. } else {
  351. return Err(AmlError::FieldRegionIsNotOpRegion);
  352. }
  353. };
  354. match region_space {
  355. RegionSpace::SystemMemory => {
  356. let address = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
  357. match length {
  358. 8 => Ok(self.handler.read_u8(address) as u64),
  359. 16 => Ok(self.handler.read_u16(address) as u64),
  360. 32 => Ok(self.handler.read_u32(address) as u64),
  361. 64 => Ok(self.handler.read_u64(address)),
  362. _ => Err(AmlError::FieldInvalidAccessSize),
  363. }
  364. }
  365. RegionSpace::SystemIo => {
  366. let port = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
  367. match length {
  368. 8 => Ok(self.handler.read_io_u8(port) as u64),
  369. 16 => Ok(self.handler.read_io_u16(port) as u64),
  370. 32 => Ok(self.handler.read_io_u32(port) as u64),
  371. _ => Err(AmlError::FieldInvalidAccessSize),
  372. }
  373. }
  374. RegionSpace::PciConfig => {
  375. /*
  376. * First, we need to get some extra information out of objects in the parent object. Both
  377. * `_SEG` and `_BBN` seem optional, with defaults that line up with legacy PCI implementations
  378. * (e.g. systems with a single segment group and a single root, respectively).
  379. */
  380. let parent_device = parent_device.as_ref().unwrap();
  381. let seg = match self.namespace.search(&AmlName::from_str("_SEG").unwrap(), parent_device) {
  382. Ok((_, handle)) => self
  383. .namespace
  384. .get(handle)?
  385. .as_integer(self)?
  386. .try_into()
  387. .map_err(|_| AmlError::FieldInvalidAddress)?,
  388. Err(AmlError::ValueDoesNotExist(_)) => 0,
  389. Err(err) => return Err(err),
  390. };
  391. let bbn = match self.namespace.search(&AmlName::from_str("_BBN").unwrap(), parent_device) {
  392. Ok((_, handle)) => self
  393. .namespace
  394. .get(handle)?
  395. .as_integer(self)?
  396. .try_into()
  397. .map_err(|_| AmlError::FieldInvalidAddress)?,
  398. Err(AmlError::ValueDoesNotExist(_)) => 0,
  399. Err(err) => return Err(err),
  400. };
  401. let adr = {
  402. let (_, handle) = self.namespace.search(&AmlName::from_str("_ADR").unwrap(), parent_device)?;
  403. self.namespace.get(handle)?.as_integer(self)?
  404. };
  405. let device = adr.get_bits(16..24) as u8;
  406. let function = adr.get_bits(0..8) as u8;
  407. let offset = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
  408. match length {
  409. 8 => Ok(self.handler.read_pci_u8(seg, bbn, device, function, offset) as u64),
  410. 16 => Ok(self.handler.read_pci_u16(seg, bbn, device, function, offset) as u64),
  411. 32 => Ok(self.handler.read_pci_u32(seg, bbn, device, function, offset) as u64),
  412. _ => Err(AmlError::FieldInvalidAccessSize),
  413. }
  414. }
  415. // TODO
  416. _ => unimplemented!(),
  417. }
  418. }
  419. pub(crate) fn write_region(
  420. &mut self,
  421. region_handle: AmlHandle,
  422. offset: u64,
  423. length: u64,
  424. value: u64,
  425. ) -> Result<(), AmlError> {
  426. use bit_field::BitField;
  427. use core::convert::TryInto;
  428. use value::RegionSpace;
  429. let (region_space, region_base, region_length, parent_device) = {
  430. if let AmlValue::OpRegion { region, offset, length, parent_device } =
  431. self.namespace.get(region_handle)?
  432. {
  433. (region, offset, length, parent_device)
  434. } else {
  435. return Err(AmlError::FieldRegionIsNotOpRegion);
  436. }
  437. };
  438. match region_space {
  439. RegionSpace::SystemMemory => {
  440. let address = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
  441. match length {
  442. 8 => Ok(self.handler.write_u8(address, value as u8)),
  443. 16 => Ok(self.handler.write_u16(address, value as u16)),
  444. 32 => Ok(self.handler.write_u32(address, value as u32)),
  445. 64 => Ok(self.handler.write_u64(address, value)),
  446. _ => Err(AmlError::FieldInvalidAccessSize),
  447. }
  448. }
  449. RegionSpace::SystemIo => {
  450. let port = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
  451. match length {
  452. 8 => Ok(self.handler.write_io_u8(port, value as u8)),
  453. 16 => Ok(self.handler.write_io_u16(port, value as u16)),
  454. 32 => Ok(self.handler.write_io_u32(port, value as u32)),
  455. _ => Err(AmlError::FieldInvalidAccessSize),
  456. }
  457. }
  458. RegionSpace::PciConfig => {
  459. /*
  460. * First, we need to get some extra information out of objects in the parent object. Both
  461. * `_SEG` and `_BBN` seem optional, with defaults that line up with legacy PCI implementations
  462. * (e.g. systems with a single segment group and a single root, respectively).
  463. */
  464. let parent_device = parent_device.as_ref().unwrap();
  465. let seg = match self.namespace.search(&AmlName::from_str("_SEG").unwrap(), parent_device) {
  466. Ok((_, handle)) => self
  467. .namespace
  468. .get(handle)?
  469. .as_integer(self)?
  470. .try_into()
  471. .map_err(|_| AmlError::FieldInvalidAddress)?,
  472. Err(AmlError::ValueDoesNotExist(_)) => 0,
  473. Err(err) => return Err(err),
  474. };
  475. let bbn = match self.namespace.search(&AmlName::from_str("_BBN").unwrap(), parent_device) {
  476. Ok((_, handle)) => self
  477. .namespace
  478. .get(handle)?
  479. .as_integer(self)?
  480. .try_into()
  481. .map_err(|_| AmlError::FieldInvalidAddress)?,
  482. Err(AmlError::ValueDoesNotExist(_)) => 0,
  483. Err(err) => return Err(err),
  484. };
  485. let adr = {
  486. let (_, handle) = self.namespace.search(&AmlName::from_str("_ADR").unwrap(), parent_device)?;
  487. self.namespace.get(handle)?.as_integer(self)?
  488. };
  489. let device = adr.get_bits(16..24) as u8;
  490. let function = adr.get_bits(0..8) as u8;
  491. let offset = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
  492. match length {
  493. 8 => Ok(self.handler.write_pci_u8(seg, bbn, device, function, offset, value as u8)),
  494. 16 => Ok(self.handler.write_pci_u16(seg, bbn, device, function, offset, value as u16)),
  495. 32 => Ok(self.handler.write_pci_u32(seg, bbn, device, function, offset, value as u32)),
  496. _ => Err(AmlError::FieldInvalidAccessSize),
  497. }
  498. }
  499. // TODO
  500. _ => unimplemented!(),
  501. }
  502. }
  503. fn add_predefined_objects(&mut self) {
  504. /*
  505. * These are the scopes predefined by the spec. Some tables will try to access them without defining them
  506. * themselves, and so we have to pre-create them.
  507. */
  508. self.namespace.add_level(AmlName::from_str("\\_GPE").unwrap(), LevelType::Scope).unwrap();
  509. self.namespace.add_level(AmlName::from_str("\\_SB").unwrap(), LevelType::Scope).unwrap();
  510. self.namespace.add_level(AmlName::from_str("\\_SI").unwrap(), LevelType::Scope).unwrap();
  511. self.namespace.add_level(AmlName::from_str("\\_PR").unwrap(), LevelType::Scope).unwrap();
  512. self.namespace.add_level(AmlName::from_str("\\_TZ").unwrap(), LevelType::Scope).unwrap();
  513. /*
  514. * In the dark ages of ACPI 1.0, before `\_OSI`, `\_OS` was used to communicate to the firmware which OS
  515. * was running. This was predictably not very good, and so was replaced in ACPI 3.0 with `_OSI`, which
  516. * allows support for individual capabilities to be queried. `_OS` should not be used by modern firmwares,
  517. * but to avoid problems we follow Linux in returning `"Microsoft Windows NT"`.
  518. *
  519. * See https://www.kernel.org/doc/html/latest/firmware-guide/acpi/osi.html for more information.
  520. */
  521. self.namespace
  522. .add_value(AmlName::from_str("\\_OS").unwrap(), AmlValue::String("Microsoft Windows NT".to_string()))
  523. .unwrap();
  524. /*
  525. * `\_OSI` was introduced by ACPI 3.0 to improve the situation created by `\_OS`. Unfortunately, exactly
  526. * the same problem was immediately repeated by introducing capabilities reflecting that an ACPI
  527. * implementation is exactly the same as a particular version of Windows' (e.g. firmwares will call
  528. * `\_OSI("Windows 2001")`).
  529. *
  530. * We basically follow suit with whatever Linux does, as this will hopefully minimise breakage:
  531. * - We always claim `Windows *` compatability
  532. * - We answer 'yes' to `_OSI("Darwin")
  533. * - We answer 'no' to `_OSI("Linux")`, and report that the tables are doing the wrong thing
  534. */
  535. self.namespace
  536. .add_value(
  537. AmlName::from_str("\\_OSI").unwrap(),
  538. AmlValue::native_method(1, false, 0, |context| {
  539. Ok(match context.current_arg(0)?.as_string(context)?.as_str() {
  540. "Windows 2000" => true, // 2000
  541. "Windows 2001" => true, // XP
  542. "Windows 2001 SP1" => true, // XP SP1
  543. "Windows 2001 SP2" => true, // XP SP2
  544. "Windows 2001.1" => true, // Server 2003
  545. "Windows 2001.1 SP1" => true, // Server 2003 SP1
  546. "Windows 2006" => true, // Vista
  547. "Windows 2006 SP1" => true, // Vista SP1
  548. "Windows 2006 SP2" => true, // Vista SP2
  549. "Windows 2006.1" => true, // Server 2008
  550. "Windows 2009" => true, // 7 and Server 2008 R2
  551. "Windows 2012" => true, // 8 and Server 2012
  552. "Windows 2013" => true, // 8.1 and Server 2012 R2
  553. "Windows 2015" => true, // 10
  554. "Windows 2016" => true, // 10 version 1607
  555. "Windows 2017" => true, // 10 version 1703
  556. "Windows 2017.2" => true, // 10 version 1709
  557. "Windows 2018" => true, // 10 version 1803
  558. "Windows 2018.2" => true, // 10 version 1809
  559. "Windows 2019" => true, // 10 version 1903
  560. "Darwin" => true,
  561. "Linux" => {
  562. // TODO: should we allow users to specify that this should be true? Linux has a
  563. // command line option for this.
  564. warn!("ACPI evaluated `_OSI(\"Linux\")`. This is a bug. Reporting no support.");
  565. false
  566. }
  567. "Extended Address Space Descriptor" => true,
  568. // TODO: support module devices
  569. "Module Device" => false,
  570. "3.0 Thermal Model" => true,
  571. "3.0 _SCP Extensions" => true,
  572. // TODO: support processor aggregator devices
  573. "Processor Aggregator Device" => false,
  574. _ => false,
  575. }
  576. .then_some(AmlValue::ones())
  577. .unwrap_or(AmlValue::zero()))
  578. }),
  579. )
  580. .unwrap();
  581. /*
  582. * `\_REV` evaluates to the version of the ACPI specification supported by this interpreter. Linux did this
  583. * correctly until 2015, but firmwares misused this to detect Linux (as even modern versions of Windows
  584. * return `2`), and so they switched to just returning `2` (as we'll also do). `_REV` should be considered
  585. * useless and deprecated (this is mirrored in newer specs, which claim `2` means "ACPI 2 or greater").
  586. */
  587. self.namespace.add_value(AmlName::from_str("\\_REV").unwrap(), AmlValue::Integer(2)).unwrap();
  588. }
  589. }
  590. /// Trait type used by [`AmlContext`] to handle reading and writing to various types of memory in the system.
  591. pub trait Handler: Send + Sync {
  592. fn read_u8(&self, address: usize) -> u8;
  593. fn read_u16(&self, address: usize) -> u16;
  594. fn read_u32(&self, address: usize) -> u32;
  595. fn read_u64(&self, address: usize) -> u64;
  596. fn write_u8(&mut self, address: usize, value: u8);
  597. fn write_u16(&mut self, address: usize, value: u16);
  598. fn write_u32(&mut self, address: usize, value: u32);
  599. fn write_u64(&mut self, address: usize, value: u64);
  600. fn read_io_u8(&self, port: u16) -> u8;
  601. fn read_io_u16(&self, port: u16) -> u16;
  602. fn read_io_u32(&self, port: u16) -> u32;
  603. fn write_io_u8(&self, port: u16, value: u8);
  604. fn write_io_u16(&self, port: u16, value: u16);
  605. fn write_io_u32(&self, port: u16, value: u32);
  606. fn read_pci_u8(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16) -> u8;
  607. fn read_pci_u16(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16) -> u16;
  608. fn read_pci_u32(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16) -> u32;
  609. fn write_pci_u8(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16, value: u8);
  610. fn write_pci_u16(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16, value: u16);
  611. fn write_pci_u32(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16, value: u32);
  612. /// Stall for at least the given number of **microseconds**. An implementation should not relinquish control of
  613. /// the processor during the stall, and for this reason, firmwares should not stall for periods of more than
  614. /// 100 microseconds.
  615. fn stall(&self, microseconds: u64);
  616. /// Sleep for at least the given number of **milliseconds**. An implementation may round to the closest sleep time
  617. /// supported, and should relinquish the processor.
  618. fn sleep(&self, milliseconds: u64);
  619. fn handle_fatal_error(&self, fatal_type: u8, fatal_code: u32, fatal_arg: u64) {
  620. panic!("Fatal error while executing AML (encountered DefFatal op). fatal_type = {:?}, fatal_code = {:?}, fatal_arg = {:?}", fatal_type, fatal_code, fatal_arg);
  621. }
  622. }
  623. /// Used when an [`AmlContext`] encounters an error.
  624. #[derive(Clone, PartialEq, Eq, Debug)]
  625. pub enum AmlError {
  626. /*
  627. * Errors produced parsing the AML stream.
  628. */
  629. UnexpectedEndOfStream,
  630. UnexpectedByte(u8),
  631. /// Produced when the stream evaluates to something other than nothing or an error.
  632. MalformedStream,
  633. InvalidNameSeg,
  634. InvalidPkgLength,
  635. /// Invalid PkgLength relative to an OperationRegion
  636. InvalidRegionPkgLength {
  637. region_bit_length: u64,
  638. raw_length: u32,
  639. },
  640. InvalidFieldFlags,
  641. UnterminatedStringConstant,
  642. InvalidStringConstant,
  643. InvalidRegionSpace(u8),
  644. /// Produced when a `DefPackage` contains a different number of elements to the package's length.
  645. MalformedPackage,
  646. /// Produced when a `DefBuffer` contains more bytes that its size.
  647. MalformedBuffer,
  648. /// Emitted by a parser when it's clear that the stream doesn't encode the object parsed by
  649. /// that parser (e.g. the wrong opcode starts the stream). This is handled specially by some
  650. /// parsers such as `or` and `choice!`.
  651. WrongParser,
  652. /// Returned when a `DefFatal` op is encountered. This is separately reported using [`Handler::handle_fatal_error`].
  653. FatalError,
  654. /*
  655. * Errors produced manipulating AML names.
  656. */
  657. EmptyNamesAreInvalid,
  658. /// Produced when trying to normalize a path that does not point to a valid level of the
  659. /// namespace. E.g. `\_SB.^^PCI0` goes above the root of the namespace. The contained value is the name that
  660. /// normalization was attempted upon.
  661. InvalidNormalizedName(AmlName),
  662. RootHasNoParent,
  663. /*
  664. * Errors produced working with the namespace.
  665. */
  666. /// Produced when a sub-level or value is added to a level that has not yet been added to the namespace. The
  667. /// `AmlName` is the name of the entire sub-level/value.
  668. LevelDoesNotExist(AmlName),
  669. ValueDoesNotExist(AmlName),
  670. /// Produced when two values with the same name are added to the namespace.
  671. NameCollision(AmlName),
  672. TriedToRemoveRootNamespace,
  673. /*
  674. * Errors produced executing control methods.
  675. */
  676. /// Produced when AML tries to do something only possible in a control method (e.g. read from an argument)
  677. /// when there's no control method executing.
  678. NotExecutingControlMethod,
  679. /// Produced when a method accesses an argument it does not have (e.g. a method that takes 2
  680. /// arguments accesses `Arg4`). The inner value is the number of the argument accessed.
  681. InvalidArgAccess(ArgNum),
  682. /// Produced when a method accesses a local that it has not stored into.
  683. InvalidLocalAccess(LocalNum),
  684. /// Tried to invoke a method with too many arguments.
  685. TooManyArgs,
  686. /// A `DefBreak` operation was performed outside of a `DefWhile` or `DefSwitch`.
  687. BreakInInvalidPosition,
  688. /// A `DefContinue` operation was performed outside of a `DefWhile`.
  689. ContinueInInvalidPosition,
  690. /*
  691. * Errors produced parsing the PCI routing tables (_PRT objects).
  692. */
  693. PrtInvalidAddress,
  694. PrtInvalidPin,
  695. PrtInvalidSource,
  696. PrtInvalidGsi,
  697. /// Produced when the PRT doesn't contain an entry for the requested address + pin
  698. PrtNoEntry,
  699. /*
  700. * Errors produced parsing Resource Descriptors.
  701. */
  702. ReservedResourceType,
  703. ResourceDescriptorTooShort,
  704. ResourceDescriptorTooLong,
  705. UnexpectedResourceType,
  706. /*
  707. * Errors produced working with AML values.
  708. */
  709. IncompatibleValueConversion {
  710. current: AmlType,
  711. target: AmlType,
  712. },
  713. InvalidStatusObject,
  714. InvalidShiftLeft,
  715. InvalidShiftRight,
  716. FieldRegionIsNotOpRegion,
  717. FieldInvalidAddress,
  718. FieldInvalidAccessSize,
  719. TypeCannotBeCompared(AmlType),
  720. /// Produced when the `Mid` operator is applied to a value of a type other than `Buffer` or `String`.
  721. TypeCannotBeSliced(AmlType),
  722. TypeCannotBeWrittenToBufferField(AmlType),
  723. BufferFieldIndexesOutOfBounds,
  724. InvalidSizeOfApplication(AmlType),
  725. /// Unimplemented functionality - return error rather than abort
  726. Unimplemented,
  727. }
  728. #[cfg(test)]
  729. mod tests {
  730. use super::*;
  731. #[test]
  732. fn test_send_sync() {
  733. // verify that AmlContext implements Send and Sync
  734. fn test_send_sync<T: Send + Sync>() {}
  735. test_send_sync::<AmlContext>();
  736. }
  737. }