@@ -2,9 +2,23 @@ use crate::{
22 parser:: { take, take_n, Parser , Propagate } ,
33 AmlContext ,
44 AmlError ,
5+ AmlHandle ,
6+ AmlValue ,
57} ;
68use bit_field:: BitField ;
79
10+ /*
11+ * There are two types of PkgLength implemented: PkgLength and RegionPkgLength. The reason for this
12+ * is that while both are parsed as PkgLength op, they might have different meanings in different
13+ * contexts:
14+ *
15+ * - PkgLength refers to an offset within the AML input slice
16+ * - RegionPkgLength refers to an offset within an operation region (and is used this way in parsers
17+ * like def_field())
18+ *
19+ * They both have identical fields, but the fields themselves have an entirely different meaning.
20+ */
21+
822#[ derive( Clone , Copy , PartialEq , Eq , Debug ) ]
923pub struct PkgLength {
1024 pub raw_length : u32 ,
@@ -14,6 +28,12 @@ pub struct PkgLength {
1428 pub end_offset : u32 ,
1529}
1630
31+ #[ derive( Clone , Copy , PartialEq , Eq , Debug ) ]
32+ pub struct RegionPkgLength {
33+ pub raw_length : u32 ,
34+ pub end_offset : u32 ,
35+ }
36+
1737impl PkgLength {
1838 pub fn from_raw_length ( stream : & [ u8 ] , raw_length : u32 ) -> Result < PkgLength , AmlError > {
1939 Ok ( PkgLength {
@@ -29,6 +49,48 @@ impl PkgLength {
2949 }
3050}
3151
52+ impl RegionPkgLength {
53+ pub fn from_raw_length ( region_bit_length : u64 , raw_length : u32 ) -> Result < RegionPkgLength , AmlError > {
54+ Ok ( RegionPkgLength {
55+ raw_length,
56+ end_offset : ( region_bit_length as u32 )
57+ . checked_sub ( raw_length)
58+ . ok_or ( AmlError :: InvalidRegionPkgLength { region_bit_length, raw_length } ) ?,
59+ } )
60+ }
61+ }
62+
63+ pub fn region_pkg_length < ' a , ' c > ( region_handle : AmlHandle ) -> impl Parser < ' a , ' c , RegionPkgLength >
64+ where
65+ ' c : ' a ,
66+ {
67+ move |input : & ' a [ u8 ] , context : & ' c mut AmlContext | -> crate :: parser:: ParseResult < ' a , ' c , RegionPkgLength > {
68+ let region_value = match context. namespace . get ( region_handle) {
69+ Ok ( value) => value,
70+ Err ( err) => return Err ( ( input, context, Propagate :: Err ( err) ) ) ,
71+ } ;
72+
73+ /*
74+ * OperationRegion length is in bytes, PkgLength is in bits, so conversion is needed
75+ */
76+ let region_bit_length = match region_value {
77+ AmlValue :: OpRegion { length, .. } => * length * 8 ,
78+ _ => return Err ( ( input, context, Propagate :: Err ( AmlError :: FieldRegionIsNotOpRegion ) ) ) ,
79+ } ;
80+
81+ let ( new_input, context, raw_length) = raw_pkg_length ( ) . parse ( input, context) ?;
82+
83+ /*
84+ * NOTE: we use the original input here, because `raw_length` includes the length of the
85+ * `PkgLength`.
86+ */
87+ match RegionPkgLength :: from_raw_length ( region_bit_length, raw_length) {
88+ Ok ( pkg_length) => Ok ( ( new_input, context, pkg_length) ) ,
89+ Err ( err) => Err ( ( input, context, Propagate :: Err ( err) ) ) ,
90+ }
91+ }
92+ }
93+
3294pub fn pkg_length < ' a , ' c > ( ) -> impl Parser < ' a , ' c , PkgLength >
3395where
3496 ' c : ' a ,
0 commit comments