1use 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#[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}