mod.rs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. pub mod address;
  2. pub mod interrupt;
  3. use crate::{fadt::Fadt, madt::Madt, AcpiError, AcpiHandler, AcpiTables, PowerProfile};
  4. use address::GenericAddress;
  5. use alloc::vec::Vec;
  6. use interrupt::InterruptModel;
  7. #[derive(Clone, Copy, Debug, PartialEq, Eq)]
  8. pub enum ProcessorState {
  9. /// A processor in this state is unusable, and you must not attempt to bring it up.
  10. Disabled,
  11. /// A processor waiting for a SIPI (Startup Inter-processor Interrupt) is currently not active,
  12. /// but may be brought up.
  13. WaitingForSipi,
  14. /// A Running processor is currently brought up and running code.
  15. Running,
  16. }
  17. #[derive(Clone, Copy, Debug, PartialEq, Eq)]
  18. pub struct Processor {
  19. pub processor_uid: u8,
  20. pub local_apic_id: u8,
  21. /// The state of this processor. Always check that the processor is not `Disabled` before
  22. /// attempting to bring it up!
  23. pub state: ProcessorState,
  24. /// Whether this processor is the Bootstrap Processor (BSP), or an Application Processor (AP).
  25. /// When the bootloader is entered, the BSP is the only processor running code. To run code on
  26. /// more than one processor, you need to "bring up" the APs.
  27. pub is_ap: bool,
  28. }
  29. pub struct ProcessorInfo {
  30. pub boot_processor: Processor,
  31. /// Application processors should be brought up in the order they're defined in this list.
  32. pub application_processors: Vec<Processor>,
  33. }
  34. /// Information about the ACPI Power Management Timer (ACPI PM Timer).
  35. pub struct PmTimer {
  36. /// A generic address to the register block of ACPI PM Timer.
  37. pub base: GenericAddress,
  38. /// This field is `true` if the hardware supports 32-bit timer, and `false` if the hardware supports 24-bit timer.
  39. pub supports_32bit: bool,
  40. }
  41. impl PmTimer {
  42. pub fn new(fadt: &Fadt) -> Result<Option<PmTimer>, AcpiError> {
  43. match fadt.pm_timer_block()? {
  44. Some(base) => Ok(Some(PmTimer { base, supports_32bit: { fadt.flags }.pm_timer_is_32_bit() })),
  45. None => Ok(None),
  46. }
  47. }
  48. }
  49. /// `PlatformInfo` allows the collection of some basic information about the platform from some of the fixed-size
  50. /// tables in a nice way. It requires access to the `FADT` and `MADT`. It is the easiest way to get information
  51. /// about the processors and interrupt controllers on a platform.
  52. pub struct PlatformInfo {
  53. pub power_profile: PowerProfile,
  54. pub interrupt_model: InterruptModel,
  55. /// On `x86_64` platforms that support the APIC, the processor topology must also be inferred from the
  56. /// interrupt model. That information is stored here, if present.
  57. pub processor_info: Option<ProcessorInfo>,
  58. pub pm_timer: Option<PmTimer>,
  59. /*
  60. * TODO: we could provide a nice view of the hardware register blocks in the FADT here.
  61. */
  62. }
  63. impl PlatformInfo {
  64. pub fn new<H>(tables: &AcpiTables<H>) -> Result<PlatformInfo, AcpiError>
  65. where
  66. H: AcpiHandler,
  67. {
  68. let fadt = unsafe {
  69. tables
  70. .get_sdt::<Fadt>(crate::sdt::Signature::FADT)?
  71. .ok_or(AcpiError::TableMissing(crate::sdt::Signature::FADT))?
  72. };
  73. let power_profile = fadt.power_profile();
  74. let madt = unsafe { tables.get_sdt::<Madt>(crate::sdt::Signature::MADT)? };
  75. let (interrupt_model, processor_info) = match madt {
  76. Some(madt) => madt.parse_interrupt_model()?,
  77. None => (InterruptModel::Unknown, None),
  78. };
  79. let pm_timer = PmTimer::new(&fadt)?;
  80. Ok(PlatformInfo { power_profile, interrupt_model, processor_info, pm_timer })
  81. }
  82. }