Skip to content

Commit 544e1ca

Browse files
committed
multiboot2: Implement setting the command line
1 parent 152c985 commit 544e1ca

File tree

3 files changed

+66
-7
lines changed

3 files changed

+66
-7
lines changed

multiboot2/src/builder/information.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,24 @@
22
use crate::{builder::traits::StructAsBytes, CommandLineTag};
33

44
use alloc::boxed::Box;
5+
use alloc::vec::Vec;
56

67
/// Builder to construct a valid Multiboot2 information dynamically at runtime.
78
/// The tags will appear in the order of their corresponding enumeration,
89
/// except for the END tag.
910
#[derive(Debug)]
10-
pub struct Multiboot2InformationBuilder {}
11+
pub struct Multiboot2InformationBuilder {
12+
command_line_tag: Option<Box<CommandLineTag>>,
13+
}
1114

1215
impl Multiboot2InformationBuilder {
1316
pub const fn new() -> Self {
14-
Self {}
17+
Self {
18+
command_line_tag: None,
19+
}
20+
}
21+
22+
pub fn command_line_tag(&mut self, command_line_tag: Box<CommandLineTag>) {
23+
self.command_line_tag = Some(command_line_tag);
1524
}
1625
}

multiboot2/src/builder/mod.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,41 @@ mod information;
44
pub(self) mod traits;
55

66
pub use information::Multiboot2InformationBuilder;
7+
8+
use alloc::alloc::alloc;
9+
use alloc::boxed::Box;
10+
use core::alloc::Layout;
11+
use core::mem::size_of;
12+
13+
use crate::{TagTrait, TagTypeId};
14+
15+
/// Create a boxed tag with the given content.
16+
pub(super) fn boxed_dst_tag<T: TagTrait<Metadata = usize> + ?Sized>(
17+
typ: impl Into<TagTypeId>,
18+
content: &[u8],
19+
) -> Box<T> {
20+
// based on https://stackoverflow.com/a/64121094/2192464
21+
let (layout, size_offset) = Layout::new::<TagTypeId>()
22+
.extend(Layout::new::<u32>())
23+
.unwrap();
24+
let (layout, inner_offset) = layout
25+
.extend(Layout::array::<usize>(content.len()).unwrap())
26+
.unwrap();
27+
let ptr = unsafe { alloc(layout) };
28+
assert!(!ptr.is_null());
29+
unsafe {
30+
// initialize the content as good as we can
31+
ptr.cast::<TagTypeId>().write(typ.into());
32+
ptr.add(size_offset).cast::<u32>().write(
33+
(content.len() + size_of::<TagTypeId>() + size_of::<u32>())
34+
.try_into()
35+
.unwrap(),
36+
);
37+
// initialize body
38+
let content_ptr = ptr.add(inner_offset);
39+
for (idx, val) in content.iter().enumerate() {
40+
content_ptr.add(idx).write(*val);
41+
}
42+
Box::from_raw(ptr_meta::from_raw_parts_mut(ptr as *mut (), content.len()))
43+
}
44+
}

multiboot2/src/command_line.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
//! Module for [CommandLineTag].
22
3-
use crate::{Tag, TagTrait, TagTypeId};
3+
use crate::{Tag, TagTrait, TagType, TagTypeId};
44
use core::fmt::{Debug, Formatter};
5+
use core::mem;
56
use core::str;
67

8+
#[cfg(feature = "builder")]
9+
use {crate::builder::boxed_dst_tag, alloc::boxed::Box, alloc::vec::Vec};
10+
11+
pub(crate) const METADATA_SIZE: usize = mem::size_of::<TagTypeId>() + mem::size_of::<u32>();
12+
713
/// This tag contains the command line string.
814
///
915
/// The string is a normal C-style UTF-8 zero-terminated string that can be
@@ -18,6 +24,14 @@ pub struct CommandLineTag {
1824
}
1925

2026
impl CommandLineTag {
27+
/// Create a new command line tag from the given string.
28+
#[cfg(feature = "builder")]
29+
pub fn new(command_line: &str) -> Box<Self> {
30+
let mut bytes: Vec<_> = command_line.bytes().collect();
31+
bytes.push(0);
32+
boxed_dst_tag(TagType::Cmdline, &bytes)
33+
}
34+
2135
/// Reads the command line of the kernel as Rust string slice without
2236
/// the null-byte.
2337
///
@@ -52,10 +66,8 @@ impl Debug for CommandLineTag {
5266

5367
impl TagTrait for CommandLineTag {
5468
fn dst_size(base_tag: &Tag) -> usize {
55-
// The size of the sized portion of the command line tag.
56-
let tag_base_size = 8;
57-
assert!(base_tag.size >= 8);
58-
base_tag.size as usize - tag_base_size
69+
assert!(base_tag.size as usize >= METADATA_SIZE);
70+
base_tag.size as usize - METADATA_SIZE
5971
}
6072
}
6173

0 commit comments

Comments
 (0)