type2.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. use crate::{
  2. name_object::{name_string, super_name, target},
  3. opcode::{self, opcode},
  4. parser::{
  5. choice,
  6. comment_scope,
  7. make_parser_concrete,
  8. n_of,
  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, Args},
  17. AmlError,
  18. DebugVerbosity,
  19. };
  20. use alloc::vec::Vec;
  21. use core::{cmp::Ordering, 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. // TODO: we're struggling a little with the type limit here, is there a better way than making everything
  41. // concrete?
  42. make_parser_concrete!(comment_scope(
  43. DebugVerbosity::AllScopes,
  44. "Type2Opcode",
  45. choice!(
  46. make_parser_concrete!(def_and()),
  47. make_parser_concrete!(def_buffer()),
  48. make_parser_concrete!(def_l_equal()),
  49. make_parser_concrete!(def_l_greater()),
  50. make_parser_concrete!(def_l_greater_equal()),
  51. make_parser_concrete!(def_l_less()),
  52. make_parser_concrete!(def_l_less_equal()),
  53. make_parser_concrete!(def_l_not_equal()),
  54. make_parser_concrete!(def_l_or()),
  55. make_parser_concrete!(def_package()),
  56. make_parser_concrete!(def_shift_left()),
  57. make_parser_concrete!(def_shift_right()),
  58. make_parser_concrete!(def_store()),
  59. make_parser_concrete!(method_invocation())
  60. ),
  61. ))
  62. }
  63. pub fn def_and<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  64. where
  65. 'c: 'a,
  66. {
  67. /*
  68. * DefAnd := 0x7b Operand Operand Target
  69. * Operand := TermArg => Integer
  70. */
  71. opcode(opcode::DEF_AND_OP)
  72. .then(comment_scope(
  73. DebugVerbosity::AllScopes,
  74. "DefAnd",
  75. term_arg().then(term_arg()).then(target()).map_with_context(
  76. |((left_arg, right_arg), target), context| {
  77. let left = try_with_context!(context, left_arg.as_integer(context));
  78. let right = try_with_context!(context, right_arg.as_integer(context));
  79. (Ok(AmlValue::Integer(left & right)), context)
  80. },
  81. ),
  82. ))
  83. .map(|((), result)| Ok(result))
  84. }
  85. pub fn def_buffer<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  86. where
  87. 'c: 'a,
  88. {
  89. /*
  90. * DefBuffer := 0x11 PkgLength BufferSize ByteList
  91. * BufferSize := TermArg => Integer
  92. *
  93. * XXX: The spec says that zero-length buffers (e.g. the PkgLength is 0) are illegal, but
  94. * we've encountered them in QEMU-generated tables, so we return an empty buffer in these
  95. * cases.
  96. */
  97. opcode(opcode::DEF_BUFFER_OP)
  98. .then(comment_scope(
  99. DebugVerbosity::AllScopes,
  100. "DefBuffer",
  101. pkg_length().then(term_arg()).feed(|(pkg_length, buffer_size)| {
  102. take_to_end_of_pkglength(pkg_length).map_with_context(move |bytes, context| {
  103. let length = try_with_context!(context, buffer_size.as_integer(context));
  104. (Ok((bytes.to_vec(), length)), context)
  105. })
  106. }),
  107. ))
  108. .map(|((), (bytes, buffer_size))| Ok(AmlValue::Buffer { bytes, size: buffer_size }))
  109. }
  110. fn def_l_or<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  111. where
  112. 'c: 'a,
  113. {
  114. /*
  115. * DefLOr := 0x91 Operand Operand
  116. * Operand := TermArg => Integer
  117. */
  118. opcode(opcode::DEF_L_OR_OP)
  119. .then(comment_scope(
  120. DebugVerbosity::AllScopes,
  121. "DefLOr",
  122. term_arg().then(term_arg()).map_with_context(|(left_arg, right_arg), context| {
  123. let left = try_with_context!(context, left_arg.as_bool());
  124. let right = try_with_context!(context, right_arg.as_bool());
  125. (Ok(AmlValue::Boolean(left || right)), context)
  126. }),
  127. ))
  128. .map(|((), result)| Ok(result))
  129. }
  130. fn def_l_equal<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  131. where
  132. 'c: 'a,
  133. {
  134. /*
  135. * DefLEqual := 0x93 Operand Operand
  136. * Operand := TermArg => Integer
  137. */
  138. opcode(opcode::DEF_L_EQUAL_OP)
  139. .then(comment_scope(
  140. DebugVerbosity::AllScopes,
  141. "DefLEqual",
  142. term_arg().then(term_arg()).map_with_context(|(left_arg, right_arg), context| {
  143. let ord = try_with_context!(context, left_arg.cmp(right_arg, context));
  144. (Ok(AmlValue::Boolean(ord == Ordering::Equal)), context)
  145. }),
  146. ))
  147. .map(|((), result)| Ok(result))
  148. }
  149. fn def_l_greater<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  150. where
  151. 'c: 'a,
  152. {
  153. /*
  154. * DefLGreater := 0x94 Operand Operand
  155. */
  156. opcode(opcode::DEF_L_GREATER_OP)
  157. .then(comment_scope(
  158. DebugVerbosity::AllScopes,
  159. "DefLGreater",
  160. term_arg().then(term_arg()).map_with_context(|(left_arg, right_arg), context| {
  161. let ord = try_with_context!(context, left_arg.cmp(right_arg, context));
  162. (Ok(AmlValue::Boolean(ord == Ordering::Greater)), context)
  163. }),
  164. ))
  165. .map(|((), result)| Ok(result))
  166. }
  167. fn def_l_greater_equal<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  168. where
  169. 'c: 'a,
  170. {
  171. /*
  172. * DefLGreaterEqual := LNotOp(0x92) LLessOp(0x95) Operand Operand
  173. */
  174. opcode(opcode::DEF_L_NOT_OP)
  175. .then(opcode(opcode::DEF_L_LESS_OP))
  176. .then(comment_scope(
  177. DebugVerbosity::AllScopes,
  178. "DefLGreaterEqual",
  179. term_arg().then(term_arg()).map_with_context(|(left_arg, right_arg), context| {
  180. let ord = try_with_context!(context, left_arg.cmp(right_arg, context));
  181. (Ok(AmlValue::Boolean(ord != Ordering::Less)), context)
  182. }),
  183. ))
  184. .map(|(((), ()), result)| Ok(result))
  185. }
  186. fn def_l_less<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  187. where
  188. 'c: 'a,
  189. {
  190. /*
  191. * DefLLess := 0x95 Operand Operand
  192. */
  193. opcode(opcode::DEF_L_LESS_OP)
  194. .then(comment_scope(
  195. DebugVerbosity::AllScopes,
  196. "DefLLess",
  197. term_arg().then(term_arg()).map_with_context(|(left_arg, right_arg), context| {
  198. let ord = try_with_context!(context, left_arg.cmp(right_arg, context));
  199. (Ok(AmlValue::Boolean(ord == Ordering::Less)), context)
  200. }),
  201. ))
  202. .map(|((), result)| Ok(result))
  203. }
  204. fn def_l_less_equal<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  205. where
  206. 'c: 'a,
  207. {
  208. /*
  209. * DefLLessEqual := LNotOp(0x92) LGreaterOp(0x94) Operand Operand
  210. */
  211. opcode(opcode::DEF_L_NOT_OP)
  212. .then(opcode(opcode::DEF_L_GREATER_OP))
  213. .then(comment_scope(
  214. DebugVerbosity::AllScopes,
  215. "DefLLessEqual",
  216. term_arg().then(term_arg()).map_with_context(|(left_arg, right_arg), context| {
  217. let ord = try_with_context!(context, left_arg.cmp(right_arg, context));
  218. (Ok(AmlValue::Boolean(ord != Ordering::Greater)), context)
  219. }),
  220. ))
  221. .map(|(((), ()), result)| Ok(result))
  222. }
  223. fn def_l_not_equal<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  224. where
  225. 'c: 'a,
  226. {
  227. /*
  228. * DefLNotEqual := LNotOp(0x92) LEqualOp(0x93) Operand Operand
  229. */
  230. opcode(opcode::DEF_L_NOT_OP)
  231. .then(opcode(opcode::DEF_L_EQUAL_OP))
  232. .then(comment_scope(
  233. DebugVerbosity::AllScopes,
  234. "DefLNotEqual",
  235. term_arg().then(term_arg()).map_with_context(|(left_arg, right_arg), context| {
  236. let ord = try_with_context!(context, left_arg.cmp(right_arg, context));
  237. (Ok(AmlValue::Boolean(ord != Ordering::Equal)), context)
  238. }),
  239. ))
  240. .map(|(((), ()), result)| Ok(result))
  241. }
  242. pub fn def_package<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  243. where
  244. 'c: 'a,
  245. {
  246. /*
  247. * DefPackage := 0x12 PkgLength NumElements PackageElementList
  248. * NumElements := ByteData
  249. * PackageElementList := Nothing | <PackageElement PackageElementList>
  250. * PackageElement := DataRefObject | NameString
  251. */
  252. opcode(opcode::DEF_PACKAGE_OP)
  253. .then(comment_scope(
  254. DebugVerbosity::AllScopes,
  255. "DefPackage",
  256. pkg_length().then(take()).feed(|(pkg_length, num_elements)| {
  257. move |mut input, mut context| {
  258. let mut package_contents = Vec::new();
  259. while pkg_length.still_parsing(input) {
  260. let (new_input, new_context, value) = package_element().parse(input, context)?;
  261. input = new_input;
  262. context = new_context;
  263. package_contents.push(value);
  264. }
  265. assert_eq!(package_contents.len(), num_elements as usize);
  266. Ok((input, context, AmlValue::Package(package_contents)))
  267. }
  268. }),
  269. ))
  270. .map(|((), package)| Ok(package))
  271. }
  272. pub fn package_element<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  273. where
  274. 'c: 'a,
  275. {
  276. choice!(data_ref_object(), name_string().map(|string| Ok(AmlValue::String(string.as_string()))))
  277. }
  278. fn def_shift_left<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  279. where
  280. 'c: 'a,
  281. {
  282. /*
  283. * DefShiftLeft := 0x79 Operand ShiftCount Target
  284. * Operand := TermArg => Integer
  285. * ShiftCount := TermArg => Integer
  286. */
  287. opcode(opcode::DEF_SHIFT_LEFT)
  288. .then(comment_scope(DebugVerbosity::Scopes, "DefShiftLeft", term_arg().then(term_arg()).then(target())))
  289. .map_with_context(|((), ((operand, shift_count), target)), context| {
  290. let operand = try_with_context!(context, operand.as_integer(context));
  291. let shift_count = try_with_context!(context, shift_count.as_integer(context));
  292. let shift_count =
  293. try_with_context!(context, shift_count.try_into().map_err(|_| AmlError::InvalidShiftLeft));
  294. let result = AmlValue::Integer(try_with_context!(
  295. context,
  296. operand.checked_shl(shift_count).ok_or(AmlError::InvalidShiftLeft)
  297. ));
  298. try_with_context!(context, context.store(target, result.clone()));
  299. (Ok(result), context)
  300. })
  301. }
  302. fn def_shift_right<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  303. where
  304. 'c: 'a,
  305. {
  306. /*
  307. * DefShiftRight := 0x7a Operand ShiftCount Target
  308. * Operand := TermArg => Integer
  309. * ShiftCount := TermArg => Integer
  310. */
  311. opcode(opcode::DEF_SHIFT_RIGHT)
  312. .then(comment_scope(DebugVerbosity::Scopes, "DefShiftRight", term_arg().then(term_arg()).then(target())))
  313. .map_with_context(|((), ((operand, shift_count), target)), context| {
  314. let operand = try_with_context!(context, operand.as_integer(context));
  315. let shift_count = try_with_context!(context, shift_count.as_integer(context));
  316. let shift_count =
  317. try_with_context!(context, shift_count.try_into().map_err(|_| AmlError::InvalidShiftRight));
  318. let result = AmlValue::Integer(try_with_context!(
  319. context,
  320. operand.checked_shr(shift_count).ok_or(AmlError::InvalidShiftRight)
  321. ));
  322. try_with_context!(context, context.store(target, result.clone()));
  323. (Ok(result), context)
  324. })
  325. }
  326. fn def_store<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  327. where
  328. 'c: 'a,
  329. {
  330. /*
  331. * DefStore := 0x70 TermArg SuperName
  332. *
  333. * Implicit conversion is only applied when the destination target is a `Name` - not when we
  334. * are storing into a method local or argument (these stores are semantically identical to
  335. * CopyObject). We must also make sure to return a copy of the data that is in the destination
  336. * after the store (as opposed to the data we think we put into it), because some stores can
  337. * alter the data during the store.
  338. */
  339. opcode(opcode::DEF_STORE_OP)
  340. .then(comment_scope(DebugVerbosity::Scopes, "DefStore", term_arg().then(super_name())))
  341. .map_with_context(|((), (value, target)), context| {
  342. (Ok(try_with_context!(context, context.store(target, value))), context)
  343. })
  344. }
  345. fn method_invocation<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  346. where
  347. 'c: 'a,
  348. {
  349. /*
  350. * MethodInvocation := NameString TermArgList
  351. *
  352. * MethodInvocation is the worst of the AML structures, because you're meant to figure out how much you're
  353. * meant to parse using the name of the method (by knowing from its definition how how many arguments it
  354. * takes). However, the definition of a method can in theory appear after an invocation of that method, and
  355. * so parsing them properly can be very difficult.
  356. * NOTE: We don't support the case of the definition appearing after the invocation.
  357. */
  358. comment_scope(
  359. DebugVerbosity::Scopes,
  360. "MethodInvocation",
  361. name_string()
  362. .map_with_context(move |name, context| {
  363. let (full_path, handle) =
  364. try_with_context!(context, context.namespace.search(&name, &context.current_scope)).clone();
  365. /*
  366. * `None` if the path is not a method and so doesn't have arguments, or `Some(the number of
  367. * arguments to parse)` if it's a method.
  368. */
  369. let num_args = if let AmlValue::Method { flags, .. } =
  370. try_with_context!(context, context.namespace.get(handle))
  371. {
  372. Some(flags.arg_count())
  373. } else {
  374. None
  375. };
  376. (Ok((full_path, num_args)), context)
  377. })
  378. .feed(|(path, num_args)| {
  379. n_of(term_arg(), num_args.unwrap_or(0) as usize).map_with_context(move |arg_list, context| {
  380. if num_args.is_some() {
  381. let result = context.invoke_method(&path, Args::from_list(arg_list));
  382. (Ok(try_with_context!(context, result)), context)
  383. } else {
  384. (Ok(try_with_context!(context, context.namespace.get_by_path(&path)).clone()), context)
  385. }
  386. })
  387. }),
  388. )
  389. }