fadt.rs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. use crate::{sdt::SdtHeader, Acpi, AcpiError, AcpiHandler, AmlTable, GenericAddress, PhysicalMapping};
  2. type ExtendedField<T> = crate::sdt::ExtendedField<T, typenum::U2>;
  3. /// Represents the Fixed ACPI Description Table (FADT). This table contains various fixed hardware
  4. /// details, such as the addresses of the hardware register blocks. It also contains a pointer to
  5. /// the Differentiated Definition Block (DSDT).
  6. ///
  7. /// In cases where the FADT contains both a 32-bit and 64-bit field for the same address, we should
  8. /// always prefer the 64-bit one. Only if it's zero or the CPU will not allow us to access that
  9. /// address should the 32-bit one be used.
  10. #[repr(C, packed)]
  11. pub struct Fadt {
  12. header: SdtHeader,
  13. firmware_ctrl: u32,
  14. dsdt_address: u32,
  15. // used in acpi 1.0; compatibility only, should be zero
  16. _reserved: u8,
  17. preferred_pm_profile: u8,
  18. sci_interrupt: u16,
  19. smi_cmd_port: u32,
  20. acpi_enable: u8,
  21. acpi_disable: u8,
  22. s4bios_req: u8,
  23. pstate_control: u8,
  24. pm1a_event_block: u32,
  25. pm1b_event_block: u32,
  26. pm1a_control_block: u32,
  27. pm1b_control_block: u32,
  28. pm2_control_block: u32,
  29. pm_timer_block: u32,
  30. gpe0_block: u32,
  31. gpe1_block: u32,
  32. pm1_event_length: u8,
  33. pm1_control_length: u8,
  34. pm2_control_length: u8,
  35. pm_timer_length: u8,
  36. gpe0_block_length: u8,
  37. gpe1_block_length: u8,
  38. gpe1_base: u8,
  39. c_state_control: u8,
  40. worst_c2_latency: u16,
  41. worst_c3_latency: u16,
  42. flush_size: u16,
  43. flush_stride: u16,
  44. duty_offset: u8,
  45. duty_width: u8,
  46. day_alarm: u8,
  47. month_alarm: u8,
  48. century: u8,
  49. iapc_boot_arch: u16,
  50. _reserved2: u8, // must be 0
  51. flags: u32,
  52. reset_reg: GenericAddress,
  53. reset_value: u8,
  54. arm_boot_arch: u16,
  55. fadt_minor_version: u8,
  56. x_firmware_ctrl: ExtendedField<u64>,
  57. x_dsdt_address: ExtendedField<u64>,
  58. x_pm1a_event_block: ExtendedField<GenericAddress>,
  59. x_pm1b_event_block: ExtendedField<GenericAddress>,
  60. x_pm1a_control_block: ExtendedField<GenericAddress>,
  61. x_pm1b_control_block: ExtendedField<GenericAddress>,
  62. x_pm2_control_block: ExtendedField<GenericAddress>,
  63. x_pm_timer_block: ExtendedField<GenericAddress>,
  64. x_gpe0_block: ExtendedField<GenericAddress>,
  65. x_gpe1_block: ExtendedField<GenericAddress>,
  66. sleep_control_reg: ExtendedField<GenericAddress>,
  67. sleep_status_reg: ExtendedField<GenericAddress>,
  68. hypervisor_vendor_id: ExtendedField<u64>,
  69. }
  70. pub(crate) fn parse_fadt<H>(
  71. acpi: &mut Acpi,
  72. handler: &mut H,
  73. mapping: &PhysicalMapping<Fadt>,
  74. ) -> Result<(), AcpiError>
  75. where
  76. H: AcpiHandler,
  77. {
  78. let fadt = &*mapping;
  79. fadt.header.validate(b"FACP")?;
  80. let dsdt_address = unsafe {
  81. fadt.x_dsdt_address
  82. .get(fadt.header.revision())
  83. .filter(|p| *p != 0)
  84. .or(Some(fadt.dsdt_address as u64))
  85. .filter(|p| *p != 0)
  86. .map(|p| p as usize)
  87. };
  88. acpi.dsdt = dsdt_address.map(|address| {
  89. let dsdt_header = crate::sdt::peek_at_sdt_header(handler, address);
  90. AmlTable::new(address, dsdt_header.length())
  91. });
  92. Ok(())
  93. }