Skip to content

Commit

Permalink
feat: 完善sys_reboot
Browse files Browse the repository at this point in the history
- 校验magic number
- 支持多个cmd (具体内容未实现)

Signed-off-by: longjin <[email protected]>
  • Loading branch information
fslongjin committed Jan 2, 2025
1 parent 29f0847 commit de5deed
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 8 deletions.
2 changes: 2 additions & 0 deletions kernel/src/misc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
pub mod events;
pub mod ksysfs;
pub mod reboot;
pub mod syscall;
154 changes: 154 additions & 0 deletions kernel/src/misc/reboot.rs
Original file line number Diff line number Diff line change
@@ -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();
}
}
11 changes: 11 additions & 0 deletions kernel/src/misc/syscall.rs
Original file line number Diff line number Diff line change
@@ -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)
}
}
1 change: 0 additions & 1 deletion kernel/src/process/exit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ pub fn kernel_wait4(

// 判断pid类型
let pidtype: PidType;

if pid == -1 {
pidtype = PidType::MAX;
} else if pid < 0 {
Expand Down
15 changes: 8 additions & 7 deletions kernel/src/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use num_traits::FromPrimitive;
use system_error::SystemError;

use crate::{
arch::{cpu::cpu_reset, interrupt::TrapFrame, MMArch},
arch::{interrupt::TrapFrame, MMArch},
filesystem::vfs::{
fcntl::{AtFlags, FcntlCommand},
file::FileMode,
Expand Down Expand Up @@ -232,7 +232,13 @@ impl Syscall {
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 => {
let r = args[0] as *const u8;
Expand Down Expand Up @@ -1253,9 +1259,4 @@ impl Syscall {
print!("\x1B[38;2;{fr};{fg};{fb};48;2;{br};{bg};{bb}m{s}\x1B[0m");
return Ok(s.len());
}

pub fn reboot() -> Result<usize, SystemError> {
log::info!("reboot");
unsafe { cpu_reset() };
}
}

0 comments on commit de5deed

Please sign in to comment.