feat: 完善sys_reboot (#1084)

* fix(process): 修复copy_process的一些bug & 支持默认init进程传参

- 修复`copy_process`函数对标志位处理不正确的bug
- init进程搜索列表中,支持为默认init程序传入参数

Signed-off-by: longjin <longjin@DragonOS.org>

* feat: 完善sys_reboot

- 校验magic number
- 支持多个cmd (具体内容未实现)

Signed-off-by: longjin <longjin@DragonOS.org>

---------

Signed-off-by: longjin <longjin@DragonOS.org>
This commit is contained in:
LoGin 2025-02-06 22:55:45 +08:00 committed by GitHub
parent a3011dd24a
commit 7ae6621cfa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 176 additions and 9 deletions

View File

@ -1,2 +1,4 @@
pub mod events; pub mod events;
pub mod ksysfs; pub mod ksysfs;
pub mod reboot;
pub mod syscall;

154
kernel/src/misc/reboot.rs Normal file
View File

@ -0,0 +1,154 @@
use core::hint::spin_loop;
use system_error::SystemError;
use crate::{arch::cpu::cpu_reset, libs::mutex::Mutex, syscall::user_access::check_and_clone_cstr};
static SYSTEM_TRANSITION_MUTEX: Mutex<()> = Mutex::new(());
const LINUX_REBOOT_MAGIC1: u32 = 0xfee1dead;
const LINUX_REBOOT_MAGIC2: u32 = 672274793;
const LINUX_REBOOT_MAGIC2A: u32 = 85072278;
const LINUX_REBOOT_MAGIC2B: u32 = 369367448;
const LINUX_REBOOT_MAGIC2C: u32 = 537993216;
#[derive(Debug)]
pub enum RebootCommand {
/// 重启系统,使用默认命令和模式
Restart,
/// 停止操作系统并将系统控制权交给ROM监视器如果有
Halt,
/// Ctrl-Alt-Del序列导致执行RESTART命令
CadOn,
/// Ctrl-Alt-Del序列向init任务发送SIGINT信号
CadOff,
/// 停止操作系统,如果可能的话从系统中移除所有电源
PowerOff,
/// 使用给定的命令字符串重启系统
Restart2,
/// 使用软件挂起(如果编译在内)挂起系统
SoftwareSuspend,
/// 使用预先加载的Linux内核重启系统
Kexec,
}
impl TryFrom<u32> for RebootCommand {
type Error = SystemError;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
0x01234567 => Ok(RebootCommand::Restart),
0xCDEF0123 => Ok(RebootCommand::Halt),
0x89ABCDEF => Ok(RebootCommand::CadOn),
0x00000000 => Ok(RebootCommand::CadOff),
0x4321FEDC => Ok(RebootCommand::PowerOff),
0xA1B2C3D4 => Ok(RebootCommand::Restart2),
0xD000FCE2 => Ok(RebootCommand::SoftwareSuspend),
0x45584543 => Ok(RebootCommand::Kexec),
_ => Err(SystemError::EINVAL),
}
}
}
impl From<RebootCommand> for u32 {
fn from(val: RebootCommand) -> Self {
match val {
RebootCommand::Restart => 0x01234567,
RebootCommand::Halt => 0xCDEF0123,
RebootCommand::CadOn => 0x89ABCDEF,
RebootCommand::CadOff => 0x00000000,
RebootCommand::PowerOff => 0x4321FEDC,
RebootCommand::Restart2 => 0xA1B2C3D4,
RebootCommand::SoftwareSuspend => 0xD000FCE2,
RebootCommand::Kexec => 0x45584543,
}
}
}
/// 系统调用reboot的实现
///
/// 参考https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/reboot.c#700
pub(super) fn do_sys_reboot(
magic1: u32,
magic2: u32,
cmd: u32,
arg: usize,
) -> Result<(), SystemError> {
if magic1 != LINUX_REBOOT_MAGIC1
|| (magic2 != LINUX_REBOOT_MAGIC2
&& magic2 != LINUX_REBOOT_MAGIC2A
&& magic2 != LINUX_REBOOT_MAGIC2B
&& magic2 != LINUX_REBOOT_MAGIC2C)
{
return Err(SystemError::EINVAL);
}
let command = RebootCommand::try_from(cmd)?;
let _guard = SYSTEM_TRANSITION_MUTEX.lock();
log::debug!(
"do_sys_reboot: magic1={}, magic2={}, cmd={:?}",
magic1,
magic2,
command
);
match command {
RebootCommand::Restart => kernel_restart(None),
RebootCommand::Halt => kernel_halt(),
RebootCommand::CadOn => {
// todo: 支持Ctrl-Alt-Del序列
return Ok(());
}
RebootCommand::CadOff => {
// todo: 支持Ctrl-Alt-Del序列
return Ok(());
}
RebootCommand::PowerOff => kernel_power_off(),
RebootCommand::Restart2 => {
let s = check_and_clone_cstr(arg as *const u8, Some(256))?;
let cmd_str = s.to_str().map_err(|_| SystemError::EINVAL)?;
kernel_restart(Some(cmd_str));
}
RebootCommand::SoftwareSuspend => {
log::warn!("do_sys_reboot: SoftwareSuspend not implemented");
return Err(SystemError::ENOSYS);
}
RebootCommand::Kexec => {
log::warn!("do_sys_reboot: Kexec not implemented");
return Err(SystemError::ENOSYS);
}
}
}
/// kernel_restart - 重启系统
///
/// ## 参数
/// - cmd: 指向包含重启命令的缓冲区的指针,或者 None
///
/// 关闭所有东西并执行一个干净的重启。
/// 在中断上下文中调用这是不安全的。
///
/// todo: 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/reboot.c#265
pub fn kernel_restart(cmd: Option<&str>) -> ! {
if let Some(cmd) = cmd {
log::warn!("Restarting system with command: '{}'", cmd);
} else {
log::warn!("Restarting system...");
}
unsafe { cpu_reset() }
}
/// todo: 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/reboot.c#678
pub fn kernel_power_off() -> ! {
log::warn!("Power down");
log::warn!("Currently, the system cannot be powered off, so we halt here.");
loop {
spin_loop();
}
}
/// todo: 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/reboot.c#293
pub fn kernel_halt() -> ! {
log::warn!("System halted.");
loop {
spin_loop();
}
}

View File

@ -0,0 +1,11 @@
use system_error::SystemError;
use crate::syscall::Syscall;
use super::reboot::do_sys_reboot;
impl Syscall {
pub fn reboot(magic1: u32, magic2: u32, cmd: u32, arg: usize) -> Result<usize, SystemError> {
do_sys_reboot(magic1, magic2, cmd, arg).map(|_| 0)
}
}

View File

@ -63,7 +63,6 @@ pub fn kernel_wait4(
// 判断pid类型 // 判断pid类型
let pidtype: PidType; let pidtype: PidType;
if pid == -1 { if pid == -1 {
pidtype = PidType::MAX; pidtype = PidType::MAX;
} else if pid < 0 { } else if pid < 0 {

View File

@ -24,7 +24,7 @@ use num_traits::FromPrimitive;
use system_error::SystemError; use system_error::SystemError;
use crate::{ use crate::{
arch::{cpu::cpu_reset, interrupt::TrapFrame, MMArch}, arch::{interrupt::TrapFrame, MMArch},
filesystem::vfs::{ filesystem::vfs::{
fcntl::{AtFlags, FcntlCommand}, fcntl::{AtFlags, FcntlCommand},
file::FileMode, file::FileMode,
@ -232,7 +232,13 @@ impl Syscall {
Self::sbrk(increment).map(|vaddr: VirtAddr| vaddr.data()) Self::sbrk(increment).map(|vaddr: VirtAddr| vaddr.data())
} }
SYS_REBOOT => Self::reboot(), SYS_REBOOT => {
let magic1 = args[0] as u32;
let magic2 = args[1] as u32;
let cmd = args[2] as u32;
let arg = args[3];
Self::reboot(magic1, magic2, cmd, arg)
}
SYS_CHDIR => { SYS_CHDIR => {
let r = args[0] as *const u8; let r = args[0] as *const u8;
@ -1253,9 +1259,4 @@ impl Syscall {
print!("\x1B[38;2;{fr};{fg};{fb};48;2;{br};{bg};{bb}m{s}\x1B[0m"); print!("\x1B[38;2;{fr};{fg};{fb};48;2;{br};{bg};{bb}m{s}\x1B[0m");
return Ok(s.len()); return Ok(s.len());
} }
pub fn reboot() -> Result<usize, SystemError> {
log::info!("reboot");
unsafe { cpu_reset() };
}
} }

View File

@ -24,7 +24,7 @@ source = "git"
source-path = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/NovaShell.git" source-path = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/NovaShell.git"
# git标签或分支 # git标签或分支
# 注意: branch和revision只能二选一且source要设置为"git" # 注意: branch和revision只能二选一且source要设置为"git"
revision = "feaebefaef" revision = "d7d2136c5a"
# 构建相关信息 # 构建相关信息
[build] [build]
# (可选)构建命令 # (可选)构建命令