Skip to main content

raw_acpi/
rsdp.rs

1use crate::{rsdt::RootSystemDescriptionTable, xsdt::ExtendedSystemDescriptionTable};
2
3#[derive(Copy, Clone)]
4#[repr(C, packed)]
5/// ## Root System Description Pointer structure.
6///
7/// During OS initialization, OSPM must obtain the Root System Description Pointer (RSDP) structure from the platform.
8/// When OSPM locates the Root System Description Pointer (RSDP) structure,
9/// it then locates the Root System Description Table (RSDT) or the Extended Root System Description Table (XSDT) using the physical system address supplied in the RSDP.
10///
11/// ## Finding the RSDP on IA-PC Systems
12///
13/// OSPM finds the Root System Description Pointer (RSDP) structure by searching physical memory ranges on 16-byte boundaries for a valid Root System Description Pointer structure signature and checksum match as follows:
14/// - The first 1 KB of the Extended BIOS Data Area (EBDA). For EISA or MCA systems, the EBDA can be found in the two-byte location 40:0Eh on the BIOS data area.
15/// - The BIOS read-only memory space between 0E0000h and 0FFFFFh.
16///
17/// ## Finding the RSDP on UEFI Enabled Systems
18///
19/// In Unified Extensible Firmware Interface (UEFI) enabled systems, a pointer to the RSDP structure exists within the EFI System Table.
20/// The OS loader is provided a pointer to the EFI System Table at invocation.
21/// The OS loader must retrieve the pointer to the RSDP structure from the EFI System Table and convey the pointer to OSPM, using an OS dependent data structure, as part of the hand off of control from the OS loader to the OS.
22///
23/// The OS loader locates the pointer to the RSDP structure by examining the EFI Configuration Table within the EFI System Table.
24/// EFI Configuration Table entries consist of Globally Unique Identifier (GUID)/table pointer pairs.
25/// The UEFI specification defines two GUIDs for ACPI; one for ACPI 1.0 and the other for ACPI 2.0 or later specification revisions.
26///
27/// The EFI GUID for a pointer to the ACPI 1.0 specification RSDP structure is:
28/// - eb9d2d30-2d88-11d3-9a16-0090273fc14d
29///
30/// The EFI GUID for a pointer to the ACPI 2.0 or later specification RSDP structure is:
31/// - 8868e871-e4f1-11d3-bc22-0080c73c8881
32///
33/// The OS loader for an ACPI-compatible OS will search for an RSDP structure pointer (RSDP Structure) using the current revision GUID first and if it finds one, will use the corresponding RSDP structure pointer.
34/// If the GUID is not found then the OS loader will search for the RSDP structure pointer using the ACPI 1.0 version GUID.
35///
36/// The OS loader must retrieve the pointer to the RSDP structure from the EFI System Table before assuming platform control via the EFI ExitBootServices interface. See the UEFI Specification for more information.
37pub struct RootSystemDescriptionPointer {
38    /// "RSD PTR "<br>
39    /// Notice that this signature must contain a trailing blank character.
40    pub signature: [u8; 8],
41    /// This is the checksum of the fields defined in the ACPI 1.0 specification.<br>
42    /// This includes only the first 20 bytes of this table, bytes 0 to 19, including the checksum field.<br>
43    /// These bytes must sum to zero.
44    pub checksum: u8,
45    /// An OEM-supplied string that identifies the OEM.
46    pub oemid: [u8; 6],
47    /// The revision of this structure.
48    ///
49    /// Larger revision numbers are backward compatible to lower revision numbers.<br>
50    /// The ACPI version 1.0 revision number of this table is zero.
51    /// The ACPI version 1.0 RSDP Structure only includes the first 20 bytes of this table, bytes 0 to 19.
52    /// It does not include the Length field and beyond.
53    pub revision: u8,
54    /// 32 bit physical address of the RSDT.
55    ///
56    /// **JJ's note: Assume undefined behavior if revision is 2.0+.**
57    pub rsdt_address: u32,
58
59    /// The length of the table, in bytes, including the header, starting from offset 0x0.
60    /// This field is used to record the size of the entire table.
61    ///
62    /// **This field is only available in the ACPI version 2.0+ RSDP Structure.**
63    pub length: u32,
64    /// 64 bit physical address of the XSDT.
65    ///
66    /// **This field is only available in the ACPI version 2.0+ RSDP Structure.**
67    pub xsdt_address: u64,
68    /// This is a checksum of the entire table, including both checksum fields.
69    ///
70    /// **This field is only available in the ACPI version 2.0+ RSDP Structure.**
71    pub extended_checksum: u8,
72    /// Reseved field.
73    ///
74    /// **This field is only available in the ACPI version 2.0+ RSDP Structure.**
75    reserved: [u8; 3],
76}
77impl RootSystemDescriptionPointer {
78    /// Returns true if the rsdp signature is "RSD PTR "; otherwise, false.
79    pub const fn validate_signature(&self) -> bool {
80        self.signature[0] == b'R'
81            && self.signature[1] == b'S'
82            && self.signature[2] == b'D'
83            && self.signature[3] == b' '
84            && self.signature[4] == b'P'
85            && self.signature[5] == b'T'
86            && self.signature[6] == b'R'
87            && self.signature[7] == b' '
88    }
89    /// Returns true if the rsdt or xsdt address matches the signature for RSDT or XSDT, more for simplicity than anything else.
90    pub const fn validate_sdt_signature(&self) -> bool {
91        unsafe {
92            if self.revision < 2 {
93                (&*(self.rsdt_address as usize as *const RootSystemDescriptionTable))
94                    .header
95                    .signature[0]
96                    == b'R'
97                    && (&*(self.rsdt_address as usize as *const RootSystemDescriptionTable))
98                        .header
99                        .signature[1]
100                        == b'S'
101                    && (&*(self.rsdt_address as usize as *const RootSystemDescriptionTable))
102                        .header
103                        .signature[2]
104                        == b'D'
105                    && (&*(self.rsdt_address as usize as *const RootSystemDescriptionTable))
106                        .header
107                        .signature[3]
108                        == b'T'
109            } else {
110                (&*(self.xsdt_address as usize as *const ExtendedSystemDescriptionTable))
111                    .header
112                    .signature[0]
113                    == b'X'
114                    && (&*(self.xsdt_address as usize as *const ExtendedSystemDescriptionTable))
115                        .header
116                        .signature[1]
117                        == b'S'
118                    && (&*(self.xsdt_address as usize as *const ExtendedSystemDescriptionTable))
119                        .header
120                        .signature[2]
121                        == b'D'
122                    && (&*(self.xsdt_address as usize as *const ExtendedSystemDescriptionTable))
123                        .header
124                        .signature[3]
125                        == b'T'
126            }
127        }
128    }
129}