lib.rs 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. #![no_std]
  2. #![feature(decl_macro, type_ascription, box_syntax)]
  3. extern crate alloc;
  4. #[cfg(test)]
  5. extern crate std;
  6. #[cfg(test)]
  7. mod test_utils;
  8. pub(crate) mod name_object;
  9. pub(crate) mod opcode;
  10. pub(crate) mod parser;
  11. pub(crate) mod pkg_length;
  12. pub(crate) mod term_object;
  13. pub mod value;
  14. pub use crate::value::AmlValue;
  15. use alloc::collections::BTreeMap;
  16. use log::{error, trace};
  17. use name_object::AmlName;
  18. use parser::Parser;
  19. use pkg_length::PkgLength;
  20. /// AML has a `RevisionOp` operator that returns the "AML interpreter revision". It's not clear
  21. /// what this is actually used for, but this is ours.
  22. pub const AML_INTERPRETER_REVISION: u64 = 0;
  23. #[derive(Clone, Copy, Debug, PartialEq, Eq)]
  24. pub enum AmlError {
  25. UnexpectedEndOfStream,
  26. UnexpectedByte(u8),
  27. InvalidNameSeg([u8; 4]),
  28. InvalidFieldFlags,
  29. IncompatibleValueConversion,
  30. UnterminatedStringConstant,
  31. InvalidStringConstant,
  32. InvalidRegionSpace(u8),
  33. /// Error produced when none of the parsers in a `choice!` could parse the next part of the
  34. /// stream. Contains the next two bytes to make debugging missing extended opcodes easier.
  35. NoParsersCouldParse([u8; 2]),
  36. }
  37. #[derive(Debug)]
  38. pub struct AmlContext {
  39. namespace: BTreeMap<AmlName, AmlValue>,
  40. current_scope: AmlName,
  41. }
  42. impl AmlContext {
  43. pub fn new() -> AmlContext {
  44. AmlContext { namespace: BTreeMap::new(), current_scope: AmlName::root() }
  45. }
  46. pub fn parse_table(&mut self, stream: &[u8]) -> Result<(), AmlError> {
  47. if stream.len() == 0 {
  48. return Err(AmlError::UnexpectedEndOfStream);
  49. }
  50. let table_length = PkgLength::from_raw_length(stream, stream.len() as u32) as PkgLength;
  51. match term_object::term_list(table_length).parse(stream, self) {
  52. Ok(_) => Ok(()),
  53. Err((remaining, _context, err)) => {
  54. error!("Failed to parse AML stream. Err = {:?}", err);
  55. Err(err)
  56. }
  57. /// Resolves a given path relative to the current scope (if the given path is not absolute).
  58. /// The returned path can be used to index the namespace.
  59. pub fn resolve_path(&mut self, path: &AmlName) -> AmlName {
  60. // TODO: we should normalize the path by resolving prefix chars etc.
  61. // If the path is absolute, just return it.
  62. if path.is_absolute() {
  63. return path.clone();
  64. }
  65. // Otherwise, it's relative to the current scope so append it onto that.
  66. let mut new_path = self.current_scope.clone();
  67. new_path.0.extend_from_slice(&(path.0));
  68. new_path
  69. }
  70. /// Add an `AmlValue` to the namespace. `path` can either be absolute, or relative (in which
  71. /// case it's treated as relative to the current scope).
  72. pub fn add_to_namespace(&mut self, path: AmlName, value: AmlValue) {
  73. let resolved_path = self.resolve_path(&path);
  74. self.namespace.insert(resolved_path, value);
  75. }
  76. }