type2.rs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. use crate::{
  2. name_object::{name_string, super_name, target},
  3. opcode::{self, opcode},
  4. parser::{
  5. choice,
  6. comment_scope,
  7. id,
  8. make_parser_concrete,
  9. take,
  10. take_to_end_of_pkglength,
  11. try_with_context,
  12. Parser,
  13. },
  14. pkg_length::pkg_length,
  15. term_object::{data_ref_object, term_arg},
  16. value::AmlValue,
  17. AmlError,
  18. DebugVerbosity,
  19. };
  20. use alloc::vec::Vec;
  21. use core::convert::TryInto;
  22. /// Type 2 opcodes return a value and so can be used in expressions.
  23. pub fn type2_opcode<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  24. where
  25. 'c: 'a,
  26. {
  27. /*
  28. * Type2Opcode := DefAquire | DefAdd | DefAnd | DefBuffer | DefConcat | DefConcatRes |
  29. * DefCondRefOf | DefCopyObject | DefDecrement | DefDerefOf | DefDivide |
  30. * DefFindSetLeftBit | DefFindSetRightBit | DefFromBCD | DefIncrement | DefIndex |
  31. * DefLAnd | DefLEqual | DefLGreater | DefLGreaterEqual | DefLLess | DefLLessEqual |
  32. * DefMid | DefLNot | DefLNotEqual | DefLoadTable | DefLOr | DefMatch | DefMod |
  33. * DefMultiply | DefNAnd | DefNOr | DefNot | DefObjectType | DefOr | DefPackage |
  34. * DefVarPackage | DefRefOf | DefShiftLeft | DefShitRight | DefSizeOf | DefStore |
  35. * DefSubtract | DefTimer | DefToBCD | DefToBuffer | DefToDecimalString |
  36. * DefToHexString | DefToInteger | DefToString | DefWait | DefXOr | MethodInvocation
  37. *
  38. * NOTE: MethodInvocation should always appear last in the choice.
  39. */
  40. make_parser_concrete!(comment_scope(
  41. DebugVerbosity::AllScopes,
  42. "Type2Opcode",
  43. choice!(
  44. def_buffer(),
  45. def_l_equal(),
  46. def_package(),
  47. def_shift_left(),
  48. def_shift_right(),
  49. def_store(),
  50. method_invocation()
  51. ),
  52. ))
  53. }
  54. pub fn def_buffer<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  55. where
  56. 'c: 'a,
  57. {
  58. /*
  59. * DefBuffer := 0x11 PkgLength BufferSize ByteList
  60. * BufferSize := TermArg => Integer
  61. *
  62. * XXX: The spec says that zero-length buffers (e.g. the PkgLength is 0) are illegal, but
  63. * we've encountered them in QEMU-generated tables, so we return an empty buffer in these
  64. * cases.
  65. */
  66. opcode(opcode::DEF_BUFFER_OP)
  67. .then(comment_scope(
  68. DebugVerbosity::AllScopes,
  69. "DefBuffer",
  70. pkg_length().then(term_arg()).feed(|(pkg_length, buffer_size)| {
  71. take_to_end_of_pkglength(pkg_length).map_with_context(move |bytes, context| {
  72. let length = try_with_context!(context, buffer_size.as_integer(context));
  73. (Ok((bytes.to_vec(), length)), context)
  74. })
  75. }),
  76. ))
  77. .map(|((), (bytes, buffer_size))| Ok(AmlValue::Buffer { bytes, size: buffer_size }))
  78. }
  79. fn def_l_equal<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  80. where
  81. 'c: 'a,
  82. {
  83. /*
  84. * DefLEqual := 0x93 Operand Operand
  85. * Operand := TermArg => Integer
  86. */
  87. opcode(opcode::DEF_L_EQUAL_OP)
  88. .then(comment_scope(
  89. DebugVerbosity::AllScopes,
  90. "DefLEqual",
  91. term_arg().then(term_arg()).map_with_context(|(left_arg, right_arg), context| {
  92. let left = try_with_context!(context, left_arg.as_integer(context));
  93. let right = try_with_context!(context, right_arg.as_integer(context));
  94. (Ok(AmlValue::Boolean(left == right)), context)
  95. }),
  96. ))
  97. .map(|((), result)| Ok(result))
  98. }
  99. pub fn def_package<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  100. where
  101. 'c: 'a,
  102. {
  103. /*
  104. * DefPackage := 0x12 PkgLength NumElements PackageElementList
  105. * NumElements := ByteData
  106. * PackageElementList := Nothing | <PackageElement PackageElementList>
  107. * PackageElement := DataRefObject | NameString
  108. */
  109. opcode(opcode::DEF_PACKAGE_OP)
  110. .then(comment_scope(
  111. DebugVerbosity::AllScopes,
  112. "DefPackage",
  113. pkg_length().then(take()).feed(|(pkg_length, num_elements)| {
  114. move |mut input, mut context| {
  115. let mut package_contents = Vec::new();
  116. while pkg_length.still_parsing(input) {
  117. let (new_input, new_context, value) = package_element().parse(input, context)?;
  118. input = new_input;
  119. context = new_context;
  120. package_contents.push(value);
  121. }
  122. assert_eq!(package_contents.len(), num_elements as usize);
  123. Ok((input, context, AmlValue::Package(package_contents)))
  124. }
  125. }),
  126. ))
  127. .map(|((), package)| Ok(package))
  128. }
  129. pub fn package_element<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  130. where
  131. 'c: 'a,
  132. {
  133. choice!(data_ref_object(), name_string().map(|string| Ok(AmlValue::String(string.as_string()))))
  134. }
  135. fn def_shift_left<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  136. where
  137. 'c: 'a,
  138. {
  139. /*
  140. * DefShiftLeft := 0x79 Operand ShiftCount Target
  141. * Operand := TermArg => Integer
  142. * ShiftCount := TermArg => Integer
  143. */
  144. opcode(opcode::DEF_SHIFT_LEFT)
  145. .then(comment_scope(DebugVerbosity::Scopes, "DefShiftLeft", term_arg().then(term_arg()).then(target())))
  146. .map_with_context(|((), ((operand, shift_count), target)), context| {
  147. let operand = try_with_context!(context, operand.as_integer(context));
  148. let shift_count = try_with_context!(context, shift_count.as_integer(context));
  149. let shift_count =
  150. try_with_context!(context, shift_count.try_into().map_err(|_| AmlError::InvalidShiftLeft));
  151. let result = AmlValue::Integer(try_with_context!(
  152. context,
  153. operand.checked_shl(shift_count).ok_or(AmlError::InvalidShiftLeft)
  154. ));
  155. try_with_context!(context, context.store(target, result.clone()));
  156. (Ok(result), context)
  157. })
  158. }
  159. fn def_shift_right<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  160. where
  161. 'c: 'a,
  162. {
  163. /*
  164. * DefShiftRight := 0x7a Operand ShiftCount Target
  165. * Operand := TermArg => Integer
  166. * ShiftCount := TermArg => Integer
  167. */
  168. opcode(opcode::DEF_SHIFT_RIGHT)
  169. .then(comment_scope(DebugVerbosity::Scopes, "DefShiftRight", term_arg().then(term_arg()).then(target())))
  170. .map_with_context(|((), ((operand, shift_count), target)), context| {
  171. let operand = try_with_context!(context, operand.as_integer(context));
  172. let shift_count = try_with_context!(context, shift_count.as_integer(context));
  173. let shift_count =
  174. try_with_context!(context, shift_count.try_into().map_err(|_| AmlError::InvalidShiftRight));
  175. let result = AmlValue::Integer(try_with_context!(
  176. context,
  177. operand.checked_shr(shift_count).ok_or(AmlError::InvalidShiftRight)
  178. ));
  179. try_with_context!(context, context.store(target, result.clone()));
  180. (Ok(result), context)
  181. })
  182. }
  183. fn def_store<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  184. where
  185. 'c: 'a,
  186. {
  187. /*
  188. * DefStore := 0x70 TermArg SuperName
  189. *
  190. * Implicit conversion is only applied when the destination target is a `Name` - not when we
  191. * are storing into a method local or argument (these stores are semantically identical to
  192. * CopyObject). We must also make sure to return a copy of the data that is in the destination
  193. * after the store (as opposed to the data we think we put into it), because some stores can
  194. * alter the data during the store.
  195. */
  196. opcode(opcode::DEF_STORE_OP)
  197. .then(comment_scope(DebugVerbosity::Scopes, "DefStore", term_arg().then(super_name())))
  198. .map_with_context(|((), (value, target)), context| {
  199. (Ok(try_with_context!(context, context.store(target, value))), context)
  200. })
  201. }
  202. fn method_invocation<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  203. where
  204. 'c: 'a,
  205. {
  206. /*
  207. * MethodInvocation := NameString TermArgList
  208. *
  209. * MethodInvocation is the worst of the AML structures, because you're meant to figure out how much you're
  210. * meant to parse using the name of the method (by knowing from its definition how how many arguments it
  211. * takes). However, the definition of a method can in theory appear after an invocation of that method, and
  212. * so parsing them properly can be very difficult.
  213. * NOTE: We don't support the case of the definition appearing after the invocation.
  214. */
  215. comment_scope(
  216. DebugVerbosity::Scopes,
  217. "MethodInvocation",
  218. name_string()
  219. .map_with_context(move |name, context| {
  220. let (_, handle) =
  221. try_with_context!(context, context.namespace.search(&name, &context.current_scope)).clone();
  222. (Ok(handle), context)
  223. })
  224. .feed(|handle| {
  225. id().map_with_context(move |(), context| {
  226. let object = try_with_context!(context, context.namespace.get(handle));
  227. if let AmlValue::Method { ref code, .. } = object {
  228. // TODO: we need to allow a method to be invoked from inside another method before we can
  229. // implement this (basically a stack of contexts) then implement this
  230. unimplemented!()
  231. } else {
  232. // We appear to be seeing AML where a MethodInvocation actually doesn't point to a method
  233. // at all, which isn't mentioned in the spec afaict. However, if we treat it as an
  234. // "invocation" with 0 arguments and simply return the object, the AML seems to do sensible
  235. // things.
  236. (Ok(object.clone()), context)
  237. }
  238. })
  239. }),
  240. )
  241. }