sdt.rs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. use core::str;
  2. use {AcpiError, AcpiHandler};
  3. /// All SDTs share the same header, and are `length` bytes long. The signature tells us which SDT
  4. /// this is.
  5. #[repr(C, packed)]
  6. pub struct SdtHeader
  7. {
  8. signature : [u8; 4],
  9. length : u32,
  10. revision : u8,
  11. checksum : u8,
  12. oem_id : [u8; 6],
  13. oem_table_id : [u8; 8],
  14. oem_revision : u32,
  15. creator_id : u32,
  16. creator_revision : u32,
  17. }
  18. impl SdtHeader
  19. {
  20. /// Check that:
  21. /// a) The signature is valid UTF8
  22. /// b) The checksum of the SDT.
  23. ///
  24. /// This assumes that the whole SDT is mapped.
  25. fn validate(&self) -> Result<(), AcpiError>
  26. {
  27. // Check the signature
  28. if str::from_utf8(&self.signature).is_err()
  29. {
  30. return Err(AcpiError::SdtInvalidSignature);
  31. }
  32. // Check the OEM id
  33. if str::from_utf8(&self.oem_id).is_err()
  34. {
  35. return Err(AcpiError::SdtInvalidOemId);
  36. }
  37. // Check the OEM table id
  38. if str::from_utf8(&self.oem_table_id).is_err()
  39. {
  40. return Err(AcpiError::SdtInvalidTableId);
  41. }
  42. // Sum all bytes in the SDT (not just the header)
  43. let mut sum : usize = 0;
  44. for i in 0..self.length
  45. {
  46. sum += unsafe { *(self as *const SdtHeader as *const u8).offset(i as isize) } as usize;
  47. }
  48. // Check that the lowest byte is 0
  49. if sum & 0b1111_1111 != 0
  50. {
  51. return Err(AcpiError::SdtInvalidChecksum);
  52. }
  53. Ok(())
  54. }
  55. pub fn signature<'a>(&'a self) -> &'a str
  56. {
  57. // Safe to unwrap because we check signature is valid UTF8 in `validate`
  58. str::from_utf8(&self.signature).unwrap()
  59. }
  60. pub fn length(&self) -> u32
  61. {
  62. self.length
  63. }
  64. pub fn revision(&self) -> u8
  65. {
  66. self.revision
  67. }
  68. pub fn oem_id<'a>(&'a self) -> &'a str
  69. {
  70. // Safe to unwrap because checked in `validate`
  71. str::from_utf8(&self.oem_id).unwrap()
  72. }
  73. pub fn oem_table_id<'a>(&'a self) -> &'a str
  74. {
  75. // Safe to unwrap because checked in `validate`
  76. str::from_utf8(&self.oem_table_id).unwrap()
  77. }
  78. }
  79. /// This takes the physical address of an SDT, maps it correctly and dispatches it to whatever
  80. /// function parses that table.
  81. pub(crate) fn dispatch_sdt<H>(handler : &mut H, physical_address : usize) -> Result<(), AcpiError>
  82. where H : AcpiHandler
  83. {
  84. let header_mapping = handler.map_physical_region::<SdtHeader>(physical_address);
  85. {
  86. let signature = (*header_mapping).signature();
  87. let length = (*header_mapping).length();
  88. /*
  89. * For a recognised signature, a new physical mapping should be created with the correct type
  90. * and length, and then the dispatched to the correct function to actually parse the table.
  91. */
  92. match signature
  93. {
  94. _ =>
  95. {
  96. /*
  97. * We don't recognise this signature. Early on, this probably just means we don't
  98. * have support yet, but later on maybe this should become an actual error
  99. */
  100. // TODO: add warn!()
  101. },
  102. }
  103. }
  104. handler.unmap_physical_region(header_mapping);
  105. Ok(())
  106. }