lib.rs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  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 (this is not yet supported) to query and change the state
  4. //! of devices in a hardware-independent way.
  5. //!
  6. //! ### Using the library
  7. //! To use the library, you will mostly interact with the `AmlContext` type. You should create an
  8. //! instance of this type using `AmlContext::new()`, and then pass it tables containing AML
  9. //! (probably from the `acpi` crate), which you've mapped into the virtual address space. This will
  10. //! parse the table, populating the namespace with objects encoded by the AML. After this, you may
  11. //! unmap the memory the table was mapped into - all the information needed will be extracted and
  12. //! allocated on the heap.
  13. //!
  14. //! You can then access specific objects by name like so: e.g.
  15. //! ```ignore
  16. //! let my_aml_value = aml_context.lookup(&AmlName::from_str("\\_SB.PCI0.S08._ADR").unwrap());
  17. //! ```
  18. // TODO: add example of invoking a method
  19. //!
  20. //! ### About the parser
  21. //! The parser is written using a set of custom parser combinators - the code can be confusing on
  22. //! first reading, but provides an extensible and type-safe way to write parsers. For an easy
  23. //! introduction to parser combinators and the foundations used for this library, I suggest reading
  24. //! [Bodil's fantastic blog post](https://bodil.lol/parser-combinators/).
  25. //!
  26. //! The actual combinators can be found in `parser.rs`. Various tricks are used to provide a nice
  27. //! API and work around limitations in the type system, such as the concrete types like
  28. //! `MapWithContext`, and the `make_parser_concrete` hack macro.
  29. //!
  30. //! The actual parsers are then grouped into categories based loosely on the AML grammar sections in
  31. //! the ACPI spec. Most are written in terms of combinators, but some have to be written in a more
  32. //! imperitive style, either because they're clearer, or because we haven't yet found good
  33. //! combinator patterns to express the parse.
  34. #![no_std]
  35. #![feature(decl_macro, type_ascription, box_syntax)]
  36. extern crate alloc;
  37. #[cfg(test)]
  38. extern crate std;
  39. #[cfg(test)]
  40. mod test_utils;
  41. pub(crate) mod misc;
  42. pub(crate) mod name_object;
  43. pub(crate) mod namespace;
  44. pub(crate) mod opcode;
  45. pub(crate) mod parser;
  46. pub mod pci_routing;
  47. pub(crate) mod pkg_length;
  48. pub mod resource;
  49. pub(crate) mod term_object;
  50. pub(crate) mod type1;
  51. pub(crate) mod type2;
  52. pub mod value;
  53. pub use crate::{
  54. namespace::{AmlHandle, AmlName, Namespace},
  55. value::AmlValue,
  56. };
  57. use alloc::{boxed::Box, string::ToString};
  58. use core::mem;
  59. use log::error;
  60. use misc::{ArgNum, LocalNum};
  61. use name_object::Target;
  62. use namespace::LevelType;
  63. use parser::Parser;
  64. use pkg_length::PkgLength;
  65. use term_object::term_list;
  66. use value::{AmlType, Args};
  67. /// AML has a `RevisionOp` operator that returns the "AML interpreter revision". It's not clear
  68. /// what this is actually used for, but this is ours.
  69. pub const AML_INTERPRETER_REVISION: u64 = 0;
  70. /// Describes how much debug information the parser should emit. Set the "maximum" expected verbosity in
  71. /// the context's `debug_verbosity` - everything will be printed that is less or equal in 'verbosity'.
  72. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
  73. pub enum DebugVerbosity {
  74. /// Print no debug information
  75. None,
  76. /// Print heads and tails when entering and leaving scopes of major objects, but not more minor ones.
  77. Scopes,
  78. /// Print heads and tails when entering and leaving scopes of all objects.
  79. AllScopes,
  80. /// Print heads and tails of all objects, and extra debug information as it's parsed.
  81. All,
  82. }
  83. struct MethodContext {
  84. /*
  85. * AML local variables. These are used when we invoke a control method. A `None` value
  86. * represents a null AML object.
  87. */
  88. local_0: Option<AmlValue>,
  89. local_1: Option<AmlValue>,
  90. local_2: Option<AmlValue>,
  91. local_3: Option<AmlValue>,
  92. local_4: Option<AmlValue>,
  93. local_5: Option<AmlValue>,
  94. local_6: Option<AmlValue>,
  95. local_7: Option<AmlValue>,
  96. /// If we're currently invoking a control method, this stores the arguments that were passed to
  97. /// it. It's `None` if we aren't invoking a method.
  98. args: Args,
  99. }
  100. impl MethodContext {
  101. fn new(args: Args) -> MethodContext {
  102. MethodContext {
  103. local_0: None,
  104. local_1: None,
  105. local_2: None,
  106. local_3: None,
  107. local_4: None,
  108. local_5: None,
  109. local_6: None,
  110. local_7: None,
  111. args,
  112. }
  113. }
  114. }
  115. pub struct AmlContext {
  116. /// The `Handler` passed from the library user. This is stored as a boxed trait object simply to avoid having
  117. /// to add a lifetime and type parameter to `AmlContext`, as they would massively complicate the parser types.
  118. handler: Box<dyn Handler>,
  119. pub namespace: Namespace,
  120. method_context: Option<MethodContext>,
  121. /*
  122. * These track the state of the context while it's parsing an AML table.
  123. */
  124. current_scope: AmlName,
  125. scope_indent: usize,
  126. debug_verbosity: DebugVerbosity,
  127. }
  128. impl AmlContext {
  129. /// Creates a new `AmlContext` - the central type in managing the AML tables. Only one of these should be
  130. /// created, and it should be passed the DSDT and all SSDTs defined by the hardware.
  131. pub fn new(handler: Box<dyn Handler>, debug_verbosity: DebugVerbosity) -> AmlContext {
  132. let mut context = AmlContext {
  133. handler,
  134. namespace: Namespace::new(),
  135. method_context: None,
  136. current_scope: AmlName::root(),
  137. scope_indent: 0,
  138. debug_verbosity,
  139. };
  140. context.add_predefined_objects();
  141. context
  142. }
  143. pub fn parse_table(&mut self, stream: &[u8]) -> Result<(), AmlError> {
  144. if stream.len() == 0 {
  145. return Err(AmlError::UnexpectedEndOfStream);
  146. }
  147. let table_length = PkgLength::from_raw_length(stream, stream.len() as u32).unwrap();
  148. match term_object::term_list(table_length).parse(stream, self) {
  149. Ok(_) => Ok(()),
  150. Err((_, _, err)) => {
  151. error!("Failed to parse AML stream. Err = {:?}", err);
  152. Err(err)
  153. }
  154. }
  155. }
  156. // TODO: docs
  157. pub fn invoke_method(&mut self, path: &AmlName, args: Args) -> Result<AmlValue, AmlError> {
  158. match self.namespace.get_by_path(path)?.clone() {
  159. AmlValue::Method { flags, code } => {
  160. /*
  161. * First, set up the state we expect to enter the method with, but clearing local
  162. * variables to "null" and setting the arguments. Save the current method state and scope, so if we're
  163. * already executing another control method, we resume into it correctly.
  164. */
  165. let old_context = mem::replace(&mut self.method_context, Some(MethodContext::new(args)));
  166. let old_scope = mem::replace(&mut self.current_scope, path.clone());
  167. /*
  168. * Create a namespace level to store local objects created by the invocation.
  169. */
  170. self.namespace.add_level(path.clone(), LevelType::MethodLocals)?;
  171. let return_value = match term_list(PkgLength::from_raw_length(&code, code.len() as u32).unwrap())
  172. .parse(&code, self)
  173. {
  174. // If the method doesn't return a value, we implicitly return `0`
  175. Ok(_) => Ok(AmlValue::Integer(0)),
  176. Err((_, _, AmlError::Return(result))) => Ok(result),
  177. Err((_, _, err)) => {
  178. error!("Failed to execute control method: {:?}", err);
  179. Err(err)
  180. }
  181. };
  182. /*
  183. * Locally-created objects should be destroyed on method exit (see §5.5.2.3 of the ACPI spec). We do
  184. * this by simply removing the method's local object layer.
  185. */
  186. // TODO: this should also remove objects created by the method outside the method's scope, if they
  187. // weren't statically created. This is harder.
  188. self.namespace.remove_level(path.clone())?;
  189. /*
  190. * Restore the old state.
  191. */
  192. self.method_context = old_context;
  193. self.current_scope = old_scope;
  194. return_value
  195. }
  196. /*
  197. * AML can encode methods that don't require any computation simply as the value that would otherwise be
  198. * returned (e.g. a `_STA` object simply being an `AmlValue::Integer`, instead of a method that just
  199. * returns an integer).
  200. */
  201. value => Ok(value),
  202. }
  203. }
  204. // TODO: docs
  205. pub fn initialize_objects(&mut self) -> Result<(), AmlError> {
  206. use name_object::NameSeg;
  207. use namespace::NamespaceLevel;
  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 either of these contain devices?
  248. LevelType::Processor => Ok(false),
  249. LevelType::MethodLocals => Ok(false),
  250. })?;
  251. Ok(())
  252. }
  253. /// Get the value of an argument by its argument number. Can only be executed from inside a control method.
  254. pub(crate) fn current_arg(&self, arg: ArgNum) -> Result<&AmlValue, AmlError> {
  255. self.method_context.as_ref().ok_or(AmlError::NotExecutingControlMethod)?.args.arg(arg)
  256. }
  257. /// Get the current value of a local by its local number. Can only be executed from inside a control method.
  258. pub(crate) fn local(&self, local: LocalNum) -> Result<&AmlValue, AmlError> {
  259. if let None = self.method_context {
  260. return Err(AmlError::NotExecutingControlMethod);
  261. }
  262. match local {
  263. 0 => self.method_context.as_ref().unwrap().local_0.as_ref().ok_or(AmlError::InvalidLocalAccess(local)),
  264. 1 => self.method_context.as_ref().unwrap().local_1.as_ref().ok_or(AmlError::InvalidLocalAccess(local)),
  265. 2 => self.method_context.as_ref().unwrap().local_2.as_ref().ok_or(AmlError::InvalidLocalAccess(local)),
  266. 3 => self.method_context.as_ref().unwrap().local_3.as_ref().ok_or(AmlError::InvalidLocalAccess(local)),
  267. 4 => self.method_context.as_ref().unwrap().local_4.as_ref().ok_or(AmlError::InvalidLocalAccess(local)),
  268. 5 => self.method_context.as_ref().unwrap().local_5.as_ref().ok_or(AmlError::InvalidLocalAccess(local)),
  269. 6 => self.method_context.as_ref().unwrap().local_6.as_ref().ok_or(AmlError::InvalidLocalAccess(local)),
  270. 7 => self.method_context.as_ref().unwrap().local_7.as_ref().ok_or(AmlError::InvalidLocalAccess(local)),
  271. _ => Err(AmlError::InvalidLocalAccess(local)),
  272. }
  273. }
  274. /// Perform a store into a `Target`. This returns a value read out of the target, if neccessary, as values can
  275. /// be altered during a store in some circumstances. If the target is a `Name`, this also performs required
  276. /// implicit conversions. Stores to other targets are semantically equivalent to a `CopyObject`.
  277. pub(crate) fn store(&mut self, target: Target, value: AmlValue) -> Result<AmlValue, AmlError> {
  278. match target {
  279. Target::Name(ref path) => {
  280. let (_, handle) = self.namespace.search(path, &self.current_scope)?;
  281. let converted_object = match self.namespace.get(handle).unwrap().type_of() {
  282. /*
  283. * We special-case FieldUnits here because we don't have the needed information to actually do
  284. * the write if we try and convert using `as_type`.
  285. */
  286. AmlType::FieldUnit => {
  287. let mut field = self.namespace.get(handle).unwrap().clone();
  288. field.write_field(value, self)?;
  289. field.read_field(self)?
  290. }
  291. typ => value.as_type(typ, self)?,
  292. };
  293. *self.namespace.get_mut(handle)? = converted_object;
  294. Ok(self.namespace.get(handle)?.clone())
  295. }
  296. Target::Debug => {
  297. // TODO
  298. unimplemented!()
  299. }
  300. Target::Arg(arg_num) => {
  301. if let None = self.method_context {
  302. return Err(AmlError::NotExecutingControlMethod);
  303. }
  304. match arg_num {
  305. 1 => self.method_context.as_mut().unwrap().args.arg_1 = Some(value.clone()),
  306. 2 => self.method_context.as_mut().unwrap().args.arg_2 = Some(value.clone()),
  307. 3 => self.method_context.as_mut().unwrap().args.arg_3 = Some(value.clone()),
  308. 4 => self.method_context.as_mut().unwrap().args.arg_4 = Some(value.clone()),
  309. 5 => self.method_context.as_mut().unwrap().args.arg_5 = Some(value.clone()),
  310. 6 => self.method_context.as_mut().unwrap().args.arg_6 = Some(value.clone()),
  311. _ => return Err(AmlError::InvalidArgAccess(arg_num)),
  312. }
  313. Ok(value)
  314. }
  315. Target::Local(local_num) => {
  316. if let None = self.method_context {
  317. return Err(AmlError::NotExecutingControlMethod);
  318. }
  319. match local_num {
  320. 0 => self.method_context.as_mut().unwrap().local_0 = Some(value.clone()),
  321. 1 => self.method_context.as_mut().unwrap().local_1 = Some(value.clone()),
  322. 2 => self.method_context.as_mut().unwrap().local_2 = Some(value.clone()),
  323. 3 => self.method_context.as_mut().unwrap().local_3 = Some(value.clone()),
  324. 4 => self.method_context.as_mut().unwrap().local_4 = Some(value.clone()),
  325. 5 => self.method_context.as_mut().unwrap().local_5 = Some(value.clone()),
  326. 6 => self.method_context.as_mut().unwrap().local_6 = Some(value.clone()),
  327. 7 => self.method_context.as_mut().unwrap().local_7 = Some(value.clone()),
  328. _ => return Err(AmlError::InvalidLocalAccess(local_num)),
  329. }
  330. Ok(value)
  331. }
  332. Target::Null => Ok(value),
  333. }
  334. }
  335. /// Read from an operation-region, performing only standard-sized reads (supported powers-of-2 only. If a field
  336. /// is not one of these sizes, it may need to be masked, or multiple reads may need to be performed).
  337. pub(crate) fn read_region(&self, region_handle: AmlHandle, offset: u64, length: u64) -> Result<u64, AmlError> {
  338. use bit_field::BitField;
  339. use core::convert::TryInto;
  340. use value::RegionSpace;
  341. let (region_space, region_base, region_length, parent_device) = {
  342. if let AmlValue::OpRegion { region, offset, length, parent_device } =
  343. self.namespace.get(region_handle)?
  344. {
  345. (region, offset, length, parent_device)
  346. } else {
  347. return Err(AmlError::FieldRegionIsNotOpRegion);
  348. }
  349. };
  350. match region_space {
  351. RegionSpace::SystemMemory => {
  352. let address = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
  353. match length {
  354. 8 => Ok(self.handler.read_u8(address) as u64),
  355. 16 => Ok(self.handler.read_u16(address) as u64),
  356. 32 => Ok(self.handler.read_u32(address) as u64),
  357. 64 => Ok(self.handler.read_u64(address)),
  358. _ => Err(AmlError::FieldInvalidAccessSize),
  359. }
  360. }
  361. RegionSpace::SystemIo => {
  362. let port = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
  363. match length {
  364. 8 => Ok(self.handler.read_io_u8(port) as u64),
  365. 16 => Ok(self.handler.read_io_u16(port) as u64),
  366. 32 => Ok(self.handler.read_io_u32(port) as u64),
  367. _ => Err(AmlError::FieldInvalidAccessSize),
  368. }
  369. }
  370. RegionSpace::PciConfig => {
  371. /*
  372. * First, we need to get some extra information out of objects in the parent object. Both
  373. * `_SEG` and `_BBN` seem optional, with defaults that line up with legacy PCI implementations
  374. * (e.g. systems with a single segment group and a single root, respectively).
  375. */
  376. let parent_device = parent_device.as_ref().unwrap();
  377. let seg = match self.namespace.search(&AmlName::from_str("_SEG").unwrap(), parent_device) {
  378. Ok((_, handle)) => self
  379. .namespace
  380. .get(handle)?
  381. .as_integer(self)?
  382. .try_into()
  383. .map_err(|_| AmlError::FieldInvalidAddress)?,
  384. Err(AmlError::ValueDoesNotExist(_)) => 0,
  385. Err(err) => return Err(err),
  386. };
  387. let bbn = match self.namespace.search(&AmlName::from_str("_BBN").unwrap(), parent_device) {
  388. Ok((_, handle)) => self
  389. .namespace
  390. .get(handle)?
  391. .as_integer(self)?
  392. .try_into()
  393. .map_err(|_| AmlError::FieldInvalidAddress)?,
  394. Err(AmlError::ValueDoesNotExist(_)) => 0,
  395. Err(err) => return Err(err),
  396. };
  397. let adr = {
  398. let (_, handle) = self.namespace.search(&AmlName::from_str("_ADR").unwrap(), parent_device)?;
  399. self.namespace.get(handle)?.as_integer(self)?
  400. };
  401. let device = adr.get_bits(16..24) as u8;
  402. let function = adr.get_bits(0..8) as u8;
  403. let offset = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
  404. match length {
  405. 8 => Ok(self.handler.read_pci_u8(seg, bbn, device, function, offset) as u64),
  406. 16 => Ok(self.handler.read_pci_u16(seg, bbn, device, function, offset) as u64),
  407. 32 => Ok(self.handler.read_pci_u32(seg, bbn, device, function, offset) as u64),
  408. _ => Err(AmlError::FieldInvalidAccessSize),
  409. }
  410. }
  411. // TODO
  412. _ => unimplemented!(),
  413. }
  414. }
  415. pub(crate) fn write_region(
  416. &mut self,
  417. region_handle: AmlHandle,
  418. offset: u64,
  419. length: u64,
  420. value: u64,
  421. ) -> Result<(), AmlError> {
  422. use bit_field::BitField;
  423. use core::convert::TryInto;
  424. use value::RegionSpace;
  425. let (region_space, region_base, region_length, parent_device) = {
  426. if let AmlValue::OpRegion { region, offset, length, parent_device } =
  427. self.namespace.get(region_handle)?
  428. {
  429. (region, offset, length, parent_device)
  430. } else {
  431. return Err(AmlError::FieldRegionIsNotOpRegion);
  432. }
  433. };
  434. match region_space {
  435. RegionSpace::SystemMemory => {
  436. let address = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
  437. match length {
  438. 8 => Ok(self.handler.write_u8(address, value as u8)),
  439. 16 => Ok(self.handler.write_u16(address, value as u16)),
  440. 32 => Ok(self.handler.write_u32(address, value as u32)),
  441. 64 => Ok(self.handler.write_u64(address, value)),
  442. _ => Err(AmlError::FieldInvalidAccessSize),
  443. }
  444. }
  445. RegionSpace::SystemIo => {
  446. let port = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
  447. match length {
  448. 8 => Ok(self.handler.write_io_u8(port, value as u8)),
  449. 16 => Ok(self.handler.write_io_u16(port, value as u16)),
  450. 32 => Ok(self.handler.write_io_u32(port, value as u32)),
  451. _ => Err(AmlError::FieldInvalidAccessSize),
  452. }
  453. }
  454. RegionSpace::PciConfig => {
  455. /*
  456. * First, we need to get some extra information out of objects in the parent object. Both
  457. * `_SEG` and `_BBN` seem optional, with defaults that line up with legacy PCI implementations
  458. * (e.g. systems with a single segment group and a single root, respectively).
  459. */
  460. let parent_device = parent_device.as_ref().unwrap();
  461. let seg = match self.namespace.search(&AmlName::from_str("_SEG").unwrap(), parent_device) {
  462. Ok((_, handle)) => self
  463. .namespace
  464. .get(handle)?
  465. .as_integer(self)?
  466. .try_into()
  467. .map_err(|_| AmlError::FieldInvalidAddress)?,
  468. Err(AmlError::ValueDoesNotExist(_)) => 0,
  469. Err(err) => return Err(err),
  470. };
  471. let bbn = match self.namespace.search(&AmlName::from_str("_BBN").unwrap(), parent_device) {
  472. Ok((_, handle)) => self
  473. .namespace
  474. .get(handle)?
  475. .as_integer(self)?
  476. .try_into()
  477. .map_err(|_| AmlError::FieldInvalidAddress)?,
  478. Err(AmlError::ValueDoesNotExist(_)) => 0,
  479. Err(err) => return Err(err),
  480. };
  481. let adr = {
  482. let (_, handle) = self.namespace.search(&AmlName::from_str("_ADR").unwrap(), parent_device)?;
  483. self.namespace.get(handle)?.as_integer(self)?
  484. };
  485. let device = adr.get_bits(16..24) as u8;
  486. let function = adr.get_bits(0..8) as u8;
  487. let offset = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
  488. match length {
  489. 8 => Ok(self.handler.write_pci_u8(seg, bbn, device, function, offset, value as u8)),
  490. 16 => Ok(self.handler.write_pci_u16(seg, bbn, device, function, offset, value as u16)),
  491. 32 => Ok(self.handler.write_pci_u32(seg, bbn, device, function, offset, value as u32)),
  492. _ => Err(AmlError::FieldInvalidAccessSize),
  493. }
  494. }
  495. // TODO
  496. _ => unimplemented!(),
  497. }
  498. }
  499. fn add_predefined_objects(&mut self) {
  500. /*
  501. * In the dark ages of ACPI 1.0, before `\_OSI`, `\_OS` was used to communicate to the firmware which OS
  502. * was running. This was predictably not very good, and so was replaced in ACPI 3.0 with `_OSI`, which
  503. * allows support for individual capabilities to be queried. `_OS` should not be used by modern firmwares,
  504. * but to avoid problems we follow Linux in returning `"Microsoft Windows NT"`.
  505. *
  506. * See https://www.kernel.org/doc/html/latest/firmware-guide/acpi/osi.html for more information.
  507. */
  508. self.namespace
  509. .add_value(AmlName::from_str("\\_OS").unwrap(), AmlValue::String("Microsoft Windows NT".to_string()))
  510. .unwrap();
  511. /*
  512. * `\_OSI` was introduced by ACPI 3.0 to improve the situation created by `\_OS`. Unfortunately, exactly
  513. * the same problem was immediately repeated by introducing capabilities reflecting that an ACPI
  514. * implementation is exactly the same as a particular version of Windows' (e.g. firmwares will call
  515. * `\_OSI("Windows 2001")`).
  516. *
  517. * We basically follow suit with whatever Linux does, as this will hopefully minimise breakage:
  518. * - We always claim `Windows *` compatability
  519. * - We answer 'yes' to `_OSI("Darwin")
  520. * - We answer 'no' to `_OSI("Linux")`, and report that the tables are doing the wrong thing
  521. */
  522. // TODO
  523. // self.namespace.add_value(AmlName::from_str("\\_OSI").unwrap(), todo!()).unwrap();
  524. /*
  525. * `\_REV` evaluates to the version of the ACPI specification supported by this interpreter. Linux did this
  526. * correctly until 2015, but firmwares misused this to detect Linux (as even modern versions of Windows
  527. * return `2`), and so they switched to just returning `2` (as we'll also do). `_REV` should be considered
  528. * useless and deprecated (this is mirrored in newer specs, which claim `2` means "ACPI 2 or greater").
  529. */
  530. self.namespace.add_value(AmlName::from_str("\\_REV").unwrap(), AmlValue::Integer(2)).unwrap();
  531. }
  532. }
  533. // TODO: docs
  534. pub trait Handler {
  535. fn read_u8(&self, address: usize) -> u8;
  536. fn read_u16(&self, address: usize) -> u16;
  537. fn read_u32(&self, address: usize) -> u32;
  538. fn read_u64(&self, address: usize) -> u64;
  539. fn write_u8(&mut self, address: usize, value: u8);
  540. fn write_u16(&mut self, address: usize, value: u16);
  541. fn write_u32(&mut self, address: usize, value: u32);
  542. fn write_u64(&mut self, address: usize, value: u64);
  543. fn read_io_u8(&self, port: u16) -> u8;
  544. fn read_io_u16(&self, port: u16) -> u16;
  545. fn read_io_u32(&self, port: u16) -> u32;
  546. fn write_io_u8(&self, port: u16, value: u8);
  547. fn write_io_u16(&self, port: u16, value: u16);
  548. fn write_io_u32(&self, port: u16, value: u32);
  549. fn read_pci_u8(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16) -> u8;
  550. fn read_pci_u16(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16) -> u16;
  551. fn read_pci_u32(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16) -> u32;
  552. fn write_pci_u8(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16, value: u8);
  553. fn write_pci_u16(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16, value: u16);
  554. fn write_pci_u32(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16, value: u32);
  555. }
  556. #[derive(Clone, Debug, PartialEq, Eq)]
  557. pub enum AmlError {
  558. /*
  559. * Errors produced parsing the AML stream.
  560. */
  561. UnexpectedEndOfStream,
  562. UnexpectedByte(u8),
  563. InvalidNameSeg,
  564. InvalidPkgLength,
  565. InvalidFieldFlags,
  566. IncompatibleValueConversion,
  567. UnterminatedStringConstant,
  568. InvalidStringConstant,
  569. InvalidRegionSpace(u8),
  570. /// Produced when a `DefPackage` contains a different number of elements to the package's length.
  571. MalformedPackage,
  572. /// Produced when a `DefBuffer` contains more bytes that its size.
  573. MalformedBuffer,
  574. /// Emitted by a parser when it's clear that the stream doesn't encode the object parsed by
  575. /// that parser (e.g. the wrong opcode starts the stream). This is handled specially by some
  576. /// parsers such as `or` and `choice!`.
  577. WrongParser,
  578. /*
  579. * Errors produced manipulating AML names.
  580. */
  581. EmptyNamesAreInvalid,
  582. /// Produced when trying to normalize a path that does not point to a valid level of the
  583. /// namespace. E.g. `\_SB.^^PCI0` goes above the root of the namespace. The contained value is the name that
  584. /// normalization was attempted upon.
  585. InvalidNormalizedName(AmlName),
  586. RootHasNoParent,
  587. /*
  588. * Errors produced working with the namespace.
  589. */
  590. /// Produced when a sub-level or value is added to a level that has not yet been added to the namespace. The
  591. /// `AmlName` is the name of the entire sub-level/value.
  592. LevelDoesNotExist(AmlName),
  593. ValueDoesNotExist(AmlName),
  594. /// Produced when two values with the same name are added to the namespace.
  595. NameCollision(AmlName),
  596. TriedToRemoveRootNamespace,
  597. /*
  598. * Errors produced executing control methods.
  599. */
  600. /// Produced when AML tries to do something only possible in a control method (e.g. read from an argument)
  601. /// when there's no control method executing.
  602. NotExecutingControlMethod,
  603. /// Produced when a method accesses an argument it does not have (e.g. a method that takes 2
  604. /// arguments accesses `Arg4`). The inner value is the number of the argument accessed.
  605. InvalidArgAccess(ArgNum),
  606. /// Produced when a method accesses a local that it has not stored into.
  607. InvalidLocalAccess(LocalNum),
  608. /// This is not a real error, but is used to propagate return values from within the deep
  609. /// parsing call-stack. It should only be emitted when parsing a `DefReturn`. We use the
  610. /// error system here because the way errors are propagated matches how we want to handle
  611. /// return values.
  612. Return(AmlValue),
  613. /*
  614. * Errors produced parsing the PCI routing tables (_PRT objects).
  615. */
  616. PrtInvalidAddress,
  617. PrtInvalidPin,
  618. PrtInvalidSource,
  619. PrtInvalidGsi,
  620. /// Produced when the PRT doesn't contain an entry for the requested address + pin
  621. PrtNoEntry,
  622. /*
  623. * Errors produced parsing Resource Descriptors.
  624. */
  625. ReservedResourceType,
  626. ResourceDescriptorTooShort,
  627. ResourceDescriptorTooLong,
  628. /*
  629. * Errors produced working with AML values.
  630. */
  631. InvalidStatusObject,
  632. InvalidShiftLeft,
  633. InvalidShiftRight,
  634. FieldRegionIsNotOpRegion,
  635. FieldInvalidAddress,
  636. FieldInvalidAccessSize,
  637. TypeCannotBeCompared(AmlType),
  638. }