119 lines
3.6 KiB
Rust
119 lines
3.6 KiB
Rust
|
//! Kernel commandline parameters handling
|
||
|
|
||
|
use alloc::string::String;
|
||
|
use libk_util::OneTimeInit;
|
||
|
use yggdrasil_abi::error::Error;
|
||
|
|
||
|
use crate::fs::sysfs::{
|
||
|
self,
|
||
|
attribute::{StringAttribute, StringAttributeOps},
|
||
|
};
|
||
|
|
||
|
#[cfg(any(target_arch = "x86_64", target_arch = "x86", rust_analyzer))]
|
||
|
mod x86;
|
||
|
#[cfg(any(target_arch = "x86_64", target_arch = "x86", rust_analyzer))]
|
||
|
pub use x86::X86Options;
|
||
|
|
||
|
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||
|
mod x86_64;
|
||
|
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||
|
pub use x86_64::X86_64Options;
|
||
|
|
||
|
mod general;
|
||
|
pub use general::DebugOptions;
|
||
|
|
||
|
trait SetOption {
|
||
|
fn set_key_value(&mut self, key: &str, value: &str) -> bool;
|
||
|
fn set_flag(&mut self, value: &str) -> bool;
|
||
|
}
|
||
|
|
||
|
/// Kernel commandline options
|
||
|
#[derive(Debug, Default)]
|
||
|
pub struct Options {
|
||
|
pub debug: DebugOptions,
|
||
|
#[cfg(any(target_arch = "x86_64", target_arch = "x86", rust_analyzer))]
|
||
|
pub x86: X86Options,
|
||
|
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||
|
pub x86_64: X86_64Options,
|
||
|
}
|
||
|
|
||
|
impl SetOption for Options {
|
||
|
fn set_flag(&mut self, value: &str) -> bool {
|
||
|
match value {
|
||
|
_ if let Some(value) = value.strip_prefix("debug.") => self.debug.set_flag(value),
|
||
|
#[cfg(any(target_arch = "x86_64", target_arch = "x86", rust_analyzer))]
|
||
|
_ if let Some(value) = value.strip_prefix("x86.") => self.x86.set_flag(value),
|
||
|
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||
|
_ if let Some(value) = value.strip_prefix("x86_64.") => self.x86_64.set_flag(value),
|
||
|
_ => false,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn set_key_value(&mut self, key: &str, value: &str) -> bool {
|
||
|
match key {
|
||
|
_ if let Some(key) = key.strip_prefix("debug.") => self.debug.set_key_value(key, value),
|
||
|
#[cfg(any(target_arch = "x86_64", target_arch = "x86", rust_analyzer))]
|
||
|
_ if let Some(key) = key.strip_prefix("x86.") => self.x86.set_key_value(key, value),
|
||
|
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||
|
_ if let Some(key) = key.strip_prefix("x86_64.") => {
|
||
|
self.x86_64.set_key_value(key, value)
|
||
|
}
|
||
|
_ => false,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static OPTIONS: OneTimeInit<Options> = OneTimeInit::new();
|
||
|
static OPTIONS_STRING: OneTimeInit<String> = OneTimeInit::new();
|
||
|
|
||
|
pub fn get() -> &'static Options {
|
||
|
OPTIONS.get()
|
||
|
}
|
||
|
|
||
|
fn parse_argument(options: &mut Options, arg: &str) -> bool {
|
||
|
let arg = arg.trim();
|
||
|
|
||
|
if let Some((key, value)) = arg.split_once('=') {
|
||
|
options.set_key_value(key.trim_end(), value.trim_start())
|
||
|
} else {
|
||
|
options.set_flag(arg)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Sets up kernel options from an argument list
|
||
|
pub fn parse_boot_argument_list<'a, I: Iterator<Item = &'a str>>(args: I) {
|
||
|
let mut options = Default::default();
|
||
|
let mut string = String::new();
|
||
|
|
||
|
args.for_each(|arg| {
|
||
|
if parse_argument(&mut options, arg) {
|
||
|
string.push_str(arg);
|
||
|
string.push('\n');
|
||
|
}
|
||
|
});
|
||
|
|
||
|
OPTIONS.init(options);
|
||
|
OPTIONS_STRING.init(string);
|
||
|
|
||
|
// Add to sysfs
|
||
|
if let Some(kernel) = sysfs::kernel() {
|
||
|
struct Cmdline;
|
||
|
|
||
|
impl StringAttributeOps for Cmdline {
|
||
|
const NAME: &'static str = "cmdline";
|
||
|
const NEWLINE: bool = false;
|
||
|
|
||
|
fn read(_state: &Self::Data) -> Result<String, Error> {
|
||
|
Ok(OPTIONS_STRING.get().into())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
kernel.add_attribute(StringAttribute::from(Cmdline)).ok();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Sets up kernel options from an argument string, where options are separated by whitespace
|
||
|
pub fn parse_boot_arguments(args: &str) {
|
||
|
parse_boot_argument_list(args.trim().split(' '));
|
||
|
}
|