|
14 | 14 | // limitations under the License. |
15 | 15 | // |
16 | 16 |
|
| 17 | +use alloc::boxed::Box; |
17 | 18 | use core::fmt::Debug; |
18 | 19 |
|
19 | 20 | use x86_64::VirtAddr; |
@@ -140,7 +141,7 @@ impl Rsdp for Rsdp1 { |
140 | 141 | /// See Section 5.2.5.3 in the ACPI specification, Version 6.6 for more details. |
141 | 142 | #[repr(C, packed)] |
142 | 143 | #[derive(Debug, IntoBytes, Immutable, KnownLayout, TryFromBytes)] |
143 | | -struct Rsdp2 { |
| 144 | +pub struct Rsdp2 { |
144 | 145 | /// Signature: "RSD PTR " (note the trailing space). |
145 | 146 | signature: RsdpSignature, |
146 | 147 |
|
@@ -172,6 +173,41 @@ struct Rsdp2 { |
172 | 173 | } |
173 | 174 | static_assertions::assert_eq_size!(Rsdp2, [u8; 36usize]); |
174 | 175 |
|
| 176 | +impl Rsdp2 { |
| 177 | + #[allow(unused)] |
| 178 | + fn checksum(&self) -> u8 { |
| 179 | + // Just the RSDP1 header. |
| 180 | + self.as_bytes()[..size_of::<Rsdp1>()].iter().fold(0u8, |lhs, &rhs| lhs.wrapping_add(rhs)) |
| 181 | + } |
| 182 | + |
| 183 | + #[allow(unused)] |
| 184 | + fn extended_checksum(&self) -> u8 { |
| 185 | + self.as_bytes().iter().fold(0u8, |lhs, &rhs| lhs.wrapping_add(rhs)) |
| 186 | + } |
| 187 | + |
| 188 | + #[allow(unused)] |
| 189 | + pub fn new(rsdt: VirtAddr) -> Result<Box<Self>> { |
| 190 | + let mut rsdp = Box::new(Self { |
| 191 | + signature: RsdpSignature::default(), |
| 192 | + checksum: 0, |
| 193 | + oemid: [0; 6], |
| 194 | + revision: RsdpAcpi2Version::default(), |
| 195 | + rsdt_address: rsdt |
| 196 | + .as_u64() |
| 197 | + .try_into() |
| 198 | + .map_err(|_| "RSDT address not in low 32 bits")?, |
| 199 | + length: size_of::<Rsdp2>() as u32, |
| 200 | + xsdt_address: 0, |
| 201 | + extended_checksum: 0, |
| 202 | + _reserved: [0; 3], |
| 203 | + }); |
| 204 | + rsdp.checksum = rsdp.checksum.wrapping_sub(rsdp.checksum()); |
| 205 | + rsdp.extended_checksum = rsdp.extended_checksum.wrapping_sub(rsdp.extended_checksum()); |
| 206 | + |
| 207 | + Ok(rsdp) |
| 208 | + } |
| 209 | +} |
| 210 | + |
175 | 211 | impl Rsdp for Rsdp2 { |
176 | 212 | fn validate(&self) -> Result<()> { |
177 | 213 | let checksum = self.as_bytes().iter().fold(0u8, |lhs, &rhs| lhs.wrapping_add(rhs)); |
@@ -256,4 +292,16 @@ mod tests { |
256 | 292 | let mut buf = Vec::from(b"\x01\x02\x03\x04\x05\x06\x07\x08\x55 TEST \x00\x02\x02\x03\x04"); |
257 | 293 | assert_that!(<dyn Rsdp>::try_from_bytes_mut(&mut buf[..]), err(anything())); |
258 | 294 | } |
| 295 | + |
| 296 | + #[test] |
| 297 | + pub fn test_new_parse() { |
| 298 | + let rsdp = Rsdp2::new(VirtAddr::new(0x1000)).unwrap(); |
| 299 | + assert_that!(rsdp.rsdt(), some(eq(VirtAddr::new(0x1000)))); |
| 300 | + assert_that!(rsdp.xsdt(), none()); |
| 301 | + |
| 302 | + let mut buf = rsdp.as_bytes().to_vec(); |
| 303 | + let rsdp2 = <dyn Rsdp>::try_from_bytes_mut(&mut buf[..]).unwrap(); |
| 304 | + assert_that!(rsdp2.rsdt(), eq(rsdp.rsdt())); |
| 305 | + assert_that!(rsdp2.xsdt(), eq(rsdp.xsdt())); |
| 306 | + } |
259 | 307 | } |
0 commit comments