1use crate::core::{strings::*, UndefinedStruct};
2use crate::SMBiosStruct;
3use serde::{ser::SerializeStruct, Serialize, Serializer};
4use std::{array::TryFromSliceError, convert::TryFrom, fmt, ops::Deref};
5
6pub struct SMBiosTpmDevice<'a> {
8 parts: &'a UndefinedStruct,
9}
10
11impl<'a> SMBiosStruct<'a> for SMBiosTpmDevice<'a> {
12 const STRUCT_TYPE: u8 = 43u8;
13
14 fn new(parts: &'a UndefinedStruct) -> Self {
15 Self { parts }
16 }
17
18 fn parts(&self) -> &'a UndefinedStruct {
19 self.parts
20 }
21}
22
23impl<'a> SMBiosTpmDevice<'a> {
24 pub fn vendor_id(&self) -> Option<VendorId<'_>> {
33 self.parts
34 .get_field_data(0x04, 0x08)
35 .and_then(|array| Some(VendorId::try_from(array).expect("Vendor Id is 4 bytes")))
36 }
37
38 pub fn major_spec_version(&self) -> Option<u8> {
44 self.parts.get_field_byte(0x08)
45 }
46
47 pub fn minor_spec_version(&self) -> Option<u8> {
53 self.parts.get_field_byte(0x09)
54 }
55
56 pub fn firmware_version_1(&self) -> Option<u32> {
68 self.parts.get_field_dword(0x0A)
69 }
70
71 pub fn firmware_version_2(&self) -> Option<u32> {
81 self.parts.get_field_dword(0x0E)
82 }
83
84 pub fn description(&self) -> SMBiosString {
88 self.parts.get_field_string(0x12)
89 }
90
91 pub fn characteristics(&self) -> Option<TpmDeviceCharacteristics> {
95 self.parts
96 .get_field_qword(0x13)
97 .map(|raw| TpmDeviceCharacteristics::from(raw))
98 }
99
100 pub fn oem_defined(&self) -> Option<u32> {
104 self.parts.get_field_dword(0x1B)
105 }
106}
107
108impl fmt::Debug for SMBiosTpmDevice<'_> {
109 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
110 fmt.debug_struct(std::any::type_name::<SMBiosTpmDevice<'_>>())
111 .field("header", &self.parts.header)
112 .field("vendor_id", &self.vendor_id())
113 .field("major_spec_version", &self.major_spec_version())
114 .field("minor_spec_version", &self.minor_spec_version())
115 .field("firmware_version_1", &self.firmware_version_1())
116 .field("firmware_version_2", &self.firmware_version_2())
117 .field("description", &self.description())
118 .field("characteristics", &self.characteristics())
119 .field("oem_defined", &self.oem_defined())
120 .finish()
121 }
122}
123
124impl Serialize for SMBiosTpmDevice<'_> {
125 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
126 where
127 S: Serializer,
128 {
129 let mut state = serializer.serialize_struct("SMBiosTpmDevice", 9)?;
130 state.serialize_field("header", &self.parts.header)?;
131 state.serialize_field("vendor_id", &self.vendor_id())?;
132 state.serialize_field("major_spec_version", &self.major_spec_version())?;
133 state.serialize_field("minor_spec_version", &self.minor_spec_version())?;
134 state.serialize_field("firmware_version_1", &self.firmware_version_1())?;
135 state.serialize_field("firmware_version_2", &self.firmware_version_2())?;
136 state.serialize_field("description", &self.description())?;
137 state.serialize_field("characteristics", &self.characteristics())?;
138 state.serialize_field("oem_defined", &self.oem_defined())?;
139 state.end()
140 }
141}
142
143#[derive(PartialEq, Eq)]
149pub struct VendorId<'a> {
150 pub array: &'a [u8; 4],
154}
155
156impl<'a> TryFrom<&'a [u8]> for VendorId<'a> {
157 type Error = TryFromSliceError;
158
159 fn try_from(raw: &'a [u8]) -> Result<Self, Self::Error> {
160 <&[u8; 4]>::try_from(raw).and_then(|array| Ok(VendorId { array }))
161 }
162}
163
164impl<'a> fmt::Debug for VendorId<'a> {
165 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
166 fmt.debug_struct(std::any::type_name::<VendorId<'_>>())
167 .field("array", &self.array)
168 .field("string", &String::from_utf8_lossy(self.array))
169 .finish()
170 }
171}
172
173impl<'a> Serialize for VendorId<'a> {
174 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
175 where
176 S: Serializer,
177 {
178 let mut state = serializer.serialize_struct("VendorId", 2)?;
179 state.serialize_field("array", &self.array)?;
180 state.serialize_field("string", &String::from_utf8_lossy(self.array))?;
181 state.end()
182 }
183}
184
185#[derive(PartialEq, Eq)]
187pub struct TpmDeviceCharacteristics {
188 pub raw: u64,
195}
196
197impl Deref for TpmDeviceCharacteristics {
198 type Target = u64;
199
200 fn deref(&self) -> &Self::Target {
201 &self.raw
202 }
203}
204
205impl From<u64> for TpmDeviceCharacteristics {
206 fn from(raw: u64) -> Self {
207 TpmDeviceCharacteristics { raw }
208 }
209}
210
211impl TpmDeviceCharacteristics {
212 pub fn reserved_0(&self) -> bool {
214 self.raw & 0x0000000000000001 == 0x0000000000000001
215 }
216
217 pub fn reserved_1(&self) -> bool {
219 self.raw & 0x0000000000000002 == 0x0000000000000002
220 }
221
222 pub fn not_supported(&self) -> bool {
224 self.raw & 0x0000000000000004 == 0x0000000000000004
225 }
226
227 pub fn family_configurable_via_firmware(&self) -> bool {
229 self.raw & 0x0000000000000008 == 0x0000000000000008
230 }
231
232 pub fn family_configurable_via_software(&self) -> bool {
234 self.raw & 0x0000000000000010 == 0x0000000000000010
235 }
236
237 pub fn family_configurable_via_oem(&self) -> bool {
239 self.raw & 0x0000000000000020 == 0x0000000000000020
240 }
241}
242
243impl fmt::Debug for TpmDeviceCharacteristics {
244 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
245 fmt.debug_struct(std::any::type_name::<TpmDeviceCharacteristics>())
246 .field("raw", &self.raw)
247 .field("reserved_0", &self.reserved_0())
248 .field("reserved_1", &self.reserved_1())
249 .field("not_supported", &self.not_supported())
250 .field(
251 "family_configurable_via_firmware",
252 &self.family_configurable_via_firmware(),
253 )
254 .field(
255 "family_configurable_via_software",
256 &self.family_configurable_via_software(),
257 )
258 .field(
259 "family_configurable_via_oem",
260 &self.family_configurable_via_oem(),
261 )
262 .finish()
263 }
264}
265
266impl Serialize for TpmDeviceCharacteristics {
267 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
268 where
269 S: Serializer,
270 {
271 let mut state = serializer.serialize_struct("TpmDeviceCharacteristics", 7)?;
272 state.serialize_field("raw", &self.raw)?;
273 state.serialize_field("reserved_0", &self.reserved_0())?;
274 state.serialize_field("reserved_1", &self.reserved_1())?;
275 state.serialize_field("not_supported", &self.not_supported())?;
276 state.serialize_field(
277 "family_configurable_via_firmware",
278 &self.family_configurable_via_firmware(),
279 )?;
280 state.serialize_field(
281 "family_configurable_via_software",
282 &self.family_configurable_via_software(),
283 )?;
284 state.serialize_field(
285 "family_configurable_via_oem",
286 &self.family_configurable_via_oem(),
287 )?;
288 state.end()
289 }
290}
291
292#[cfg(test)]
293mod tests {
294 use super::*;
295
296 #[test]
297 fn unit_test() {
298 let struct_type43 = vec![
299 0x2B, 0x1F, 0x3C, 0x00, 0x00, 0x58, 0x46, 0x49, 0x02, 0x00, 0x3E, 0x00, 0x05, 0x00,
300 0x00, 0x36, 0x0C, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
301 0x00, 0x00, 0x00, 0x54, 0x50, 0x4D, 0x20, 0x32, 0x2E, 0x30, 0x00, 0x49, 0x4E, 0x46,
302 0x49, 0x4E, 0x45, 0x4F, 0x4E, 0x00, 0x00,
303 ];
304
305 let parts = UndefinedStruct::new(&struct_type43);
306 let test_struct = SMBiosTpmDevice::new(&parts);
307
308 println!("{:?}", test_struct);
309 assert_eq!(
310 test_struct.vendor_id().unwrap().array,
311 &[0, b'X', b'F', b'I']
312 );
313 assert_eq!(test_struct.major_spec_version(), Some(2));
314 assert_eq!(test_struct.minor_spec_version(), Some(0));
315 assert_eq!(test_struct.firmware_version_1(), Some(327742));
316 assert_eq!(test_struct.firmware_version_2(), Some(800256));
317 assert_eq!(
318 test_struct.description().to_string(),
319 "INFINEON".to_string()
320 );
321 assert_eq!(
322 test_struct.characteristics(),
323 Some(TpmDeviceCharacteristics::from(16))
324 );
325 assert_eq!(test_struct.oem_defined(), Some(0));
326 }
327}