1use crate::TagType;
4use crate::tag::TagHeader;
5use core::fmt::Debug;
6use core::mem;
7use multiboot2_common::{MaybeDynSized, Tag};
8#[cfg(feature = "builder")]
9use {alloc::boxed::Box, multiboot2_common::new_boxed};
10
11#[derive(ptr_meta::Pointee, PartialEq, Eq, PartialOrd, Ord, Hash)]
13#[repr(C, align(8))]
14pub struct SmbiosTag {
15 header: TagHeader,
16 major: u8,
17 minor: u8,
18 _reserved: [u8; 6],
19 tables: [u8],
20}
21
22impl SmbiosTag {
23 #[cfg(feature = "builder")]
25 #[must_use]
26 pub fn new(major: u8, minor: u8, tables: &[u8]) -> Box<Self> {
27 let header = TagHeader::new(Self::ID, 0);
28 let reserved = [0, 0, 0, 0, 0, 0];
29 new_boxed(header, &[&[major, minor], &reserved, tables])
30 }
31
32 #[must_use]
34 pub const fn major(&self) -> u8 {
35 self.major
36 }
37
38 #[must_use]
40 pub const fn minor(&self) -> u8 {
41 self.minor
42 }
43
44 #[must_use]
46 pub const fn tables(&self) -> &[u8] {
47 &self.tables
48 }
49}
50
51impl MaybeDynSized for SmbiosTag {
52 type Header = TagHeader;
53
54 const BASE_SIZE: usize = mem::size_of::<TagHeader>() + mem::size_of::<u8>() * 8;
55
56 fn dst_len(header: &TagHeader) -> usize {
57 assert!(header.size as usize >= Self::BASE_SIZE);
58 header.size as usize - Self::BASE_SIZE
59 }
60}
61
62impl Tag for SmbiosTag {
63 type IDType = TagType;
64
65 const ID: TagType = TagType::Smbios;
66}
67
68impl Debug for SmbiosTag {
69 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
70 f.debug_struct("BootLoaderNameTag")
71 .field("typ", &self.header.typ)
72 .field("size", &self.header.size)
73 .field("major", &self.major)
74 .field("minor", &self.minor)
75 .finish()
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82 use crate::GenericInfoTag;
83 use core::borrow::Borrow;
84 use multiboot2_common::test_utils::AlignedBytes;
85
86 #[rustfmt::skip]
87 fn get_bytes() -> AlignedBytes<32> {
88 AlignedBytes::new([
89 TagType::Smbios.val() as u8, 0, 0, 0,
90 25, 0, 0, 0,
91 7,
93 42,
95 0, 0, 0, 0, 0, 0,
97 0, 1, 2, 3, 4, 5, 6, 7, 8,
99 0, 0, 0, 0, 0, 0, 0
101 ])
102 }
103
104 #[test]
106 fn test_parse() {
107 let bytes = get_bytes();
108 let tag = GenericInfoTag::ref_from_slice(bytes.borrow()).unwrap();
109 let tag = tag.cast::<SmbiosTag>();
110 assert_eq!(tag.header.typ, TagType::Smbios);
111 assert_eq!(tag.major, 7);
112 assert_eq!(tag.minor, 42);
113 assert_eq!(&tag.tables, [0, 1, 2, 3, 4, 5, 6, 7, 8]);
114 }
115
116 #[test]
118 #[cfg(feature = "builder")]
119 fn test_build() {
120 let tag = SmbiosTag::new(7, 42, &[0, 1, 2, 3, 4, 5, 6, 7, 8]);
121 let bytes = tag.as_bytes().as_ref();
122 let bytes = &bytes[..tag.header.size as usize];
123 assert_eq!(bytes, &get_bytes()[..tag.header.size as usize]);
124 }
125}