value.rs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. use crate::{name_object::AmlName, AmlError};
  2. use alloc::{boxed::Box, string::String, vec::Vec};
  3. use bit_field::BitField;
  4. #[derive(Clone, Copy, PartialEq, Eq, Debug)]
  5. pub enum RegionSpace {
  6. SystemMemory,
  7. SystemIo,
  8. PciConfig,
  9. EmbeddedControl,
  10. SMBus,
  11. SystemCmos,
  12. PciBarTarget,
  13. IPMI,
  14. GeneralPurposeIo,
  15. GenericSerialBus,
  16. OemDefined(u8),
  17. }
  18. #[derive(Clone, Copy, PartialEq, Eq, Debug)]
  19. pub enum FieldAccessType {
  20. Any,
  21. Byte,
  22. Word,
  23. DWord,
  24. QWord,
  25. Buffer,
  26. Reserved,
  27. }
  28. #[derive(Clone, Copy, PartialEq, Eq, Debug)]
  29. pub enum FieldUpdateRule {
  30. Preserve,
  31. WriteAsOnes,
  32. WriteAsZeros,
  33. }
  34. // TODO: custom debug impl
  35. #[derive(Clone, Copy, PartialEq, Eq, Debug)]
  36. pub struct FieldFlags(u8);
  37. impl FieldFlags {
  38. pub fn new(value: u8) -> FieldFlags {
  39. FieldFlags(value)
  40. }
  41. pub fn access_type(&self) -> Result<FieldAccessType, AmlError> {
  42. match self.0.get_bits(0..4) {
  43. 0 => Ok(FieldAccessType::Any),
  44. 1 => Ok(FieldAccessType::Byte),
  45. 2 => Ok(FieldAccessType::Word),
  46. 3 => Ok(FieldAccessType::DWord),
  47. 4 => Ok(FieldAccessType::QWord),
  48. 5 => Ok(FieldAccessType::Buffer),
  49. _ => Err(AmlError::InvalidFieldFlags),
  50. }
  51. }
  52. pub fn lock_rule(&self) -> bool {
  53. self.0.get_bit(4)
  54. }
  55. pub fn field_update_rule(&self) -> Result<FieldUpdateRule, AmlError> {
  56. match self.0.get_bits(5..7) {
  57. 0 => Ok(FieldUpdateRule::Preserve),
  58. 1 => Ok(FieldUpdateRule::WriteAsOnes),
  59. 2 => Ok(FieldUpdateRule::WriteAsZeros),
  60. _ => Err(AmlError::InvalidFieldFlags),
  61. }
  62. }
  63. }
  64. #[derive(Clone, Copy, PartialEq, Eq, Debug)]
  65. pub struct MethodFlags(u8);
  66. impl MethodFlags {
  67. pub fn new(value: u8) -> MethodFlags {
  68. MethodFlags(value)
  69. }
  70. pub fn arg_count(&self) -> u8 {
  71. self.0.get_bits(0..3)
  72. }
  73. pub fn serialize(&self) -> bool {
  74. self.0.get_bit(3)
  75. }
  76. pub fn sync_level(&self) -> u8 {
  77. self.0.get_bits(4..8)
  78. }
  79. }
  80. #[derive(Clone, PartialEq, Eq, Debug)]
  81. pub enum AmlValue {
  82. Integer(u64),
  83. String(String),
  84. Name(Box<AmlValue>),
  85. OpRegion { region: RegionSpace, offset: u64, length: u64 },
  86. Field { region: AmlName, flags: FieldFlags, offset: u64, length: u64 },
  87. Device,
  88. Method { flags: MethodFlags, code: Vec<u8> },
  89. Buffer { bytes: Vec<u8>, size: u64 },
  90. Processor { id: u8, pblk_address: u32, pblk_len: u8 },
  91. Mutex { sync_level: u8 },
  92. Package(Vec<AmlValue>),
  93. }
  94. impl AmlValue {
  95. pub fn as_integer(&self) -> Result<u64, AmlError> {
  96. match self {
  97. AmlValue::Integer(value) => Ok(*value),
  98. AmlValue::Buffer { size, ref bytes } => {
  99. /*
  100. * "The first 8 bytes of the buffer are converted to an integer, taking the first
  101. * byte as the least significant byte of the integer. A zero-length buffer is
  102. * illegal." - §19.6.140
  103. *
  104. * XXX: We return `0` for zero-length buffers because they literally occur in
  105. * the reference implementation.
  106. */
  107. let bytes = if bytes.len() > 8 { &bytes[0..8] } else { bytes };
  108. Ok(bytes.iter().rev().fold(0: u64, |mut i, &popped| {
  109. i <<= 8;
  110. i += popped as u64;
  111. i
  112. }))
  113. }
  114. _ => Err(AmlError::IncompatibleValueConversion),
  115. }
  116. }
  117. }