acpi/dsdt/
helpers.rs
1pub fn encode_name(name: &[u8]) -> Vec<u8> {
5 let mut encoded_name: Vec<u8> = Vec::new();
6 let mut segments: Vec<[u8; 4]> = Vec::new();
7 let mut i = 0;
8 if name[0] == b'\\' {
9 encoded_name.push(b'\\');
10 i = 1;
11 }
12 loop {
13 if i == name.len() {
14 break;
15 }
16
17 if name[i] == b'^' {
18 assert!(
19 (encoded_name.is_empty() || encoded_name[encoded_name.len() - 1] == b'^')
20 && segments.is_empty()
21 );
22 encoded_name.push(b'^');
23 i += 1;
24 continue;
25 }
26
27 assert!((name[i] == b'_') || (name[i] >= b'A' && name[i] <= b'Z'));
28 let mut seg: [u8; 4] = [b'_'; 4];
29 let mut seg_i = 0;
30 loop {
31 let off = i + seg_i;
32 if off == name.len() || name[off] == b'.' {
33 break;
34 }
35
36 assert!(seg_i < 4);
37 assert!(
38 (name[off] == b'_')
39 || (name[off] >= b'A' && name[off] <= b'Z')
40 || (name[off] >= b'0' && name[off] <= b'9')
41 );
42 seg[seg_i] = name[off];
43 seg_i += 1
44 }
45 assert!(seg_i > 0);
46 segments.push(seg);
47 i += seg_i;
49 if i < name.len() {
50 i += 1;
52 }
53 }
54 if segments.len() > 2 {
55 encoded_name.push(0x2f);
56 encoded_name.push(u8::try_from(segments.len()).unwrap());
57 } else if segments.len() > 1 {
58 encoded_name.push(0x2e);
59 }
60 for seg in segments {
61 encoded_name.extend_from_slice(&seg);
62 }
63 encoded_name
64}
65
66pub fn encode_package_len(len: usize) -> Vec<u8> {
67 assert!(len < (1 << 28) - 1);
68 let mut result: Vec<u8> = Vec::new();
69 if len < 63 {
70 result.push(u8::try_from(len).unwrap() + 1);
71 } else {
72 let len_bytes = if len < 1 << 12 {
76 2
77 } else if len < 1 << 20 {
78 3
79 } else {
80 4
81 };
82
83 let mut encoded_len: [u8; 4] = [0; 4];
84 let mut rem = len + len_bytes;
85 encoded_len[0] =
87 u8::try_from((len_bytes - 1) << 6).unwrap() | u8::try_from(rem & 0xf).unwrap();
88 rem >>= 4;
89 for e in encoded_len.iter_mut().take(len_bytes).skip(1) {
90 *e = u8::try_from(rem & 0xff).unwrap();
91 rem >>= 8;
92 }
93
94 result.extend_from_slice(&encoded_len[..len_bytes]);
95 }
96 result
97}
98
99pub fn encode_integer(value: u64) -> Vec<u8> {
100 let mut byte_stream: Vec<u8> = Vec::new();
101 let end;
102 if value == 0 {
103 return vec![0];
105 } else if value == 1 {
106 return vec![1];
108 } else if value <= 0xff {
109 byte_stream.push(0xa);
110 end = 1;
111 } else if value <= 0xffff {
112 byte_stream.push(0xb);
113 end = 2;
114 } else if value <= 0xffffffff {
115 byte_stream.push(0xc);
116 end = 4;
117 } else {
118 byte_stream.push(0xe);
119 end = 8;
120 }
121
122 let bytes = value.to_le_bytes();
123 byte_stream.extend_from_slice(&bytes[..end]);
124 byte_stream
125}
126
127pub fn encode_dword(value: u32) -> Vec<u8> {
128 let mut byte_stream = vec![0xcu8];
129 byte_stream.extend_from_slice(&value.to_le_bytes());
130 while byte_stream.len() < 5 {
131 byte_stream.push(0);
132 }
133 byte_stream
134}
135
136pub fn encode_string(value: &[u8]) -> Vec<u8> {
137 let mut byte_stream: Vec<u8> = Vec::new();
138 byte_stream.push(0xd);
139 byte_stream.extend_from_slice(value);
140 byte_stream.push(0);
141 byte_stream
142}
143
144pub fn char_to_hex(value: u8) -> u8 {
145 match value {
146 b'0'..=b'9' => value - b'0',
147 b'a'..=b'f' => 10 + value - b'a',
148 b'A'..=b'F' => 10 + value - b'A',
149 _ => panic!("Unsupported hex char {}", value),
150 }
151}
152
153#[cfg(test)]
154mod tests {
155 use super::*;
156 use crate::dsdt::tests::verify_expected_bytes;
157
158 #[test]
159 fn verify_simple_name() {
160 let bytes = encode_name(b"FOO");
161 verify_expected_bytes(&bytes, b"FOO_");
162 }
163
164 #[test]
165 fn verify_simple_name_with_root() {
166 let bytes = encode_name(b"\\FOO");
167 verify_expected_bytes(&bytes, b"\\FOO_");
168 }
169
170 #[test]
171 fn verify_simple_name_with_prefix() {
172 let bytes = encode_name(b"^FOO");
173 verify_expected_bytes(&bytes, b"^FOO_");
174 }
175
176 #[test]
177 fn verify_dual_name() {
178 let bytes = encode_name(b"FOO.BAR");
179 verify_expected_bytes(&bytes, b"\x2eFOO_BAR_");
180 }
181
182 #[test]
183 fn verify_dual_name_with_root() {
184 let bytes = encode_name(b"\\_SB.FOO");
185 verify_expected_bytes(&bytes, b"\\\x2e_SB_FOO_");
186 }
187
188 #[test]
189 fn verify_multi_name() {
190 let bytes = encode_name(b"FOO.BAR.BAZ.BLAM");
191 verify_expected_bytes(&bytes, b"\x2f\x04FOO_BAR_BAZ_BLAM");
192 }
193}