fadt.rs 3.1 KB

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