term_object.rs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. use crate::{
  2. misc::{arg_obj, local_obj},
  3. name_object::{name_seg, name_string},
  4. namespace::{AmlName, LevelType},
  5. opcode::{self, ext_opcode, opcode},
  6. parser::{
  7. choice,
  8. comment_scope,
  9. make_parser_concrete,
  10. take,
  11. take_to_end_of_pkglength,
  12. take_u16,
  13. take_u32,
  14. take_u64,
  15. try_with_context,
  16. ParseResult,
  17. Parser,
  18. },
  19. pkg_length::{pkg_length, PkgLength},
  20. type1::type1_opcode,
  21. type2::{def_buffer, def_package, type2_opcode},
  22. value::{AmlValue, FieldFlags, MethodFlags, RegionSpace},
  23. AmlContext,
  24. AmlError,
  25. DebugVerbosity,
  26. };
  27. use alloc::string::String;
  28. use core::str;
  29. /// `TermList`s are usually found within explicit-length objects (so they have a `PkgLength`
  30. /// elsewhere in the structure), so this takes a number of bytes to parse.
  31. pub fn term_list<'a, 'c>(list_length: PkgLength) -> impl Parser<'a, 'c, ()>
  32. where
  33. 'c: 'a,
  34. {
  35. /*
  36. * TermList := Nothing | <TermObj TermList>
  37. */
  38. move |mut input: &'a [u8], mut context: &'c mut AmlContext| {
  39. while list_length.still_parsing(input) {
  40. // TODO: currently, we ignore the value of the expression. We may need to propagate
  41. // this.
  42. let (new_input, new_context, _) = term_object().parse(input, context)?;
  43. input = new_input;
  44. context = new_context;
  45. }
  46. Ok((input, context, ()))
  47. }
  48. }
  49. pub fn term_object<'a, 'c>() -> impl Parser<'a, 'c, Option<AmlValue>>
  50. where
  51. 'c: 'a,
  52. {
  53. /*
  54. * TermObj := NamespaceModifierObj | NamedObj | Type1Opcode | Type2Opcode
  55. */
  56. comment_scope(
  57. DebugVerbosity::AllScopes,
  58. "TermObj",
  59. choice!(
  60. namespace_modifier().map(|()| Ok(None)),
  61. named_obj().map(|()| Ok(None)),
  62. type1_opcode().map(|()| Ok(None)),
  63. type2_opcode().map(|value| Ok(Some(value)))
  64. ),
  65. )
  66. }
  67. pub fn namespace_modifier<'a, 'c>() -> impl Parser<'a, 'c, ()>
  68. where
  69. 'c: 'a,
  70. {
  71. /*
  72. * NamespaceModifierObj := DefAlias | DefName | DefScope
  73. */
  74. choice!(def_name(), def_scope())
  75. }
  76. pub fn named_obj<'a, 'c>() -> impl Parser<'a, 'c, ()>
  77. where
  78. 'c: 'a,
  79. {
  80. /*
  81. * NamedObj := DefBankField | DefCreateBitField | DefCreateByteField | DefCreateDWordField |
  82. * DefCreateField | DefCreateQWordField | DefCreateWordField | DefDataRegion |
  83. * DefExternal | DefOpRegion | DefPowerRes | DefProcessor | DefThermalZone |
  84. * DefMethod | DefMutex
  85. *
  86. * XXX: DefMethod and DefMutex (at least) are not included in any rule in the AML grammar,
  87. * but are defined in the NamedObj section so we assume they're part of NamedObj
  88. */
  89. comment_scope(
  90. DebugVerbosity::AllScopes,
  91. "NamedObj",
  92. choice!(def_op_region(), def_field(), def_method(), def_device(), def_processor(), def_mutex()),
  93. )
  94. }
  95. pub fn def_name<'a, 'c>() -> impl Parser<'a, 'c, ()>
  96. where
  97. 'c: 'a,
  98. {
  99. /*
  100. * DefName := 0x08 NameString DataRefObject
  101. */
  102. opcode(opcode::DEF_NAME_OP)
  103. .then(comment_scope(
  104. DebugVerbosity::Scopes,
  105. "DefName",
  106. name_string().then(data_ref_object()).map_with_context(|(name, data_ref_object), context| {
  107. try_with_context!(
  108. context,
  109. context.namespace.add_value_at_resolved_path(name, &context.current_scope, data_ref_object,)
  110. );
  111. (Ok(()), context)
  112. }),
  113. ))
  114. .discard_result()
  115. }
  116. pub fn def_scope<'a, 'c>() -> impl Parser<'a, 'c, ()>
  117. where
  118. 'c: 'a,
  119. {
  120. /*
  121. * DefScope := 0x10 PkgLength NameString TermList
  122. */
  123. opcode(opcode::DEF_SCOPE_OP)
  124. .then(comment_scope(
  125. DebugVerbosity::Scopes,
  126. "DefScope",
  127. pkg_length()
  128. .then(name_string())
  129. .map_with_context(|(length, name), context| {
  130. let previous_scope = context.current_scope.clone();
  131. context.current_scope = try_with_context!(context, name.resolve(&context.current_scope));
  132. context.comment(
  133. DebugVerbosity::Scopes,
  134. &(String::from("Scope name: ") + &context.current_scope.as_string()),
  135. );
  136. try_with_context!(
  137. context,
  138. context.namespace.add_level(context.current_scope.clone(), LevelType::Scope)
  139. );
  140. (Ok((length, previous_scope)), context)
  141. })
  142. .feed(|(pkg_length, previous_scope)| {
  143. term_list(pkg_length).map(move |_| Ok(previous_scope.clone()))
  144. })
  145. .map_with_context(|previous_scope, context| {
  146. context.current_scope = previous_scope;
  147. (Ok(()), context)
  148. }),
  149. ))
  150. .discard_result()
  151. }
  152. pub fn def_op_region<'a, 'c>() -> impl Parser<'a, 'c, ()>
  153. where
  154. 'c: 'a,
  155. {
  156. /*
  157. * DefOpRegion := ExtOpPrefix 0x80 NameString RegionSpace RegionOffset RegionLen
  158. * RegionSpace := ByteData (where 0x00 = SystemMemory
  159. * 0x01 = SystemIO
  160. * 0x02 = PciConfig
  161. * 0x03 = EmbeddedControl
  162. * 0x04 = SMBus
  163. * 0x05 = SystemCMOS
  164. * 0x06 = PciBarTarget
  165. * 0x07 = IPMI
  166. * 0x08 = GeneralPurposeIO
  167. * 0x09 = GenericSerialBus
  168. * 0x80-0xff = OEM Defined)
  169. * ByteData := 0x00 - 0xff
  170. * RegionOffset := TermArg => Integer
  171. * RegionLen := TermArg => Integer
  172. */
  173. ext_opcode(opcode::EXT_DEF_OP_REGION_OP)
  174. .then(comment_scope(
  175. DebugVerbosity::Scopes,
  176. "DefOpRegion",
  177. name_string().then(take()).then(term_arg()).then(term_arg()).map_with_context(
  178. |(((name, space), offset), length), context| {
  179. let region = match space {
  180. 0x00 => RegionSpace::SystemMemory,
  181. 0x01 => RegionSpace::SystemIo,
  182. 0x02 => RegionSpace::PciConfig,
  183. 0x03 => RegionSpace::EmbeddedControl,
  184. 0x04 => RegionSpace::SMBus,
  185. 0x05 => RegionSpace::SystemCmos,
  186. 0x06 => RegionSpace::PciBarTarget,
  187. 0x07 => RegionSpace::IPMI,
  188. 0x08 => RegionSpace::GeneralPurposeIo,
  189. 0x09 => RegionSpace::GenericSerialBus,
  190. space @ 0x80..=0xff => RegionSpace::OemDefined(space),
  191. byte => return (Err(AmlError::InvalidRegionSpace(byte)), context),
  192. };
  193. let offset = match offset.as_integer() {
  194. Ok(offset) => offset,
  195. Err(err) => return (Err(err), context),
  196. };
  197. let length = match length.as_integer() {
  198. Ok(length) => length,
  199. Err(err) => return (Err(err), context),
  200. };
  201. try_with_context!(
  202. context,
  203. context.namespace.add_value_at_resolved_path(
  204. name,
  205. &context.current_scope,
  206. AmlValue::OpRegion { region, offset, length }
  207. )
  208. );
  209. (Ok(()), context)
  210. },
  211. ),
  212. ))
  213. .discard_result()
  214. }
  215. pub fn def_field<'a, 'c>() -> impl Parser<'a, 'c, ()>
  216. where
  217. 'c: 'a,
  218. {
  219. /*
  220. * DefField = ExtOpPrefix 0x81 PkgLength NameString FieldFlags FieldList
  221. * FieldFlags := ByteData
  222. */
  223. ext_opcode(opcode::EXT_DEF_FIELD_OP)
  224. .then(comment_scope(
  225. DebugVerbosity::Scopes,
  226. "DefField",
  227. pkg_length().then(name_string()).then(take()).feed(|((list_length, region_name), flags)| {
  228. move |mut input: &'a [u8], mut context: &'c mut AmlContext| -> ParseResult<'a, 'c, ()> {
  229. /*
  230. * FieldList := Nothing | <FieldElement FieldList>
  231. */
  232. // TODO: can this pattern be expressed as a combinator
  233. let mut current_offset = 0;
  234. while list_length.still_parsing(input) {
  235. let (new_input, new_context, field_length) =
  236. field_element(region_name.clone(), FieldFlags::new(flags), current_offset)
  237. .parse(input, context)?;
  238. input = new_input;
  239. context = new_context;
  240. current_offset += field_length;
  241. }
  242. Ok((input, context, ()))
  243. }
  244. }),
  245. ))
  246. .discard_result()
  247. }
  248. /// Parses a `FieldElement`. Takes the current offset within the field list, and returns the length
  249. /// of the field element parsed.
  250. pub fn field_element<'a, 'c>(
  251. region_name: AmlName,
  252. flags: FieldFlags,
  253. current_offset: u64,
  254. ) -> impl Parser<'a, 'c, u64>
  255. where
  256. 'c: 'a,
  257. {
  258. /*
  259. * FieldElement := NamedField | ReservedField | AccessField | ExtendedAccessField |
  260. * ConnectField
  261. * NamedField := NameSeg PkgLength
  262. * ReservedField := 0x00 PkgLength
  263. * AccessField := 0x01 AccessType AccessAttrib
  264. * ConnectField := <0x02 NameString> | <0x02 BufferData>
  265. * ExtendedAccessField := 0x03 AccessType ExtendedAccessAttrib AccessLength
  266. *
  267. * AccessType := ByteData
  268. * AccessAttrib := ByteData
  269. *
  270. * XXX: The spec says a ConnectField can be <0x02 BufferData>, but BufferData isn't an AML
  271. * object (it seems to be defined in ASL). We treat BufferData as if it was encoded like
  272. * DefBuffer, and this seems to work so far.
  273. */
  274. // TODO: parse ConnectField and ExtendedAccessField
  275. /*
  276. * Reserved fields shouldn't actually be added to the namespace; they seem to show gaps in
  277. * the operation region that aren't used for anything.
  278. */
  279. let reserved_field =
  280. opcode(opcode::RESERVED_FIELD).then(pkg_length()).map(|((), length)| Ok(length.raw_length as u64));
  281. // TODO: work out what to do with an access field
  282. // let access_field = opcode(opcode::ACCESS_FIELD)
  283. // .then(take())
  284. // .then(take())
  285. // .map_with_context(|(((), access_type), access_attrib), context| (Ok( , context));
  286. let named_field = name_seg().then(pkg_length()).map_with_context(move |(name_seg, length), context| {
  287. try_with_context!(
  288. context,
  289. context.namespace.add_value_at_resolved_path(
  290. AmlName::from_name_seg(name_seg),
  291. &context.current_scope,
  292. AmlValue::Field {
  293. region: region_name.clone(),
  294. flags,
  295. offset: current_offset,
  296. length: length.raw_length as u64,
  297. },
  298. )
  299. );
  300. (Ok(length.raw_length as u64), context)
  301. });
  302. choice!(reserved_field, named_field)
  303. }
  304. pub fn def_method<'a, 'c>() -> impl Parser<'a, 'c, ()>
  305. where
  306. 'c: 'a,
  307. {
  308. /*
  309. * DefMethod := 0x14 PkgLength NameString MethodFlags TermList
  310. * MethodFlags := ByteData (where bits 0-2: ArgCount (0 to 7)
  311. * bit 3: SerializeFlag (0 = Not Serialized, 1 = Serialized)
  312. * bits 4-7: SyncLevel (0x00 to 0x0f))
  313. */
  314. opcode(opcode::DEF_METHOD_OP)
  315. .then(comment_scope(
  316. DebugVerbosity::Scopes,
  317. "DefMethod",
  318. pkg_length()
  319. .then(name_string())
  320. .then(take())
  321. .feed(|((length, name), flags)| {
  322. take_to_end_of_pkglength(length).map(move |code| Ok((name.clone(), flags, code)))
  323. })
  324. .map_with_context(|(name, flags, code), context| {
  325. try_with_context!(
  326. context,
  327. context.namespace.add_value_at_resolved_path(
  328. name,
  329. &context.current_scope,
  330. AmlValue::Method { flags: MethodFlags::new(flags), code: code.to_vec() },
  331. )
  332. );
  333. (Ok(()), context)
  334. }),
  335. ))
  336. .discard_result()
  337. }
  338. pub fn def_device<'a, 'c>() -> impl Parser<'a, 'c, ()>
  339. where
  340. 'c: 'a,
  341. {
  342. /*
  343. * DefDevice := ExtOpPrefix 0x82 PkgLength NameString TermList
  344. */
  345. ext_opcode(opcode::EXT_DEF_DEVICE_OP)
  346. .then(comment_scope(
  347. DebugVerbosity::Scopes,
  348. "DefDevice",
  349. pkg_length()
  350. .then(name_string())
  351. .map_with_context(|(length, name), context| {
  352. let resolved_name = try_with_context!(context, name.clone().resolve(&context.current_scope));
  353. try_with_context!(context, context.namespace.add_level(resolved_name, LevelType::Device));
  354. let previous_scope = context.current_scope.clone();
  355. context.current_scope = try_with_context!(context, name.resolve(&context.current_scope));
  356. (Ok((length, previous_scope)), context)
  357. })
  358. .feed(|(length, previous_scope)| term_list(length).map(move |_| Ok(previous_scope.clone())))
  359. .map_with_context(|previous_scope, context| {
  360. context.current_scope = previous_scope;
  361. (Ok(()), context)
  362. }),
  363. ))
  364. .discard_result()
  365. }
  366. pub fn def_processor<'a, 'c>() -> impl Parser<'a, 'c, ()>
  367. where
  368. 'c: 'a,
  369. {
  370. /*
  371. * DefProcessor := ExtOpPrefix 0x83 PkgLength NameString ProcID PblkAddress PblkLen TermList
  372. * ProcID := ByteData
  373. * PblkAddress := DWordData
  374. * PblkLen := ByteData
  375. */
  376. ext_opcode(opcode::EXT_DEF_PROCESSOR_OP)
  377. .then(comment_scope(
  378. DebugVerbosity::Scopes,
  379. "DefProcessor",
  380. pkg_length()
  381. .then(name_string())
  382. .then(take())
  383. .then(take_u32())
  384. .then(take())
  385. .map_with_context(|((((pkg_length, name), proc_id), pblk_address), pblk_len), context| {
  386. try_with_context!(
  387. context,
  388. context.namespace.add_value_at_resolved_path(
  389. name.clone(),
  390. &context.current_scope,
  391. AmlValue::Processor { id: proc_id, pblk_address, pblk_len }
  392. )
  393. );
  394. let previous_scope = context.current_scope.clone();
  395. context.current_scope = try_with_context!(context, name.resolve(&context.current_scope));
  396. (Ok((previous_scope, pkg_length)), context)
  397. })
  398. .feed(move |(previous_scope, pkg_length)| {
  399. term_list(pkg_length).map(move |_| Ok(previous_scope.clone()))
  400. })
  401. .map_with_context(|previous_scope, context| {
  402. context.current_scope = previous_scope;
  403. (Ok(()), context)
  404. }),
  405. ))
  406. .discard_result()
  407. }
  408. pub fn def_mutex<'a, 'c>() -> impl Parser<'a, 'c, ()>
  409. where
  410. 'c: 'a,
  411. {
  412. /*
  413. * DefMutex := ExtOpPrefix 0x01 NameString SyncFlags
  414. * SyncFlags := ByteData (where bits 0-3: SyncLevel
  415. * bits 4-7: Reserved)
  416. */
  417. ext_opcode(opcode::EXT_DEF_MUTEX_OP)
  418. .then(comment_scope(
  419. DebugVerbosity::Scopes,
  420. "DefMutex",
  421. name_string().then(take()).map_with_context(|(name, sync_level), context| {
  422. try_with_context!(
  423. context,
  424. context.namespace.add_value_at_resolved_path(
  425. name,
  426. &context.current_scope,
  427. AmlValue::Mutex { sync_level }
  428. )
  429. );
  430. (Ok(()), context)
  431. }),
  432. ))
  433. .discard_result()
  434. }
  435. pub fn term_arg<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  436. where
  437. 'c: 'a,
  438. {
  439. /*
  440. * TermArg := Type2Opcode | DataObject | ArgObj | LocalObj
  441. */
  442. comment_scope(
  443. DebugVerbosity::AllScopes,
  444. "TermArg",
  445. choice!(
  446. data_object(),
  447. arg_obj().map_with_context(|arg_num, context| {
  448. (Ok(try_with_context!(context, context.current_arg(arg_num)).clone()), context)
  449. }),
  450. local_obj().map_with_context(|local_num, context| {
  451. (Ok(try_with_context!(context, context.local(local_num)).clone()), context)
  452. }),
  453. make_parser_concrete!(type2_opcode())
  454. ),
  455. )
  456. }
  457. pub fn data_ref_object<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  458. where
  459. 'c: 'a,
  460. {
  461. /*
  462. * DataRefObject := DataObject | ObjectReference | DDBHandle
  463. */
  464. comment_scope(DebugVerbosity::AllScopes, "DataRefObject", choice!(data_object()))
  465. }
  466. pub fn data_object<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  467. where
  468. 'c: 'a,
  469. {
  470. /*
  471. * DataObject := DefPackage | DefVarPackage | ComputationalData
  472. *
  473. * The order of the parsers are important here, as DefPackage and DefVarPackage can be
  474. * accidently parsed as ComputationalDatas.
  475. */
  476. // TODO: this doesn't yet parse DefVarPackage
  477. comment_scope(DebugVerbosity::AllScopes, "DataObject", choice!(def_package(), computational_data()))
  478. }
  479. pub fn computational_data<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  480. where
  481. 'c: 'a,
  482. {
  483. /*
  484. * ComputationalData := ByteConst | WordConst | DWordConst | QWordConst | String |
  485. * ConstObj | RevisionOp | DefBuffer
  486. * ByteConst := 0x0a ByteData
  487. * WordConst := 0x0b WordData
  488. * DWordConst := 0x0c DWordData
  489. * QWordConst := 0x0e QWordData
  490. * String := 0x0d AsciiCharList NullChar
  491. * ConstObj := ZeroOp(0x00) | OneOp(0x01) | OnesOp(0xff)
  492. * RevisionOp := ExtOpPrefix(0x5b) 0x30
  493. */
  494. let const_parser = |input: &'a [u8], context: &'c mut AmlContext| {
  495. let string_parser = |input: &'a [u8], context| -> ParseResult<'a, 'c, AmlValue> {
  496. /*
  497. * Using `position` isn't very efficient here, but is probably fine because the
  498. * strings are usually quite short.
  499. */
  500. let nul_position = match input.iter().position(|&c| c == b'\0') {
  501. Some(position) => position,
  502. None => return Err((input, context, AmlError::UnterminatedStringConstant)),
  503. };
  504. let string = String::from(match str::from_utf8(&input[0..nul_position]) {
  505. Ok(string) => string,
  506. Err(_) => return Err((input, context, AmlError::InvalidStringConstant)),
  507. });
  508. Ok((&input[(nul_position + 1)..], context, AmlValue::String(string)))
  509. };
  510. let (new_input, context, op) = take().parse(input, context)?;
  511. match op {
  512. opcode::BYTE_CONST => {
  513. take().map(|value| Ok(AmlValue::Integer(value as u64))).parse(new_input, context)
  514. }
  515. opcode::WORD_CONST => {
  516. take_u16().map(|value| Ok(AmlValue::Integer(value as u64))).parse(new_input, context)
  517. }
  518. opcode::DWORD_CONST => {
  519. take_u32().map(|value| Ok(AmlValue::Integer(value as u64))).parse(new_input, context)
  520. }
  521. opcode::QWORD_CONST => take_u64().map(|value| Ok(AmlValue::Integer(value))).parse(new_input, context),
  522. opcode::STRING_PREFIX => string_parser.parse(new_input, context),
  523. opcode::ZERO_OP => Ok((new_input, context, AmlValue::Integer(0))),
  524. opcode::ONE_OP => Ok((new_input, context, AmlValue::Integer(1))),
  525. opcode::ONES_OP => Ok((new_input, context, AmlValue::Integer(u64::max_value()))),
  526. _ => Err((input, context, AmlError::WrongParser)),
  527. }
  528. };
  529. comment_scope(
  530. DebugVerbosity::AllScopes,
  531. "ComputationalData",
  532. choice!(
  533. ext_opcode(opcode::EXT_REVISION_OP).map(|_| Ok(AmlValue::Integer(crate::AML_INTERPRETER_REVISION))),
  534. const_parser,
  535. make_parser_concrete!(def_buffer())
  536. ),
  537. )
  538. }
  539. #[cfg(test)]
  540. mod test {
  541. use super::*;
  542. use crate::{test_utils::*, AmlContext, DebugVerbosity};
  543. #[test]
  544. fn test_computational_data() {
  545. let mut context = AmlContext::new(DebugVerbosity::None);
  546. check_ok!(
  547. computational_data().parse(&[0x00, 0x34, 0x12], &mut context),
  548. AmlValue::Integer(0),
  549. &[0x34, 0x12]
  550. );
  551. check_ok!(
  552. computational_data().parse(&[0x01, 0x18, 0xf3], &mut context),
  553. AmlValue::Integer(1),
  554. &[0x18, 0xf3]
  555. );
  556. check_ok!(
  557. computational_data().parse(&[0xff, 0x98, 0xc3], &mut context),
  558. AmlValue::Integer(u64::max_value()),
  559. &[0x98, 0xc3]
  560. );
  561. check_ok!(
  562. computational_data().parse(&[0x5b, 0x30], &mut context),
  563. AmlValue::Integer(crate::AML_INTERPRETER_REVISION),
  564. &[]
  565. );
  566. check_ok!(computational_data().parse(&[0x0a, 0xf3, 0x35], &mut context), AmlValue::Integer(0xf3), &[0x35]);
  567. check_ok!(computational_data().parse(&[0x0b, 0xf3, 0x35], &mut context), AmlValue::Integer(0x35f3), &[]);
  568. check_ok!(
  569. computational_data().parse(&[0x0c, 0xf3, 0x35, 0x12, 0x65, 0xff, 0x00], &mut context),
  570. AmlValue::Integer(0x651235f3),
  571. &[0xff, 0x00]
  572. );
  573. check_ok!(
  574. computational_data()
  575. .parse(&[0x0e, 0xf3, 0x35, 0x12, 0x65, 0xff, 0x00, 0x67, 0xde, 0x28], &mut context),
  576. AmlValue::Integer(0xde6700ff651235f3),
  577. &[0x28]
  578. );
  579. check_ok!(
  580. computational_data().parse(&[0x0d, b'A', b'B', b'C', b'D', b'\0', 0xff, 0xf5], &mut context),
  581. AmlValue::String(String::from("ABCD")),
  582. &[0xff, 0xf5]
  583. );
  584. }
  585. }