2
0

term_object.rs 21 KB

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