blob: cbadcc539415c047b861e90aa8573f24db598fb5 [file] [log] [blame]
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! See https://www.kernel.org/doc/html/latest/admin-guide/sysrq.html.
use crate::{
task::{CurrentTask, Kernel},
vfs::{
FileObject, FileOps, FsNode, FsNodeHandle, FsNodeOps, FsStr, InputBuffer, OutputBuffer,
SeekTarget,
},
};
use fidl_fuchsia_hardware_power_statecontrol::{AdminMarker, RebootReason};
use fuchsia_component::client::connect_to_protocol_sync;
use fuchsia_zircon as zx;
use starnix_logging::{log_warn, track_stub};
use starnix_sync::{FileOpsCore, Locked, WriteOps};
use starnix_uapi::{
auth::FsCred, device_type::DeviceType, error, errors::Errno, file_mode::FileMode, off_t,
open_flags::OpenFlags,
};
pub struct SysRqNode {}
impl SysRqNode {
pub fn new(_kernel: &Kernel) -> Self {
Self {}
}
}
impl FsNodeOps for SysRqNode {
fn create_file_ops(
&self,
_locked: &mut Locked<'_, FileOpsCore>,
_node: &FsNode,
_current_task: &CurrentTask,
_flags: OpenFlags,
) -> Result<Box<dyn FileOps>, Errno> {
Ok(Box::new(SysRqFile {}))
}
fn mknod(
&self,
_locked: &mut Locked<'_, FileOpsCore>,
_node: &FsNode,
_current_task: &CurrentTask,
_name: &FsStr,
_mode: FileMode,
_dev: DeviceType,
_owner: FsCred,
) -> Result<FsNodeHandle, Errno> {
error!(EINVAL)
}
fn mkdir(
&self,
_node: &FsNode,
_current_task: &CurrentTask,
_name: &FsStr,
_mode: FileMode,
_owner: FsCred,
) -> Result<FsNodeHandle, Errno> {
error!(EINVAL)
}
fn create_symlink(
&self,
_node: &FsNode,
_current_task: &CurrentTask,
_name: &FsStr,
_target: &FsStr,
_owner: FsCred,
) -> Result<FsNodeHandle, Errno> {
error!(EINVAL)
}
fn unlink(
&self,
_locked: &mut Locked<'_, FileOpsCore>,
_node: &FsNode,
_current_task: &CurrentTask,
_name: &FsStr,
_child: &FsNodeHandle,
) -> Result<(), Errno> {
error!(EINVAL)
}
fn truncate(
&self,
_locked: &mut Locked<'_, FileOpsCore>,
_node: &FsNode,
_current_task: &CurrentTask,
_length: u64,
) -> Result<(), Errno> {
// This file doesn't store any contents, but userspace expects to truncate it on open.
Ok(())
}
}
pub struct SysRqFile {}
impl FileOps for SysRqFile {
fn is_seekable(&self) -> bool {
false
}
fn read(
&self,
_locked: &mut Locked<'_, FileOpsCore>,
_file: &FileObject,
_current_task: &CurrentTask,
_offset: usize,
_data: &mut dyn OutputBuffer,
) -> Result<usize, Errno> {
error!(EINVAL)
}
fn write(
&self,
_locked: &mut Locked<'_, WriteOps>,
_file: &FileObject,
_current_task: &CurrentTask,
_offset: usize,
data: &mut dyn InputBuffer,
) -> Result<usize, Errno> {
let commands = data.read_all()?;
for command in &commands {
match *command {
b'b' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqRebootNoSync"),
b'c' => {
log_warn!("SysRq kernel crash request.");
// Attempt to "crash" the whole device, if that fails settle for just Starnix.
// When this call succeeds with a production implementation it should never
// return. If it returns at all it is a sign the kernel either doesn't have the
// capability or there was a problem with the shutdown request.
let reboot_res = connect_to_protocol_sync::<AdminMarker>()
.unwrap()
.reboot(RebootReason::CriticalComponentFailure, zx::Time::INFINITE);
// LINT.IfChange
panic!(
"reboot call returned unexpectedly ({:?}), crashing from SysRq",
reboot_res
);
// LINT.ThenChange(src/starnix/tests/sysrq/src/lib.rs)
}
b'd' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqDumpLocksHeld"),
b'e' => {
track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqSigtermAllButInit")
}
b'f' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqOomKiller"),
b'h' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqPrintHelp"),
b'i' => {
track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqSigkillAllButInit")
}
b'j' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqJustThawIt"),
b'k' => {
track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqSecureAccessKey")
}
b'l' => {
track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqBacktraceActiveCpus",)
}
b'm' => {
track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqDumpMemoryInfo")
}
b'n' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqRealtimeNice"),
b'o' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqPowerOff"),
b'p' => {
track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqDumpRegistersAndFlags",)
}
b'q' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqDumpHrTimers"),
b'r' => {
track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqDisableKeyboardRawMode",)
}
b's' => {
track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqSyncMountedFilesystems",)
}
b't' => {
track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqDumpCurrentTasks")
}
b'u' => {
track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqRemountAllReadonly")
}
b'v' => {
track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqRestoreFramebuffer")
}
b'w' => {
track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqDumpBlockedTasks")
}
b'x' => {
track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqDumpFtraceBuffer")
}
b'0' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqLogLevel0"),
b'1' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqLogLevel1"),
b'2' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqLogLevel2"),
b'3' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqLogLevel3"),
b'4' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqLogLevel4"),
b'5' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqLogLevel5"),
b'6' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqLogLevel6"),
b'7' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqLogLevel7"),
b'8' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqLogLevel8"),
b'9' => track_stub!(TODO("https://fxbug.dev/319745106"), "SysRqLogLevel9"),
_ => return error!(EINVAL),
}
}
Ok(commands.len())
}
fn seek(
&self,
_file: &FileObject,
_current_task: &CurrentTask,
_current_offset: off_t,
_target: SeekTarget,
) -> Result<off_t, Errno> {
error!(EINVAL)
}
}