Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions acpi/src/fadt.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
platform::address::RawGenericAddress,
platform::address::{GenericAddress, RawGenericAddress},
sdt::{ExtendedField, SdtHeader},
AcpiError,
AcpiTable,
Expand Down Expand Up @@ -70,7 +70,7 @@ pub struct Fadt {
century: u8,
iapc_boot_arch: u16,
_reserved2: u8, // must be 0
flags: u32,
pub flags: u32,
reset_reg: RawGenericAddress,
reset_value: u8,
arm_boot_arch: u16,
Expand Down Expand Up @@ -127,4 +127,27 @@ impl Fadt {
other => PowerProfile::Reserved(other),
}
}

pub fn pm_timer_block(&self) -> Result<Option<GenericAddress>, AcpiError> {
let raw = unsafe {
self.x_pm_timer_block.access(self.header().revision).or_else(|| {
if self.pm_timer_block != 0 {
Some(RawGenericAddress {
address_space: 1,
bit_width: 0,
bit_offset: 0,
access_size: self.pm_timer_length,
address: self.pm_timer_block.into(),
})
} else {
None
}
})
};

match raw {
Some(raw) => Ok(Some(GenericAddress::from_raw(raw)?)),
None => Ok(None),
}
}
}
27 changes: 26 additions & 1 deletion acpi/src/platform/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
pub mod address;
pub mod interrupt;

use address::GenericAddress;
use bit_field::BitField;
pub use interrupt::{
Apic,
InterruptModel,
Expand Down Expand Up @@ -51,6 +53,27 @@ pub struct ProcessorInfo {
pub application_processors: Vec<Processor>,
}

/// Information about the ACPI Power Management Timer (ACPI PM Timer).
pub struct PmTimer {
/// A generic address to the register block of ACPI PM Timer.
pub base: GenericAddress,
/// This field is true if the hardware supports 32-bit timer, and false if the hardware
/// supports 24-bit timer.
pub supports_32bit: bool,
}
impl PmTimer {
/// Creates a new instance of `PmTimer`.
pub fn new(fadt: &Fadt) -> Result<Option<PmTimer>, AcpiError> {
let base = fadt.pm_timer_block()?;
let flags = fadt.flags;

match base {
Some(base) => Ok(Some(PmTimer { base, supports_32bit: flags.get_bit(8) })),
None => Ok(None),
}
}
}

/// `PlatformInfo` allows the collection of some basic information about the platform from some of the fixed-size
/// tables in a nice way. It requires access to the `FADT` and `MADT`. It is the easiest way to get information
/// about the processors and interrupt controllers on a platform.
Expand All @@ -60,6 +83,7 @@ pub struct PlatformInfo {
/// On `x86_64` platforms that support the APIC, the processor topology must also be inferred from the
/// interrupt model. That information is stored here, if present.
pub processor_info: Option<ProcessorInfo>,
pub pm_timer: Option<PmTimer>,
/*
* TODO: we could provide a nice view of the hardware register blocks in the FADT here.
*/
Expand All @@ -82,7 +106,8 @@ impl PlatformInfo {
Some(madt) => madt.parse_interrupt_model()?,
None => (InterruptModel::Unknown, None),
};
let pm_timer = PmTimer::new(&fadt)?;

Ok(PlatformInfo { power_profile, interrupt_model, processor_info })
Ok(PlatformInfo { power_profile, interrupt_model, processor_info, pm_timer })
}
}