1use vm_memory::{Bytes, GuestAddress, GuestMemory};
7use zerocopy::little_endian::{U16, U32, U64};
8use zerocopy::{Immutable, IntoBytes};
9
10use crate::{GenericAddressStructure, Result, Sdt, SdtHeader, checksum};
11
12#[cfg(target_arch = "x86_64")]
13pub const IAPC_BOOT_ARG_FLAGS_VGA_NOT_PRESENT: u16 = 2;
14#[cfg(target_arch = "x86_64")]
15pub const IAPC_BOOT_ARG_FLAGS_MSI_NOT_PRESENT: u16 = 3;
16#[cfg(target_arch = "x86_64")]
17pub const IAPC_BOOT_ARG_FLAGS_PCI_ASPM: u16 = 4;
18
19pub const FADT_F_PWR_BUTTON: u8 = 4;
26pub const FADT_F_SLP_BUTTON: u8 = 5;
30pub const FADT_F_HW_REDUCED_ACPI: u8 = 20;
33
34#[allow(dead_code)]
38#[repr(C, packed)]
45#[derive(Debug, Copy, Clone, Default, IntoBytes, Immutable)]
46pub struct Fadt {
47 header: SdtHeader,
48 firmware_control: U32,
49 dsdt: U32,
50 reserved_1: u8,
51 preferred_pm_profile: u8,
52 sci_int: U16,
54 smi_cmd: U32,
55 acpi_enable: u8,
56 acpi_disable: u8,
57 s4bios_req: u8,
58 pstate_cnt: u8,
59 pm1a_evt_blk: U32,
60 pm1b_evt_blk: U32,
61 pm1a_cnt_blk: U32,
62 pm1b_cnt_blk: U32,
63 pm2_cnt_blk: U32,
64 pm_tmr_blk: U32,
65 gpe0_blk: U32,
66 gpe1_blk: U32,
67 pm1_evt_len: u8,
68 pm1_cnt_len: u8,
69 pm2_cnt_len: u8,
70 pm_tmr_len: u8,
71 gpe0_blk_len: u8,
72 gpe1_blk_len: u8,
73 gpe1_base: u8,
74 cst_cnt: u8,
75 p_lvl2_lat: U16,
76 p_lvl3_lat: U16,
77 flush_size: U16,
78 flush_stride: U16,
79 duty_offset: u8,
80 duty_width: u8,
81 day_alrm: u8,
82 mon_alrm: u8,
83 century: u8,
84 iapc_boot_arch: U16,
85 reserved_2: u8,
86 flags: U32,
87 reset_reg: GenericAddressStructure,
88 reset_value: u8,
89 arm_boot_arch: U16,
90 fadt_minor_version: u8,
91 x_firmware_ctrl: U64,
92 x_dsdt: U64,
93 x_pm1a_evt_blk: GenericAddressStructure,
96 x_pm1b_evt_blk: GenericAddressStructure,
97 x_pm1a_cnt_blk: GenericAddressStructure,
98 x_pm1b_cnt_blk: GenericAddressStructure,
99 x_pm2_cnt_blk: GenericAddressStructure,
100 x_pm_tmr_blk: GenericAddressStructure,
101 x_gpe0_blk: GenericAddressStructure,
102 x_gpe1_blk: GenericAddressStructure,
103 sleep_control_reg: GenericAddressStructure,
104 sleep_status_reg: GenericAddressStructure,
105 hypervisor_vendor_id: [u8; 8],
106}
107
108impl Fadt {
109 pub fn new(oem_id: [u8; 6], oem_table_id: [u8; 8], oem_revision: u32) -> Self {
110 let header = SdtHeader::new(
111 *b"FACP",
112 std::mem::size_of::<Self>().try_into().unwrap(),
115 6, oem_id,
117 oem_table_id,
118 oem_revision,
119 );
120
121 Fadt {
122 header,
123 fadt_minor_version: 5,
124 ..Default::default()
125 }
126 }
127
128 pub fn set_x_dsdt(&mut self, addr: u64) {
132 self.x_dsdt = U64::new(addr);
133 }
134
135 pub fn set_flags(&mut self, flags: u32) {
137 self.flags = U32::new(flags);
138 }
139
140 pub fn setup_iapc_flags(&mut self, flags: u16) {
142 self.iapc_boot_arch = U16::new(flags);
143 }
144
145 pub fn set_hypervisor_vendor_id(&mut self, hypervisor_vendor_id: [u8; 8]) {
147 self.hypervisor_vendor_id = hypervisor_vendor_id;
148 }
149}
150
151impl Sdt for Fadt {
152 fn len(&self) -> usize {
153 self.header.length.get().try_into().unwrap()
154 }
155
156 fn write_to_guest<M: GuestMemory>(&mut self, mem: &M, address: GuestAddress) -> Result<()> {
157 self.header.checksum = checksum(&[self.as_bytes()]);
158 mem.write_slice(self.as_bytes(), address)?;
159 Ok(())
160 }
161}