mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-25 02:13:24 +00:00
Fix multiple issues in the initproc path
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
4a33020b4f
commit
acfbc7efdc
2
.github/workflows/syscall_test.yml
vendored
2
.github/workflows/syscall_test.yml
vendored
@ -18,4 +18,4 @@ jobs:
|
||||
|
||||
- name: Syscall Test
|
||||
id: syscall_test
|
||||
run: make syscall_test ENABLE_KVM=false
|
||||
run: make run AUTO_SYSCALL_TEST=1 ENABLE_KVM=0
|
||||
|
@ -13,14 +13,13 @@ use std::{
|
||||
process::Command,
|
||||
};
|
||||
|
||||
use clap::{Parser, builder::Str};
|
||||
use clap::{builder::Str, Parser};
|
||||
|
||||
/// The CLI of this runner.
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
struct Args {
|
||||
// Positional arguments.
|
||||
|
||||
/// The Jinux binary path.
|
||||
path: PathBuf,
|
||||
|
||||
@ -29,7 +28,6 @@ struct Args {
|
||||
kcmdline: String,
|
||||
|
||||
// Optional arguments.
|
||||
|
||||
/// Enable KVM when running QEMU.
|
||||
#[arg(long, default_value_t = false)]
|
||||
enable_kvm: bool,
|
||||
|
@ -5,5 +5,5 @@
|
||||
//! on its way.
|
||||
//!
|
||||
|
||||
pub mod multiboot2;
|
||||
mod multiboot2;
|
||||
pub use self::multiboot2::init_boot_args;
|
||||
|
@ -13,12 +13,9 @@ use alloc::{
|
||||
vec,
|
||||
vec::Vec,
|
||||
};
|
||||
use log::debug;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct InitprocArg {
|
||||
// Since environment arguments can precede the init path argument, we
|
||||
// have no choice but to wrap the path in `Option` and check it later.
|
||||
struct InitprocArgs {
|
||||
path: Option<String>,
|
||||
argv: Vec<CString>,
|
||||
envp: Vec<CString>,
|
||||
@ -27,7 +24,7 @@ struct InitprocArg {
|
||||
/// The struct to store the parsed kernel command-line arguments.
|
||||
#[derive(Debug)]
|
||||
pub struct KCmdlineArg {
|
||||
initproc: Option<InitprocArg>,
|
||||
initproc: InitprocArgs,
|
||||
module_args: BTreeMap<String, Vec<CString>>,
|
||||
}
|
||||
|
||||
@ -35,18 +32,15 @@ pub struct KCmdlineArg {
|
||||
impl KCmdlineArg {
|
||||
/// Get the path of the initprocess.
|
||||
pub fn get_initproc_path(&self) -> Option<&str> {
|
||||
self.initproc
|
||||
.as_ref()
|
||||
.and_then(|i| i.path.as_ref())
|
||||
.map(|s| s.as_str())
|
||||
self.initproc.path.as_ref().map(|s| s.as_str())
|
||||
}
|
||||
/// Get the argument vector(argv) of the initprocess.
|
||||
pub fn get_initproc_argv(&self) -> Option<&Vec<CString>> {
|
||||
self.initproc.as_ref().map(|i| &i.argv)
|
||||
pub fn get_initproc_argv(&self) -> &Vec<CString> {
|
||||
&self.initproc.argv
|
||||
}
|
||||
/// Get the environment vector(envp) of the initprocess.
|
||||
pub fn get_initproc_envp(&self) -> Option<&Vec<CString>> {
|
||||
self.initproc.as_ref().map(|i| &i.argv)
|
||||
pub fn get_initproc_envp(&self) -> &Vec<CString> {
|
||||
&self.initproc.envp
|
||||
}
|
||||
/// Get the argument vector of a kernel module.
|
||||
pub fn get_module_args(&self, module: &str) -> Option<&Vec<CString>> {
|
||||
@ -72,8 +66,12 @@ fn split_arg(input: &str) -> impl Iterator<Item = &str> {
|
||||
impl From<&str> for KCmdlineArg {
|
||||
fn from(cmdline: &str) -> Self {
|
||||
// What we construct.
|
||||
let mut result = KCmdlineArg {
|
||||
initproc: None,
|
||||
let mut result: KCmdlineArg = KCmdlineArg {
|
||||
initproc: InitprocArgs {
|
||||
path: None,
|
||||
argv: Vec::new(),
|
||||
envp: Vec::new(),
|
||||
},
|
||||
module_args: BTreeMap::new(),
|
||||
};
|
||||
|
||||
@ -87,11 +85,10 @@ impl From<&str> for KCmdlineArg {
|
||||
// KernelArg => Arg "\s+" KernelArg | %empty
|
||||
// InitArg => Arg "\s+" InitArg | %empty
|
||||
if kcmdline_end {
|
||||
if let Some(&mut ref mut i) = result.initproc.as_mut() {
|
||||
i.argv.push(CString::new(arg).unwrap());
|
||||
} else {
|
||||
if result.initproc.path == None {
|
||||
panic!("Initproc arguments provided but no initproc path specified!");
|
||||
}
|
||||
result.initproc.argv.push(CString::new(arg).unwrap());
|
||||
continue;
|
||||
}
|
||||
if arg == "--" {
|
||||
@ -134,32 +131,16 @@ impl From<&str> for KCmdlineArg {
|
||||
// The option has a value.
|
||||
match option {
|
||||
"init" => {
|
||||
if let Some(&mut ref mut i) = result.initproc.as_mut() {
|
||||
if let Some(v) = &i.path {
|
||||
if let Some(v) = &result.initproc.path {
|
||||
panic!("Initproc assigned twice in the command line!");
|
||||
}
|
||||
i.path = Some(value.to_string());
|
||||
} else {
|
||||
result.initproc = Some(InitprocArg {
|
||||
path: Some(value.to_string()),
|
||||
argv: Vec::new(),
|
||||
envp: Vec::new(),
|
||||
});
|
||||
}
|
||||
result.initproc.path = Some(value.to_string());
|
||||
}
|
||||
_ => {
|
||||
// If the option is not recognized, it is passed to the initproc.
|
||||
// Pattern 'option=value' is treated as the init environment.
|
||||
let envp_entry = CString::new(option.to_string() + "=" + value).unwrap();
|
||||
if let Some(&mut ref mut i) = result.initproc.as_mut() {
|
||||
i.envp.push(envp_entry);
|
||||
} else {
|
||||
result.initproc = Some(InitprocArg {
|
||||
path: None,
|
||||
argv: Vec::new(),
|
||||
envp: vec![envp_entry],
|
||||
});
|
||||
}
|
||||
result.initproc.envp.push(envp_entry);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -169,27 +150,11 @@ impl From<&str> for KCmdlineArg {
|
||||
// If the option is not recognized, it is passed to the initproc.
|
||||
// Pattern 'option' without value is treated as the init argument.
|
||||
let argv_entry = CString::new(option.to_string()).unwrap();
|
||||
if let Some(&mut ref mut i) = result.initproc.as_mut() {
|
||||
i.argv.push(argv_entry);
|
||||
} else {
|
||||
result.initproc = Some(InitprocArg {
|
||||
path: None,
|
||||
argv: vec![argv_entry],
|
||||
envp: Vec::new(),
|
||||
});
|
||||
result.initproc.argv.push(argv_entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug!("{:?}", result);
|
||||
|
||||
if let Some(&ref i) = result.initproc.as_ref() {
|
||||
if i.path == None {
|
||||
panic!("Initproc arguments provided but no initproc! Maybe have bad option.");
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
@ -2,8 +2,6 @@
|
||||
//! from the bootloader to the rest of the framework.
|
||||
//!
|
||||
|
||||
use crate::arch::boot::init_boot_args;
|
||||
|
||||
pub mod kcmdline;
|
||||
use kcmdline::KCmdlineArg;
|
||||
|
||||
@ -13,6 +11,8 @@ use self::memory_region::MemoryRegion;
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use spin::Once;
|
||||
|
||||
/// ACPI information from the bootloader.
|
||||
///
|
||||
/// The boot crate can choose either providing the raw RSDP physical address or
|
||||
/// providing the RSDT/XSDT physical address after parsing RSDP.
|
||||
/// This is because bootloaders differ in such behaviors.
|
||||
@ -36,32 +36,29 @@ pub struct BootloaderFramebufferArg {
|
||||
pub bpp: usize,
|
||||
}
|
||||
|
||||
// Use a macro to simplify coding.
|
||||
macro_rules! define_global_static_boot_arguments {
|
||||
( $( $lower:ident, $upper:ident, $typ:ty; )* ) => {
|
||||
// Define statics and corresponding public get APIs.
|
||||
// Define statics and corresponding public getter APIs.
|
||||
$(
|
||||
static $upper: Once<$typ> = Once::new();
|
||||
/// Macro generated public get API.
|
||||
/// Macro generated public getter API.
|
||||
pub fn $lower() -> &'static $typ {
|
||||
$upper.get().unwrap()
|
||||
}
|
||||
)*
|
||||
|
||||
// Produce a init function call. The init function must
|
||||
// be defined in the `arch::boot` module conforming to this
|
||||
// definition.
|
||||
fn arch_init_boot_args() {
|
||||
init_boot_args( $( &$upper, )* );
|
||||
crate::arch::boot::init_boot_args( $( &$upper, )* );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Define a series of static variable definitions and its APIs. The names in
|
||||
// each line are:
|
||||
// 1. The lowercase name of the variable, also the name of the get API;
|
||||
// 2. the uppercase name of the variable;
|
||||
// 3. the type of the variable.
|
||||
// Define a series of static variables and their getter APIs.
|
||||
define_global_static_boot_arguments!(
|
||||
// Getter Names | Static Variables | Variable Types
|
||||
bootloader_name, BOOTLOADER_NAME, String;
|
||||
kernel_cmdline, KERNEL_CMDLINE, KCmdlineArg;
|
||||
initramfs, INITRAMFS, &'static [u8];
|
||||
@ -70,6 +67,8 @@ define_global_static_boot_arguments!(
|
||||
memory_regions, MEMORY_REGIONS, Vec<MemoryRegion>;
|
||||
);
|
||||
|
||||
/// The initialization method of the boot module.
|
||||
///
|
||||
/// After initializing the boot module, the get functions could be called.
|
||||
/// The initialization must be done after the heap is set and before physical
|
||||
/// mappings are cancelled.
|
||||
|
@ -81,25 +81,25 @@ fn init_thread() {
|
||||
|
||||
let initproc = Process::spawn_user_process(
|
||||
karg.get_initproc_path().unwrap(),
|
||||
karg.get_initproc_argv().unwrap().to_vec(),
|
||||
karg.get_initproc_envp().unwrap().to_vec(),
|
||||
karg.get_initproc_argv().to_vec(),
|
||||
karg.get_initproc_envp().to_vec(),
|
||||
)
|
||||
.expect("Run init process failed.");
|
||||
|
||||
loop {
|
||||
// If initproc becomes zombie, then exit qemu.
|
||||
if *initproc.status().lock() == ProcessStatus::Zombie {
|
||||
// Wait till initproc become zombie.
|
||||
while *initproc.status().lock() != ProcessStatus::Zombie {
|
||||
// We don't have preemptive scheduler now.
|
||||
// The long running init thread should yield its own execution to allow other tasks to go on.
|
||||
Thread::yield_now();
|
||||
}
|
||||
|
||||
// TODO: exit via qemu isa debug device should not be the only way.
|
||||
let exit_code = if initproc.exit_code().load(Ordering::Relaxed) == 0 {
|
||||
QemuExitCode::Success
|
||||
} else {
|
||||
QemuExitCode::Failed
|
||||
};
|
||||
exit_qemu(exit_code);
|
||||
}
|
||||
// We don't have preemptive scheduler now.
|
||||
// The long running init thread should yield its own execution to allow other tasks to go on.
|
||||
Thread::yield_now();
|
||||
}
|
||||
}
|
||||
|
||||
/// first process never return
|
||||
|
Reference in New Issue
Block a user