expression.rs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. use crate::{
  2. misc::debug_obj,
  3. name_object::{name_string, simple_name, super_name, target},
  4. opcode::{self, opcode},
  5. parser::{choice, comment_scope, n_of, take, take_to_end_of_pkglength, try_with_context, Parser, Propagate},
  6. pkg_length::pkg_length,
  7. term_object::{data_ref_object, def_cond_ref_of, term_arg},
  8. value::{AmlType, AmlValue, Args},
  9. AmlError,
  10. DebugVerbosity,
  11. };
  12. use alloc::{
  13. string::{String, ToString},
  14. sync::Arc,
  15. vec,
  16. vec::Vec,
  17. };
  18. use core::{cmp::Ordering, convert::TryInto, mem, ops::Deref};
  19. pub fn expression_opcode<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  20. where
  21. 'c: 'a,
  22. {
  23. /*
  24. * ExpressionOpcode := DefAquire | DefAdd | DefAnd | DefBuffer | DefConcat | DefConcatRes |
  25. * DefCondRefOf | DefCopyObject | DefDecrement | DefDerefOf | DefDivide |
  26. * DefFindSetLeftBit | DefFindSetRightBit | DefFromBCD | DefIncrement | DefIndex |
  27. * DefLAnd | DefLEqual | DefLGreater | DefLGreaterEqual | DefLLess | DefLLessEqual |
  28. * DefMid | DefLNot | DefLNotEqual | DefLoad | DefLoadTable | DefLOr | DefMatch | DefMod |
  29. * DefMultiply | DefNAnd | DefNOr | DefNot | DefObjectType | DefOr | DefPackage |
  30. * DefVarPackage | DefRefOf | DefShiftLeft | DefShiftRight | DefSizeOf | DefStore |
  31. * DefSubtract | DefTimer | DefToBCD | DefToBuffer | DefToDecimalString |
  32. * DefToHexString | DefToInteger | DefToString | DefWait | DefXOr | MethodInvocation
  33. */
  34. comment_scope(
  35. DebugVerbosity::AllScopes,
  36. "ExpressionOpcode",
  37. choice!(
  38. def_add(),
  39. def_and(),
  40. def_buffer(),
  41. def_concat(),
  42. def_concat_res(),
  43. def_increment(),
  44. def_decrement(),
  45. def_l_equal(),
  46. def_l_greater(),
  47. def_l_greater_equal(),
  48. def_l_less(),
  49. def_l_less_equal(),
  50. def_l_not_equal(),
  51. def_l_and(),
  52. def_l_or(),
  53. def_mid(),
  54. def_object_type(),
  55. def_package(),
  56. def_shift_left(),
  57. def_shift_right(),
  58. def_store(),
  59. def_to_integer(),
  60. def_cond_ref_of(),
  61. def_size_of(),
  62. method_invocation() // XXX: this must always appear last. See how we have to parse it to see why.
  63. ),
  64. )
  65. }
  66. pub fn def_add<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  67. where
  68. 'c: 'a,
  69. {
  70. /*
  71. * DefAdd := 0x72 Operand Operand Target
  72. * Operand := TermArg => Integer
  73. */
  74. opcode(opcode::DEF_ADD_OP)
  75. .then(comment_scope(
  76. DebugVerbosity::AllScopes,
  77. "DefAdd",
  78. term_arg().then(term_arg()).then(target()).map_with_context(
  79. |((left_arg, right_arg), target), context| {
  80. let left = try_with_context!(context, left_arg.as_integer(context));
  81. let right = try_with_context!(context, right_arg.as_integer(context));
  82. let result = AmlValue::Integer(left.wrapping_add(right));
  83. try_with_context!(context, context.store(target, result.clone()));
  84. (Ok(result), context)
  85. },
  86. ),
  87. ))
  88. .map(|((), result)| Ok(result))
  89. }
  90. pub fn def_and<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  91. where
  92. 'c: 'a,
  93. {
  94. /*
  95. * DefAnd := 0x7b Operand Operand Target
  96. * Operand := TermArg => Integer
  97. */
  98. opcode(opcode::DEF_AND_OP)
  99. .then(comment_scope(
  100. DebugVerbosity::AllScopes,
  101. "DefAnd",
  102. term_arg().then(term_arg()).then(target()).map_with_context(
  103. |((left_arg, right_arg), target), context| {
  104. let left = try_with_context!(context, left_arg.as_integer(context));
  105. let right = try_with_context!(context, right_arg.as_integer(context));
  106. let result = AmlValue::Integer(left & right);
  107. try_with_context!(context, context.store(target, result.clone()));
  108. (Ok(result), context)
  109. },
  110. ),
  111. ))
  112. .map(|((), result)| Ok(result))
  113. }
  114. pub fn def_buffer<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  115. where
  116. 'c: 'a,
  117. {
  118. /*
  119. * DefBuffer := 0x11 PkgLength BufferSize ByteList
  120. * BufferSize := TermArg => Integer
  121. *
  122. * XXX: The spec says that zero-length buffers (e.g. the PkgLength is 0) are illegal, but
  123. * we've encountered them in QEMU-generated tables, so we return an empty buffer in these
  124. * cases.
  125. *
  126. * Uninitialized elements are initialized to zero.
  127. */
  128. opcode(opcode::DEF_BUFFER_OP)
  129. .then(comment_scope(
  130. DebugVerbosity::AllScopes,
  131. "DefBuffer",
  132. pkg_length().then(term_arg()).feed(|(pkg_length, buffer_size)| {
  133. take_to_end_of_pkglength(pkg_length).map_with_context(move |bytes, context| {
  134. let buffer_size = try_with_context!(context, buffer_size.as_integer(context)) as usize;
  135. if buffer_size < bytes.len() {
  136. return (Err(Propagate::Err(AmlError::MalformedBuffer)), context);
  137. }
  138. let mut buffer = vec![0; buffer_size];
  139. (&mut buffer[0..bytes.len()]).copy_from_slice(bytes);
  140. (Ok(buffer), context)
  141. })
  142. }),
  143. ))
  144. .map(|((), buffer)| Ok(AmlValue::Buffer(Arc::new(spinning_top::Spinlock::new(buffer)))))
  145. }
  146. pub fn def_concat<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  147. where
  148. 'c: 'a,
  149. {
  150. /*
  151. * DefConcat := 0x73 Data Data Target
  152. * Data := TermArg => ComputationalData
  153. */
  154. opcode(opcode::DEF_CONCAT_OP)
  155. .then(comment_scope(
  156. DebugVerbosity::AllScopes,
  157. "DefConcat",
  158. term_arg().then(term_arg()).then(target()).map_with_context(|((left, right), target), context| {
  159. let result = match left.as_concat_type() {
  160. AmlValue::Integer(left) => {
  161. let right = try_with_context!(context, right.as_integer(context));
  162. let mut buffer = Vec::with_capacity(mem::size_of::<u64>() * 2);
  163. buffer.extend_from_slice(&left.to_le_bytes());
  164. buffer.extend_from_slice(&right.to_le_bytes());
  165. AmlValue::Buffer(Arc::new(spinning_top::Spinlock::new(buffer)))
  166. }
  167. AmlValue::Buffer(left) => {
  168. let mut new: Vec<u8> = left.lock().deref().clone();
  169. new.extend(try_with_context!(context, right.as_buffer(context)).lock().iter());
  170. AmlValue::Buffer(Arc::new(spinning_top::Spinlock::new(new)))
  171. }
  172. AmlValue::String(left) => {
  173. let right = match right.as_concat_type() {
  174. AmlValue::String(right) => right,
  175. AmlValue::Integer(_) => try_with_context!(context, right.as_string(context)),
  176. AmlValue::Buffer(_) => try_with_context!(context, right.as_string(context)),
  177. _ => panic!("Invalid type returned from `as_concat_type`"),
  178. };
  179. AmlValue::String(left + &right)
  180. }
  181. _ => panic!("Invalid type returned from `as_concat_type`"),
  182. };
  183. try_with_context!(context, context.store(target, result.clone()));
  184. (Ok(result), context)
  185. }),
  186. ))
  187. .map(|((), result)| Ok(result))
  188. }
  189. pub fn def_concat_res<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  190. where
  191. 'c: 'a,
  192. {
  193. /*
  194. * DefConcatRes := 0x84 BufData BufData Target
  195. * BufData := TermArg => Buffer
  196. */
  197. opcode(opcode::DEF_CONCAT_RES_OP)
  198. .then(comment_scope(
  199. DebugVerbosity::AllScopes,
  200. "DefConcatRes",
  201. term_arg().then(term_arg()).then(target()).map_with_context(|((left, right), target), context| {
  202. let left = try_with_context!(context, left.as_buffer(context));
  203. let right = try_with_context!(context, right.as_buffer(context));
  204. let left_len = left.lock().len();
  205. let right_len = right.lock().len();
  206. if left_len == 1 || right_len == 1 {
  207. return (Err(Propagate::Err(AmlError::ResourceDescriptorTooShort)), context);
  208. }
  209. /*
  210. * `left` and `right` are buffers of resource descriptors, which we're trying to concatenate into a
  211. * new, single buffer containing all of the descriptors from the source buffers. We need to strip
  212. * off the end tags (2 bytes from each buffer), and then add our own end tag.
  213. *
  214. * XXX: either buffer may be empty (contains no tags), and so our arithmetic has to be careful.
  215. */
  216. let result = {
  217. let mut result =
  218. Vec::with_capacity(left_len.saturating_sub(2) + right_len.saturating_sub(2) + 2);
  219. let left_contents = left.lock();
  220. let right_contents = right.lock();
  221. result.extend_from_slice(if left_len == 0 { &[] } else { &left_contents[..(left_len - 2)] });
  222. result.extend_from_slice(if right_len == 0 {
  223. &[]
  224. } else {
  225. &right_contents[..(right_len - 2)]
  226. });
  227. /*
  228. * Construct a new end tag, including a new checksum:
  229. * | Bits | Field | Value |
  230. * |-------------|-------------------|---------------------------|
  231. * | 0-2 | Length - n bytes | 1 (for checksum) |
  232. * | 3-6 | Small item type | 0x0f = end tag descriptor |
  233. * | 7 | 0 = small item | 0 |
  234. */
  235. result.push(0b01111001);
  236. result.push(
  237. result.iter().fold(0u8, |checksum, byte| checksum.wrapping_add(*byte)).wrapping_neg(),
  238. );
  239. AmlValue::Buffer(Arc::new(spinning_top::Spinlock::new(result)))
  240. };
  241. try_with_context!(context, context.store(target, result.clone()));
  242. (Ok(result), context)
  243. }),
  244. ))
  245. .map(|((), result)| Ok(result))
  246. }
  247. fn def_increment<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  248. where
  249. 'c: 'a,
  250. {
  251. /*
  252. * DefIncrement := 0x75 SuperName
  253. */
  254. opcode(opcode::DEF_INCREMENT_OP)
  255. .then(comment_scope(
  256. DebugVerbosity::AllScopes,
  257. "DefIncrement",
  258. super_name().map_with_context(|addend, context| {
  259. let value = try_with_context!(context, context.read_target(&addend));
  260. let value = try_with_context!(context, value.as_integer(context));
  261. let new_value = AmlValue::Integer(value + 1);
  262. try_with_context!(context, context.store(addend, new_value.clone()));
  263. (Ok(new_value), context)
  264. }),
  265. ))
  266. .map(|((), result)| Ok(result))
  267. }
  268. fn def_decrement<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  269. where
  270. 'c: 'a,
  271. {
  272. /*
  273. * DefDecrement := 0x76 SuperName
  274. */
  275. opcode(opcode::DEF_DECREMENT_OP)
  276. .then(comment_scope(
  277. DebugVerbosity::AllScopes,
  278. "DefDecrement",
  279. super_name().map_with_context(|minuend, context| {
  280. let value = try_with_context!(context, context.read_target(&minuend));
  281. let value = try_with_context!(context, value.as_integer(context));
  282. let new_value = AmlValue::Integer(value - 1);
  283. try_with_context!(context, context.store(minuend, new_value.clone()));
  284. (Ok(new_value), context)
  285. }),
  286. ))
  287. .map(|((), result)| Ok(result))
  288. }
  289. fn def_l_and<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  290. where
  291. 'c: 'a,
  292. {
  293. /*
  294. * DefLAnd := 0x90 Operand Operand
  295. * Operand := TermArg => Integer
  296. */
  297. opcode(opcode::DEF_L_AND_OP)
  298. .then(comment_scope(
  299. DebugVerbosity::AllScopes,
  300. "DefLOr",
  301. term_arg().then(term_arg()).map_with_context(|(left_arg, right_arg), context| {
  302. let left = try_with_context!(context, left_arg.as_bool());
  303. let right = try_with_context!(context, right_arg.as_bool());
  304. (Ok(AmlValue::Boolean(left && right)), context)
  305. }),
  306. ))
  307. .map(|((), result)| Ok(result))
  308. }
  309. fn def_l_or<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  310. where
  311. 'c: 'a,
  312. {
  313. /*
  314. * DefLOr := 0x91 Operand Operand
  315. * Operand := TermArg => Integer
  316. */
  317. opcode(opcode::DEF_L_OR_OP)
  318. .then(comment_scope(
  319. DebugVerbosity::AllScopes,
  320. "DefLOr",
  321. term_arg().then(term_arg()).map_with_context(|(left_arg, right_arg), context| {
  322. let left = try_with_context!(context, left_arg.as_bool());
  323. let right = try_with_context!(context, right_arg.as_bool());
  324. (Ok(AmlValue::Boolean(left || right)), context)
  325. }),
  326. ))
  327. .map(|((), result)| Ok(result))
  328. }
  329. fn def_l_equal<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  330. where
  331. 'c: 'a,
  332. {
  333. /*
  334. * DefLEqual := 0x93 Operand Operand
  335. * Operand := TermArg => Integer
  336. */
  337. opcode(opcode::DEF_L_EQUAL_OP)
  338. .then(comment_scope(
  339. DebugVerbosity::AllScopes,
  340. "DefLEqual",
  341. term_arg().then(term_arg()).map_with_context(|(left_arg, right_arg), context| {
  342. let ord = try_with_context!(context, left_arg.cmp(right_arg, context));
  343. (Ok(AmlValue::Boolean(ord == Ordering::Equal)), context)
  344. }),
  345. ))
  346. .map(|((), result)| Ok(result))
  347. }
  348. fn def_l_greater<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  349. where
  350. 'c: 'a,
  351. {
  352. /*
  353. * DefLGreater := 0x94 Operand Operand
  354. */
  355. opcode(opcode::DEF_L_GREATER_OP)
  356. .then(comment_scope(
  357. DebugVerbosity::AllScopes,
  358. "DefLGreater",
  359. term_arg().then(term_arg()).map_with_context(|(left_arg, right_arg), context| {
  360. let ord = try_with_context!(context, left_arg.cmp(right_arg, context));
  361. (Ok(AmlValue::Boolean(ord == Ordering::Greater)), context)
  362. }),
  363. ))
  364. .map(|((), result)| Ok(result))
  365. }
  366. fn def_l_greater_equal<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  367. where
  368. 'c: 'a,
  369. {
  370. /*
  371. * DefLGreaterEqual := LNotOp(0x92) LLessOp(0x95) Operand Operand
  372. */
  373. opcode(opcode::DEF_L_NOT_OP)
  374. .then(opcode(opcode::DEF_L_LESS_OP))
  375. .then(comment_scope(
  376. DebugVerbosity::AllScopes,
  377. "DefLGreaterEqual",
  378. term_arg().then(term_arg()).map_with_context(|(left_arg, right_arg), context| {
  379. let ord = try_with_context!(context, left_arg.cmp(right_arg, context));
  380. (Ok(AmlValue::Boolean(ord != Ordering::Less)), context)
  381. }),
  382. ))
  383. .map(|(((), ()), result)| Ok(result))
  384. }
  385. fn def_l_less<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  386. where
  387. 'c: 'a,
  388. {
  389. /*
  390. * DefLLess := 0x95 Operand Operand
  391. */
  392. opcode(opcode::DEF_L_LESS_OP)
  393. .then(comment_scope(
  394. DebugVerbosity::AllScopes,
  395. "DefLLess",
  396. term_arg().then(term_arg()).map_with_context(|(left_arg, right_arg), context| {
  397. let ord = try_with_context!(context, left_arg.cmp(right_arg, context));
  398. (Ok(AmlValue::Boolean(ord == Ordering::Less)), context)
  399. }),
  400. ))
  401. .map(|((), result)| Ok(result))
  402. }
  403. fn def_l_less_equal<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  404. where
  405. 'c: 'a,
  406. {
  407. /*
  408. * DefLLessEqual := LNotOp(0x92) LGreaterOp(0x94) Operand Operand
  409. */
  410. opcode(opcode::DEF_L_NOT_OP)
  411. .then(opcode(opcode::DEF_L_GREATER_OP))
  412. .then(comment_scope(
  413. DebugVerbosity::AllScopes,
  414. "DefLLessEqual",
  415. term_arg().then(term_arg()).map_with_context(|(left_arg, right_arg), context| {
  416. let ord = try_with_context!(context, left_arg.cmp(right_arg, context));
  417. (Ok(AmlValue::Boolean(ord != Ordering::Greater)), context)
  418. }),
  419. ))
  420. .map(|(((), ()), result)| Ok(result))
  421. }
  422. fn def_l_not_equal<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  423. where
  424. 'c: 'a,
  425. {
  426. /*
  427. * DefLNotEqual := LNotOp(0x92) LEqualOp(0x93) Operand Operand
  428. */
  429. opcode(opcode::DEF_L_NOT_OP)
  430. .then(opcode(opcode::DEF_L_EQUAL_OP))
  431. .then(comment_scope(
  432. DebugVerbosity::AllScopes,
  433. "DefLNotEqual",
  434. term_arg().then(term_arg()).map_with_context(|(left_arg, right_arg), context| {
  435. let ord = try_with_context!(context, left_arg.cmp(right_arg, context));
  436. (Ok(AmlValue::Boolean(ord != Ordering::Equal)), context)
  437. }),
  438. ))
  439. .map(|(((), ()), result)| Ok(result))
  440. }
  441. fn def_mid<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  442. where
  443. 'c: 'a,
  444. {
  445. /*
  446. * DefMid := 0x9e MidObj TermArg TermArg Target
  447. * MidObj := TermArg => Buffer | String
  448. */
  449. opcode(opcode::DEF_MID_OP)
  450. .then(comment_scope(
  451. DebugVerbosity::AllScopes,
  452. "DefMid",
  453. term_arg().then(term_arg()).then(term_arg()).then(target()).map_with_context(
  454. |(((source, index), length), target), context| {
  455. let index = try_with_context!(context, index.as_integer(context)) as usize;
  456. let length = try_with_context!(context, length.as_integer(context)) as usize;
  457. let result = try_with_context!(
  458. context,
  459. match source {
  460. AmlValue::Buffer(bytes) => {
  461. let foo = bytes.lock();
  462. if index >= foo.len() {
  463. Ok(AmlValue::Buffer(Arc::new(spinning_top::Spinlock::new(vec![]))))
  464. } else if (index + length) >= foo.len() {
  465. Ok(AmlValue::Buffer(Arc::new(spinning_top::Spinlock::new(
  466. foo[index..].to_vec(),
  467. ))))
  468. } else {
  469. Ok(AmlValue::Buffer(Arc::new(spinning_top::Spinlock::new(
  470. foo[index..(index + length)].to_vec(),
  471. ))))
  472. }
  473. }
  474. /*
  475. * XXX: The spec conflates characters and bytes, so we effectively ignore unicode and do
  476. * this bytewise, to hopefully match other implementations.
  477. */
  478. AmlValue::String(string) => {
  479. if index >= string.len() {
  480. Ok(AmlValue::String(String::new()))
  481. } else if (index + length) >= string.len() {
  482. Ok(AmlValue::String(string[index..].to_string()))
  483. } else {
  484. Ok(AmlValue::String(string[index..(index + length)].to_string()))
  485. }
  486. }
  487. _ => Err(AmlError::TypeCannotBeSliced(source.type_of())),
  488. }
  489. );
  490. try_with_context!(context, context.store(target, result.clone()));
  491. (Ok(result), context)
  492. },
  493. ),
  494. ))
  495. .map(|((), result)| Ok(result))
  496. }
  497. pub fn def_object_type<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  498. where
  499. 'c: 'a,
  500. {
  501. /*
  502. * DefObjectType := 0x8e <SimpleName | DebugObj | DefRefOf | DefDerefOf | DefIndex>
  503. *
  504. * Returns an integer representing the type of an AML object. If executed on an object that is a reference to a
  505. * value (e.g. produced by `Alias`, `RefOf`, or `Index`), the type of the base object is returned. For typeless
  506. * objects, such as scopes, a type of `0 - Uninitialized` is returned.
  507. *
  508. * 0 = Uninitialized
  509. * 1 = Integer
  510. * 2 = String
  511. * 3 = Buffer
  512. * 4 = Package
  513. * 5 = Field Unit
  514. * 6 = Device
  515. * 7 = Event
  516. * 8 = Method
  517. * 9 = Mutex
  518. * 10 = Operation Region
  519. * 11 = Power Resource
  520. * 12 = Processor
  521. * 13 = Thermal Zone
  522. * 14 = Buffer Field
  523. * 15 = Reserved
  524. * 16 = Debug Object
  525. * >16 = *Reserved*
  526. */
  527. // TODO: this doesn't correctly handle taking the type of a namespace node (e.g. `\_SB`), but I'm not sure any
  528. // other implementations do either?
  529. opcode(opcode::DEF_OBJECT_TYPE_OP)
  530. .then(comment_scope(
  531. DebugVerbosity::AllScopes,
  532. "DefObjectType",
  533. choice!(
  534. simple_name().map_with_context(|target, context| {
  535. let value = try_with_context!(context, context.read_target(&target));
  536. let typ = match value.type_of() {
  537. AmlType::Uninitialized => 0,
  538. AmlType::Integer => 1,
  539. AmlType::String => 2,
  540. AmlType::Buffer => 3,
  541. AmlType::RawDataBuffer => 3, // TODO: not sure if this is correct
  542. AmlType::Package => 4,
  543. AmlType::FieldUnit => 5,
  544. AmlType::Device => 6,
  545. AmlType::Event => 7,
  546. AmlType::Method => 8,
  547. AmlType::Mutex => 9,
  548. AmlType::OpRegion => 10,
  549. AmlType::PowerResource => 11,
  550. AmlType::Processor => 12,
  551. AmlType::ThermalZone => 13,
  552. AmlType::BufferField => 14,
  553. AmlType::DebugObject => 16,
  554. // TODO: what to do with this?
  555. AmlType::DdbHandle => 0,
  556. AmlType::ObjReference => todo!(),
  557. };
  558. (Ok(AmlValue::Integer(typ)), context)
  559. }),
  560. debug_obj().map(|()| Ok(AmlValue::Integer(16)))
  561. ),
  562. ))
  563. .map(|((), result)| Ok(result))
  564. }
  565. pub fn def_package<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  566. where
  567. 'c: 'a,
  568. {
  569. /*
  570. * DefPackage := 0x12 PkgLength NumElements PackageElementList
  571. * NumElements := ByteData
  572. * PackageElementList := Nothing | <PackageElement PackageElementList>
  573. * PackageElement := DataRefObject | NameString
  574. */
  575. opcode(opcode::DEF_PACKAGE_OP)
  576. .then(comment_scope(
  577. DebugVerbosity::AllScopes,
  578. "DefPackage",
  579. pkg_length().then(take()).feed(|(pkg_length, num_elements)| {
  580. move |mut input, mut context| {
  581. let mut package_contents = Vec::new();
  582. while pkg_length.still_parsing(input) {
  583. let (new_input, new_context, value) = package_element().parse(input, context)?;
  584. input = new_input;
  585. context = new_context;
  586. package_contents.push(value);
  587. }
  588. if package_contents.len() != num_elements as usize {
  589. return Err((input, context, Propagate::Err(AmlError::MalformedPackage)));
  590. }
  591. Ok((input, context, AmlValue::Package(package_contents)))
  592. }
  593. }),
  594. ))
  595. .map(|((), package)| Ok(package))
  596. }
  597. pub fn package_element<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  598. where
  599. 'c: 'a,
  600. {
  601. choice!(data_ref_object(), name_string().map(|string| Ok(AmlValue::String(string.as_string()))))
  602. }
  603. fn def_shift_left<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  604. where
  605. 'c: 'a,
  606. {
  607. /*
  608. * DefShiftLeft := 0x79 Operand ShiftCount Target
  609. * Operand := TermArg => Integer
  610. * ShiftCount := TermArg => Integer
  611. */
  612. opcode(opcode::DEF_SHIFT_LEFT)
  613. .then(comment_scope(DebugVerbosity::Scopes, "DefShiftLeft", term_arg().then(term_arg()).then(target())))
  614. .map_with_context(|((), ((operand, shift_count), target)), context| {
  615. let operand = try_with_context!(context, operand.as_integer(context));
  616. let shift_count = try_with_context!(context, shift_count.as_integer(context));
  617. let shift_count =
  618. try_with_context!(context, shift_count.try_into().map_err(|_| AmlError::InvalidShiftLeft));
  619. let result = AmlValue::Integer(try_with_context!(
  620. context,
  621. operand.checked_shl(shift_count).ok_or(AmlError::InvalidShiftLeft)
  622. ));
  623. try_with_context!(context, context.store(target, result.clone()));
  624. (Ok(result), context)
  625. })
  626. }
  627. fn def_shift_right<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  628. where
  629. 'c: 'a,
  630. {
  631. /*
  632. * DefShiftRight := 0x7a Operand ShiftCount Target
  633. * Operand := TermArg => Integer
  634. * ShiftCount := TermArg => Integer
  635. */
  636. opcode(opcode::DEF_SHIFT_RIGHT)
  637. .then(comment_scope(DebugVerbosity::Scopes, "DefShiftRight", term_arg().then(term_arg()).then(target())))
  638. .map_with_context(|((), ((operand, shift_count), target)), context| {
  639. let operand = try_with_context!(context, operand.as_integer(context));
  640. let shift_count = try_with_context!(context, shift_count.as_integer(context));
  641. let shift_count =
  642. try_with_context!(context, shift_count.try_into().map_err(|_| AmlError::InvalidShiftRight));
  643. let result = AmlValue::Integer(try_with_context!(
  644. context,
  645. operand.checked_shr(shift_count).ok_or(AmlError::InvalidShiftRight)
  646. ));
  647. try_with_context!(context, context.store(target, result.clone()));
  648. (Ok(result), context)
  649. })
  650. }
  651. fn def_store<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  652. where
  653. 'c: 'a,
  654. {
  655. /*
  656. * DefStore := 0x70 TermArg SuperName
  657. *
  658. * Implicit conversion is only applied when the destination target is a `Name` - not when we
  659. * are storing into a method local or argument (these stores are semantically identical to
  660. * CopyObject). We must also make sure to return a copy of the data that is in the destination
  661. * after the store (as opposed to the data we think we put into it), because some stores can
  662. * alter the data during the store.
  663. */
  664. opcode(opcode::DEF_STORE_OP)
  665. .then(comment_scope(DebugVerbosity::Scopes, "DefStore", term_arg().then(super_name())))
  666. .map_with_context(|((), (value, target)), context| {
  667. (Ok(try_with_context!(context, context.store(target, value))), context)
  668. })
  669. }
  670. fn def_to_integer<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  671. where
  672. 'c: 'a,
  673. {
  674. /*
  675. * DefToInteger := 0x99 Operand Target
  676. * Operand := TermArg
  677. */
  678. opcode(opcode::DEF_TO_INTEGER_OP)
  679. .then(comment_scope(DebugVerbosity::AllScopes, "DefToInteger", term_arg().then(target())))
  680. .map_with_context(|((), (operand, target)), context| {
  681. let result = match operand {
  682. AmlValue::Integer(value) => AmlValue::Integer(value),
  683. AmlValue::Buffer(data) => {
  684. AmlValue::Integer(try_with_context!(context, AmlValue::Buffer(data).as_integer(context)))
  685. }
  686. AmlValue::String(string) => AmlValue::Integer(try_with_context!(
  687. context,
  688. if string.starts_with("0x") {
  689. u64::from_str_radix(string.trim_start_matches("0x"), 16)
  690. } else {
  691. string.parse::<u64>()
  692. }
  693. .map_err(|_| AmlError::IncompatibleValueConversion {
  694. current: AmlType::String,
  695. target: AmlType::Integer,
  696. })
  697. )),
  698. _ => {
  699. return (
  700. Err(Propagate::Err(AmlError::IncompatibleValueConversion {
  701. current: operand.type_of(),
  702. target: AmlType::Integer,
  703. })),
  704. context,
  705. )
  706. }
  707. };
  708. try_with_context!(context, context.store(target, result.clone()));
  709. (Ok(result), context)
  710. })
  711. }
  712. fn def_size_of<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  713. where
  714. 'c: 'a,
  715. {
  716. /*
  717. * SizeOf := 0x87 SuperName
  718. */
  719. opcode(opcode::DEF_SIZE_OF_OP)
  720. .then(comment_scope(
  721. DebugVerbosity::AllScopes,
  722. "DefSizeOf",
  723. super_name().map_with_context(|target, context| {
  724. let value = try_with_context!(context, context.read_target(&target));
  725. let size_of = try_with_context!(context, value.size_of());
  726. (Ok(AmlValue::Integer(size_of)), context)
  727. }),
  728. ))
  729. .map(|((), value)| Ok(value))
  730. }
  731. fn method_invocation<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  732. where
  733. 'c: 'a,
  734. {
  735. /*
  736. * MethodInvocation := NameString TermArgList
  737. *
  738. * MethodInvocation is the worst of the AML structures, because you're meant to figure out how much you're
  739. * meant to parse using the name of the method (by knowing from its definition how how many arguments it
  740. * takes). However, the definition of a method can in theory appear after an invocation of that method, and
  741. * so parsing them properly can be very difficult.
  742. * NOTE: We don't support the case of the definition appearing after the invocation.
  743. */
  744. comment_scope(
  745. DebugVerbosity::Scopes,
  746. "MethodInvocation",
  747. name_string()
  748. .map_with_context(move |name, context| {
  749. let (full_path, handle) =
  750. try_with_context!(context, context.namespace.search(&name, &context.current_scope)).clone();
  751. /*
  752. * `None` if the path is not a method and so doesn't have arguments, or `Some(the number of
  753. * arguments to parse)` if it's a method.
  754. */
  755. let num_args = if let AmlValue::Method { flags, .. } =
  756. try_with_context!(context, context.namespace.get(handle))
  757. {
  758. Some(flags.arg_count())
  759. } else {
  760. None
  761. };
  762. (Ok((full_path, num_args)), context)
  763. })
  764. .feed(|(path, num_args)| {
  765. n_of(term_arg(), num_args.unwrap_or(0) as usize).map_with_context(move |arg_list, context| {
  766. if num_args.is_some() {
  767. let args = try_with_context!(context, Args::from_list(arg_list));
  768. let result = context.invoke_method(&path, args);
  769. (Ok(try_with_context!(context, result)), context)
  770. } else {
  771. (Ok(try_with_context!(context, context.namespace.get_by_path(&path)).clone()), context)
  772. }
  773. })
  774. }),
  775. )
  776. }