acpi_tables/
xsdt.rs

1// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// Copyright 2023 Rivos, Inc.
3//
4// SPDX-License-Identifier: Apache-2.0
5
6use std::mem::size_of;
7
8use vm_memory::{Address, Bytes, GuestAddress, GuestMemory};
9use zerocopy::IntoBytes;
10
11use crate::{AcpiError, Result, Sdt, SdtHeader, checksum};
12
13/// Extended System Description Table (XSDT)
14///
15/// This table provides 64bit addresses to the rest of the ACPI tables defined by the platform
16/// More information about this table can be found in the ACPI specification:
17/// https://uefi.org/specs/ACPI/6.5/05_ACPI_Software_Programming_Model.html#extended-system-description-table-xsdt
18#[derive(Clone, Default, Debug)]
19pub struct Xsdt {
20    header: SdtHeader,
21    tables: Vec<u8>,
22}
23
24impl Xsdt {
25    pub fn new(
26        oem_id: [u8; 6],
27        oem_table_id: [u8; 8],
28        oem_revision: u32,
29        tables: Vec<u64>,
30    ) -> Self {
31        let mut tables_bytes = Vec::with_capacity(8 * tables.len());
32        for addr in tables {
33            tables_bytes.extend(&addr.to_le_bytes());
34        }
35
36        let header = SdtHeader::new(
37            *b"XSDT",
38            (std::mem::size_of::<SdtHeader>() + tables_bytes.len())
39                .try_into()
40                .unwrap(),
41            1,
42            oem_id,
43            oem_table_id,
44            oem_revision,
45        );
46
47        let mut xsdt = Xsdt {
48            header,
49
50            tables: tables_bytes,
51        };
52
53        xsdt.header.checksum = checksum(&[xsdt.header.as_bytes(), (xsdt.tables.as_slice())]);
54
55        xsdt
56    }
57}
58
59impl Sdt for Xsdt {
60    fn len(&self) -> usize {
61        std::mem::size_of::<SdtHeader>() + self.tables.len()
62    }
63
64    fn write_to_guest<M: GuestMemory>(&mut self, mem: &M, address: GuestAddress) -> Result<()> {
65        mem.write_slice(self.header.as_bytes(), address)?;
66        let address = address
67            .checked_add(size_of::<SdtHeader>() as u64)
68            .ok_or(AcpiError::InvalidGuestAddress)?;
69        mem.write_slice(self.tables.as_slice(), address)?;
70        Ok(())
71    }
72}