|
@@ -1,11 +1,12 @@
|
|
|
use crate::{
|
|
|
- name_object::name_string,
|
|
|
- opcode::{opcode, SCOPE_OP},
|
|
|
- parser::{choice, comment, comment_scope, take_n, ParseResult, Parser},
|
|
|
+ name_object::{name_seg, name_string},
|
|
|
+ opcode::{self, ext_opcode, opcode},
|
|
|
+ parser::{choice, comment_scope, take, take_u16, take_u32, take_u64, ParseResult, Parser},
|
|
|
pkg_length::{pkg_length, PkgLength},
|
|
|
value::{AmlValue, FieldFlags},
|
|
|
- AmlNamespace,
|
|
|
+ AmlError,
|
|
|
};
|
|
|
+use alloc::string::String;
|
|
|
use log::{debug, trace};
|
|
|
|
|
|
/// `TermList`s are usually found within explicit-length objects (so they have a `PkgLength`
|
|
@@ -30,14 +31,14 @@ pub fn term_object<'a>() -> impl Parser<'a, ()> {
|
|
|
* TermObj := NamespaceModifierObj | NamedObj | Type1Opcode | Type2Opcode
|
|
|
* NamespaceModifierObj := DefAlias | DefName | DefScope
|
|
|
*/
|
|
|
- comment_scope("TermObj", choice!(def_scope()))
|
|
|
+ comment_scope("TermObj", choice!(def_scope(), def_op_region(), def_field()))
|
|
|
}
|
|
|
|
|
|
pub fn def_scope<'a>() -> impl Parser<'a, ()> {
|
|
|
/*
|
|
|
* DefScope := 0x10 PkgLength NameString TermList
|
|
|
*/
|
|
|
- opcode(SCOPE_OP)
|
|
|
+ opcode(opcode::SCOPE_OP)
|
|
|
.then(comment_scope(
|
|
|
"DefScope",
|
|
|
pkg_length().then(name_string()).feed(move |(pkg_length, name)| {
|
|
@@ -47,6 +48,127 @@ pub fn def_scope<'a>() -> impl Parser<'a, ()> {
|
|
|
))
|
|
|
.discard_result()
|
|
|
}
|
|
|
+
|
|
|
+pub fn def_op_region<'a>() -> impl Parser<'a, ()> {
|
|
|
+ /*
|
|
|
+ * DefOpRegion := ExtOpPrefix 0x80 NameString RegionSpace RegionOffset RegionLen
|
|
|
+ * RegionSpace := ByteData (where 0x00 = SystemMemory
|
|
|
+ * 0x01 = SystemIO
|
|
|
+ * 0x02 = PciConfig
|
|
|
+ * 0x03 = EmbeddedControl
|
|
|
+ * 0x04 = SMBus
|
|
|
+ * 0x05 = SystemCMOS
|
|
|
+ * 0x06 = PciBarTarget
|
|
|
+ * 0x07 = IPMI
|
|
|
+ * 0x08 = GeneralPurposeIO
|
|
|
+ * 0x09 = GenericSerialBus
|
|
|
+ * 0x80-0xff = OEM Defined)
|
|
|
+ * ByteData := 0x00 - 0xff
|
|
|
+ * RegionOffset := TermArg => Integer
|
|
|
+ * RegionLen := TermArg => Integer
|
|
|
+ */
|
|
|
+ ext_opcode(opcode::EXT_OP_REGION_OP)
|
|
|
+ .then(comment_scope(
|
|
|
+ "DefOpRegion",
|
|
|
+ name_string().then(take()).then(term_arg()).then(term_arg()).map(
|
|
|
+ |(((name, space), offset), region_len)| {
|
|
|
+ trace!("Op region: {}, {}, {:?}, {:?}", name, space, offset, region_len);
|
|
|
+ ()
|
|
|
+ },
|
|
|
+ ),
|
|
|
+ ))
|
|
|
+ .discard_result()
|
|
|
+}
|
|
|
+
|
|
|
+pub fn def_field<'a>() -> impl Parser<'a, ()> {
|
|
|
+ /*
|
|
|
+ * DefField = ExtOpPrefix 0x81 PkgLength NameString FieldFlags FieldList
|
|
|
+ * FieldFlags := ByteData
|
|
|
+ */
|
|
|
+ ext_opcode(opcode::EXT_FIELD_OP)
|
|
|
+ .then(comment_scope(
|
|
|
+ "DefField",
|
|
|
+ pkg_length().then(name_string()).then(take()).feed(
|
|
|
+ |((list_length, region_name), flags)| {
|
|
|
+ move |mut input: &'a [u8]| -> ParseResult<'a, ()> {
|
|
|
+ /*
|
|
|
+ * FieldList := Nothing | <FieldElement FieldList>
|
|
|
+ */
|
|
|
+ // TODO: can this pattern be expressed as a combinator
|
|
|
+ while list_length.still_parsing(input) {
|
|
|
+ let (new_input, ()) =
|
|
|
+ field_element(®ion_name, FieldFlags::new(flags)).parse(input)?;
|
|
|
+ input = new_input;
|
|
|
+ }
|
|
|
+
|
|
|
+ Ok((input, ()))
|
|
|
+ }
|
|
|
+ },
|
|
|
+ ),
|
|
|
+ ))
|
|
|
+ .discard_result()
|
|
|
+}
|
|
|
+
|
|
|
+pub fn field_element<'a>(region_name: &String, flags: FieldFlags) -> impl Parser<'a, ()> {
|
|
|
+ /*
|
|
|
+ * FieldElement := NamedField | ReservedField | AccessField | ExtendedAccessField |
|
|
|
+ * ConnectField
|
|
|
+ * NamedField := NameSeg PkgLength
|
|
|
+ * ReservedField := 0x00 PkgLength
|
|
|
+ * AccessField := 0x01 AccessType AccessAttrib
|
|
|
+ * ConnectField := <0x02 NameString> | <0x02 BufferData>
|
|
|
+ * ExtendedAccessField := 0x03 AccessType ExtendedAccessAttrib AccessLength
|
|
|
+ *
|
|
|
+ * AccessType := ByteData
|
|
|
+ * AccessAttrib := ByteData
|
|
|
+ *
|
|
|
+ * XXX: The spec says a ConnectField can be <0x02 BufferData>, but BufferData isn't an AML
|
|
|
+ * object (it seems to be defined in ASL). We treat BufferData as if it was encoded like
|
|
|
+ * DefBuffer, and this seems to work so far.
|
|
|
+ */
|
|
|
+ // TODO: replace these maps with `with_context` and register the fields in the namespace
|
|
|
+ // TODO: parse ConnectField and ExtendedAccessField
|
|
|
+ let reserved_field =
|
|
|
+ opcode(opcode::RESERVED_FIELD).then(pkg_length()).map(|((), pkg_length)| {
|
|
|
+ trace!("Adding reserved field with length: {}", pkg_length.raw_length);
|
|
|
+ });
|
|
|
+
|
|
|
+ let access_field = opcode(opcode::ACCESS_FIELD).then(take()).then(take()).map(
|
|
|
+ |(((), access_type), access_attrib)| {
|
|
|
+ trace!(
|
|
|
+ "Adding access field with access_type: {}, access_attrib: {}",
|
|
|
+ access_type,
|
|
|
+ access_attrib
|
|
|
+ );
|
|
|
+ },
|
|
|
+ );
|
|
|
+
|
|
|
+ let named_field = name_seg().then(pkg_length()).map(|(name, length)| {
|
|
|
+ trace!("Named field with name {} and length {}", name.as_str(), length.raw_length);
|
|
|
+ });
|
|
|
+
|
|
|
+ choice!(reserved_field, access_field, named_field)
|
|
|
+}
|
|
|
+
|
|
|
+pub fn term_arg<'a>() -> impl Parser<'a, AmlValue> {
|
|
|
+ /*
|
|
|
+ * TermArg := Type2Opcode | DataObject | ArgObj | LocalObj
|
|
|
+ */
|
|
|
+ // TODO: this doesn't yet parse Term2Opcode, ArgObj, or LocalObj
|
|
|
+ comment_scope("TermArg", choice!(data_object()))
|
|
|
+}
|
|
|
+
|
|
|
+pub fn data_object<'a>() -> impl Parser<'a, AmlValue> {
|
|
|
+ /*
|
|
|
+ * DataObject := DefPackage | DefVarPackage | ComputationalData
|
|
|
+ *
|
|
|
+ * The order of the parsers are important here, as DefPackage and DefVarPackage can be
|
|
|
+ * accidently parsed as ComputationalDatas.
|
|
|
+ */
|
|
|
+ // TODO: this doesn't yet parse DefPackage or DefVarPackage
|
|
|
+ comment_scope("DataObject", choice!(computational_data()))
|
|
|
+}
|
|
|
+
|
|
|
pub fn computational_data<'a>() -> impl Parser<'a, AmlValue> {
|
|
|
/*
|
|
|
* ComputationalData := ByteConst | WordConst | DWordConst | QWordConst | String |
|