Files
asterinas/osdk/src/config/scheme/qemu.rs
2024-05-06 12:19:16 +08:00

108 lines
3.0 KiB
Rust

// SPDX-License-Identifier: MPL-2.0
//! A module about QEMU settings and arguments.
use std::{path::PathBuf, process};
use crate::{
arch::{get_default_arch, Arch},
config::unix_args::{apply_kv_array, get_key, split_to_kv_array},
error::Errno,
error_msg,
};
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct QemuScheme {
/// The additional arguments for running QEMU, in the form of raw
/// command line arguments.
pub args: Option<String>,
/// The path of qemu
pub path: Option<PathBuf>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Qemu {
pub args: String,
pub path: PathBuf,
}
impl Default for Qemu {
fn default() -> Self {
Qemu {
args: String::new(),
path: PathBuf::from(get_default_arch().system_qemu()),
}
}
}
impl Qemu {
pub fn apply_qemu_args(&mut self, args: &Vec<String>) {
let mut joined = split_to_kv_array(&self.args);
// Check the soundness of qemu arguments
for arg in joined.iter() {
check_qemu_arg(arg);
}
apply_kv_array(&mut joined, args, " ", MULTI_VALUE_KEYS);
self.args = joined.join(" ");
}
}
impl QemuScheme {
pub fn inherit(&mut self, from: &Self) {
if self.args.is_none() {
self.args.clone_from(&from.args);
}
if self.path.is_none() {
self.path.clone_from(&from.path);
}
}
pub fn finalize(self, arch: Arch) -> Qemu {
Qemu {
args: self.args.unwrap_or_default(),
path: self.path.unwrap_or(PathBuf::from(arch.system_qemu())),
}
}
}
// Below are checked keys in qemu arguments. The key list is non-exhaustive.
/// Keys with multiple values
const MULTI_VALUE_KEYS: &[&str] = &[
"-device", "-chardev", "-object", "-netdev", "-drive", "-cdrom",
];
/// Keys with only single value
const SINGLE_VALUE_KEYS: &[&str] = &["-cpu", "-machine", "-m", "-serial", "-monitor", "-display"];
/// Keys with no value
const NO_VALUE_KEYS: &[&str] = &["--no-reboot", "-nographic", "-enable-kvm"];
/// Keys are not allowed to set in configuration files and command line
const NOT_ALLOWED_TO_SET_KEYS: &[&str] = &["-kernel", "-append", "-initrd"];
fn check_qemu_arg(arg: &str) {
let key = if let Some(key) = get_key(arg, " ") {
key
} else {
arg.to_string()
};
if NOT_ALLOWED_TO_SET_KEYS.contains(&key.as_str()) {
error_msg!("`{}` is not allowed to set", arg);
process::exit(Errno::ParseMetadata as _);
}
if NO_VALUE_KEYS.contains(&key.as_str()) && key.as_str() != arg {
error_msg!("`{}` cannot have value", arg);
process::exit(Errno::ParseMetadata as _);
}
if (SINGLE_VALUE_KEYS.contains(&key.as_str()) || MULTI_VALUE_KEYS.contains(&key.as_str()))
&& key.as_str() == arg
{
error_msg!("`{}` should have value", arg);
process::exit(Errno::ParseMetadata as _);
}
}