Skip to content

Commit 3c4ee32

Browse files
committed
multiboot2: Add SMBIOS tag
1 parent d2f43f1 commit 3c4ee32

File tree

3 files changed

+113
-1
lines changed

3 files changed

+113
-1
lines changed

multiboot2/src/builder/information.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::builder::traits::StructAsBytes;
33
use crate::{
44
BasicMemoryInfoTag, BootInformationInner, BootLoaderNameTag, CommandLineTag,
55
EFISdt32, EFISdt64, ElfSectionsTag, EndTag, FramebufferTag, MemoryMapTag,
6-
ModuleTag,
6+
ModuleTag, SmbiosTag,
77
};
88

99
use alloc::boxed::Box;
@@ -24,6 +24,7 @@ pub struct Multiboot2InformationBuilder {
2424
module_tags: Vec<Box<ModuleTag>>,
2525
efisdt32: Option<EFISdt32>,
2626
efisdt64: Option<EFISdt64>,
27+
smbios_tags: Vec<Box<SmbiosTag>>,
2728
}
2829

2930
impl Multiboot2InformationBuilder {
@@ -38,6 +39,7 @@ impl Multiboot2InformationBuilder {
3839
framebuffer_tag: None,
3940
memory_map_tag: None,
4041
module_tags: Vec::new(),
42+
smbios_tags: Vec::new(),
4143
}
4244
}
4345

@@ -89,6 +91,9 @@ impl Multiboot2InformationBuilder {
8991
for tag in &self.module_tags {
9092
len += Self::size_or_up_aligned(tag.byte_size())
9193
}
94+
for tag in &self.smbios_tags {
95+
len += Self::size_or_up_aligned(tag.byte_size())
96+
}
9297
// only here size_or_up_aligned is not important, because it is the last tag
9398
len += size_of::<EndTag>();
9499
len
@@ -148,6 +153,9 @@ impl Multiboot2InformationBuilder {
148153
for tag in self.module_tags {
149154
Self::build_add_bytes(&mut data, &tag.struct_as_bytes(), false)
150155
}
156+
for tag in self.smbios_tags {
157+
Self::build_add_bytes(&mut data, &tag.struct_as_bytes(), false)
158+
}
151159

152160
Self::build_add_bytes(&mut data, &EndTag::new().struct_as_bytes(), true);
153161

@@ -189,6 +197,10 @@ impl Multiboot2InformationBuilder {
189197
pub fn add_module_tag(&mut self, module_tag: Box<ModuleTag>) {
190198
self.module_tags.push(module_tag);
191199
}
200+
201+
pub fn add_smbios_tag(&mut self, smbios_tag: Box<SmbiosTag>) {
202+
self.smbios_tags.push(smbios_tag);
203+
}
192204
}
193205

194206
#[cfg(test)]

multiboot2/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ pub use memory_map::{
6060
};
6161
pub use module::{ModuleIter, ModuleTag};
6262
pub use rsdp::{RsdpV1Tag, RsdpV2Tag};
63+
pub use smbios::SmbiosTag;
6364
pub use tag_type::TagType;
6465
use tag_type::{EndTag, METADATA_SIZE, Tag, TagIter};
6566
pub use vbe_info::{
@@ -79,6 +80,7 @@ mod image_load_addr;
7980
mod memory_map;
8081
mod module;
8182
mod rsdp;
83+
mod smbios;
8284
mod tag_type;
8385
mod vbe_info;
8486

multiboot2/src/smbios.rs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
use crate::TagType;
2+
#[cfg(feature = "builder")]
3+
use crate::builder::boxed_dst_tag;
4+
#[cfg(feature = "builder")]
5+
use crate::builder::traits::StructAsBytes;
6+
7+
use core::convert::TryInto;
8+
use core::fmt::Debug;
9+
10+
#[cfg(feature = "builder")]
11+
use alloc::boxed::Box;
12+
13+
#[cfg(test)]
14+
const METADATA_SIZE: usize = core::mem::size_of::<TagType>()
15+
+ core::mem::size_of::<u32>() + core::mem::size_of::<u8>() * 8;
16+
17+
18+
/// This tag contains a copy of SMBIOS tables as well as their version.
19+
#[repr(C, packed)]
20+
pub struct SmbiosTag {
21+
typ: TagType,
22+
size: u32,
23+
pub major: u8,
24+
pub minor: u8,
25+
_reserved: [u8; 6],
26+
pub tables: [u8],
27+
}
28+
29+
impl SmbiosTag {
30+
#[cfg(feature = "builder")]
31+
pub fn new(major: u8, minor: u8, tables: &[u8]) -> Box<Self> {
32+
let mut bytes = [major, minor].to_vec();
33+
bytes.extend(tables);
34+
let tag = boxed_dst_tag(
35+
TagType::Smbios, bytes.as_slice(),
36+
);
37+
unsafe { Box::from_raw(Box::into_raw(tag) as *mut Self) }
38+
}
39+
}
40+
41+
#[cfg(feature = "builder")]
42+
impl StructAsBytes for SmbiosTag {
43+
fn byte_size(&self) -> usize {
44+
self.size.try_into().unwrap()
45+
}
46+
}
47+
48+
impl Debug for SmbiosTag {
49+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
50+
f.debug_struct("BootLoaderNameTag")
51+
.field("typ", &{self.typ})
52+
.field("size", &{self.size})
53+
.field("major", &{self.major})
54+
.field("minor", &{self.minor})
55+
.finish()
56+
}
57+
}
58+
59+
#[cfg(test)]
60+
mod tests {
61+
use core::ptr::slice_from_raw_parts;
62+
63+
use crate::{TagType, smbios::METADATA_SIZE};
64+
65+
/// Returns the tag structure in bytes in native endian format.
66+
fn get_bytes() -> std::vec::Vec<u8> {
67+
let tables = [0xabu8; 24];
68+
// size is: 4 bytes for tag + 4 bytes for size + 1 byte for major and minor
69+
// + 6 bytes reserved + the actual tables
70+
let size = (4 + 4 + 1 + 1 + 6 + tables.len()) as u32;
71+
let mut bytes = [
72+
((TagType::Smbios as u32).to_ne_bytes()), size.to_ne_bytes()
73+
].concat();
74+
bytes.push(3);
75+
bytes.push(0);
76+
bytes.extend([0; 6]);
77+
bytes.extend(tables);
78+
bytes
79+
}
80+
81+
/// Tests to parse a string with a terminating null byte from the tag (as the spec defines).
82+
#[test]
83+
fn test_parse() {
84+
let tag = get_bytes();
85+
let tag = unsafe {
86+
let ptr = tag.as_ptr() as *const ();
87+
(slice_from_raw_parts(
88+
ptr, tag.len() - METADATA_SIZE
89+
) as *const super::SmbiosTag)
90+
.as_ref()
91+
.unwrap()
92+
};
93+
assert_eq!({ tag.typ }, TagType::Smbios);
94+
assert_eq!(tag.major, 3);
95+
assert_eq!(tag.minor, 0);
96+
assert_eq!(tag.tables, [0xabu8; 24]);
97+
}
98+
}

0 commit comments

Comments
 (0)