acpi_tables/
rsdp.rs

1// Copyright © 2019 Intel Corporation
2// Copyright © 2023 Rivos, Inc.
3// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4//
5// SPDX-License-Identifier: Apache-2.0
6
7use vm_memory::{Bytes, GuestAddress, GuestMemory};
8use zerocopy::little_endian::{U32, U64};
9use zerocopy::{Immutable, IntoBytes};
10
11use crate::{Result, Sdt, checksum};
12
13// clippy doesn't understand that we actually "use" the fields of this struct when we serialize
14// them as bytes in guest memory, so here we just ignore dead code to avoid having to name
15// everything with an underscore prefix
16#[allow(dead_code)]
17/// Root System Description Pointer
18///
19/// This is the root pointer to the ACPI hierarchy. This is what OSs
20/// are looking for in the memory when initializing ACPI. It includes
21/// a pointer to XSDT
22/// More information about this structure can be found in the ACPI specification:
23/// https://uefi.org/specs/ACPI/6.5/05_ACPI_Software_Programming_Model.html#root-system-description-pointer-rsdp
24#[repr(C, packed)]
25#[derive(Clone, Copy, Debug, Default, IntoBytes, Immutable)]
26pub struct Rsdp {
27    signature: [u8; 8],
28    checksum: u8,
29    oem_id: [u8; 6],
30    revision: u8,
31    rsdt_addr: U32,
32    length: U32,
33    xsdt_addr: U64,
34    extended_checksum: u8,
35    reserved: [u8; 3],
36}
37
38impl Rsdp {
39    pub fn new(oem_id: [u8; 6], xsdt_addr: u64) -> Self {
40        let mut rsdp = Rsdp {
41            // Space in the end of string is needed!
42            signature: *b"RSD PTR ",
43            checksum: 0,
44            oem_id,
45            revision: 2,
46            rsdt_addr: U32::ZERO,
47            length: U32::new(std::mem::size_of::<Rsdp>().try_into().unwrap()),
48            xsdt_addr: U64::new(xsdt_addr),
49            extended_checksum: 0,
50            reserved: [0u8; 3],
51        };
52
53        rsdp.checksum = checksum(&[&rsdp.as_bytes()[..20]]);
54        rsdp.extended_checksum = checksum(&[rsdp.as_bytes()]);
55        rsdp
56    }
57}
58
59impl Sdt for Rsdp {
60    fn len(&self) -> usize {
61        self.as_bytes().len()
62    }
63
64    fn write_to_guest<M: GuestMemory>(&mut self, mem: &M, address: GuestAddress) -> Result<()> {
65        mem.write_slice(self.as_bytes(), address)?;
66        Ok(())
67    }
68}