fadt.rs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. use aml::{parse_aml_table, AmlTable};
  2. use sdt;
  3. use sdt::SdtHeader;
  4. use {Acpi, AcpiError, AcpiHandler, GenericAddress, PhysicalMapping};
  5. /// Represents the Fixed ACPI Description Table (FADT). This table contains various fixed hardware
  6. /// details, such as the addresses of the hardware register blocks. It also contains a pointer to
  7. /// the Differentiated Definition Block (DSDT).
  8. ///
  9. /// In cases where the FADT contains both a 32-bit and 64-bit field for the same address, we should
  10. /// always prefer the 64-bit one. Only if it's zero or the CPU will not allow us to access that
  11. /// address should the 32-bit one be used.
  12. #[repr(C, packed)]
  13. pub struct Fadt {
  14. header: SdtHeader,
  15. firmware_ctrl: u32,
  16. dsdt_address: u32,
  17. // used in acpi 1.0; compatibility only, should be zero
  18. reserved: u8,
  19. preferred_pm_profile: u8,
  20. sci_interrupt: u16,
  21. smi_cmd_port: u32,
  22. acpi_enable: u8,
  23. acpi_disable: u8,
  24. s4bios_req: u8,
  25. pstate_control: u8,
  26. pm1a_event_block: u32,
  27. pm1b_event_block: u32,
  28. pm1a_control_block: u32,
  29. pm1b_control_block: u32,
  30. pm2_control_block: u32,
  31. pm_timer_block: u32,
  32. gpe0_block: u32,
  33. gpe1_block: u32,
  34. pm1_event_length: u8,
  35. pm1_control_length: u8,
  36. pm2_control_length: u8,
  37. pm_timer_length: u8,
  38. gpe0_block_length: u8,
  39. gpe1_block_length: u8,
  40. gpe1_base: u8,
  41. c_state_control: u8,
  42. worst_c2_latency: u16,
  43. worst_c3_latency: u16,
  44. flush_size: u16,
  45. flush_stride: u16,
  46. duty_offset: u8,
  47. duty_width: u8,
  48. day_alarm: u8,
  49. month_alarm: u8,
  50. century: u8,
  51. iapc_boot_arch: u16,
  52. reserved2: u8, // must be 0
  53. flags: u32,
  54. reset_reg: GenericAddress,
  55. reset_value: u8,
  56. arm_boot_arch: u16,
  57. fadt_minor_version: u8,
  58. x_firmware_control: u64,
  59. x_dsdt_address: u64,
  60. x_pm1a_event_block: GenericAddress,
  61. x_pm1b_event_block: GenericAddress,
  62. x_pm1a_control_block: GenericAddress,
  63. x_pm1b_control_block: GenericAddress,
  64. x_pm2_control_block: GenericAddress,
  65. x_pm_timer_block: GenericAddress,
  66. x_gpe0_block: GenericAddress,
  67. x_gpe1_block: GenericAddress,
  68. sleep_control_reg: GenericAddress,
  69. sleep_status_reg: GenericAddress,
  70. hypervisor_vendor_id: u64,
  71. }
  72. pub(crate) fn parse_fadt<H>(
  73. acpi: &mut Acpi,
  74. handler: &mut H,
  75. mapping: &PhysicalMapping<Fadt>,
  76. ) -> Result<(), AcpiError>
  77. where
  78. H: AcpiHandler,
  79. {
  80. let fadt = &*mapping;
  81. fadt.header.validate(b"FACP")?;
  82. // TODO more generic typesafe way of accessing the x_ fields
  83. let dsdt_physical_address: usize = if fadt.header.revision() > 1 && fadt.x_dsdt_address != 0 {
  84. fadt.x_dsdt_address as usize
  85. } else {
  86. fadt.dsdt_address as usize
  87. };
  88. // Parse the DSDT
  89. let dsdt_header = sdt::peek_at_sdt_header(handler, dsdt_physical_address);
  90. let dsdt_mapping = handler
  91. .map_physical_region::<AmlTable>(dsdt_physical_address, dsdt_header.length() as usize);
  92. if let Err(error) = parse_aml_table(acpi, handler, &dsdt_mapping, b"DSDT") {
  93. error!("Failed to parse DSDT: {:?}. At this stage, this is expected, but should be fatal in the future", error);
  94. }
  95. handler.unmap_physical_region(dsdt_mapping);
  96. Ok(())
  97. }
  98. #[cfg(test)]
  99. mod tests {
  100. use fadt::Fadt;
  101. use sdt::SdtHeader;
  102. use std::mem;
  103. use GenericAddress;
  104. impl Fadt {
  105. fn make_testcase(
  106. oem_id: [u8; 6],
  107. oem_table_id: [u8; 8],
  108. oem_revision: u32,
  109. creator_id: u32,
  110. creator_revision: u32,
  111. ) -> Fadt {
  112. Fadt {
  113. header: SdtHeader::make_testcase(
  114. *b"FACP",
  115. mem::size_of::<Fadt>() as u32,
  116. 6,
  117. 5, //checksum
  118. oem_id,
  119. oem_table_id,
  120. oem_revision,
  121. creator_id,
  122. creator_revision,
  123. ),
  124. firmware_ctrl: 0xDEADBEEF as u32,
  125. dsdt_address: 0xDEADBEEF as u32,
  126. // used in acpi 1.0; compatibility only, should be zero
  127. reserved: 0 as u8,
  128. preferred_pm_profile: 0 as u8,
  129. sci_interrupt: 0 as u16,
  130. smi_cmd_port: 0 as u32,
  131. acpi_enable: 0 as u8,
  132. acpi_disable: 0 as u8,
  133. s4bios_req: 0 as u8,
  134. pstate_control: 0 as u8,
  135. pm1a_event_block: 0xDEADBEEF as u32,
  136. pm1b_event_block: 0xDEADBEEF as u32,
  137. pm1a_control_block: 0xDEADBEEF as u32,
  138. pm1b_control_block: 0xDEADBEEF as u32,
  139. pm2_control_block: 0xDEADBEEF as u32,
  140. pm_timer_block: 0xDEADBEEF as u32,
  141. gpe0_block: 0xDEADBEEF as u32,
  142. gpe1_block: 0xDEADBEEF as u32,
  143. pm1_event_length: 4 as u8,
  144. pm1_control_length: 2 as u8,
  145. pm2_control_length: 0 as u8,
  146. pm_timer_length: 0 as u8,
  147. gpe0_block_length: 2 as u8,
  148. gpe1_block_length: 2 as u8,
  149. gpe1_base: 0 as u8,
  150. c_state_control: 0 as u8,
  151. worst_c2_latency: 0 as u16,
  152. worst_c3_latency: 0 as u16,
  153. flush_size: 0 as u16,
  154. flush_stride: 0 as u16,
  155. duty_offset: 0 as u8,
  156. duty_width: 0 as u8,
  157. day_alarm: 0 as u8,
  158. month_alarm: 0 as u8,
  159. century: 0 as u8,
  160. iapc_boot_arch: 0 as u16,
  161. reserved2: 0 as u8,
  162. flags: 0 as u32,
  163. reset_reg: GenericAddress::make_testcase(),
  164. reset_value: 0 as u8,
  165. arm_boot_arch: 0 as u16,
  166. fadt_minor_version: 2 as u8,
  167. x_firmware_control: 0 as u64,
  168. x_dsdt_address: 0 as u64,
  169. x_pm1a_event_block: GenericAddress::make_testcase(),
  170. x_pm1b_event_block: GenericAddress::make_testcase(),
  171. x_pm1a_control_block: GenericAddress::make_testcase(),
  172. x_pm1b_control_block: GenericAddress::make_testcase(),
  173. x_pm2_control_block: GenericAddress::make_testcase(),
  174. x_pm_timer_block: GenericAddress::make_testcase(),
  175. x_gpe0_block: GenericAddress::make_testcase(),
  176. x_gpe1_block: GenericAddress::make_testcase(),
  177. sleep_control_reg: GenericAddress::make_testcase(),
  178. sleep_status_reg: GenericAddress::make_testcase(),
  179. hypervisor_vendor_id: 0 as u64,
  180. }
  181. }
  182. }
  183. }