Skip to content

Commit 798e081

Browse files
authored
Merge pull request #137 from YtvwlD/bootloader-tags
Add BasicMemoryInfo and SMBIOS tags
2 parents 2d0add1 + c3aca97 commit 798e081

File tree

3 files changed

+118
-2
lines changed

3 files changed

+118
-2
lines changed

multiboot2/src/lib.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,12 @@ pub use elf_sections::{
5252
pub use framebuffer::{FramebufferColor, FramebufferField, FramebufferTag, FramebufferType};
5353
pub use image_load_addr::ImageLoadPhysAddr;
5454
pub use memory_map::{
55-
EFIMemoryAreaType, EFIMemoryDesc, EFIMemoryMapTag, MemoryArea, MemoryAreaIter, MemoryAreaType,
56-
MemoryMapTag,
55+
BasicMemoryInfoTag, EFIMemoryAreaType, EFIMemoryDesc, EFIMemoryMapTag, MemoryArea,
56+
MemoryAreaIter, MemoryAreaType, MemoryMapTag,
5757
};
5858
pub use module::{ModuleIter, ModuleTag};
5959
pub use rsdp::{RsdpV1Tag, RsdpV2Tag};
60+
pub use smbios::SmbiosTag;
6061
use tag_type::TagIter;
6162
pub use tag_type::{Tag, TagType, TagTypeId};
6263
pub use vbe_info::{
@@ -76,6 +77,7 @@ mod image_load_addr;
7677
mod memory_map;
7778
mod module;
7879
mod rsdp;
80+
mod smbios;
7981
mod tag_type;
8082
mod vbe_info;
8183

@@ -218,6 +220,11 @@ impl BootInformation {
218220
self.get().total_size as usize
219221
}
220222

223+
/// Search for the basic memory info tag.
224+
pub fn basic_memory_info_tag(&self) -> Option<&BasicMemoryInfoTag> {
225+
self.get_tag::<BasicMemoryInfoTag, _>(TagType::BasicMeminfo)
226+
}
227+
221228
/// Search for the ELF Sections tag.
222229
pub fn elf_sections_tag(&self) -> Option<ElfSectionsTag> {
223230
self.get_tag::<Tag, _>(TagType::ElfSections)
@@ -304,6 +311,11 @@ impl BootInformation {
304311
self.get_tag::<VBEInfoTag, _>(TagType::Vbe)
305312
}
306313

314+
/// Search for the SMBIOS tag.
315+
pub fn smbios_tag(&self) -> Option<&SmbiosTag> {
316+
self.get_tag::<SmbiosTag, _>(TagType::Smbios)
317+
}
318+
307319
fn get(&self) -> &BootInformationInner {
308320
unsafe { &*self.inner }
309321
}

multiboot2/src/memory_map.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,41 @@ impl<'a> Iterator for MemoryAreaIter<'a> {
123123
}
124124
}
125125

126+
/// Basic memory info
127+
///
128+
/// This tag includes "basic memory information".
129+
/// This means (legacy) lower and upper memory:
130+
/// In Real Mode (modeled after the 8086),
131+
/// only the first 1MB of memory is accessible.
132+
/// Typically, the region between 640KB and 1MB is not freely usable,
133+
/// because it is used for memory-mapped IO, for instance.
134+
/// The term “lower memory” refers to those first 640KB of memory that are
135+
/// freely usable for an application in Real Mode.
136+
/// “Upper memory” then refers to the next freely usable chunk of memory,
137+
/// starting at 1MB up to about 10MB, in practice.
138+
/// This is the memory an application running on a 286
139+
/// (which had a 24-bit address bus) could use, historically.
140+
/// Nowadays, much bigger chunks of continuous memory are available at higher
141+
/// addresses, but the Multiboot standard still references those two terms.
142+
#[derive(Debug)]
143+
#[repr(C, packed)]
144+
pub struct BasicMemoryInfoTag {
145+
typ: TagTypeId,
146+
size: u32,
147+
memory_lower: u32,
148+
memory_upper: u32,
149+
}
150+
151+
impl BasicMemoryInfoTag {
152+
pub fn memory_lower(&self) -> u32 {
153+
self.memory_lower
154+
}
155+
156+
pub fn memory_upper(&self) -> u32 {
157+
self.memory_upper
158+
}
159+
}
160+
126161
/// EFI memory map as per EFI specification.
127162
#[derive(Debug)]
128163
#[repr(C)]

multiboot2/src/smbios.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use crate::{Tag, TagTrait, TagTypeId};
2+
3+
use core::fmt::Debug;
4+
5+
const METADATA_SIZE: usize = core::mem::size_of::<TagTypeId>()
6+
+ core::mem::size_of::<u32>()
7+
+ core::mem::size_of::<u8>() * 8;
8+
9+
/// This tag contains a copy of SMBIOS tables as well as their version.
10+
#[derive(ptr_meta::Pointee)]
11+
#[repr(C, packed)]
12+
pub struct SmbiosTag {
13+
typ: TagTypeId,
14+
size: u32,
15+
pub major: u8,
16+
pub minor: u8,
17+
_reserved: [u8; 6],
18+
pub tables: [u8],
19+
}
20+
21+
impl TagTrait for SmbiosTag {
22+
fn dst_size(base_tag: &Tag) -> usize {
23+
assert!(base_tag.size as usize >= METADATA_SIZE);
24+
base_tag.size as usize - METADATA_SIZE
25+
}
26+
}
27+
28+
impl Debug for SmbiosTag {
29+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
30+
f.debug_struct("BootLoaderNameTag")
31+
.field("typ", &{ self.typ })
32+
.field("size", &{ self.size })
33+
.field("major", &{ self.major })
34+
.field("minor", &{ self.minor })
35+
.finish()
36+
}
37+
}
38+
39+
#[cfg(test)]
40+
mod tests {
41+
use crate::{SmbiosTag, Tag, TagType};
42+
43+
/// Returns the tag structure in bytes in native endian format.
44+
fn get_bytes() -> std::vec::Vec<u8> {
45+
let tables = [0xabu8; 24];
46+
// size is: 4 bytes for tag + 4 bytes for size + 1 byte for major and minor
47+
// + 6 bytes reserved + the actual tables
48+
let size = (4 + 4 + 1 + 1 + 6 + tables.len()) as u32;
49+
let typ: u32 = TagType::Smbios.into();
50+
let mut bytes = [typ.to_ne_bytes(), size.to_ne_bytes()].concat();
51+
bytes.push(3);
52+
bytes.push(0);
53+
bytes.extend([0; 6]);
54+
bytes.extend(tables);
55+
bytes
56+
}
57+
58+
/// Test to parse a given tag.
59+
#[test]
60+
fn test_parse() {
61+
let tag = get_bytes();
62+
let tag = unsafe { &*tag.as_ptr().cast::<Tag>() };
63+
let tag = tag.cast_tag::<SmbiosTag>();
64+
assert_eq!({ tag.typ }, TagType::Smbios);
65+
assert_eq!(tag.major, 3);
66+
assert_eq!(tag.minor, 0);
67+
assert_eq!(tag.tables, [0xabu8; 24]);
68+
}
69+
}

0 commit comments

Comments
 (0)