1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use super::AcpiError;
use core::{mem, str};
#[repr(C, packed)]
pub(crate) struct Rsdp {
signature: [u8; 8],
checksum: u8,
oem_id: [u8; 6],
revision: u8,
rsdt_address: u32,
length: u32,
xsdt_address: u64,
ext_checksum: u8,
reserved: [u8; 3],
}
impl Rsdp {
pub(crate) fn validate(&self) -> Result<(), AcpiError> {
if &self.signature != b"RSD PTR " {
return Err(AcpiError::RsdpIncorrectSignature);
}
if str::from_utf8(&self.oem_id).is_err() {
return Err(AcpiError::RsdpInvalidOemId);
}
let length = if self.revision > 0 {
mem::size_of::<Self>()
} else {
mem::size_of::<[u8; 8]>()
+ mem::size_of::<u8>()
+ mem::size_of::<[u8; 6]>()
+ mem::size_of::<u8>()
+ mem::size_of::<u32>()
};
let self_ptr = self as *const Rsdp as *const u8;
let mut sum: u8 = 0;
for i in 0..length {
sum = sum.wrapping_add(unsafe { *(self_ptr.offset(i as isize)) });
}
if sum != 0 {
return Err(AcpiError::RsdpInvalidChecksum);
}
Ok(())
}
pub(crate) fn oem_id<'a>(&'a self) -> &'a str {
str::from_utf8(&self.oem_id).unwrap()
}
pub(crate) fn revision(&self) -> u8 {
self.revision
}
pub(crate) fn rsdt_address(&self) -> u32 {
self.rsdt_address
}
pub(crate) fn xsdt_address(&self) -> u64 {
assert!(self.revision > 0, "Tried to read extended RSDP field with ACPI Version 1.0");
self.xsdt_address
}
}