term_object.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. use crate::{
  2. name_object::{name_seg, name_string},
  3. opcode::{self, ext_opcode, opcode},
  4. parser::{
  5. choice,
  6. comment_scope,
  7. take,
  8. take_to_end_of_pkglength,
  9. take_u16,
  10. take_u32,
  11. take_u64,
  12. ParseResult,
  13. Parser,
  14. },
  15. pkg_length::{pkg_length, PkgLength},
  16. value::{AmlValue, FieldFlags},
  17. AmlContext,
  18. AmlError,
  19. };
  20. use alloc::string::String;
  21. use log::trace;
  22. /// `TermList`s are usually found within explicit-length objects (so they have a `PkgLength`
  23. /// elsewhere in the structure), so this takes a number of bytes to parse.
  24. pub fn term_list<'a, 'c>(list_length: PkgLength) -> impl Parser<'a, 'c, ()>
  25. where
  26. 'c: 'a,
  27. {
  28. /*
  29. * TermList := Nothing | <TermObj TermList>
  30. */
  31. move |mut input: &'a [u8], mut context: &'c mut AmlContext| {
  32. while list_length.still_parsing(input) {
  33. let (new_input, new_context, ()) = term_object().parse(input, context)?;
  34. input = new_input;
  35. context = new_context;
  36. }
  37. Ok((input, context, ()))
  38. }
  39. }
  40. pub fn term_object<'a, 'c>() -> impl Parser<'a, 'c, ()>
  41. where
  42. 'c: 'a,
  43. {
  44. /*
  45. * TermObj := NamespaceModifierObj | NamedObj | Type1Opcode | Type2Opcode
  46. */
  47. comment_scope("TermObj", choice!(namespace_modifier(), named_obj()))
  48. }
  49. pub fn namespace_modifier<'a, 'c>() -> impl Parser<'a, 'c, ()>
  50. where
  51. 'c: 'a,
  52. {
  53. /*
  54. * NamespaceModifierObj := DefAlias | DefName | DefScope
  55. */
  56. choice!(def_name(), def_scope())
  57. }
  58. pub fn named_obj<'a, 'c>() -> impl Parser<'a, 'c, ()>
  59. where
  60. 'c: 'a,
  61. {
  62. /*
  63. * NamedObj := DefBankField | DefCreateBitField | DefCreateByteField | DefCreateDWordField |
  64. * DefCreateField | DefCreateQWordField | DefCreateWordField | DefDataRegion |
  65. * DefExternal | DefOpRegion | DefPowerRes | DefProcessor | DefThermalZone |
  66. * DefMethod | DefMutex
  67. *
  68. * XXX: DefMethod and DefMutex (at least) are not included in any rule in the AML grammar,
  69. * but are defined in the NamedObj section so we assume they're part of NamedObj
  70. */
  71. comment_scope("NamedObj", choice!(def_op_region(), def_field(), def_method(), def_device()))
  72. }
  73. pub fn def_name<'a, 'c>() -> impl Parser<'a, 'c, ()>
  74. where
  75. 'c: 'a,
  76. {
  77. /*
  78. * DefName := 0x08 NameString DataRefObject
  79. */
  80. opcode(opcode::DEF_NAME_OP)
  81. .then(comment_scope(
  82. "DefName",
  83. name_string().then(data_ref_object()).map_with_context(
  84. |(name, data_ref_object), context| {
  85. // TODO: add to namespace
  86. trace!("Defined name: {}", name);
  87. ((), context)
  88. },
  89. ),
  90. ))
  91. .discard_result()
  92. }
  93. pub fn def_scope<'a, 'c>() -> impl Parser<'a, 'c, ()>
  94. where
  95. 'c: 'a,
  96. {
  97. /*
  98. * DefScope := 0x10 PkgLength NameString TermList
  99. */
  100. opcode(opcode::DEF_SCOPE_OP)
  101. .then(comment_scope(
  102. "DefScope",
  103. pkg_length()
  104. .then(name_string())
  105. .map_with_context(|(length, name), context| {
  106. // TODO: change scope in `context`
  107. trace!("Moving to scope: {:?}", name);
  108. ((length, name), context)
  109. })
  110. .feed(move |(pkg_length, name)| {
  111. trace!("Scope with name: {}, length: {:?}", name, pkg_length);
  112. term_list(pkg_length).map(move |_| name.clone())
  113. })
  114. .map_with_context(|name, context| {
  115. // TODO: remove scope
  116. trace!("Exiting scope: {}", name);
  117. ((), context)
  118. }),
  119. ))
  120. .discard_result()
  121. }
  122. pub fn def_op_region<'a, 'c>() -> impl Parser<'a, 'c, ()>
  123. where
  124. 'c: 'a,
  125. {
  126. /*
  127. * DefOpRegion := ExtOpPrefix 0x80 NameString RegionSpace RegionOffset RegionLen
  128. * RegionSpace := ByteData (where 0x00 = SystemMemory
  129. * 0x01 = SystemIO
  130. * 0x02 = PciConfig
  131. * 0x03 = EmbeddedControl
  132. * 0x04 = SMBus
  133. * 0x05 = SystemCMOS
  134. * 0x06 = PciBarTarget
  135. * 0x07 = IPMI
  136. * 0x08 = GeneralPurposeIO
  137. * 0x09 = GenericSerialBus
  138. * 0x80-0xff = OEM Defined)
  139. * ByteData := 0x00 - 0xff
  140. * RegionOffset := TermArg => Integer
  141. * RegionLen := TermArg => Integer
  142. */
  143. ext_opcode(opcode::EXT_DEF_OP_REGION_OP)
  144. .then(comment_scope(
  145. "DefOpRegion",
  146. name_string().then(take()).then(term_arg()).then(term_arg()).map_with_context(
  147. |(((name, space), offset), region_len), context| {
  148. trace!("Op region: {}, {}, {:?}, {:?}", name, space, offset, region_len);
  149. // TODO: add to namespace
  150. ((), context)
  151. },
  152. ),
  153. ))
  154. .discard_result()
  155. }
  156. pub fn def_field<'a, 'c>() -> impl Parser<'a, 'c, ()>
  157. where
  158. 'c: 'a,
  159. {
  160. /*
  161. * DefField = ExtOpPrefix 0x81 PkgLength NameString FieldFlags FieldList
  162. * FieldFlags := ByteData
  163. */
  164. ext_opcode(opcode::EXT_DEF_FIELD_OP)
  165. .then(comment_scope(
  166. "DefField",
  167. pkg_length().then(name_string()).then(take()).feed(
  168. |((list_length, region_name), flags)| {
  169. move |mut input: &'a [u8],
  170. mut context: &'c mut AmlContext|
  171. -> ParseResult<'a, 'c, ()> {
  172. /*
  173. * FieldList := Nothing | <FieldElement FieldList>
  174. */
  175. // TODO: can this pattern be expressed as a combinator
  176. while list_length.still_parsing(input) {
  177. let (new_input, new_context, ()) =
  178. field_element(&region_name, FieldFlags::new(flags))
  179. .parse(input, context)?;
  180. input = new_input;
  181. context = new_context;
  182. }
  183. Ok((input, context, ()))
  184. }
  185. },
  186. ),
  187. ))
  188. .discard_result()
  189. }
  190. pub fn field_element<'a, 'c>(region_name: &String, flags: FieldFlags) -> impl Parser<'a, 'c, ()>
  191. where
  192. 'c: 'a,
  193. {
  194. /*
  195. * FieldElement := NamedField | ReservedField | AccessField | ExtendedAccessField |
  196. * ConnectField
  197. * NamedField := NameSeg PkgLength
  198. * ReservedField := 0x00 PkgLength
  199. * AccessField := 0x01 AccessType AccessAttrib
  200. * ConnectField := <0x02 NameString> | <0x02 BufferData>
  201. * ExtendedAccessField := 0x03 AccessType ExtendedAccessAttrib AccessLength
  202. *
  203. * AccessType := ByteData
  204. * AccessAttrib := ByteData
  205. *
  206. * XXX: The spec says a ConnectField can be <0x02 BufferData>, but BufferData isn't an AML
  207. * object (it seems to be defined in ASL). We treat BufferData as if it was encoded like
  208. * DefBuffer, and this seems to work so far.
  209. */
  210. // TODO: replace these maps with `with_context` and register the fields in the namespace
  211. // TODO: parse ConnectField and ExtendedAccessField
  212. let reserved_field = opcode(opcode::RESERVED_FIELD).then(pkg_length()).map_with_context(
  213. |((), pkg_length), context| {
  214. trace!("Adding reserved field with length: {}", pkg_length.raw_length);
  215. // TODO: put it in the namespace
  216. ((), context)
  217. },
  218. );
  219. let access_field = opcode(opcode::ACCESS_FIELD).then(take()).then(take()).map(
  220. |(((), access_type), access_attrib)| {
  221. trace!(
  222. "Adding access field with access_type: {}, access_attrib: {}",
  223. access_type,
  224. access_attrib
  225. );
  226. // TODO: put it in the namespace
  227. },
  228. );
  229. let named_field = name_seg().then(pkg_length()).map_with_context(|(name, length), context| {
  230. trace!("Named field with name {} and length {}", name.as_str(), length.raw_length);
  231. // TODO: put it in the namespace
  232. ((), context)
  233. });
  234. choice!(reserved_field, access_field, named_field)
  235. }
  236. pub fn def_method<'a, 'c>() -> impl Parser<'a, 'c, ()>
  237. where
  238. 'c: 'a,
  239. {
  240. /*
  241. * DefMethod := 0x14 PkgLength NameString MethodFlags TermList
  242. * MethodFlags := ByteData (where bits 0-2: ArgCount (0 to 7)
  243. * bit 3: SerializeFlag (0 = Not Serialized, 1 = Serialized)
  244. * bits 4-7: SyncLevel (0x00 to 0x0f))
  245. */
  246. opcode(opcode::DEF_METHOD_OP)
  247. .then(comment_scope(
  248. "DefMethod",
  249. pkg_length()
  250. .then(name_string())
  251. .then(take())
  252. .feed(|((length, name), flags)| {
  253. take_to_end_of_pkglength(length).map(move |code| (name.clone(), flags, code))
  254. })
  255. .map_with_context(|(name, flags, code), context| {
  256. // TODO: put it in the namespace
  257. trace!(
  258. "Method with name {} with flags {:#b}, length = {}",
  259. name,
  260. flags,
  261. code.len()
  262. );
  263. ((), context)
  264. }),
  265. ))
  266. .discard_result()
  267. }
  268. pub fn def_device<'a, 'c>() -> impl Parser<'a, 'c, ()>
  269. where
  270. 'c: 'a,
  271. {
  272. /*
  273. * DefDevice := ExtOpPrefix 0x82 PkgLength NameString TermList
  274. */
  275. ext_opcode(opcode::EXT_DEF_DEVICE_OP)
  276. .then(comment_scope(
  277. "DefDevice",
  278. pkg_length()
  279. .then(name_string())
  280. .feed(|(length, name)| term_list(length).map(move |result| (name.clone(), result)))
  281. .map_with_context(|(name, result), context| {
  282. // TODO: add to namespace
  283. trace!("Device with name: {}", name);
  284. ((), context)
  285. }),
  286. ))
  287. .discard_result()
  288. }
  289. pub fn term_arg<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  290. where
  291. 'c: 'a,
  292. {
  293. /*
  294. * TermArg := Type2Opcode | DataObject | ArgObj | LocalObj
  295. */
  296. // TODO: this doesn't yet parse Term2Opcode, ArgObj, or LocalObj
  297. comment_scope("TermArg", choice!(data_object()))
  298. }
  299. pub fn data_ref_object<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  300. where
  301. 'c: 'a,
  302. {
  303. /*
  304. * DataRefObject := DataObject | ObjectReference | DDBHandle
  305. */
  306. comment_scope("DataRefObject", choice!(data_object()))
  307. }
  308. pub fn data_object<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  309. where
  310. 'c: 'a,
  311. {
  312. /*
  313. * DataObject := DefPackage | DefVarPackage | ComputationalData
  314. *
  315. * The order of the parsers are important here, as DefPackage and DefVarPackage can be
  316. * accidently parsed as ComputationalDatas.
  317. */
  318. // TODO: this doesn't yet parse DefPackage or DefVarPackage
  319. comment_scope("DataObject", choice!(computational_data()))
  320. }
  321. pub fn computational_data<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  322. where
  323. 'c: 'a,
  324. {
  325. /*
  326. * ComputationalData := ByteConst | WordConst | DWordConst | QWordConst | String |
  327. * ConstObj | RevisionOp | DefBuffer
  328. * ByteConst := 0x0a ByteData
  329. * WordConst := 0x0b WordData
  330. * DWordConst := 0x0c DWordData
  331. * QWordConst := 0x0e QWordData
  332. * String := 0x0d AsciiCharList NullChar
  333. * ConstObj := ZeroOp(0x00) | OneOp(0x01) | OnesOp(0xff)
  334. * RevisionOp := ExtOpPrefix(0x5b) 0x30
  335. */
  336. let const_parser = |input: &'a [u8], context: &'c mut AmlContext| {
  337. let (new_input, context, op) = take().parse(input, context)?;
  338. match op {
  339. opcode::BYTE_CONST => {
  340. take().map(|value| AmlValue::Integer(value as u64)).parse(new_input, context)
  341. }
  342. opcode::WORD_CONST => {
  343. take_u16().map(|value| AmlValue::Integer(value as u64)).parse(new_input, context)
  344. }
  345. opcode::DWORD_CONST => {
  346. take_u32().map(|value| AmlValue::Integer(value as u64)).parse(new_input, context)
  347. }
  348. opcode::QWORD_CONST => {
  349. take_u64().map(|value| AmlValue::Integer(value)).parse(new_input, context)
  350. }
  351. // TODO: implement String
  352. opcode::ZERO_OP => Ok((new_input, context, AmlValue::Integer(0))),
  353. opcode::ONE_OP => Ok((new_input, context, AmlValue::Integer(1))),
  354. opcode::ONES_OP => Ok((new_input, context, AmlValue::Integer(u64::max_value()))),
  355. _ => Err((input, context, AmlError::UnexpectedByte(op))),
  356. }
  357. };
  358. comment_scope(
  359. "ComputationalData",
  360. choice!(
  361. ext_opcode(opcode::EXT_REVISION_OP)
  362. .map(|_| AmlValue::Integer(crate::AML_INTERPRETER_REVISION)),
  363. const_parser //TODO: parse DefBuffer here too
  364. ),
  365. )
  366. }
  367. #[cfg(test)]
  368. mod test {
  369. use super::*;
  370. use crate::test_utils::*;
  371. #[test]
  372. fn test_computational_data() {
  373. let mut context = AmlContext::new();
  374. check_ok!(
  375. computational_data().parse(&[0x00, 0x34, 0x12], &mut context),
  376. AmlValue::Integer(0),
  377. &[0x34, 0x12]
  378. );
  379. check_ok!(
  380. computational_data().parse(&[0x01, 0x18, 0xf3], &mut context),
  381. AmlValue::Integer(1),
  382. &[0x18, 0xf3]
  383. );
  384. check_ok!(
  385. computational_data().parse(&[0xff, 0x98, 0xc3], &mut context),
  386. AmlValue::Integer(u64::max_value()),
  387. &[0x98, 0xc3]
  388. );
  389. check_ok!(
  390. computational_data().parse(&[0x5b, 0x30], &mut context),
  391. AmlValue::Integer(crate::AML_INTERPRETER_REVISION),
  392. &[]
  393. );
  394. check_ok!(
  395. computational_data().parse(&[0x0a, 0xf3, 0x35], &mut context),
  396. AmlValue::Integer(0xf3),
  397. &[0x35]
  398. );
  399. check_ok!(
  400. computational_data().parse(&[0x0b, 0xf3, 0x35], &mut context),
  401. AmlValue::Integer(0x35f3),
  402. &[]
  403. );
  404. check_ok!(
  405. computational_data().parse(&[0x0c, 0xf3, 0x35, 0x12, 0x65, 0xff, 0x00], &mut context),
  406. AmlValue::Integer(0x651235f3),
  407. &[0xff, 0x00]
  408. );
  409. check_ok!(
  410. computational_data()
  411. .parse(&[0x0e, 0xf3, 0x35, 0x12, 0x65, 0xff, 0x00, 0x67, 0xde, 0x28], &mut context),
  412. AmlValue::Integer(0xde6700ff651235f3),
  413. &[0x28]
  414. );
  415. }
  416. }