1use crate::{AcpiError, AcpiHandler, AcpiResult, AcpiTable, PhysicalMapping};
2use core::{fmt, mem::MaybeUninit, str};
3
4#[derive(Debug, Clone, Copy)]
7#[repr(transparent)]
8pub struct ExtendedField<T: Copy, const MIN_REVISION: u8>(MaybeUninit<T>);
9
10impl<T: Copy, const MIN_REVISION: u8> ExtendedField<T, MIN_REVISION> {
11 pub unsafe fn access(&self, revision: u8) -> Option<T> {
16 if revision >= MIN_REVISION {
17 Some(unsafe { self.0.assume_init() })
18 } else {
19 None
20 }
21 }
22}
23
24#[derive(Debug, Clone, Copy)]
99#[repr(C, packed)]
100pub struct SdtHeader {
101 pub signature: Signature,
102 pub length: u32,
103 pub revision: u8,
104 pub checksum: u8,
105 pub oem_id: [u8; 6],
106 pub oem_table_id: [u8; 8],
107 pub oem_revision: u32,
108 pub creator_id: u32,
109 pub creator_revision: u32,
110}
111
112impl SdtHeader {
113 fn validate_header_fields(&self, signature: Signature) -> AcpiResult<()> {
115 if self.signature != signature || str::from_utf8(&self.signature.0).is_err() {
117 return Err(AcpiError::SdtInvalidSignature(signature));
118 }
119
120 if str::from_utf8(&self.oem_id).is_err() {
122 return Err(AcpiError::SdtInvalidOemId(signature));
123 }
124
125 if str::from_utf8(&self.oem_table_id).is_err() {
127 return Err(AcpiError::SdtInvalidTableId(signature));
128 }
129
130 Ok(())
131 }
132
133 fn validate_checksum(&self, signature: Signature) -> AcpiResult<()> {
135 let table_bytes =
137 unsafe { core::slice::from_raw_parts((self as *const SdtHeader).cast::<u8>(), self.length as usize) };
138 let sum = table_bytes.iter().fold(0u8, |sum, &byte| sum.wrapping_add(byte));
139
140 if sum == 0 {
141 Ok(())
142 } else {
143 Err(AcpiError::SdtInvalidChecksum(signature))
144 }
145 }
146
147 pub fn validate(&self, signature: Signature) -> AcpiResult<()> {
155 self.validate_header_fields(signature)?;
156 self.validate_checksum(signature)?;
157
158 Ok(())
159 }
160
161 pub(crate) fn validate_lazy<H: AcpiHandler, T: AcpiTable>(
168 header_mapping: PhysicalMapping<H, Self>,
169 handler: H,
170 ) -> AcpiResult<PhysicalMapping<H, T>> {
171 header_mapping.validate_header_fields(T::SIGNATURE)?;
172
173 let table_length = header_mapping.length as usize;
175 let table_mapping = if header_mapping.mapped_length() >= table_length {
176 let header_mapping = core::mem::ManuallyDrop::new(header_mapping);
178
179 unsafe {
181 PhysicalMapping::new(
182 header_mapping.physical_start(),
183 header_mapping.virtual_start().cast::<T>(),
184 table_length,
185 header_mapping.mapped_length(),
186 handler,
187 )
188 }
189 } else {
190 let table_phys_start = header_mapping.physical_start();
192 drop(header_mapping);
193
194 unsafe { handler.map_physical_region(table_phys_start, table_length) }
196 };
197
198 table_mapping.get().validate()?;
201
202 Ok(table_mapping)
203 }
204
205 pub fn oem_id(&self) -> &str {
206 str::from_utf8(&self.oem_id).unwrap()
208 }
209
210 pub fn oem_table_id(&self) -> &str {
211 str::from_utf8(&self.oem_table_id).unwrap()
213 }
214}
215
216#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
217#[repr(transparent)]
218pub struct Signature([u8; 4]);
219
220impl Signature {
221 pub const RSDT: Signature = Signature(*b"RSDT");
222 pub const XSDT: Signature = Signature(*b"XSDT");
223 pub const FADT: Signature = Signature(*b"FACP");
224 pub const HPET: Signature = Signature(*b"HPET");
225 pub const MADT: Signature = Signature(*b"APIC");
226 pub const MCFG: Signature = Signature(*b"MCFG");
227 pub const SSDT: Signature = Signature(*b"SSDT");
228 pub const BERT: Signature = Signature(*b"BERT");
229 pub const BGRT: Signature = Signature(*b"BGRT");
230 pub const CPEP: Signature = Signature(*b"CPEP");
231 pub const DSDT: Signature = Signature(*b"DSDT");
232 pub const ECDT: Signature = Signature(*b"ECDT");
233 pub const EINJ: Signature = Signature(*b"EINJ");
234 pub const ERST: Signature = Signature(*b"ERST");
235 pub const FACS: Signature = Signature(*b"FACS");
236 pub const FPDT: Signature = Signature(*b"FPDT");
237 pub const GTDT: Signature = Signature(*b"GTDT");
238 pub const HEST: Signature = Signature(*b"HEST");
239 pub const MSCT: Signature = Signature(*b"MSCT");
240 pub const MPST: Signature = Signature(*b"MPST");
241 pub const NFIT: Signature = Signature(*b"NFIT");
242 pub const PCCT: Signature = Signature(*b"PCCT");
243 pub const PHAT: Signature = Signature(*b"PHAT");
244 pub const PMTT: Signature = Signature(*b"PMTT");
245 pub const PSDT: Signature = Signature(*b"PSDT");
246 pub const RASF: Signature = Signature(*b"RASF");
247 pub const SBST: Signature = Signature(*b"SBST");
248 pub const SDEV: Signature = Signature(*b"SDEV");
249 pub const SLIT: Signature = Signature(*b"SLIT");
250 pub const SRAT: Signature = Signature(*b"SRAT");
251 pub const AEST: Signature = Signature(*b"AEST");
252 pub const BDAT: Signature = Signature(*b"BDAT");
253 pub const CDIT: Signature = Signature(*b"CDIT");
254 pub const CEDT: Signature = Signature(*b"CEDT");
255 pub const CRAT: Signature = Signature(*b"CRAT");
256 pub const CSRT: Signature = Signature(*b"CSRT");
257 pub const DBGP: Signature = Signature(*b"DBGP");
258 pub const DBG2: Signature = Signature(*b"DBG2");
259 pub const DMAR: Signature = Signature(*b"DMAR");
260 pub const DRTM: Signature = Signature(*b"DRTM");
261 pub const ETDT: Signature = Signature(*b"ETDT");
262 pub const IBFT: Signature = Signature(*b"IBFT");
263 pub const IORT: Signature = Signature(*b"IORT");
264 pub const IVRS: Signature = Signature(*b"IVRS");
265 pub const LPIT: Signature = Signature(*b"LPIT");
266 pub const MCHI: Signature = Signature(*b"MCHI");
267 pub const MPAM: Signature = Signature(*b"MPAM");
268 pub const MSDM: Signature = Signature(*b"MSDM");
269 pub const PRMT: Signature = Signature(*b"PRMT");
270 pub const RGRT: Signature = Signature(*b"RGRT");
271 pub const SDEI: Signature = Signature(*b"SDEI");
272 pub const SLIC: Signature = Signature(*b"SLIC");
273 pub const SPCR: Signature = Signature(*b"SPCR");
274 pub const SPMI: Signature = Signature(*b"SPMI");
275 pub const STAO: Signature = Signature(*b"STAO");
276 pub const SVKL: Signature = Signature(*b"SVKL");
277 pub const TCPA: Signature = Signature(*b"TCPA");
278 pub const TPM2: Signature = Signature(*b"TPM2");
279 pub const UEFI: Signature = Signature(*b"UEFI");
280 pub const WAET: Signature = Signature(*b"WAET");
281 pub const WDAT: Signature = Signature(*b"WDAT");
282 pub const WDRT: Signature = Signature(*b"WDRT");
283 pub const WPBT: Signature = Signature(*b"WPBT");
284 pub const WSMT: Signature = Signature(*b"WSMT");
285 pub const XENV: Signature = Signature(*b"XENV");
286
287 pub fn as_str(&self) -> &str {
288 str::from_utf8(&self.0).unwrap()
289 }
290}
291
292impl fmt::Display for Signature {
293 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
294 write!(f, "{}", self.as_str())
295 }
296}
297
298impl fmt::Debug for Signature {
299 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300 write!(f, "\"{}\"", self.as_str())
301 }
302}