sdt.rs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. use crate::{fadt::Fadt, hpet::Hpet, madt::Madt, Acpi, AcpiError, AcpiHandler};
  2. use core::{mem, str};
  3. /// All SDTs share the same header, and are `length` bytes long. The signature tells us which SDT
  4. /// this is.
  5. ///
  6. /// The ACPI Spec (Version 6.2) defines the following SDT signatures:
  7. /// "APIC" - Multiple APIC Descriptor Table (MADT)
  8. /// "BGRT" - Boot Graphics Resource Table
  9. /// "BERT" - Boot Error Record Table
  10. /// "CPEP" - Corrected Platform Error Polling Table
  11. /// "DSDT" - Differentiated System Descriptor Table
  12. /// "ECDT" - Embedded Controller Boot Resources Table
  13. /// "EINJ" - Error Injection Table
  14. /// "ERST" - Error Record Serialization Table
  15. /// "FACP" - Fixed ACPI Description Table (FADT)
  16. /// "FACS" - Firmware ACPI Control Structure
  17. /// "FPDT" - Firmware Performance Data Table
  18. /// "GTDT" - Generic Timer Description Table
  19. /// "HEST" - Hardware Error Source Table
  20. /// "HMAT" - Heterogeneous Memory Attributes Table
  21. /// "MSCT" - Maximum System Characteristics Table
  22. /// "MPST" - Memory Power State Table
  23. /// "NFIT" - NVDIMM Firmware Interface Table
  24. /// "OEMx" - Various OEM-specific tables
  25. /// "PDTT" - Platform Debug Trigger Table
  26. /// "PMTT" - Platform Memory Topology Table
  27. /// "PPTT" - Processor Properties Topology Table
  28. /// "PSDT" - Persistent System Description Table
  29. /// "RASF" - ACPI RAS Feature Table
  30. /// "RSDT" - Root System Descriptor Table
  31. /// "SBST" - Smart Battery Specification Table
  32. /// "SLIT" - System Locality Information Table
  33. /// "SRAT" - System Resource Affinity Table
  34. /// "SSDT" - Secondary System Description Table
  35. /// "XSDT" - eXtended System Descriptor Table
  36. #[derive(Clone, Copy)]
  37. #[repr(C, packed)]
  38. pub struct SdtHeader {
  39. signature: [u8; 4],
  40. length: u32,
  41. revision: u8,
  42. checksum: u8,
  43. oem_id: [u8; 6],
  44. oem_table_id: [u8; 8],
  45. oem_revision: u32,
  46. creator_id: u32,
  47. creator_revision: u32,
  48. }
  49. impl SdtHeader {
  50. /// Check that:
  51. /// a) The signature matches the one given
  52. /// b) The checksum of the SDT
  53. ///
  54. /// This assumes that the whole SDT is mapped.
  55. pub fn validate(&self, signature: &[u8; 4]) -> Result<(), AcpiError> {
  56. // Check the signature
  57. if &self.signature != signature {
  58. return Err(AcpiError::SdtInvalidSignature(*signature));
  59. }
  60. // Check the OEM id
  61. if str::from_utf8(&self.oem_id).is_err() {
  62. return Err(AcpiError::SdtInvalidOemId(*signature));
  63. }
  64. // Check the OEM table id
  65. if str::from_utf8(&self.oem_table_id).is_err() {
  66. return Err(AcpiError::SdtInvalidTableId(*signature));
  67. }
  68. // Validate the checksum
  69. let self_ptr = self as *const SdtHeader as *const u8;
  70. let mut sum: u8 = 0;
  71. for i in 0..self.length {
  72. sum = sum.wrapping_add(unsafe { *(self_ptr.offset(i as isize)) } as u8);
  73. }
  74. if sum > 0 {
  75. return Err(AcpiError::SdtInvalidChecksum(*signature));
  76. }
  77. Ok(())
  78. }
  79. pub fn raw_signature(&self) -> [u8; 4] {
  80. self.signature
  81. }
  82. pub fn signature<'a>(&'a self) -> &'a str {
  83. // Safe to unwrap because we check signature is valid UTF8 in `validate`
  84. str::from_utf8(&self.signature).unwrap()
  85. }
  86. pub fn length(&self) -> u32 {
  87. self.length
  88. }
  89. pub fn revision(&self) -> u8 {
  90. self.revision
  91. }
  92. pub fn oem_id<'a>(&'a self) -> &'a str {
  93. // Safe to unwrap because checked in `validate`
  94. str::from_utf8(&self.oem_id).unwrap()
  95. }
  96. pub fn oem_table_id<'a>(&'a self) -> &'a str {
  97. // Safe to unwrap because checked in `validate`
  98. str::from_utf8(&self.oem_table_id).unwrap()
  99. }
  100. }
  101. /// Takes the physical address of an SDT, and maps, clones and unmaps its header. Useful for
  102. /// finding out how big it is to map it correctly later.
  103. pub(crate) fn peek_at_sdt_header<H>(handler: &mut H, physical_address: usize) -> SdtHeader
  104. where
  105. H: AcpiHandler,
  106. {
  107. let mapping =
  108. handler.map_physical_region::<SdtHeader>(physical_address, mem::size_of::<SdtHeader>());
  109. let header = (*mapping).clone();
  110. handler.unmap_physical_region(mapping);
  111. header
  112. }
  113. /// This takes the physical address of an SDT, maps it correctly and dispatches it to whatever
  114. /// function parses that table.
  115. pub(crate) fn dispatch_sdt<H>(
  116. acpi: &mut Acpi,
  117. handler: &mut H,
  118. physical_address: usize,
  119. ) -> Result<(), AcpiError>
  120. where
  121. H: AcpiHandler,
  122. {
  123. let header = peek_at_sdt_header(handler, physical_address);
  124. info!(
  125. "Dispatching SDT with signature {:?} and length {:?}",
  126. header.signature(),
  127. header.length()
  128. );
  129. /*
  130. * For a recognised signature, a new physical mapping should be created with the correct type
  131. * and length, and then the dispatched to the correct function to actually parse the table.
  132. */
  133. match header.signature() {
  134. "FACP" => {
  135. let fadt_mapping =
  136. handler.map_physical_region::<Fadt>(physical_address, mem::size_of::<Fadt>());
  137. crate::fadt::parse_fadt(acpi, handler, &fadt_mapping)?;
  138. handler.unmap_physical_region(fadt_mapping);
  139. }
  140. "HPET" => {
  141. let hpet_mapping =
  142. handler.map_physical_region::<Hpet>(physical_address, mem::size_of::<Hpet>());
  143. crate::hpet::parse_hpet(&hpet_mapping)?;
  144. handler.unmap_physical_region(hpet_mapping);
  145. }
  146. "APIC" => {
  147. let madt_mapping =
  148. handler.map_physical_region::<Madt>(physical_address, header.length() as usize);
  149. crate::madt::parse_madt(acpi, handler, &madt_mapping)?;
  150. handler.unmap_physical_region(madt_mapping);
  151. }
  152. signature => {
  153. /*
  154. * We don't recognise this signature. Early on, this probably just means we don't
  155. * have support yet, but later on maybe this should become an actual error
  156. */
  157. warn!("Unsupported SDT signature: {}. Skipping.", signature);
  158. }
  159. }
  160. Ok(())
  161. }