fadt.rs 3.3 KB

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