2
0

term_object.rs 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093
  1. use crate::{
  2. expression::{def_buffer, def_package, expression_opcode},
  3. misc::{arg_obj, local_obj},
  4. name_object::{name_seg, name_string, target, Target},
  5. namespace::{AmlName, LevelType},
  6. opcode::{self, ext_opcode, opcode},
  7. parser::{
  8. choice,
  9. comment_scope,
  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. Propagate,
  19. },
  20. pkg_length::{pkg_length, region_pkg_length, PkgLength},
  21. statement::statement_opcode,
  22. value::{AmlValue, FieldFlags, MethodCode, MethodFlags, RegionSpace},
  23. AmlContext,
  24. AmlError,
  25. AmlHandle,
  26. DebugVerbosity,
  27. };
  28. use alloc::{string::String, sync::Arc, vec::Vec};
  29. use core::str;
  30. /// `TermList`s are usually found within explicit-length objects (so they have a `PkgLength`
  31. /// elsewhere in the structure), so this takes a number of bytes to parse.
  32. pub fn term_list<'a, 'c>(list_length: PkgLength) -> impl Parser<'a, 'c, ()>
  33. where
  34. 'c: 'a,
  35. {
  36. /*
  37. * TermList := Nothing | <TermObj TermList>
  38. */
  39. // TODO: why does this use still_parsing, instead of just taking the whole thing and parsing it til it's empty?
  40. move |mut input: &'a [u8], mut context: &'c mut AmlContext| {
  41. while list_length.still_parsing(input) {
  42. // TODO: currently, we ignore the value of the expression. We may need to propagate
  43. // this.
  44. let (new_input, new_context, _) = term_object().parse(input, context)?;
  45. input = new_input;
  46. context = new_context;
  47. }
  48. Ok((input, context, ()))
  49. }
  50. }
  51. pub fn term_object<'a, 'c>() -> impl Parser<'a, 'c, Option<AmlValue>>
  52. where
  53. 'c: 'a,
  54. {
  55. /*
  56. * TermObj := NamespaceModifierObj | NamedObj | StatementOpcode | ExpressionOpcode
  57. */
  58. comment_scope(
  59. DebugVerbosity::AllScopes,
  60. "TermObj",
  61. choice!(
  62. namespace_modifier().map(|()| Ok(None)),
  63. named_obj().map(|()| Ok(None)),
  64. statement_opcode().map(|()| Ok(None)),
  65. expression_opcode().map(|value| Ok(Some(value)))
  66. ),
  67. )
  68. }
  69. pub fn namespace_modifier<'a, 'c>() -> impl Parser<'a, 'c, ()>
  70. where
  71. 'c: 'a,
  72. {
  73. /*
  74. * NamespaceModifierObj := DefAlias | DefName | DefScope
  75. */
  76. choice!(def_alias(), def_name(), def_scope())
  77. }
  78. pub fn named_obj<'a, 'c>() -> impl Parser<'a, 'c, ()>
  79. where
  80. 'c: 'a,
  81. {
  82. /*
  83. * NamedObj := DefBankField | DefCreateBitField | DefCreateByteField | DefCreateWordField | DefCreateDWordField |
  84. * DefCreateQWordField | DefCreateField | DefDataRegion | DefExternal | DefOpRegion | DefPowerRes |
  85. * DefProcessor | DefThermalZone | DefMethod | DefMutex
  86. *
  87. * XXX: DefMethod and DefMutex (at least) are not included in any rule in the AML grammar,
  88. * but are defined in the NamedObj section so we assume they're part of NamedObj
  89. */
  90. comment_scope(
  91. DebugVerbosity::AllScopes,
  92. "NamedObj",
  93. choice!(
  94. def_create_bit_field(),
  95. def_create_byte_field(),
  96. def_create_word_field(),
  97. def_create_dword_field(),
  98. def_create_qword_field(),
  99. def_create_field(),
  100. def_op_region(),
  101. def_field(),
  102. def_method(),
  103. def_external(),
  104. def_device(),
  105. def_processor(),
  106. def_power_res(),
  107. def_thermal_zone(),
  108. def_mutex()
  109. ),
  110. )
  111. }
  112. pub fn def_name<'a, 'c>() -> impl Parser<'a, 'c, ()>
  113. where
  114. 'c: 'a,
  115. {
  116. /*
  117. * DefName := 0x08 NameString DataRefObject
  118. */
  119. opcode(opcode::DEF_NAME_OP)
  120. .then(comment_scope(
  121. DebugVerbosity::Scopes,
  122. "DefName",
  123. name_string().then(data_ref_object()).map_with_context(|(name, data_ref_object), context| {
  124. try_with_context!(
  125. context,
  126. context.namespace.add_value_at_resolved_path(name, &context.current_scope, data_ref_object)
  127. );
  128. (Ok(()), context)
  129. }),
  130. ))
  131. .discard_result()
  132. }
  133. pub fn def_alias<'a, 'c>() -> impl Parser<'a, 'c, ()>
  134. where
  135. 'c: 'a,
  136. {
  137. /*
  138. * DefAlias := 0x06 NameString NameString
  139. * The second name refers to the same object as the first
  140. */
  141. opcode(opcode::DEF_ALIAS_OP)
  142. .then(comment_scope(
  143. DebugVerbosity::Scopes,
  144. "DefAlias",
  145. name_string().then(name_string()).map_with_context(|(target, alias), context| {
  146. try_with_context!(
  147. context,
  148. context.namespace.add_alias_at_resolved_path(alias, &context.current_scope, target)
  149. );
  150. (Ok(()), context)
  151. }),
  152. ))
  153. .discard_result()
  154. }
  155. pub fn def_scope<'a, 'c>() -> impl Parser<'a, 'c, ()>
  156. where
  157. 'c: 'a,
  158. {
  159. /*
  160. * DefScope := 0x10 PkgLength NameString TermList
  161. */
  162. opcode(opcode::DEF_SCOPE_OP)
  163. .then(comment_scope(
  164. DebugVerbosity::Scopes,
  165. "DefScope",
  166. pkg_length()
  167. .then(name_string())
  168. .map_with_context(|(length, name), context| {
  169. let previous_scope = context.current_scope.clone();
  170. context.current_scope = try_with_context!(context, name.resolve(&context.current_scope));
  171. context.comment(
  172. DebugVerbosity::Scopes,
  173. &(String::from("Scope name: ") + &context.current_scope.as_string()),
  174. );
  175. try_with_context!(
  176. context,
  177. context.namespace.add_level(context.current_scope.clone(), LevelType::Scope)
  178. );
  179. (Ok((length, previous_scope)), context)
  180. })
  181. .feed(|(pkg_length, previous_scope)| {
  182. term_list(pkg_length).map(move |_| Ok(previous_scope.clone()))
  183. })
  184. .map_with_context(|previous_scope, context| {
  185. context.current_scope = previous_scope;
  186. (Ok(()), context)
  187. }),
  188. ))
  189. .discard_result()
  190. }
  191. pub fn def_create_bit_field<'a, 'c>() -> impl Parser<'a, 'c, ()>
  192. where
  193. 'c: 'a,
  194. {
  195. /*
  196. * DefCreateBitField := 0x8d SourceBuf BitIndex NameString
  197. * SourceBuf := TermArg => Buffer
  198. * BitIndex := TermArg => Integer
  199. */
  200. opcode(opcode::DEF_CREATE_BIT_FIELD_OP)
  201. .then(comment_scope(
  202. DebugVerbosity::AllScopes,
  203. "DefCreateBitField",
  204. term_arg().then(term_arg()).then(name_string()).map_with_context(
  205. |((source, index), name), context| {
  206. let source_data: Arc<spinning_top::Spinlock<Vec<u8>>> =
  207. try_with_context!(context, source.as_buffer(context)).clone();
  208. let index = try_with_context!(context, index.as_integer(context));
  209. try_with_context!(
  210. context,
  211. context.namespace.add_value_at_resolved_path(
  212. name,
  213. &context.current_scope,
  214. AmlValue::BufferField { buffer_data: source_data, offset: index, length: 1 }
  215. )
  216. );
  217. (Ok(()), context)
  218. },
  219. ),
  220. ))
  221. .discard_result()
  222. }
  223. pub fn def_create_byte_field<'a, 'c>() -> impl Parser<'a, 'c, ()>
  224. where
  225. 'c: 'a,
  226. {
  227. /*
  228. * DefCreateByteField := 0x8c SourceBuf ByteIndex NameString
  229. * SourceBuf := TermArg => Buffer
  230. * ByteIndex := TermArg => Integer
  231. */
  232. opcode(opcode::DEF_CREATE_BYTE_FIELD_OP)
  233. .then(comment_scope(
  234. DebugVerbosity::AllScopes,
  235. "DefCreateByteField",
  236. term_arg().then(term_arg()).then(name_string()).map_with_context(
  237. |((source, index), name), context| {
  238. let source_data: Arc<spinning_top::Spinlock<Vec<u8>>> =
  239. try_with_context!(context, source.as_buffer(context)).clone();
  240. let index = try_with_context!(context, index.as_integer(context));
  241. try_with_context!(
  242. context,
  243. context.namespace.add_value_at_resolved_path(
  244. name,
  245. &context.current_scope,
  246. AmlValue::BufferField { buffer_data: source_data, offset: index * 8, length: 8 }
  247. )
  248. );
  249. (Ok(()), context)
  250. },
  251. ),
  252. ))
  253. .discard_result()
  254. }
  255. pub fn def_create_word_field<'a, 'c>() -> impl Parser<'a, 'c, ()>
  256. where
  257. 'c: 'a,
  258. {
  259. /*
  260. * DefCreateWordField := 0x8b SourceBuf ByteIndex NameString
  261. * SourceBuf := TermArg => Buffer
  262. * ByteIndex := TermArg => Integer
  263. */
  264. opcode(opcode::DEF_CREATE_WORD_FIELD_OP)
  265. .then(comment_scope(
  266. DebugVerbosity::AllScopes,
  267. "DefCreateWordField",
  268. term_arg().then(term_arg()).then(name_string()).map_with_context(
  269. |((source, index), name), context| {
  270. let source_data: Arc<spinning_top::Spinlock<Vec<u8>>> =
  271. try_with_context!(context, source.as_buffer(context)).clone();
  272. let index = try_with_context!(context, index.as_integer(context));
  273. try_with_context!(
  274. context,
  275. context.namespace.add_value_at_resolved_path(
  276. name,
  277. &context.current_scope,
  278. AmlValue::BufferField { buffer_data: source_data, offset: index * 8, length: 16 }
  279. )
  280. );
  281. (Ok(()), context)
  282. },
  283. ),
  284. ))
  285. .discard_result()
  286. }
  287. pub fn def_create_dword_field<'a, 'c>() -> impl Parser<'a, 'c, ()>
  288. where
  289. 'c: 'a,
  290. {
  291. /*
  292. * DefCreateDWordField := 0x8a SourceBuf ByteIndex NameString
  293. * SourceBuf := TermArg => Buffer
  294. * ByteIndex := TermArg => Integer
  295. */
  296. opcode(opcode::DEF_CREATE_DWORD_FIELD_OP)
  297. .then(comment_scope(
  298. DebugVerbosity::AllScopes,
  299. "DefCreateDWordField",
  300. term_arg().then(term_arg()).then(name_string()).map_with_context(
  301. |((source, index), name), context| {
  302. let source_data: Arc<spinning_top::Spinlock<Vec<u8>>> =
  303. try_with_context!(context, source.as_buffer(context)).clone();
  304. let index = try_with_context!(context, index.as_integer(context));
  305. try_with_context!(
  306. context,
  307. context.namespace.add_value_at_resolved_path(
  308. name,
  309. &context.current_scope,
  310. AmlValue::BufferField { buffer_data: source_data, offset: index * 8, length: 32 }
  311. )
  312. );
  313. (Ok(()), context)
  314. },
  315. ),
  316. ))
  317. .discard_result()
  318. }
  319. pub fn def_create_qword_field<'a, 'c>() -> impl Parser<'a, 'c, ()>
  320. where
  321. 'c: 'a,
  322. {
  323. /*
  324. * DefCreateQWordField := 0x8f SourceBuf ByteIndex NameString
  325. * SourceBuf := TermArg => Buffer
  326. * ByteIndex := TermArg => Integer
  327. */
  328. opcode(opcode::DEF_CREATE_QWORD_FIELD_OP)
  329. .then(comment_scope(
  330. DebugVerbosity::AllScopes,
  331. "DefCreateQWordField",
  332. term_arg().then(term_arg()).then(name_string()).map_with_context(
  333. |((source, index), name), context| {
  334. let source_data: Arc<spinning_top::Spinlock<Vec<u8>>> =
  335. try_with_context!(context, source.as_buffer(context)).clone();
  336. let index = try_with_context!(context, index.as_integer(context));
  337. try_with_context!(
  338. context,
  339. context.namespace.add_value_at_resolved_path(
  340. name,
  341. &context.current_scope,
  342. AmlValue::BufferField { buffer_data: source_data, offset: index * 8, length: 64 }
  343. )
  344. );
  345. (Ok(()), context)
  346. },
  347. ),
  348. ))
  349. .discard_result()
  350. }
  351. pub fn def_create_field<'a, 'c>() -> impl Parser<'a, 'c, ()>
  352. where
  353. 'c: 'a,
  354. {
  355. /*
  356. * DefCreateField := ExtOpPrefix 0x13 SourceBuf BitIndex NumBits NameString
  357. * SourceBuf := TermArg => Buffer
  358. * BitIndex := TermArg => Integer
  359. * NumBits := TermArg => Integer
  360. */
  361. ext_opcode(opcode::EXT_DEF_CREATE_FIELD_OP)
  362. .then(comment_scope(
  363. DebugVerbosity::Scopes,
  364. "DefCreateField",
  365. term_arg().then(term_arg()).then(term_arg()).then(name_string()).map_with_context(
  366. |(((source, index), num_bits), name), context| {
  367. let source_data: Arc<spinning_top::Spinlock<Vec<u8>>> =
  368. try_with_context!(context, source.as_buffer(context)).clone();
  369. let index = try_with_context!(context, index.as_integer(context));
  370. let num_bits = try_with_context!(context, num_bits.as_integer(context));
  371. try_with_context!(
  372. context,
  373. context.namespace.add_value_at_resolved_path(
  374. name,
  375. &context.current_scope,
  376. AmlValue::BufferField { buffer_data: source_data, offset: index, length: num_bits }
  377. )
  378. );
  379. (Ok(()), context)
  380. },
  381. ),
  382. ))
  383. .discard_result()
  384. }
  385. pub fn def_op_region<'a, 'c>() -> impl Parser<'a, 'c, ()>
  386. where
  387. 'c: 'a,
  388. {
  389. /*
  390. * DefOpRegion := ExtOpPrefix 0x80 NameString RegionSpace RegionOffset RegionLen
  391. * RegionSpace := ByteData (where 0x00 = SystemMemory
  392. * 0x01 = SystemIO
  393. * 0x02 = PciConfig
  394. * 0x03 = EmbeddedControl
  395. * 0x04 = SMBus
  396. * 0x05 = SystemCMOS
  397. * 0x06 = PciBarTarget
  398. * 0x07 = IPMI
  399. * 0x08 = GeneralPurposeIO
  400. * 0x09 = GenericSerialBus
  401. * 0x80-0xff = OEM Defined)
  402. * ByteData := 0x00 - 0xff
  403. * RegionOffset := TermArg => Integer
  404. * RegionLen := TermArg => Integer
  405. */
  406. ext_opcode(opcode::EXT_DEF_OP_REGION_OP)
  407. .then(comment_scope(
  408. DebugVerbosity::Scopes,
  409. "DefOpRegion",
  410. name_string().then(take()).then(term_arg()).then(term_arg()).map_with_context(
  411. |(((name, space), offset), length), context| {
  412. let region = match space {
  413. 0x00 => RegionSpace::SystemMemory,
  414. 0x01 => RegionSpace::SystemIo,
  415. 0x02 => RegionSpace::PciConfig,
  416. 0x03 => RegionSpace::EmbeddedControl,
  417. 0x04 => RegionSpace::SMBus,
  418. 0x05 => RegionSpace::SystemCmos,
  419. 0x06 => RegionSpace::PciBarTarget,
  420. 0x07 => RegionSpace::IPMI,
  421. 0x08 => RegionSpace::GeneralPurposeIo,
  422. 0x09 => RegionSpace::GenericSerialBus,
  423. space @ 0x80..=0xff => RegionSpace::OemDefined(space),
  424. byte => return (Err(Propagate::Err(AmlError::InvalidRegionSpace(byte))), context),
  425. };
  426. let offset = match offset.as_integer(context) {
  427. Ok(offset) => offset,
  428. Err(err) => return (Err(Propagate::Err(err)), context),
  429. };
  430. let length = match length.as_integer(context) {
  431. Ok(length) => length,
  432. Err(err) => return (Err(Propagate::Err(err)), context),
  433. };
  434. let parent_device = match region {
  435. RegionSpace::PciConfig | RegionSpace::IPMI | RegionSpace::GenericSerialBus => {
  436. let resolved_path = try_with_context!(context, name.resolve(&context.current_scope));
  437. Some(try_with_context!(context, resolved_path.parent()))
  438. }
  439. _ => None,
  440. };
  441. try_with_context!(
  442. context,
  443. context.namespace.add_value_at_resolved_path(
  444. name,
  445. &context.current_scope,
  446. AmlValue::OpRegion { region, offset, length, parent_device }
  447. )
  448. );
  449. (Ok(()), context)
  450. },
  451. ),
  452. ))
  453. .discard_result()
  454. }
  455. pub fn def_field<'a, 'c>() -> impl Parser<'a, 'c, ()>
  456. where
  457. 'c: 'a,
  458. {
  459. /*
  460. * DefField = ExtOpPrefix 0x81 PkgLength NameString FieldFlags FieldList
  461. * FieldFlags := ByteData
  462. */
  463. let opregion_as_handle = name_string().map_with_context(|region_name, context| {
  464. /*
  465. * We search for the opregion that this field is referencing here as we already have the correct starting
  466. * scope. If we leave this to later, it becomes much harder as we also need to know the field's scope.
  467. */
  468. let (_, handle) =
  469. try_with_context!(context, context.namespace.search(&region_name, &context.current_scope));
  470. (Ok(handle), context)
  471. });
  472. ext_opcode(opcode::EXT_DEF_FIELD_OP)
  473. .then(comment_scope(
  474. DebugVerbosity::Scopes,
  475. "DefField",
  476. pkg_length().then(opregion_as_handle).then(take()).feed(|((list_length, region_handle), flags)| {
  477. move |mut input: &'a [u8], mut context: &'c mut AmlContext| -> ParseResult<'a, 'c, ()> {
  478. /*
  479. * FieldList := Nothing | <FieldElement FieldList>
  480. */
  481. // TODO: can this pattern be expressed as a combinator
  482. let mut current_offset = 0;
  483. while list_length.still_parsing(input) {
  484. let (new_input, new_context, field_length) =
  485. field_element(region_handle, FieldFlags::new(flags), current_offset)
  486. .parse(input, context)?;
  487. input = new_input;
  488. context = new_context;
  489. current_offset += field_length;
  490. }
  491. Ok((input, context, ()))
  492. }
  493. }),
  494. ))
  495. .discard_result()
  496. }
  497. /// Parses a `FieldElement`. Takes the current offset within the field list, and returns the length
  498. /// of the field element parsed.
  499. pub fn field_element<'a, 'c>(
  500. region_handle: AmlHandle,
  501. flags: FieldFlags,
  502. current_offset: u64,
  503. ) -> impl Parser<'a, 'c, u64>
  504. where
  505. 'c: 'a,
  506. {
  507. /*
  508. * FieldElement := NamedField | ReservedField | AccessField | ExtendedAccessField |
  509. * ConnectField
  510. * NamedField := NameSeg PkgLength
  511. * ReservedField := 0x00 PkgLength
  512. * AccessField := 0x01 AccessType AccessAttrib
  513. * ConnectField := <0x02 NameString> | <0x02 BufferData>
  514. * ExtendedAccessField := 0x03 AccessType ExtendedAccessAttrib AccessLength
  515. *
  516. * AccessType := ByteData
  517. * AccessAttrib := ByteData
  518. *
  519. * XXX: The spec says a ConnectField can be <0x02 BufferData>, but BufferData isn't an AML
  520. * object (it seems to be defined in ASL). We treat BufferData as if it was encoded like
  521. * DefBuffer, and this seems to work so far.
  522. */
  523. // TODO: parse ConnectField and ExtendedAccessField
  524. /*
  525. * Reserved fields shouldn't actually be added to the namespace; they seem to show gaps in
  526. * the operation region that aren't used for anything.
  527. */
  528. let reserved_field = opcode(opcode::RESERVED_FIELD)
  529. .then(region_pkg_length(region_handle))
  530. .map(|((), length)| Ok(length.raw_length as u64));
  531. // TODO: work out what to do with an access field
  532. // let access_field = opcode(opcode::ACCESS_FIELD)
  533. // .then(take())
  534. // .then(take())
  535. // .map_with_context(|(((), access_type), access_attrib), context| (Ok( , context));
  536. // TODO: fields' start and end offsets need to be checked against their enclosing
  537. // OperationRegions to make sure they don't sit outside or cross the boundary.
  538. // This might not be a problem if a sane ASL compiler is used (which should check this
  539. // at compile-time), but it's better to be safe and validate that as well.
  540. let named_field =
  541. name_seg().then(region_pkg_length(region_handle)).map_with_context(move |(name_seg, length), context| {
  542. try_with_context!(
  543. context,
  544. context.namespace.add_value_at_resolved_path(
  545. AmlName::from_name_seg(name_seg),
  546. &context.current_scope,
  547. AmlValue::Field {
  548. region: region_handle,
  549. flags,
  550. offset: current_offset,
  551. length: length.raw_length as u64,
  552. },
  553. )
  554. );
  555. (Ok(length.raw_length as u64), context)
  556. });
  557. choice!(reserved_field, named_field)
  558. }
  559. pub fn def_method<'a, 'c>() -> impl Parser<'a, 'c, ()>
  560. where
  561. 'c: 'a,
  562. {
  563. /*
  564. * DefMethod := 0x14 PkgLength NameString MethodFlags TermList
  565. * MethodFlags := ByteData (where bits 0-2: ArgCount (0 to 7)
  566. * bit 3: SerializeFlag (0 = Not Serialized, 1 = Serialized)
  567. * bits 4-7: SyncLevel (0x00 to 0x0f))
  568. */
  569. opcode(opcode::DEF_METHOD_OP)
  570. .then(comment_scope(
  571. DebugVerbosity::Scopes,
  572. "DefMethod",
  573. pkg_length()
  574. .then(name_string())
  575. .then(take())
  576. .feed(|((length, name), flags)| {
  577. take_to_end_of_pkglength(length).map(move |code| Ok((name.clone(), flags, code)))
  578. })
  579. .map_with_context(|(name, flags, code), context| {
  580. try_with_context!(
  581. context,
  582. context.namespace.add_value_at_resolved_path(
  583. name,
  584. &context.current_scope,
  585. AmlValue::Method {
  586. flags: MethodFlags::from(flags),
  587. code: MethodCode::Aml(code.to_vec())
  588. },
  589. )
  590. );
  591. (Ok(()), context)
  592. }),
  593. ))
  594. .discard_result()
  595. }
  596. pub fn def_external<'a, 'c>() -> impl Parser<'a, 'c, ()>
  597. where
  598. 'c: 'a,
  599. {
  600. /*
  601. * DefExternal = 0x15 NameString ObjectType ArgumentCount
  602. * ObjectType := ByteData
  603. * ArgumentCount := ByteData (0 to 7)
  604. */
  605. opcode(opcode::DEF_EXTERNAL_OP)
  606. .then(comment_scope(DebugVerbosity::Scopes, "DefExternal", name_string().then(take()).then(take())))
  607. .discard_result()
  608. }
  609. pub fn def_device<'a, 'c>() -> impl Parser<'a, 'c, ()>
  610. where
  611. 'c: 'a,
  612. {
  613. /*
  614. * DefDevice := ExtOpPrefix 0x82 PkgLength NameString TermList
  615. */
  616. ext_opcode(opcode::EXT_DEF_DEVICE_OP)
  617. .then(comment_scope(
  618. DebugVerbosity::Scopes,
  619. "DefDevice",
  620. pkg_length()
  621. .then(name_string())
  622. .map_with_context(|(length, name), context| {
  623. let resolved_name = try_with_context!(context, name.resolve(&context.current_scope));
  624. try_with_context!(
  625. context,
  626. context.namespace.add_value(resolved_name.clone(), AmlValue::Device)
  627. );
  628. try_with_context!(
  629. context,
  630. context.namespace.add_level(resolved_name.clone(), LevelType::Device)
  631. );
  632. let previous_scope = context.current_scope.clone();
  633. context.current_scope = resolved_name;
  634. (Ok((length, previous_scope)), context)
  635. })
  636. .feed(|(length, previous_scope)| term_list(length).map(move |_| Ok(previous_scope.clone())))
  637. .map_with_context(|previous_scope, context| {
  638. context.current_scope = previous_scope;
  639. (Ok(()), context)
  640. }),
  641. ))
  642. .discard_result()
  643. }
  644. pub fn def_processor<'a, 'c>() -> impl Parser<'a, 'c, ()>
  645. where
  646. 'c: 'a,
  647. {
  648. /*
  649. * DefProcessor := ExtOpPrefix 0x83 PkgLength NameString ProcID PblkAddress PblkLen TermList
  650. * ProcID := ByteData
  651. * PblkAddress := DWordData
  652. * PblkLen := ByteData
  653. */
  654. ext_opcode(opcode::EXT_DEF_PROCESSOR_OP)
  655. .then(comment_scope(
  656. DebugVerbosity::Scopes,
  657. "DefProcessor",
  658. pkg_length()
  659. .then(name_string())
  660. .then(take())
  661. .then(take_u32())
  662. .then(take())
  663. .map_with_context(|((((pkg_length, name), proc_id), pblk_address), pblk_len), context| {
  664. /*
  665. * Legacy `Processor` objects contain data within themselves, and can also have sub-objects,
  666. * so we add both a level for the sub-objects, and a value for the data.
  667. */
  668. let resolved_name = try_with_context!(context, name.resolve(&context.current_scope));
  669. try_with_context!(
  670. context,
  671. context.namespace.add_level(resolved_name.clone(), LevelType::Processor)
  672. );
  673. try_with_context!(
  674. context,
  675. context.namespace.add_value(
  676. resolved_name.clone(),
  677. AmlValue::Processor { id: proc_id, pblk_address, pblk_len }
  678. )
  679. );
  680. let previous_scope = context.current_scope.clone();
  681. context.current_scope = resolved_name;
  682. (Ok((previous_scope, pkg_length)), context)
  683. })
  684. .feed(move |(previous_scope, pkg_length)| {
  685. term_list(pkg_length).map(move |_| Ok(previous_scope.clone()))
  686. })
  687. .map_with_context(|previous_scope, context| {
  688. context.current_scope = previous_scope;
  689. (Ok(()), context)
  690. }),
  691. ))
  692. .discard_result()
  693. }
  694. pub fn def_power_res<'a, 'c>() -> impl Parser<'a, 'c, ()>
  695. where
  696. 'c: 'a,
  697. {
  698. /*
  699. * DefPowerRes := ExtOpPrefix 0x84 PkgLength NameString SystemLevel ResourceOrder TermList
  700. * SystemLevel := ByteData
  701. * ResourceOrder := WordData
  702. */
  703. ext_opcode(opcode::EXT_DEF_POWER_RES_OP)
  704. .then(comment_scope(
  705. DebugVerbosity::Scopes,
  706. "DefPowerRes",
  707. pkg_length()
  708. .then(name_string())
  709. .then(take())
  710. .then(take_u16())
  711. .map_with_context(|(((pkg_length, name), system_level), resource_order), context| {
  712. /*
  713. * `PowerResource` objects contain data within themselves, and can also have sub-objects,
  714. * so we add both a level for the sub-objects, and a value for the data.
  715. */
  716. let resolved_name = try_with_context!(context, name.resolve(&context.current_scope));
  717. try_with_context!(
  718. context,
  719. context.namespace.add_level(resolved_name.clone(), LevelType::PowerResource)
  720. );
  721. try_with_context!(
  722. context,
  723. context.namespace.add_value(
  724. resolved_name.clone(),
  725. AmlValue::PowerResource { system_level, resource_order }
  726. )
  727. );
  728. let previous_scope = context.current_scope.clone();
  729. context.current_scope = resolved_name;
  730. (Ok((previous_scope, pkg_length)), context)
  731. })
  732. .feed(move |(previous_scope, pkg_length)| {
  733. term_list(pkg_length).map(move |_| Ok(previous_scope.clone()))
  734. })
  735. .map_with_context(|previous_scope, context| {
  736. context.current_scope = previous_scope;
  737. (Ok(()), context)
  738. }),
  739. ))
  740. .discard_result()
  741. }
  742. pub fn def_thermal_zone<'a, 'c>() -> impl Parser<'a, 'c, ()>
  743. where
  744. 'c: 'a,
  745. {
  746. /*
  747. * DefThermalZone := ExtOpPrefix 0x85 PkgLength NameString TermList
  748. * TODO: we use this pattern a lot (move into scope, parse a term_list, move back out). Could we simplify into
  749. * just a `feed` by passing a scope into term_list?
  750. */
  751. ext_opcode(opcode::EXT_DEF_THERMAL_ZONE_OP)
  752. .then(comment_scope(
  753. DebugVerbosity::Scopes,
  754. "DefThermalZone",
  755. pkg_length()
  756. .then(name_string())
  757. .map_with_context(|(pkg_length, name), context| {
  758. let resolved_name = try_with_context!(context, name.resolve(&context.current_scope));
  759. try_with_context!(
  760. context,
  761. context.namespace.add_value(resolved_name.clone(), AmlValue::ThermalZone)
  762. );
  763. try_with_context!(
  764. context,
  765. context.namespace.add_level(resolved_name.clone(), LevelType::ThermalZone)
  766. );
  767. let previous_scope = context.current_scope.clone();
  768. context.current_scope = resolved_name;
  769. (Ok((pkg_length, previous_scope)), context)
  770. })
  771. .feed(|(length, previous_scope)| term_list(length).map(move |_| Ok(previous_scope.clone())))
  772. .map_with_context(|previous_scope, context| {
  773. context.current_scope = previous_scope;
  774. (Ok(()), context)
  775. }),
  776. ))
  777. .discard_result()
  778. }
  779. pub fn def_mutex<'a, 'c>() -> impl Parser<'a, 'c, ()>
  780. where
  781. 'c: 'a,
  782. {
  783. /*
  784. * DefMutex := ExtOpPrefix 0x01 NameString SyncFlags
  785. * SyncFlags := ByteData (where bits 0-3: SyncLevel
  786. * bits 4-7: Reserved)
  787. */
  788. ext_opcode(opcode::EXT_DEF_MUTEX_OP)
  789. .then(comment_scope(
  790. DebugVerbosity::Scopes,
  791. "DefMutex",
  792. name_string().then(take()).map_with_context(|(name, sync_level), context| {
  793. try_with_context!(
  794. context,
  795. context.namespace.add_value_at_resolved_path(
  796. name,
  797. &context.current_scope,
  798. AmlValue::Mutex { sync_level }
  799. )
  800. );
  801. (Ok(()), context)
  802. }),
  803. ))
  804. .discard_result()
  805. }
  806. pub fn def_cond_ref_of<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  807. where
  808. 'c: 'a,
  809. {
  810. /*
  811. * DefCondRefOf := ExtOpPrefix 0x12 NameString Target => boolean
  812. */
  813. ext_opcode(opcode::EXT_DEF_COND_REF_OF_OP)
  814. .then(comment_scope(
  815. DebugVerbosity::Scopes,
  816. "DefCondRefOf",
  817. name_string().then(target()).map_with_context(|(source, target), context| {
  818. let handle = context.namespace.search(&source, &context.current_scope);
  819. let result = AmlValue::Boolean(handle.is_ok());
  820. if let Ok((_name, _handle)) = handle {
  821. match target {
  822. Target::Null => { /* just return the result of the check */ }
  823. _ => return (Err(Propagate::Err(AmlError::Unimplemented)), context),
  824. }
  825. }
  826. (Ok(result), context)
  827. }),
  828. ))
  829. .map(|((), result)| Ok(result))
  830. }
  831. pub fn term_arg<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  832. where
  833. 'c: 'a,
  834. {
  835. /*
  836. * TermArg := ExpressionOpcode | DataObject | ArgObj | LocalObj
  837. */
  838. comment_scope(
  839. DebugVerbosity::AllScopes,
  840. "TermArg",
  841. choice!(
  842. data_object(),
  843. arg_obj().map_with_context(|arg_num, context| {
  844. (Ok(try_with_context!(context, context.current_arg(arg_num)).clone()), context)
  845. }),
  846. local_obj().map_with_context(|local_num, context| {
  847. (Ok(try_with_context!(context, context.local(local_num)).clone()), context)
  848. }),
  849. expression_opcode()
  850. ),
  851. )
  852. }
  853. pub fn data_ref_object<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  854. where
  855. 'c: 'a,
  856. {
  857. /*
  858. * DataRefObject := DataObject | ObjectReference | DDBHandle
  859. */
  860. comment_scope(DebugVerbosity::AllScopes, "DataRefObject", choice!(data_object()))
  861. }
  862. pub fn data_object<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  863. where
  864. 'c: 'a,
  865. {
  866. /*
  867. * DataObject := DefPackage | DefVarPackage | ComputationalData
  868. *
  869. * The order of the parsers are important here, as DefPackage and DefVarPackage can be
  870. * accidently parsed as ComputationalDatas.
  871. */
  872. // TODO: this doesn't yet parse DefVarPackage
  873. comment_scope(DebugVerbosity::AllScopes, "DataObject", choice!(def_package(), computational_data()))
  874. }
  875. pub fn computational_data<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  876. where
  877. 'c: 'a,
  878. {
  879. /*
  880. * ComputationalData := ByteConst | WordConst | DWordConst | QWordConst | String |
  881. * ConstObj | RevisionOp | DefBuffer
  882. * ByteConst := 0x0a ByteData
  883. * WordConst := 0x0b WordData
  884. * DWordConst := 0x0c DWordData
  885. * QWordConst := 0x0e QWordData
  886. * String := 0x0d AsciiCharList NullChar
  887. * ConstObj := ZeroOp(0x00) | OneOp(0x01) | OnesOp(0xff)
  888. * RevisionOp := ExtOpPrefix(0x5b) 0x30
  889. */
  890. let const_parser = |input: &'a [u8], context: &'c mut AmlContext| {
  891. let string_parser = |input: &'a [u8], context| -> ParseResult<'a, 'c, AmlValue> {
  892. /*
  893. * Using `position` isn't very efficient here, but is probably fine because the
  894. * strings are usually quite short.
  895. */
  896. let nul_position = match input.iter().position(|&c| c == b'\0') {
  897. Some(position) => position,
  898. None => return Err((input, context, Propagate::Err(AmlError::UnterminatedStringConstant))),
  899. };
  900. let string = String::from(match str::from_utf8(&input[0..nul_position]) {
  901. Ok(string) => string,
  902. Err(_) => return Err((input, context, Propagate::Err(AmlError::InvalidStringConstant))),
  903. });
  904. Ok((&input[(nul_position + 1)..], context, AmlValue::String(string)))
  905. };
  906. let (new_input, context, op) = take().parse(input, context)?;
  907. match op {
  908. opcode::BYTE_CONST => {
  909. take().map(|value| Ok(AmlValue::Integer(value as u64))).parse(new_input, context)
  910. }
  911. opcode::WORD_CONST => {
  912. take_u16().map(|value| Ok(AmlValue::Integer(value as u64))).parse(new_input, context)
  913. }
  914. opcode::DWORD_CONST => {
  915. take_u32().map(|value| Ok(AmlValue::Integer(value as u64))).parse(new_input, context)
  916. }
  917. opcode::QWORD_CONST => take_u64().map(|value| Ok(AmlValue::Integer(value))).parse(new_input, context),
  918. opcode::STRING_PREFIX => string_parser.parse(new_input, context),
  919. opcode::ZERO_OP => Ok((new_input, context, AmlValue::zero())),
  920. opcode::ONE_OP => Ok((new_input, context, AmlValue::one())),
  921. opcode::ONES_OP => Ok((new_input, context, AmlValue::ones())),
  922. _ => Err((input, context, Propagate::Err(AmlError::WrongParser))),
  923. }
  924. };
  925. comment_scope(
  926. DebugVerbosity::AllScopes,
  927. "ComputationalData",
  928. choice!(
  929. ext_opcode(opcode::EXT_REVISION_OP).map(|_| Ok(AmlValue::Integer(crate::AML_INTERPRETER_REVISION))),
  930. const_parser,
  931. def_buffer()
  932. ),
  933. )
  934. }
  935. #[cfg(test)]
  936. mod test {
  937. use super::*;
  938. use crate::test_utils::*;
  939. #[test]
  940. fn test_package() {
  941. let mut context = make_test_context();
  942. // The tests also check that DefPackage consumes no more input than required
  943. // Empty DefPackage
  944. check_ok_value!(
  945. def_package().parse(&[0x12, 0x02, 0x00, 0x12, 0x34], &mut context),
  946. AmlValue::Package(Vec::new()),
  947. &[0x12, 0x34]
  948. );
  949. // DefPackage where NumElements == package_content.len()
  950. check_ok_value!(
  951. def_package()
  952. .parse(&[0x12, 0x09, 0x04, 0x01, 0x0A, 0x02, 0x0A, 0x03, 0x0A, 0x04, 0x12, 0x34], &mut context),
  953. AmlValue::Package(alloc::vec![
  954. AmlValue::Integer(1),
  955. AmlValue::Integer(2),
  956. AmlValue::Integer(3),
  957. AmlValue::Integer(4)
  958. ]),
  959. &[0x12, 0x34]
  960. );
  961. // DefPackage where NumElements > package_content.len()
  962. check_ok_value!(
  963. def_package().parse(&[0x012, 0x05, 0x04, 0x01, 0x0A, 0x02, 0x12, 0x34], &mut context),
  964. AmlValue::Package(alloc::vec![
  965. AmlValue::Integer(1),
  966. AmlValue::Integer(2),
  967. AmlValue::Uninitialized,
  968. AmlValue::Uninitialized,
  969. ]),
  970. &[0x12, 0x34]
  971. );
  972. }
  973. #[test]
  974. fn test_computational_data() {
  975. let mut context = make_test_context();
  976. check_ok_value!(
  977. computational_data().parse(&[0x00, 0x34, 0x12], &mut context),
  978. AmlValue::Integer(0),
  979. &[0x34, 0x12]
  980. );
  981. check_ok_value!(
  982. computational_data().parse(&[0x01, 0x18, 0xf3], &mut context),
  983. AmlValue::Integer(1),
  984. &[0x18, 0xf3]
  985. );
  986. check_ok_value!(
  987. computational_data().parse(&[0xff, 0x98, 0xc3], &mut context),
  988. AmlValue::Integer(u64::max_value()),
  989. &[0x98, 0xc3]
  990. );
  991. check_ok_value!(
  992. computational_data().parse(&[0x5b, 0x30], &mut context),
  993. AmlValue::Integer(crate::AML_INTERPRETER_REVISION),
  994. &[]
  995. );
  996. check_ok_value!(
  997. computational_data().parse(&[0x0a, 0xf3, 0x35], &mut context),
  998. AmlValue::Integer(0xf3),
  999. &[0x35]
  1000. );
  1001. check_ok_value!(
  1002. computational_data().parse(&[0x0b, 0xf3, 0x35], &mut context),
  1003. AmlValue::Integer(0x35f3),
  1004. &[]
  1005. );
  1006. check_ok_value!(
  1007. computational_data().parse(&[0x0c, 0xf3, 0x35, 0x12, 0x65, 0xff, 0x00], &mut context),
  1008. AmlValue::Integer(0x651235f3),
  1009. &[0xff, 0x00]
  1010. );
  1011. check_ok_value!(
  1012. computational_data()
  1013. .parse(&[0x0e, 0xf3, 0x35, 0x12, 0x65, 0xff, 0x00, 0x67, 0xde, 0x28], &mut context),
  1014. AmlValue::Integer(0xde6700ff651235f3),
  1015. &[0x28]
  1016. );
  1017. check_ok_value!(
  1018. computational_data().parse(&[0x0d, b'A', b'B', b'C', b'D', b'\0', 0xff, 0xf5], &mut context),
  1019. AmlValue::String(String::from("ABCD")),
  1020. &[0xff, 0xf5]
  1021. );
  1022. }
  1023. }