From 18bfaf93d75261a4ea5491ab4a24a70ee9027983 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Tue, 12 Apr 2022 09:55:53 +0200 Subject: [PATCH] Add a reboot command (#328) * Add a reboot command * Add STOP syscall * Add ctrl-alt-del reboot keys * Add comment to keyboard shortcut --- doc/syscalls.md | 10 ++++++++++ src/api/syscall.rs | 8 ++++++++ src/sys/keyboard.rs | 12 ++++++++++-- src/sys/syscall/mod.rs | 3 +++ src/sys/syscall/number.rs | 1 + src/sys/syscall/service.rs | 19 +++++++++++++++++++ src/usr/halt.rs | 5 +++-- src/usr/mod.rs | 1 + src/usr/reboot.rs | 12 ++++++++++++ src/usr/shell.rs | 7 ++++--- 10 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 src/usr/reboot.rs diff --git a/doc/syscalls.md b/doc/syscalls.md index 38f301e0..a8aa5da2 100644 --- a/doc/syscalls.md +++ b/doc/syscalls.md @@ -1,5 +1,7 @@ # MOROS Syscalls +This list is unstable and subject to change between versions of MOROS. + ## EXIT (0x1) ```rust @@ -71,3 +73,11 @@ pub fn realtime() -> f64 ```rust pub fn delete(path: &str) -> isize ``` + +## STOP (0xD) + +```rust +pub fn stop(code: usize) +``` + +The system will reboot with `0xcafe` and halt with `0xdead`. diff --git a/src/api/syscall.rs b/src/api/syscall.rs index 26fb0263..9ed90b88 100644 --- a/src/api/syscall.rs +++ b/src/api/syscall.rs @@ -96,6 +96,14 @@ pub fn spawn(path: &str) { unsafe { syscall!(SPAWN, ptr, len) }; } +pub fn reboot() { + unsafe { syscall!(STOP, 0xcafe) }; +} + +pub fn halt() { + unsafe { syscall!(STOP, 0xdead) }; +} + #[test_case] fn test_file() { use crate::sys::fs::{mount_mem, format_mem, dismount, OpenFlag}; diff --git a/src/sys/keyboard.rs b/src/sys/keyboard.rs index 466d8898..631dc388 100644 --- a/src/sys/keyboard.rs +++ b/src/sys/keyboard.rs @@ -1,4 +1,5 @@ use crate::sys; +use crate::api::syscall; use core::sync::atomic::{AtomicBool, Ordering}; use lazy_static::lazy_static; @@ -9,6 +10,8 @@ use x86_64::instructions::port::Port; lazy_static! { pub static ref KEYBOARD: Mutex> = Mutex::new(None); } +pub static ALT: AtomicBool = AtomicBool::new(false); +pub static CTRL: AtomicBool = AtomicBool::new(false); pub static SHIFT: AtomicBool = AtomicBool::new(false); pub enum KeyboardLayout { @@ -78,18 +81,23 @@ fn interrupt_handler() { let scancode = read_scancode(); if let Ok(Some(key_event)) = keyboard.add_byte(scancode) { match key_event.code { + KeyCode::AltLeft | KeyCode::AltRight => ALT.store(key_event.state == KeyState::Down, Ordering::Relaxed), KeyCode::ShiftLeft | KeyCode::ShiftRight => SHIFT.store(key_event.state == KeyState::Down, Ordering::Relaxed), + KeyCode::ControlLeft | KeyCode::ControlRight => CTRL.store(key_event.state == KeyState::Down, Ordering::Relaxed), _ => {} } - let is_shifted = SHIFT.load(Ordering::Relaxed); + let is_alt = ALT.load(Ordering::Relaxed); + let is_ctrl = CTRL.load(Ordering::Relaxed); + let is_shift = SHIFT.load(Ordering::Relaxed); if let Some(key) = keyboard.process_keyevent(key_event) { match key { + DecodedKey::Unicode('\u{7f}') if is_alt && is_ctrl => syscall::reboot(), // Ctrl-Alt-Del DecodedKey::RawKey(KeyCode::ArrowUp) => send_csi('A'), DecodedKey::RawKey(KeyCode::ArrowDown) => send_csi('B'), DecodedKey::RawKey(KeyCode::ArrowRight) => send_csi('C'), DecodedKey::RawKey(KeyCode::ArrowLeft) => send_csi('D'), - DecodedKey::Unicode('\t') if is_shifted => send_csi('Z'), // Convert Shift+Tab into Backtab + DecodedKey::Unicode('\t') if is_shift => send_csi('Z'), // Convert Shift-Tab into Backtab DecodedKey::Unicode(c) => send_key(c), _ => {}, }; diff --git a/src/sys/syscall/mod.rs b/src/sys/syscall/mod.rs index dfcec0dd..b9978129 100644 --- a/src/sys/syscall/mod.rs +++ b/src/sys/syscall/mod.rs @@ -76,6 +76,9 @@ pub fn dispatcher(n: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { service::spawn(path); 0 } + number::STOP => { + service::stop(arg1) + } _ => { unimplemented!(); } diff --git a/src/sys/syscall/number.rs b/src/sys/syscall/number.rs index 718ba749..839f8d88 100644 --- a/src/sys/syscall/number.rs +++ b/src/sys/syscall/number.rs @@ -10,3 +10,4 @@ pub const SLEEP: usize = 0x9; pub const UPTIME: usize = 0xA; pub const REALTIME: usize = 0xB; pub const DELETE: usize = 0xC; +pub const STOP: usize = 0xD; diff --git a/src/sys/syscall/service.rs b/src/sys/syscall/service.rs index ffaa5b99..b82e4677 100644 --- a/src/sys/syscall/service.rs +++ b/src/sys/syscall/service.rs @@ -3,6 +3,7 @@ use crate::sys::fs::FileInfo; use crate::sys::fs::FileIO; use crate::sys::process::Process; use alloc::vec; +use core::arch::asm; pub fn exit(_code: usize) -> usize { sys::process::exit(); @@ -102,3 +103,21 @@ pub fn spawn(path: &str) -> isize { } -1 } + +pub fn stop(code: usize) -> usize { + match code { + 0xcafe => { // Reboot + unsafe { + asm!( + "xor rax, rax", + "mov cr3, rax" + ); + } + } + 0xdead => { // Halt + sys::acpi::shutdown(); + } + _ => {} + } + 0 +} diff --git a/src/usr/halt.rs b/src/usr/halt.rs index 337c7a15..5ba844dc 100644 --- a/src/usr/halt.rs +++ b/src/usr/halt.rs @@ -1,4 +1,4 @@ -use crate::{sys, usr}; +use crate::usr; use crate::api::syscall; use crate::api::console::Style; @@ -6,6 +6,7 @@ pub fn main(_args: &[&str]) -> usr::shell::ExitCode { let csi_color = Style::color("Yellow"); let csi_reset = Style::reset(); println!("{}MOROS has reached its fate, the system is now halting.{}", csi_color, csi_reset); - sys::acpi::shutdown(); + syscall::sleep(0.5); + syscall::halt(); loop { syscall::sleep(1.0) } } diff --git a/src/usr/mod.rs b/src/usr/mod.rs index f6183631..eb63c22a 100644 --- a/src/usr/mod.rs +++ b/src/usr/mod.rs @@ -31,6 +31,7 @@ pub mod pow; pub mod print; pub mod r#move; pub mod read; +pub mod reboot; pub mod shell; pub mod sleep; pub mod tcp; diff --git a/src/usr/reboot.rs b/src/usr/reboot.rs new file mode 100644 index 00000000..618cc726 --- /dev/null +++ b/src/usr/reboot.rs @@ -0,0 +1,12 @@ +use crate::usr; +use crate::api::syscall; +use crate::api::console::Style; + +pub fn main(_args: &[&str]) -> usr::shell::ExitCode { + let csi_color = Style::color("Yellow"); + let csi_reset = Style::reset(); + println!("{}MOROS has reached its fate, the system is now rebooting.{}", csi_color, csi_reset); + syscall::sleep(0.5); + syscall::reboot(); + loop { syscall::sleep(1.0) } +} diff --git a/src/usr/shell.rs b/src/usr/shell.rs index dc29c034..6ccfbad2 100644 --- a/src/usr/shell.rs +++ b/src/usr/shell.rs @@ -8,11 +8,11 @@ use alloc::vec::Vec; use alloc::string::String; // TODO: Scan /bin -const AUTOCOMPLETE_COMMANDS: [&str; 37] = [ +const AUTOCOMPLETE_COMMANDS: [&str; 38] = [ "2048", "base64", "calc", "clear", "colors", "copy", "date", "delete", "dhcp", "disk", "edit", "env", "exit", "geotime", "goto", "halt", "help", "hex", "host", "http", "httpd", "install", - "keyboard", "lisp", "list", "memory", "move", "net", "pci", "print", "read", "shell", "sleep", - "tcp", "user", "vga", "write" + "keyboard", "lisp", "list", "memory", "move", "net", "pci", "print", "read", "reboot", "shell", + "sleep", "tcp", "user", "vga", "write" ]; #[repr(u8)] @@ -248,6 +248,7 @@ pub fn exec(cmd: &str) -> ExitCode { "date" => usr::date::main(&args), "env" => usr::env::main(&args), "halt" => usr::halt::main(&args), + "reboot" => usr::reboot::main(&args), "hex" => usr::hex::main(&args), "net" => usr::net::main(&args), "dhcp" => usr::dhcp::main(&args),