From 13afca6441ffbf57d5c05e891a013d598ee83763 Mon Sep 17 00:00:00 2001 From: Ruihan Li Date: Tue, 2 Dec 2025 23:42:40 +0800 Subject: [PATCH] Add `i8042.exist` to override ACPI flags --- Cargo.lock | 12 +++++ Cargo.toml | 1 + Components.toml | 1 + Makefile | 1 + kernel/Cargo.toml | 1 + kernel/comps/cmdline/Cargo.toml | 15 ++++++ .../kcmdline.rs => comps/cmdline/src/lib.rs} | 28 +++++----- kernel/comps/i8042/Cargo.toml | 1 + kernel/comps/i8042/src/controller.rs | 52 ++++++++++++++++--- kernel/src/device/tty/device.rs | 6 ++- kernel/src/init.rs | 4 +- kernel/src/lib.rs | 1 - 12 files changed, 99 insertions(+), 24 deletions(-) create mode 100644 kernel/comps/cmdline/Cargo.toml rename kernel/{src/kcmdline.rs => comps/cmdline/src/lib.rs} (93%) diff --git a/Cargo.lock b/Cargo.lock index 0890f5520..f7bed88e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -165,6 +165,16 @@ dependencies = [ "spin", ] +[[package]] +name = "aster-cmdline" +version = "0.1.0" +dependencies = [ + "component", + "log", + "ostd", + "spin", +] + [[package]] name = "aster-console" version = "0.1.0" @@ -192,6 +202,7 @@ dependencies = [ name = "aster-i8042" version = "0.1.0" dependencies = [ + "aster-cmdline", "aster-input", "bitflags 2.9.1", "component", @@ -263,6 +274,7 @@ dependencies = [ "align_ext", "aster-bigtcp", "aster-block", + "aster-cmdline", "aster-console", "aster-framebuffer", "aster-i8042", diff --git a/Cargo.toml b/Cargo.toml index a6fc4ed1d..239f900e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ members = [ "ostd/libs/ostd-test", "kernel", "kernel/comps/block", + "kernel/comps/cmdline", "kernel/comps/console", "kernel/comps/framebuffer", "kernel/comps/input", diff --git a/Components.toml b/Components.toml index 7d2cbf19a..2d0719460 100644 --- a/Components.toml +++ b/Components.toml @@ -14,6 +14,7 @@ mlsdisk = { name = "aster-mlsdisk" } systree = { name = "aster-systree" } i8042 = { name = "aster-i8042" } pci = { name = "aster-pci" } +cmdline = { name = "aster-cmdline" } [whitelist] [whitelist.nix.main] diff --git a/Makefile b/Makefile index 4979e5dec..4c750e91b 100644 --- a/Makefile +++ b/Makefile @@ -224,6 +224,7 @@ OSDK_CRATES := \ ostd/libs/linux-bzimage/setup \ kernel \ kernel/comps/block \ + kernel/comps/cmdline \ kernel/comps/console \ kernel/comps/framebuffer \ kernel/comps/input \ diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 8cbbc5725..cdee30ab2 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -10,6 +10,7 @@ align_ext = { path = "../ostd/libs/align_ext" } aster-input = { path = "comps/input" } aster-block = { path = "comps/block" } aster-network = { path = "comps/network" } +aster-cmdline = { path = "comps/cmdline" } aster-console = { path = "comps/console" } aster-framebuffer = { path = "comps/framebuffer" } aster-softirq = { path = "comps/softirq" } diff --git a/kernel/comps/cmdline/Cargo.toml b/kernel/comps/cmdline/Cargo.toml new file mode 100644 index 000000000..1f6e21e7d --- /dev/null +++ b/kernel/comps/cmdline/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "aster-cmdline" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +component = { path = "../../libs/comp-sys/component" } +ostd = { path = "../../../ostd" } +log = "0.4" +spin = "0.9.4" + +[lints] +workspace = true diff --git a/kernel/src/kcmdline.rs b/kernel/comps/cmdline/src/lib.rs similarity index 93% rename from kernel/src/kcmdline.rs rename to kernel/comps/cmdline/src/lib.rs index e0fb7b1df..d26f6e6f9 100644 --- a/kernel/src/kcmdline.rs +++ b/kernel/comps/cmdline/src/lib.rs @@ -1,7 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -#![expect(unused_variables)] - //! The module to parse kernel command-line arguments. //! //! The format of the Asterinas command line string conforms @@ -9,6 +7,10 @@ //! //! //! +#![no_std] +#![deny(unsafe_code)] + +extern crate alloc; use alloc::{ collections::BTreeMap, @@ -18,7 +20,7 @@ use alloc::{ vec::Vec, }; -use ostd::boot::boot_info; +use component::{init_component, ComponentInitError}; use spin::Once; #[derive(PartialEq, Debug)] @@ -47,13 +49,6 @@ pub struct KCmdlineArg { // Define get APIs. impl KCmdlineArg { - /// Gets the singleton instance of `KCmdlineArg`. - pub fn singleton() -> &'static KCmdlineArg { - static INSTANCE: Once = Once::new(); - - INSTANCE.call_once(|| KCmdlineArg::from(boot_info().kernel_cmdline.as_str())) - } - /// Gets the path of the init process. pub fn get_initproc_path(&self) -> Option<&str> { self.initproc.path.as_deref() @@ -75,7 +70,6 @@ impl KCmdlineArg { } /// Gets the argument vector of a kernel module. - #[expect(dead_code)] pub fn get_module_args(&self, module: &str) -> Option<&Vec> { self.module_args.get(module) } @@ -177,7 +171,7 @@ impl From<&str> for KCmdlineArg { // The option has a value. match option { "init" => { - if let Some(v) = &result.initproc.path { + if result.initproc.path.is_some() { panic!("[KCmdline] Init process specified twice"); } result.initproc.path = Some(value.to_string()); @@ -205,3 +199,13 @@ impl From<&str> for KCmdlineArg { result } } + +/// The [`KCmdlineArg`] singleton. +pub static KCMDLINE: Once = Once::new(); + +#[init_component] +fn init() -> Result<(), ComponentInitError> { + KCMDLINE.call_once(|| KCmdlineArg::from(ostd::boot::boot_info().kernel_cmdline.as_str())); + + Ok(()) +} diff --git a/kernel/comps/i8042/Cargo.toml b/kernel/comps/i8042/Cargo.toml index 4e1991a1c..f893bc50c 100644 --- a/kernel/comps/i8042/Cargo.toml +++ b/kernel/comps/i8042/Cargo.toml @@ -12,6 +12,7 @@ bitflags = "2.5" log = "0.4" spin = "0.9.4" aster-input = { path = "../input" } +aster-cmdline = { path = "../cmdline" } [lints] workspace = true diff --git a/kernel/comps/i8042/src/controller.rs b/kernel/comps/i8042/src/controller.rs index 4f4853239..58b32804e 100644 --- a/kernel/comps/i8042/src/controller.rs +++ b/kernel/comps/i8042/src/controller.rs @@ -5,6 +5,7 @@ //! Reference: //! +use aster_cmdline::{ModuleArg, KCMDLINE}; use bitflags::bitflags; use ostd::{ arch::{device::io_port::ReadWriteAccess, kernel::ACPI_INFO}, @@ -129,15 +130,32 @@ impl I8042Controller { const DATA_PORT_ADDR: u16 = 0x60; const STATUS_OR_COMMAND_PORT_ADDR: u16 = 0x64; - if ACPI_INFO - .get() - .unwrap() - .boot_flags - .is_some_and(|flags| !flags.motherboard_implements_8042()) - { + if !Self::is_present_acpi() { // The PS/2 controller does not exist. See: // . - return Err(I8042ControllerError::NotPresent); + // + // However, it may actually be present and enumerable from other sources, such as PnP + // devices. See: + // . + // + // Currently, we lack the necessary support, so we allow the user to manually override + // the ACPI flag by appending "i8042.exist" to the kernel command line. + // + // TODO: Add support for enumerating PnP devices and remove the command line option. + if !Self::is_present_cmdline() { + log::info!( + "ACPI says i8042 controller is absent; \ + if it is incorrect, append 'i8042.exist' in cmdline to override it" + ); + return Err(I8042ControllerError::NotPresent); + } else { + log::info!( + "ACPI says i8042 controller is absent; \ + however, it is overridden by 'i8042.exist' in cmdline" + ); + } + } else { + log::info!("ACPI says i8042 controller is present"); } let controller = Self { @@ -147,6 +165,26 @@ impl I8042Controller { Ok(controller) } + fn is_present_acpi() -> bool { + ACPI_INFO + .get() + .unwrap() + .boot_flags + .is_some_and(|flags| !flags.motherboard_implements_8042()) + } + + /// Checks if the kernel command line contains the "i8042.exist" option. + fn is_present_cmdline() -> bool { + !KCMDLINE + .get() + .unwrap() + .get_module_args("i8042") + .is_some_and(|args| { + args.iter() + .any(|arg| matches!(arg, ModuleArg::Arg(s) if s.as_bytes() == b"exist")) + }) + } + fn read_configuration(&mut self) -> Result { self.wait_and_send_command(Command::ReadConfiguration)?; self.wait_and_recv_data() diff --git a/kernel/src/device/tty/device.rs b/kernel/src/device/tty/device.rs index 0962f1a14..2f4b40eed 100644 --- a/kernel/src/device/tty/device.rs +++ b/kernel/src/device/tty/device.rs @@ -6,6 +6,7 @@ //! //! Reference: +use aster_cmdline::KCMDLINE; use device_id::{DeviceId, MajorId, MinorId}; use spin::Once; @@ -22,7 +23,6 @@ use crate::{ device::{Device, DeviceType}, inode_handle::FileIo, }, - kcmdline::KCmdlineArg, prelude::*, process::{JobControl, Terminal}, }; @@ -104,7 +104,9 @@ impl SystemConsole { INSTANCE.call_once(|| { // TODO: Support specifying multiple TTY devices, e.g., "console=hvc0 console=tty0". - let console_name = KCmdlineArg::singleton() + let console_name = KCMDLINE + .get() + .unwrap() .get_console_names() .first() .map(String::as_str) diff --git a/kernel/src/init.rs b/kernel/src/init.rs index 50870ff39..574553356 100644 --- a/kernel/src/init.rs +++ b/kernel/src/init.rs @@ -2,6 +2,7 @@ //! Kernel initialization. +use aster_cmdline::KCMDLINE; use component::InitStage; use ostd::{ arch::qemu::{exit_qemu, QemuExitCode}, @@ -12,7 +13,6 @@ use spin::once::Once; use crate::{ fs::{fs_resolver::FsResolver, path::MountNamespace}, - kcmdline::KCmdlineArg, prelude::*, process::{spawn_init_process, Process}, sched::SchedPolicy, @@ -144,7 +144,7 @@ fn first_kthread() { print_banner(); INIT_PROCESS.call_once(|| { - let karg = KCmdlineArg::singleton(); + let karg = KCMDLINE.get().unwrap(); spawn_init_process( karg.get_initproc_path().unwrap(), karg.get_initproc_argv().to_vec(), diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 103d281bd..00e88fec7 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -46,7 +46,6 @@ mod events; mod fs; mod init; mod ipc; -mod kcmdline; mod net; mod prelude; mod process;