@@ -2,9 +2,23 @@ use crate::{
2
2
parser:: { take, take_n, Parser , Propagate } ,
3
3
AmlContext ,
4
4
AmlError ,
5
+ AmlHandle ,
6
+ AmlValue ,
5
7
} ;
6
8
use bit_field:: BitField ;
7
9
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
+
8
22
#[ derive( Clone , Copy , PartialEq , Eq , Debug ) ]
9
23
pub struct PkgLength {
10
24
pub raw_length : u32 ,
@@ -14,6 +28,12 @@ pub struct PkgLength {
14
28
pub end_offset : u32 ,
15
29
}
16
30
31
+ #[ derive( Clone , Copy , PartialEq , Eq , Debug ) ]
32
+ pub struct RegionPkgLength {
33
+ pub raw_length : u32 ,
34
+ pub end_offset : u32 ,
35
+ }
36
+
17
37
impl PkgLength {
18
38
pub fn from_raw_length ( stream : & [ u8 ] , raw_length : u32 ) -> Result < PkgLength , AmlError > {
19
39
Ok ( PkgLength {
@@ -29,6 +49,48 @@ impl PkgLength {
29
49
}
30
50
}
31
51
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
+
32
94
pub fn pkg_length < ' a , ' c > ( ) -> impl Parser < ' a , ' c , PkgLength >
33
95
where
34
96
' c : ' a ,
0 commit comments