|  | @@ -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 |
 |