value.rs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. use crate::{misc::ArgNum, namespace::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, Copy, PartialEq, Eq, Debug)]
  81. pub enum AmlType {
  82. Uninitialized,
  83. Buffer,
  84. BufferField,
  85. /// Handle to a definition block handle. Returned by the `Load` operator.
  86. DdbHandle,
  87. DebugObject,
  88. Device,
  89. Event,
  90. FieldUnit,
  91. Integer,
  92. Method,
  93. Mutex,
  94. ObjReference,
  95. OpRegion,
  96. Package,
  97. PowerResource,
  98. Processor,
  99. RawDataBuffer,
  100. String,
  101. ThermalZone,
  102. }
  103. #[derive(Clone, PartialEq, Eq, Debug)]
  104. pub enum AmlValue {
  105. Boolean(bool),
  106. Integer(u64),
  107. String(String),
  108. Name(Box<AmlValue>),
  109. OpRegion { region: RegionSpace, offset: u64, length: u64 },
  110. Field { region: AmlName, flags: FieldFlags, offset: u64, length: u64 },
  111. Device,
  112. Method { flags: MethodFlags, code: Vec<u8> },
  113. Buffer { bytes: Vec<u8>, size: u64 },
  114. Processor { id: u8, pblk_address: u32, pblk_len: u8 },
  115. Mutex { sync_level: u8 },
  116. Package(Vec<AmlValue>),
  117. }
  118. impl AmlValue {
  119. /// Returns the AML type of this value. For `Name`, this returns the type of the inner value.
  120. pub fn type_of(&self) -> AmlType {
  121. match self {
  122. AmlValue::Boolean(_) => AmlType::Integer,
  123. AmlValue::Integer(_) => AmlType::Integer,
  124. AmlValue::String(_) => AmlType::String,
  125. AmlValue::Name(boxed_value) => boxed_value.type_of(),
  126. AmlValue::OpRegion { .. } => AmlType::OpRegion,
  127. AmlValue::Field { .. } => AmlType::FieldUnit,
  128. AmlValue::Device => AmlType::Device,
  129. AmlValue::Method { .. } => AmlType::Method,
  130. AmlValue::Buffer { .. } => AmlType::Buffer,
  131. AmlValue::Processor { .. } => AmlType::Processor,
  132. AmlValue::Mutex { .. } => AmlType::Mutex,
  133. AmlValue::Package(_) => AmlType::Package,
  134. }
  135. }
  136. pub fn as_bool(&self) -> Result<bool, AmlError> {
  137. match self {
  138. AmlValue::Boolean(value) => Ok(*value),
  139. _ => Err(AmlError::IncompatibleValueConversion),
  140. }
  141. }
  142. pub fn as_integer(&self) -> Result<u64, AmlError> {
  143. match self {
  144. AmlValue::Integer(value) => Ok(*value),
  145. AmlValue::Buffer { ref bytes, .. } => {
  146. /*
  147. * "The first 8 bytes of the buffer are converted to an integer, taking the first
  148. * byte as the least significant byte of the integer. A zero-length buffer is
  149. * illegal." - §19.6.140
  150. *
  151. * XXX: We return `0` for zero-length buffers because they literally occur in
  152. * the reference implementation.
  153. */
  154. let bytes = if bytes.len() > 8 { &bytes[0..8] } else { bytes };
  155. Ok(bytes.iter().rev().fold(0: u64, |mut i, &popped| {
  156. i <<= 8;
  157. i += popped as u64;
  158. i
  159. }))
  160. }
  161. _ => Err(AmlError::IncompatibleValueConversion),
  162. }
  163. }
  164. /// Convert this value to a value of the same data, but with the given AML type, if possible,
  165. /// by converting the implicit conversions described in §19.3.5 of the spec.
  166. ///
  167. /// The implicit conversions applied are:
  168. /// `Buffer` from: `Integer`, `String`, `Debug`
  169. /// `BufferField` from: `Integer`, `Buffer`, `String`, `Debug`
  170. /// `DdbHandle` from: `Integer`, `Debug`
  171. /// `FieldUnit` from: `Integer`,`Buffer`, `String`, `Debug`
  172. /// `Integer` from: `Buffer`, `BufferField`, `DdbHandle`, `FieldUnit`, `String`, `Debug`
  173. /// `Package` from: `Debug`
  174. /// `String` from: `Integer`, `Buffer`, `Debug`
  175. pub fn as_type(&self, desired_type: AmlType) -> Result<AmlValue, AmlError> {
  176. // Cache the type of this object
  177. let our_type = self.type_of();
  178. // If the value is already of the correct type, just return it as is
  179. if our_type == desired_type {
  180. return Ok(self.clone());
  181. }
  182. // TODO: implement all of the rules
  183. match desired_type {
  184. AmlType::Integer => self.as_integer().map(|value| AmlValue::Integer(value)),
  185. _ => Err(AmlError::IncompatibleValueConversion),
  186. }
  187. }
  188. }
  189. /// A control method can take up to 7 arguments, each of which can be an `AmlValue`.
  190. #[derive(Clone, Debug, Default)]
  191. pub struct Args {
  192. pub arg_0: Option<AmlValue>,
  193. pub arg_1: Option<AmlValue>,
  194. pub arg_2: Option<AmlValue>,
  195. pub arg_3: Option<AmlValue>,
  196. pub arg_4: Option<AmlValue>,
  197. pub arg_5: Option<AmlValue>,
  198. pub arg_6: Option<AmlValue>,
  199. }
  200. impl Args {
  201. /// Get an argument by its `ArgNum`.
  202. ///
  203. /// ### Panics
  204. /// Panics if passed an invalid argument number (valid argument numbers are `0..=6`)
  205. pub fn arg(&self, num: ArgNum) -> Result<&AmlValue, AmlError> {
  206. match num {
  207. 0 => self.arg_0.as_ref().ok_or(AmlError::InvalidArgumentAccess(num)),
  208. 1 => self.arg_1.as_ref().ok_or(AmlError::InvalidArgumentAccess(num)),
  209. 2 => self.arg_2.as_ref().ok_or(AmlError::InvalidArgumentAccess(num)),
  210. 3 => self.arg_3.as_ref().ok_or(AmlError::InvalidArgumentAccess(num)),
  211. 4 => self.arg_4.as_ref().ok_or(AmlError::InvalidArgumentAccess(num)),
  212. 5 => self.arg_5.as_ref().ok_or(AmlError::InvalidArgumentAccess(num)),
  213. 6 => self.arg_6.as_ref().ok_or(AmlError::InvalidArgumentAccess(num)),
  214. _ => panic!("Invalid argument number: {}", num),
  215. }
  216. }
  217. }