type2.rs 16 KB

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