Skip to main content

smbios/
structures.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::string_table::StringTable;
6use zerocopy::byteorder::little_endian::{U16, U64};
7use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
8
9/// SMBIOS Structure Type identifier.
10#[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    // PascalCase aliases matching C++ enum names.
48    #[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/// SMBIOS common struct header.
81#[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/// SMBIOS BIOS Information Struct v2.0.
105#[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    /// Returns extended BIOS characteristics bytes if present in the formatted portion.
135    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    /// Formats a dump of the BIOS Information Struct v2.0 to the provided writer.
146    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/// SMBIOS BIOS Information Struct v2.4.
180#[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    /// Formats a dump of the BIOS Information Struct v2.4 to the provided writer.
216    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/// SMBIOS System Information Struct v2.0.
268#[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    /// Formats a dump of the System Information Struct v2.0 to the provided writer.
296    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/// SMBIOS System Information Struct v2.1.
326#[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    /// Formats a dump of the System Information Struct v2.1 to the provided writer.
357    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/// SMBIOS System Information Struct v2.4.
388#[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    /// Formats a dump of the System Information Struct v2.4 to the provided writer.
422    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/// SMBIOS Baseboard Information Struct.
455#[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    /// Returns the asset tag string index if present within the struct length.
490    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    /// Returns the feature flags if present within the struct length.
495    pub fn feature_flags(&self) -> Option<u8> {
496        if self.hdr.length > 9 { Some(self.unsafe_feature_flags) } else { None }
497    }
498
499    /// Returns the location in chassis string index if present within the struct length.
500    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    /// Returns the chassis handle if present within the struct length.
505    pub fn chassis_handle(&self) -> Option<u16> {
506        if self.hdr.length >= 13 { Some(self.unsafe_chassis_handle.get()) } else { None }
507    }
508
509    /// Returns the board type if present within the struct length.
510    pub fn board_type(&self) -> Option<u8> {
511        if self.hdr.length > 13 { Some(self.unsafe_board_type) } else { None }
512    }
513
514    /// Returns the contained object handles count if present within the struct length.
515    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    /// Returns the slice of contained object handles if present and valid within the struct length.
520    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    /// Formats a dump of the Baseboard Information Struct to the provided writer.
532    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}