Skip to content

Commit b3d9986

Browse files
procfs: add /proc/cmdline for kernel cmdline
Signed-off-by: Andy-Python-Programmer <[email protected]>
1 parent 2d3f413 commit b3d9986

File tree

3 files changed

+48
-19
lines changed

3 files changed

+48
-19
lines changed

src/aero_kernel/src/arch/x86_64/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,12 @@ extern "C" fn x86_64_aero_main(boot_info: &'static StivaleStruct) -> ! {
160160

161161
// Parse the kernel command line.
162162
let command_line: &'static _ = boot_info.command_line().map_or("", |cmd| unsafe {
163+
let cmdline = crate::PHYSICAL_MEMORY_OFFSET + cmd.command_line;
164+
163165
// SAFETY: The bootloader has provided a pointer that points to a valid C
164166
// string with a NULL terminator of size less than `usize::MAX`, whose content
165167
// remain valid and has a static lifetime.
166-
mem::c_str_as_str(cmd.command_line as *const u8)
168+
mem::c_str_as_str(cmdline.as_ptr())
167169
});
168170

169171
let command_line = cmdline::parse(command_line, modules);

src/aero_kernel/src/cmdline.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
use core::num::ParseIntError;
22

3+
use spin::Once;
34
use stivale_boot::v2::StivaleModuleTag;
45

56
use crate::rendy;
67

8+
static RAW_CMDLINE_STR: Once<&'static str> = Once::new();
9+
710
pub struct CommandLine {
811
/// If set, then the kernel logs will be redirected onto the framebuffer until
912
/// the kernel thread jumps to userland.
@@ -47,7 +50,9 @@ fn parse_number(mut string: &str) -> Result<usize, ParseIntError> {
4750
}
4851
}
4952

50-
pub fn parse(cmdline: &str, modules: &'static StivaleModuleTag) -> CommandLine {
53+
pub fn parse(cmdline: &'static str, modules: &'static StivaleModuleTag) -> CommandLine {
54+
RAW_CMDLINE_STR.call_once(|| cmdline);
55+
5156
// Chew up the leading spaces.
5257
let cmdline = cmdline.trim();
5358
let mut result = CommandLine::new();
@@ -97,6 +102,17 @@ pub fn parse(cmdline: &str, modules: &'static StivaleModuleTag) -> CommandLine {
97102
result
98103
}
99104

105+
/// Returns the raw kernel command line string.
106+
///
107+
/// ## Panics
108+
/// * If this function was invoked before the kernel command line was
109+
/// parsed using [`self::parse`].
110+
pub fn get_raw_cmdline() -> &'static str {
111+
RAW_CMDLINE_STR
112+
.get()
113+
.expect("get_raw_cmdline: called before cmdline was parsed")
114+
}
115+
100116
#[cfg(test)]
101117
mod tests {
102118
use super::*;

src/aero_kernel/src/fs/procfs.rs

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@ fn push_string_if_some(map: &mut serde_json::Value, key: &str, value: Option<Str
2525
}
2626
}
2727

28+
fn get_cmdline_cached() -> &'static str {
29+
static CACHED: Once<String> = Once::new();
30+
31+
CACHED.call_once(|| {
32+
use serde_json::*;
33+
34+
json!({
35+
"cmdline": crate::cmdline::get_raw_cmdline(),
36+
})
37+
.to_string()
38+
})
39+
}
40+
2841
fn get_cpuinfo_cached() -> &'static str {
2942
static CACHED: Once<String> = Once::new();
3043

@@ -78,6 +91,8 @@ struct ProcINode {
7891

7992
enum FileContents {
8093
CpuInfo,
94+
CmdLine,
95+
8196
None,
8297
}
8398

@@ -90,7 +105,6 @@ impl Default for FileContents {
90105
struct LockedProcINode(RwLock<ProcINode>);
91106

92107
impl LockedProcINode {
93-
#[inline]
94108
fn new(node: ProcINode) -> Self {
95109
Self(RwLock::new(node))
96110
}
@@ -123,16 +137,13 @@ impl LockedProcINode {
123137
return Err(FileSystemError::EntryExists);
124138
}
125139

126-
let filesystem = this
127-
.filesystem
128-
.upgrade()
129-
.expect("Failed to upgrade to strong filesystem");
140+
let filesystem = this.filesystem.upgrade().unwrap();
130141

131142
let inode = filesystem.allocate_inode(file_type, contents);
132143
let inode_cached = icache.make_item_no_cache(CachedINode::new(inode));
133144

134145
downcast::<dyn INodeInterface, LockedProcINode>(&inode_cached.inner())
135-
.expect("Failed to downcast cached inode on creation")
146+
.unwrap()
136147
.init(
137148
&this.node,
138149
&inode_cached.downgrade(),
@@ -151,18 +162,17 @@ impl INodeInterface for LockedProcINode {
151162
fn read_at(&self, offset: usize, buffer: &mut [u8]) -> Result<usize> {
152163
let this = self.0.read();
153164

154-
match &this.contents {
155-
FileContents::CpuInfo => {
156-
let data = get_cpuinfo_cached();
165+
let data = match &this.contents {
166+
FileContents::CpuInfo => Ok(get_cpuinfo_cached()),
167+
FileContents::CmdLine => Ok(get_cmdline_cached()),
157168

158-
let count = core::cmp::min(buffer.len(), data.len() - offset);
159-
buffer[..count].copy_from_slice(&data.as_bytes()[offset..]);
169+
_ => Err(FileSystemError::NotSupported),
170+
}?;
160171

161-
Ok(count)
162-
}
172+
let count = core::cmp::min(buffer.len(), data.len() - offset);
173+
buffer[..count].copy_from_slice(&data.as_bytes()[offset..offset + count]);
163174

164-
_ => Err(FileSystemError::NotSupported),
165-
}
175+
Ok(count)
166176
}
167177

168178
fn lookup(&self, dir: DirCacheItem, name: &str) -> Result<DirCacheItem> {
@@ -253,8 +263,7 @@ impl ProcFs {
253263

254264
root_dir.filesystem.call_once(|| Arc::downgrade(&copy));
255265

256-
let down = downcast::<dyn INodeInterface, LockedProcINode>(root_cached.inner())
257-
.expect("cannot downcast inode to ram inode");
266+
let down = downcast::<dyn INodeInterface, LockedProcINode>(root_cached.inner()).unwrap();
258267

259268
down.init(
260269
&ramfs.root_inode.downgrade(),
@@ -264,6 +273,8 @@ impl ProcFs {
264273
);
265274

266275
down.make_inode("cpuinfo", FileType::File, FileContents::CpuInfo)?;
276+
down.make_inode("cmdline", FileType::File, FileContents::CmdLine)?;
277+
267278
Ok(ramfs)
268279
}
269280

0 commit comments

Comments
 (0)