value.rs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. use crate::{
  2. misc::ArgNum,
  3. namespace::AmlName,
  4. parser::Parser,
  5. pkg_length::PkgLength,
  6. term_object::term_list,
  7. AmlContext,
  8. AmlError,
  9. };
  10. use alloc::{boxed::Box, string::String, vec::Vec};
  11. use bit_field::BitField;
  12. use log::{error, info};
  13. #[derive(Clone, Copy, PartialEq, Eq, Debug)]
  14. pub enum RegionSpace {
  15. SystemMemory,
  16. SystemIo,
  17. PciConfig,
  18. EmbeddedControl,
  19. SMBus,
  20. SystemCmos,
  21. PciBarTarget,
  22. IPMI,
  23. GeneralPurposeIo,
  24. GenericSerialBus,
  25. OemDefined(u8),
  26. }
  27. #[derive(Clone, Copy, PartialEq, Eq, Debug)]
  28. pub enum FieldAccessType {
  29. Any,
  30. Byte,
  31. Word,
  32. DWord,
  33. QWord,
  34. Buffer,
  35. Reserved,
  36. }
  37. #[derive(Clone, Copy, PartialEq, Eq, Debug)]
  38. pub enum FieldUpdateRule {
  39. Preserve,
  40. WriteAsOnes,
  41. WriteAsZeros,
  42. }
  43. // TODO: custom debug impl
  44. #[derive(Clone, Copy, PartialEq, Eq, Debug)]
  45. pub struct FieldFlags(u8);
  46. impl FieldFlags {
  47. pub fn new(value: u8) -> FieldFlags {
  48. FieldFlags(value)
  49. }
  50. pub fn access_type(&self) -> Result<FieldAccessType, AmlError> {
  51. match self.0.get_bits(0..4) {
  52. 0 => Ok(FieldAccessType::Any),
  53. 1 => Ok(FieldAccessType::Byte),
  54. 2 => Ok(FieldAccessType::Word),
  55. 3 => Ok(FieldAccessType::DWord),
  56. 4 => Ok(FieldAccessType::QWord),
  57. 5 => Ok(FieldAccessType::Buffer),
  58. _ => Err(AmlError::InvalidFieldFlags),
  59. }
  60. }
  61. pub fn lock_rule(&self) -> bool {
  62. self.0.get_bit(4)
  63. }
  64. pub fn field_update_rule(&self) -> Result<FieldUpdateRule, AmlError> {
  65. match self.0.get_bits(5..7) {
  66. 0 => Ok(FieldUpdateRule::Preserve),
  67. 1 => Ok(FieldUpdateRule::WriteAsOnes),
  68. 2 => Ok(FieldUpdateRule::WriteAsZeros),
  69. _ => Err(AmlError::InvalidFieldFlags),
  70. }
  71. }
  72. }
  73. #[derive(Clone, Copy, PartialEq, Eq, Debug)]
  74. pub struct MethodFlags(u8);
  75. impl MethodFlags {
  76. pub fn new(value: u8) -> MethodFlags {
  77. MethodFlags(value)
  78. }
  79. pub fn arg_count(&self) -> u8 {
  80. self.0.get_bits(0..3)
  81. }
  82. pub fn serialize(&self) -> bool {
  83. self.0.get_bit(3)
  84. }
  85. pub fn sync_level(&self) -> u8 {
  86. self.0.get_bits(4..8)
  87. }
  88. }
  89. #[derive(Clone, Copy, PartialEq, Eq, Debug)]
  90. pub enum AmlType {
  91. Uninitialized,
  92. Buffer,
  93. BufferField,
  94. /// Handle to a definition block handle. Returned by the `Load` operator.
  95. DdbHandle,
  96. DebugObject,
  97. Device,
  98. Event,
  99. FieldUnit,
  100. Integer,
  101. Method,
  102. Mutex,
  103. ObjReference,
  104. OpRegion,
  105. Package,
  106. PowerResource,
  107. Processor,
  108. RawDataBuffer,
  109. String,
  110. ThermalZone,
  111. }
  112. #[derive(Clone, PartialEq, Eq, Debug)]
  113. pub enum AmlValue {
  114. Boolean(bool),
  115. Integer(u64),
  116. String(String),
  117. Name(Box<AmlValue>),
  118. OpRegion { region: RegionSpace, offset: u64, length: u64 },
  119. Field { region: AmlName, flags: FieldFlags, offset: u64, length: u64 },
  120. Device,
  121. Method { flags: MethodFlags, code: Vec<u8> },
  122. Buffer { bytes: Vec<u8>, size: u64 },
  123. Processor { id: u8, pblk_address: u32, pblk_len: u8 },
  124. Mutex { sync_level: u8 },
  125. Package(Vec<AmlValue>),
  126. }
  127. impl AmlValue {
  128. /// Returns the AML type of this value. For `Name`, this returns the type of the inner value.
  129. pub fn type_of(&self) -> AmlType {
  130. match self {
  131. AmlValue::Boolean(_) => AmlType::Integer,
  132. AmlValue::Integer(_) => AmlType::Integer,
  133. AmlValue::String(_) => AmlType::String,
  134. AmlValue::Name(boxed_value) => boxed_value.type_of(),
  135. AmlValue::OpRegion { .. } => AmlType::OpRegion,
  136. AmlValue::Field { .. } => AmlType::FieldUnit,
  137. AmlValue::Device => AmlType::Device,
  138. AmlValue::Method { .. } => AmlType::Method,
  139. AmlValue::Buffer { .. } => AmlType::Buffer,
  140. AmlValue::Processor { .. } => AmlType::Processor,
  141. AmlValue::Mutex { .. } => AmlType::Mutex,
  142. AmlValue::Package(_) => AmlType::Package,
  143. }
  144. }
  145. pub fn as_bool(&self) -> Result<bool, AmlError> {
  146. match self {
  147. AmlValue::Boolean(value) => Ok(*value),
  148. _ => Err(AmlError::IncompatibleValueConversion),
  149. }
  150. }
  151. pub fn as_integer(&self) -> Result<u64, AmlError> {
  152. match self {
  153. AmlValue::Integer(value) => Ok(*value),
  154. AmlValue::Buffer { size, ref bytes } => {
  155. /*
  156. * "The first 8 bytes of the buffer are converted to an integer, taking the first
  157. * byte as the least significant byte of the integer. A zero-length buffer is
  158. * illegal." - §19.6.140
  159. *
  160. * XXX: We return `0` for zero-length buffers because they literally occur in
  161. * the reference implementation.
  162. */
  163. let bytes = if bytes.len() > 8 { &bytes[0..8] } else { bytes };
  164. Ok(bytes.iter().rev().fold(0: u64, |mut i, &popped| {
  165. i <<= 8;
  166. i += popped as u64;
  167. i
  168. }))
  169. }
  170. _ => Err(AmlError::IncompatibleValueConversion),
  171. }
  172. }
  173. /// Convert this value to a value of the same data, but with the given AML type, if possible,
  174. /// by converting the implicit conversions described in §19.3.5 of the spec.
  175. ///
  176. /// The implicit conversions applied are:
  177. /// `Buffer` from: `Integer`, `String`, `Debug`
  178. /// `BufferField` from: `Integer`, `Buffer`, `String`, `Debug`
  179. /// `DdbHandle` from: `Integer`, `Debug`
  180. /// `FieldUnit` from: `Integer`,`Buffer`, `String`, `Debug`
  181. /// `Integer` from: `Buffer`, `BufferField`, `DdbHandle`, `FieldUnit`, `String`, `Debug`
  182. /// `Package` from: `Debug`
  183. /// `String` from: `Integer`, `Buffer`, `Debug`
  184. pub fn as_type(&self, desired_type: AmlType) -> Result<AmlValue, AmlError> {
  185. // Cache the type of this object
  186. let our_type = self.type_of();
  187. // If the value is already of the correct type, just return it as is
  188. if our_type == desired_type {
  189. return Ok(self.clone());
  190. }
  191. // TODO: implement all of the rules
  192. match desired_type {
  193. AmlType::Integer => self.as_integer().map(|value| AmlValue::Integer(value)),
  194. _ => Err(AmlError::IncompatibleValueConversion),
  195. }
  196. }
  197. /// If this value is a control method, invoke it. Returns `AmlError::IncompatibleValueConversion` if this
  198. /// is not a method.
  199. pub fn invoke(&self, context: &mut AmlContext, args: Args, scope: AmlName) -> Result<AmlValue, AmlError> {
  200. if let AmlValue::Method { flags, ref code } = self {
  201. /*
  202. * First, set up the state we expect to enter the method with, but clearing local
  203. * variables to "null" and setting the arguments.
  204. */
  205. context.current_scope = scope;
  206. context.current_args = Some(args);
  207. context.local_0 = None;
  208. context.local_1 = None;
  209. context.local_2 = None;
  210. context.local_3 = None;
  211. context.local_4 = None;
  212. context.local_5 = None;
  213. context.local_6 = None;
  214. context.local_7 = None;
  215. let return_value =
  216. match term_list(PkgLength::from_raw_length(code, code.len() as u32)).parse(code, context) {
  217. // If the method doesn't return a value, we implicitly return `0`
  218. Ok((remaining, context, result)) => Ok(AmlValue::Integer(0)),
  219. Err((remaining, context, AmlError::Return(result))) => Ok(result),
  220. Err((remaining, context, err)) => {
  221. error!("Failed to execute control method: {:?}", err);
  222. Err(err)
  223. }
  224. };
  225. /*
  226. * Now clear the state.
  227. */
  228. context.current_args = None;
  229. context.local_0 = None;
  230. context.local_1 = None;
  231. context.local_2 = None;
  232. context.local_3 = None;
  233. context.local_4 = None;
  234. context.local_5 = None;
  235. context.local_6 = None;
  236. context.local_7 = None;
  237. return_value
  238. } else {
  239. Err(AmlError::IncompatibleValueConversion)
  240. }
  241. }
  242. }
  243. /// A control method can take up to 7 arguments, each of which can be an `AmlValue`.
  244. #[derive(Clone, Debug, Default)]
  245. pub struct Args {
  246. pub arg_0: Option<AmlValue>,
  247. pub arg_1: Option<AmlValue>,
  248. pub arg_2: Option<AmlValue>,
  249. pub arg_3: Option<AmlValue>,
  250. pub arg_4: Option<AmlValue>,
  251. pub arg_5: Option<AmlValue>,
  252. pub arg_6: Option<AmlValue>,
  253. }
  254. impl Args {
  255. /// Get an argument by its `ArgNum`.
  256. ///
  257. /// ### Panics
  258. /// Panics if passed an invalid argument number (valid argument numbers are `0..=6`)
  259. pub fn arg(&self, num: ArgNum) -> Result<&AmlValue, AmlError> {
  260. match num {
  261. 0 => self.arg_0.as_ref().ok_or(AmlError::InvalidArgumentAccess(num)),
  262. 1 => self.arg_1.as_ref().ok_or(AmlError::InvalidArgumentAccess(num)),
  263. 2 => self.arg_2.as_ref().ok_or(AmlError::InvalidArgumentAccess(num)),
  264. 3 => self.arg_3.as_ref().ok_or(AmlError::InvalidArgumentAccess(num)),
  265. 4 => self.arg_4.as_ref().ok_or(AmlError::InvalidArgumentAccess(num)),
  266. 5 => self.arg_5.as_ref().ok_or(AmlError::InvalidArgumentAccess(num)),
  267. 6 => self.arg_6.as_ref().ok_or(AmlError::InvalidArgumentAccess(num)),
  268. _ => panic!("Invalid argument number: {}", num),
  269. }
  270. }
  271. }