fadt.rs 4.0 KB

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