1use crate::TagType;
16use crate::tag::TagHeader;
17#[cfg(feature = "builder")]
18use core::mem::size_of;
19use core::slice;
20use core::str;
21use core::str::Utf8Error;
22use multiboot2_common::{MaybeDynSized, Tag};
23
24const RSDPV1_LENGTH: usize = 20;
25
26#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
28#[repr(C, align(8))]
29pub struct RsdpV1Tag {
30 header: TagHeader,
31 signature: [u8; 8],
32 checksum: u8,
33 oem_id: [u8; 6],
34 revision: u8,
35 rsdt_address: u32, }
37
38impl RsdpV1Tag {
39 pub const SIGNATURE: [u8; 8] = *b"RSD PTR ";
41
42 const BASE_SIZE: usize = size_of::<TagHeader>() + 16 + 4;
43
44 #[must_use]
46 pub fn new(checksum: u8, oem_id: [u8; 6], revision: u8, rsdt_address: u32) -> Self {
47 Self {
48 header: TagHeader::new(Self::ID, Self::BASE_SIZE as u32),
49 signature: Self::SIGNATURE,
50 checksum,
51 oem_id,
52 revision,
53 rsdt_address,
54 }
55 }
56
57 pub const fn signature(&self) -> Result<&str, Utf8Error> {
61 str::from_utf8(&self.signature)
62 }
63
64 #[must_use]
66 pub fn checksum_is_valid(&self) -> bool {
67 let bytes =
68 unsafe { slice::from_raw_parts(self as *const _ as *const u8, RSDPV1_LENGTH + 8) };
69 bytes[8..]
70 .iter()
71 .fold(0u8, |acc, val| acc.wrapping_add(*val))
72 == 0
73 }
74
75 pub const fn oem_id(&self) -> Result<&str, Utf8Error> {
77 str::from_utf8(&self.oem_id)
78 }
79
80 #[must_use]
82 pub const fn revision(&self) -> u8 {
83 self.revision
84 }
85
86 #[must_use]
88 pub const fn rsdt_address(&self) -> usize {
89 self.rsdt_address as usize
90 }
91}
92
93impl MaybeDynSized for RsdpV1Tag {
94 type Header = TagHeader;
95
96 const BASE_SIZE: usize = size_of::<Self>();
97
98 fn dst_len(_: &TagHeader) {}
99}
100
101impl Tag for RsdpV1Tag {
102 type IDType = TagType;
103
104 const ID: TagType = TagType::AcpiV1;
105}
106
107#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
109#[repr(C, align(8))]
110pub struct RsdpV2Tag {
111 header: TagHeader,
112 signature: [u8; 8],
113 checksum: u8,
114 oem_id: [u8; 6],
115 revision: u8,
116 rsdt_address: u32,
117 length: u32,
118 xsdt_address: u64,
119 ext_checksum: u8,
121 _reserved: [u8; 3],
122}
123
124impl RsdpV2Tag {
125 pub const SIGNATURE: [u8; 8] = *b"RSD PTR ";
127
128 const BASE_SIZE: usize =
129 size_of::<TagHeader>() + 16 + 2 * size_of::<u32>() + size_of::<u64>() + 4;
130
131 #[allow(clippy::too_many_arguments)]
133 #[must_use]
134 pub fn new(
135 checksum: u8,
136 oem_id: [u8; 6],
137 revision: u8,
138 rsdt_address: u32,
139 length: u32,
140 xsdt_address: u64,
141 ext_checksum: u8,
142 ) -> Self {
143 Self {
144 header: TagHeader::new(Self::ID, Self::BASE_SIZE as u32),
145 signature: Self::SIGNATURE,
146 checksum,
147 oem_id,
148 revision,
149 rsdt_address,
150 length,
151 xsdt_address,
152 ext_checksum,
153 _reserved: [0; 3],
154 }
155 }
156
157 pub const fn signature(&self) -> Result<&str, Utf8Error> {
161 str::from_utf8(&self.signature)
162 }
163
164 #[must_use]
166 pub fn checksum_is_valid(&self) -> bool {
167 let bytes = unsafe {
168 slice::from_raw_parts(self as *const _ as *const u8, self.length as usize + 8)
169 };
170 bytes[8..]
171 .iter()
172 .fold(0u8, |acc, val| acc.wrapping_add(*val))
173 == 0
174 }
175
176 pub const fn oem_id(&self) -> Result<&str, Utf8Error> {
178 str::from_utf8(&self.oem_id)
179 }
180
181 #[must_use]
183 pub const fn revision(&self) -> u8 {
184 self.revision
185 }
186
187 #[must_use]
191 pub const fn xsdt_address(&self) -> usize {
192 self.xsdt_address as usize
193 }
194
195 #[must_use]
197 pub const fn ext_checksum(&self) -> u8 {
198 self.ext_checksum
199 }
200}
201
202impl MaybeDynSized for RsdpV2Tag {
203 type Header = TagHeader;
204
205 const BASE_SIZE: usize = size_of::<Self>();
206
207 fn dst_len(_: &TagHeader) {}
208}
209
210impl Tag for RsdpV2Tag {
211 type IDType = TagType;
212
213 const ID: TagType = TagType::AcpiV2;
214}