1use crate::string_table::StringTable;
6use zerocopy::byteorder::little_endian::{U16, U64};
7use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
8
9#[repr(transparent)]
11#[derive(
12 Copy,
13 Clone,
14 Debug,
15 Default,
16 Eq,
17 PartialEq,
18 Ord,
19 PartialOrd,
20 Hash,
21 FromBytes,
22 IntoBytes,
23 Immutable,
24 KnownLayout,
25 Unaligned,
26)]
27pub struct StructType(pub u8);
28
29impl StructType {
30 pub const BIOS_INFO: Self = Self(0);
31 pub const SYSTEM_INFO: Self = Self(1);
32 pub const BASEBOARD: Self = Self(2);
33 pub const SYSTEM_ENCLOSURE: Self = Self(3);
34 pub const PROCESSOR: Self = Self(4);
35 pub const MEMORY_CONTROLLER: Self = Self(5);
36 pub const MEMORY_MODULE: Self = Self(6);
37 pub const CACHE: Self = Self(7);
38 pub const PORT_CONNECTOR: Self = Self(8);
39 pub const SYSTEM_SLOTS: Self = Self(9);
40 pub const ON_BOARD_DEVICES: Self = Self(10);
41 pub const OEM_STRINGS: Self = Self(11);
42 pub const SYSTEM_CONFIG_OPTIONS: Self = Self(12);
43 pub const BIOS_LANGUAGE: Self = Self(13);
44
45 pub const END_OF_TABLE: Self = Self(127);
46
47 #[allow(non_upper_case_globals)]
49 pub const BiosInfo: Self = Self::BIOS_INFO;
50 #[allow(non_upper_case_globals)]
51 pub const SystemInfo: Self = Self::SYSTEM_INFO;
52 #[allow(non_upper_case_globals)]
53 pub const Baseboard: Self = Self::BASEBOARD;
54 #[allow(non_upper_case_globals)]
55 pub const SystemEnclosure: Self = Self::SYSTEM_ENCLOSURE;
56 #[allow(non_upper_case_globals)]
57 pub const Processor: Self = Self::PROCESSOR;
58 #[allow(non_upper_case_globals)]
59 pub const MemoryController: Self = Self::MEMORY_CONTROLLER;
60 #[allow(non_upper_case_globals)]
61 pub const MemoryModule: Self = Self::MEMORY_MODULE;
62 #[allow(non_upper_case_globals)]
63 pub const Cache: Self = Self::CACHE;
64 #[allow(non_upper_case_globals)]
65 pub const PortConnector: Self = Self::PORT_CONNECTOR;
66 #[allow(non_upper_case_globals)]
67 pub const SystemSlots: Self = Self::SYSTEM_SLOTS;
68 #[allow(non_upper_case_globals)]
69 pub const OnBoardDevices: Self = Self::ON_BOARD_DEVICES;
70 #[allow(non_upper_case_globals)]
71 pub const OemStrings: Self = Self::OEM_STRINGS;
72 #[allow(non_upper_case_globals)]
73 pub const SystemConfigOptions: Self = Self::SYSTEM_CONFIG_OPTIONS;
74 #[allow(non_upper_case_globals)]
75 pub const BiosLanguage: Self = Self::BIOS_LANGUAGE;
76 #[allow(non_upper_case_globals)]
77 pub const EndOfTable: Self = Self::END_OF_TABLE;
78}
79
80#[repr(C, packed)]
82#[derive(
83 Copy,
84 Clone,
85 Debug,
86 Default,
87 Eq,
88 PartialEq,
89 FromBytes,
90 IntoBytes,
91 Immutable,
92 KnownLayout,
93 Unaligned,
94)]
95pub struct Header {
96 pub r#type: StructType,
97 pub length: u8,
98 pub handle: U16,
99}
100
101zr::static_assert!(core::mem::size_of::<Header>() == 4);
102zr::static_assert!(core::mem::align_of::<Header>() == 1);
103
104#[repr(C, packed)]
106#[derive(
107 Copy,
108 Clone,
109 Debug,
110 Default,
111 Eq,
112 PartialEq,
113 FromBytes,
114 IntoBytes,
115 Immutable,
116 KnownLayout,
117 Unaligned,
118)]
119pub struct BiosInformationStruct2_0 {
120 pub hdr: Header,
121
122 pub vendor_str_idx: u8,
123 pub bios_version_str_idx: u8,
124 pub bios_starting_address_segment: U16,
125 pub bios_release_date_str_idx: u8,
126 pub bios_rom_size: u8,
127 pub bios_characteristics: U64,
128}
129
130zr::static_assert!(core::mem::size_of::<BiosInformationStruct2_0>() == 0x12);
131zr::static_assert!(core::mem::align_of::<BiosInformationStruct2_0>() == 1);
132
133impl BiosInformationStruct2_0 {
134 pub fn bios_characteristics_ext<'a>(&self, raw_struct_bytes: &'a [u8]) -> &'a [u8] {
136 let len = self.hdr.length as usize;
137 let base_size = core::mem::size_of::<Self>();
138 if len > base_size && raw_struct_bytes.len() >= len {
139 &raw_struct_bytes[base_size..len]
140 } else {
141 &[]
142 }
143 }
144
145 pub fn dump<W: core::fmt::Write>(
147 &self,
148 writer: &mut W,
149 st: &StringTable<'_>,
150 raw_struct_bytes: &[u8],
151 ) -> core::fmt::Result {
152 writeln!(writer, "SMBIOS BIOS Information Struct v2.0:")?;
153 writeln!(writer, " vendor: {}", st.get_string_or_default(self.vendor_str_idx as usize))?;
154 writeln!(
155 writer,
156 " BIOS version: {}",
157 st.get_string_or_default(self.bios_version_str_idx as usize)
158 )?;
159 writeln!(
160 writer,
161 " BIOS starting address segment: 0x{:04x}",
162 self.bios_starting_address_segment.get()
163 )?;
164 writeln!(
165 writer,
166 " BIOS release date: {}",
167 st.get_string_or_default(self.bios_release_date_str_idx as usize)
168 )?;
169 writeln!(writer, " BIOS ROM size: 0x{:02x}", self.bios_rom_size)?;
170 writeln!(writer, " BIOS characteristics: 0x{:016x}", self.bios_characteristics.get())?;
171 let ext = self.bios_characteristics_ext(raw_struct_bytes);
172 for &byte in ext {
173 writeln!(writer, " BIOS characteristics extended: 0x{:02x}", byte)?;
174 }
175 Ok(())
176 }
177}
178
179#[repr(C, packed)]
181#[derive(
182 Copy,
183 Clone,
184 Debug,
185 Default,
186 Eq,
187 PartialEq,
188 FromBytes,
189 IntoBytes,
190 Immutable,
191 KnownLayout,
192 Unaligned,
193)]
194pub struct BiosInformationStruct2_4 {
195 pub hdr: Header,
196
197 pub vendor_str_idx: u8,
198 pub bios_version_str_idx: u8,
199 pub bios_starting_address_segment: U16,
200 pub bios_release_date_str_idx: u8,
201 pub bios_rom_size: u8,
202 pub bios_characteristics: U64,
203 pub bios_characteristics_ext: U16,
204
205 pub bios_major_release: u8,
206 pub bios_minor_release: u8,
207 pub ec_major_release: u8,
208 pub ec_minor_release: u8,
209}
210
211zr::static_assert!(core::mem::size_of::<BiosInformationStruct2_4>() == 0x18);
212zr::static_assert!(core::mem::align_of::<BiosInformationStruct2_4>() == 1);
213
214impl BiosInformationStruct2_4 {
215 pub fn dump<W: core::fmt::Write>(
217 &self,
218 writer: &mut W,
219 st: &StringTable<'_>,
220 ) -> core::fmt::Result {
221 writeln!(writer, "SMBIOS BIOS Information Struct v2.4:")?;
222 writeln!(writer, " vendor: {}", st.get_string_or_default(self.vendor_str_idx as usize))?;
223 writeln!(
224 writer,
225 " BIOS version: {}",
226 st.get_string_or_default(self.bios_version_str_idx as usize)
227 )?;
228 writeln!(
229 writer,
230 " BIOS starting address segment: 0x{:04x}",
231 self.bios_starting_address_segment.get()
232 )?;
233 writeln!(
234 writer,
235 " BIOS release date: {}",
236 st.get_string_or_default(self.bios_release_date_str_idx as usize)
237 )?;
238 writeln!(writer, " BIOS ROM size: 0x{:02x}", self.bios_rom_size)?;
239 writeln!(writer, " BIOS characteristics: 0x{:016x}", self.bios_characteristics.get())?;
240 writeln!(
241 writer,
242 " BIOS characteristics extended: 0x{:04x}",
243 self.bios_characteristics_ext.get()
244 )?;
245 writeln!(
246 writer,
247 " BIOS version number: {}.{}",
248 self.bios_major_release, self.bios_minor_release
249 )?;
250 writeln!(
251 writer,
252 " EC version number: {}.{}",
253 self.ec_major_release, self.ec_minor_release
254 )?;
255 let base_size = core::mem::size_of::<Self>();
256 if self.hdr.length as usize > base_size {
257 writeln!(
258 writer,
259 " {} bytes of unknown trailing contents",
260 self.hdr.length as usize - base_size
261 )?;
262 }
263 Ok(())
264 }
265}
266
267#[repr(C, packed)]
269#[derive(
270 Copy,
271 Clone,
272 Debug,
273 Default,
274 Eq,
275 PartialEq,
276 FromBytes,
277 IntoBytes,
278 Immutable,
279 KnownLayout,
280 Unaligned,
281)]
282pub struct SystemInformationStruct2_0 {
283 pub hdr: Header,
284
285 pub manufacturer_str_idx: u8,
286 pub product_name_str_idx: u8,
287 pub version_str_idx: u8,
288 pub serial_number_str_idx: u8,
289}
290
291zr::static_assert!(core::mem::size_of::<SystemInformationStruct2_0>() == 0x8);
292zr::static_assert!(core::mem::align_of::<SystemInformationStruct2_0>() == 1);
293
294impl SystemInformationStruct2_0 {
295 pub fn dump<W: core::fmt::Write>(
297 &self,
298 writer: &mut W,
299 st: &StringTable<'_>,
300 ) -> core::fmt::Result {
301 writeln!(writer, "SMBIOS System Information Struct v2.0:")?;
302 writeln!(
303 writer,
304 " manufacturer: {}",
305 st.get_string_or_default(self.manufacturer_str_idx as usize)
306 )?;
307 writeln!(
308 writer,
309 " product: {}",
310 st.get_string_or_default(self.product_name_str_idx as usize)
311 )?;
312 writeln!(writer, " version: {}", st.get_string_or_default(self.version_str_idx as usize))?;
313 let base_size = core::mem::size_of::<Self>();
314 if self.hdr.length as usize > base_size {
315 writeln!(
316 writer,
317 " {} bytes of unknown trailing contents",
318 self.hdr.length as usize - base_size
319 )?;
320 }
321 Ok(())
322 }
323}
324
325#[repr(C, packed)]
327#[derive(
328 Copy,
329 Clone,
330 Debug,
331 Default,
332 Eq,
333 PartialEq,
334 FromBytes,
335 IntoBytes,
336 Immutable,
337 KnownLayout,
338 Unaligned,
339)]
340pub struct SystemInformationStruct2_1 {
341 pub hdr: Header,
342
343 pub manufacturer_str_idx: u8,
344 pub product_name_str_idx: u8,
345 pub version_str_idx: u8,
346 pub serial_number_str_idx: u8,
347
348 pub uuid: [u8; 16],
349 pub wakeup_type: u8,
350}
351
352zr::static_assert!(core::mem::size_of::<SystemInformationStruct2_1>() == 0x19);
353zr::static_assert!(core::mem::align_of::<SystemInformationStruct2_1>() == 1);
354
355impl SystemInformationStruct2_1 {
356 pub fn dump<W: core::fmt::Write>(
358 &self,
359 writer: &mut W,
360 st: &StringTable<'_>,
361 ) -> core::fmt::Result {
362 writeln!(writer, "SMBIOS System Information Struct v2.1:")?;
363 writeln!(
364 writer,
365 " manufacturer: {}",
366 st.get_string_or_default(self.manufacturer_str_idx as usize)
367 )?;
368 writeln!(
369 writer,
370 " product: {}",
371 st.get_string_or_default(self.product_name_str_idx as usize)
372 )?;
373 writeln!(writer, " version: {}", st.get_string_or_default(self.version_str_idx as usize))?;
374 writeln!(writer, " wakeup_type: 0x{:x}", self.wakeup_type)?;
375 let base_size = core::mem::size_of::<Self>();
376 if self.hdr.length as usize > base_size {
377 writeln!(
378 writer,
379 " {} bytes of unknown trailing contents",
380 self.hdr.length as usize - base_size
381 )?;
382 }
383 Ok(())
384 }
385}
386
387#[repr(C, packed)]
389#[derive(
390 Copy,
391 Clone,
392 Debug,
393 Default,
394 Eq,
395 PartialEq,
396 FromBytes,
397 IntoBytes,
398 Immutable,
399 KnownLayout,
400 Unaligned,
401)]
402pub struct SystemInformationStruct2_4 {
403 pub hdr: Header,
404
405 pub manufacturer_str_idx: u8,
406 pub product_name_str_idx: u8,
407 pub version_str_idx: u8,
408 pub serial_number_str_idx: u8,
409
410 pub uuid: [u8; 16],
411 pub wakeup_type: u8,
412
413 pub sku_number_str_idx: u8,
414 pub family_str_idx: u8,
415}
416
417zr::static_assert!(core::mem::size_of::<SystemInformationStruct2_4>() == 0x1b);
418zr::static_assert!(core::mem::align_of::<SystemInformationStruct2_4>() == 1);
419
420impl SystemInformationStruct2_4 {
421 pub fn dump<W: core::fmt::Write>(
423 &self,
424 writer: &mut W,
425 st: &StringTable<'_>,
426 ) -> core::fmt::Result {
427 writeln!(writer, "SMBIOS System Information Struct v2.4:")?;
428 writeln!(
429 writer,
430 " manufacturer: {}",
431 st.get_string_or_default(self.manufacturer_str_idx as usize)
432 )?;
433 writeln!(
434 writer,
435 " product: {}",
436 st.get_string_or_default(self.product_name_str_idx as usize)
437 )?;
438 writeln!(writer, " version: {}", st.get_string_or_default(self.version_str_idx as usize))?;
439 writeln!(writer, " wakeup_type: 0x{:x}", self.wakeup_type)?;
440 writeln!(writer, " SKU: {}", st.get_string_or_default(self.sku_number_str_idx as usize))?;
441 writeln!(writer, " family: {}", st.get_string_or_default(self.family_str_idx as usize))?;
442 let base_size = core::mem::size_of::<Self>();
443 if self.hdr.length as usize > base_size {
444 writeln!(
445 writer,
446 " {} bytes of unknown trailing contents",
447 self.hdr.length as usize - base_size
448 )?;
449 }
450 Ok(())
451 }
452}
453
454#[repr(C, packed)]
456#[derive(
457 Copy,
458 Clone,
459 Debug,
460 Default,
461 Eq,
462 PartialEq,
463 FromBytes,
464 IntoBytes,
465 Immutable,
466 KnownLayout,
467 Unaligned,
468)]
469pub struct BaseboardInformationStruct {
470 pub hdr: Header,
471 pub manufacturer_str_idx: u8,
472 pub product_name_str_idx: u8,
473 pub version_str_idx: u8,
474 pub serial_number_str_idx: u8,
475
476 pub unsafe_asset_tag_str_idx: u8,
477 pub unsafe_feature_flags: u8,
478 pub unsafe_location_in_chassis_str_idx: u8,
479 pub unsafe_chassis_handle: U16,
480
481 pub unsafe_board_type: u8,
482 pub unsafe_contained_object_handles_count: u8,
483}
484
485zr::static_assert!(core::mem::size_of::<BaseboardInformationStruct>() == 0xf);
486zr::static_assert!(core::mem::align_of::<BaseboardInformationStruct>() == 1);
487
488impl BaseboardInformationStruct {
489 pub fn asset_tag_str_idx(&self) -> Option<u8> {
491 if self.hdr.length > 8 { Some(self.unsafe_asset_tag_str_idx) } else { None }
492 }
493
494 pub fn feature_flags(&self) -> Option<u8> {
496 if self.hdr.length > 9 { Some(self.unsafe_feature_flags) } else { None }
497 }
498
499 pub fn location_in_chassis_str_idx(&self) -> Option<u8> {
501 if self.hdr.length > 10 { Some(self.unsafe_location_in_chassis_str_idx) } else { None }
502 }
503
504 pub fn chassis_handle(&self) -> Option<u16> {
506 if self.hdr.length >= 13 { Some(self.unsafe_chassis_handle.get()) } else { None }
507 }
508
509 pub fn board_type(&self) -> Option<u8> {
511 if self.hdr.length > 13 { Some(self.unsafe_board_type) } else { None }
512 }
513
514 pub fn contained_object_handles_count(&self) -> Option<u8> {
516 if self.hdr.length > 14 { Some(self.unsafe_contained_object_handles_count) } else { None }
517 }
518
519 pub fn contained_object_handles<'a>(&self, raw_struct_bytes: &'a [u8]) -> Option<&'a [U16]> {
521 let count = self.contained_object_handles_count()? as usize;
522 let start_offset = core::mem::size_of::<Self>();
523 let end_offset = start_offset + count * 2;
524 if (self.hdr.length as usize) < end_offset || raw_struct_bytes.len() < end_offset {
525 return None;
526 }
527 let handles_bytes = &raw_struct_bytes[start_offset..end_offset];
528 <[U16]>::ref_from_bytes(handles_bytes).ok()
529 }
530
531 pub fn dump<W: core::fmt::Write>(
533 &self,
534 writer: &mut W,
535 st: &StringTable<'_>,
536 ) -> core::fmt::Result {
537 writeln!(writer, "SMBIOS Baseboard Information Struct:")?;
538 writeln!(
539 writer,
540 " manufacturer: {}",
541 st.get_string_or_default(self.manufacturer_str_idx as usize)
542 )?;
543 writeln!(
544 writer,
545 " product: {}",
546 st.get_string_or_default(self.product_name_str_idx as usize)
547 )?;
548 writeln!(writer, " version: {}", st.get_string_or_default(self.version_str_idx as usize))?;
549 let ff_present = if self.feature_flags().is_some() { "" } else { "not " };
550 writeln!(
551 writer,
552 " feature flags ({}present): 0x{:02x}",
553 ff_present,
554 self.feature_flags().unwrap_or(0)
555 )?;
556 writeln!(
557 writer,
558 " location: {}",
559 st.get_string_or_default(self.location_in_chassis_str_idx().unwrap_or(0) as usize)
560 )?;
561 let bt_present = if self.board_type().is_some() { "" } else { "not " };
562 writeln!(
563 writer,
564 " board_type ({}present): 0x{:02x}",
565 bt_present,
566 self.board_type().unwrap_or(0)
567 )?;
568 Ok(())
569 }
570}