diff --git a/local/recipes/system/redbear-hwutils/source/Cargo.toml b/local/recipes/system/redbear-hwutils/source/Cargo.toml index 7d42dbcf..ec1b6947 100644 --- a/local/recipes/system/redbear-hwutils/source/Cargo.toml +++ b/local/recipes/system/redbear-hwutils/source/Cargo.toml @@ -67,6 +67,14 @@ path = "src/bin/redbear-drm-display-check.rs" name = "redbear-phase-iommu-check" path = "src/bin/redbear-phase-iommu-check.rs" +[[bin]] +name = "redbear-phase-ps2-check" +path = "src/bin/redbear-phase-ps2-check.rs" + +[[bin]] +name = "redbear-phase-timer-check" +path = "src/bin/redbear-phase-timer-check.rs" + [[bin]] name = "redbear-phase-dma-check" path = "src/bin/redbear-phase-dma-check.rs" @@ -80,3 +88,5 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" orbclient = "0.3" redox-driver-sys = { path = "../../../drivers/redox-driver-sys/source" } +libredox = "0.1" +syscall = { package = "redox_syscall", version = "0.7", features = ["std"] } diff --git a/local/recipes/system/redbear-hwutils/source/src/bin/redbear-phase-ps2-check.rs b/local/recipes/system/redbear-hwutils/source/src/bin/redbear-phase-ps2-check.rs new file mode 100644 index 00000000..b6fb31ee --- /dev/null +++ b/local/recipes/system/redbear-hwutils/source/src/bin/redbear-phase-ps2-check.rs @@ -0,0 +1,53 @@ +use std::path::Path; +use std::process::{self, Command}; + +use redbear_hwutils::parse_args; + +const PROGRAM: &str = "redbear-phase-ps2-check"; +const USAGE: &str = + "Usage: redbear-phase-ps2-check\n\nRun the bounded PS/2 and serio proof check inside the guest."; + +fn require_path(path: &str) -> Result<(), String> { + if Path::new(path).exists() { + println!("present={path}"); + Ok(()) + } else { + Err(format!("missing {path}")) + } +} + +fn run_phase3_input_check() -> Result<(), String> { + let status = Command::new("redbear-phase3-input-check") + .status() + .map_err(|err| format!("failed to run redbear-phase3-input-check: {err}"))?; + + if status.success() { + println!("phase3_input_check=ok"); + Ok(()) + } else { + Err(format!("redbear-phase3-input-check exited with status {status}")) + } +} + +fn run() -> Result<(), String> { + parse_args(PROGRAM, USAGE, std::env::args()).map_err(|err| { + if err.is_empty() { + process::exit(0); + } + err + })?; + + println!("=== Red Bear OS PS/2 Runtime Check ==="); + require_path("/scheme/serio/0")?; + require_path("/scheme/serio/1")?; + require_path("/usr/bin/redbear-phase3-input-check")?; + run_phase3_input_check()?; + Ok(()) +} + +fn main() { + if let Err(err) = run() { + eprintln!("{PROGRAM}: {err}"); + process::exit(1); + } +} diff --git a/local/recipes/system/redbear-hwutils/source/src/bin/redbear-phase-timer-check.rs b/local/recipes/system/redbear-hwutils/source/src/bin/redbear-phase-timer-check.rs new file mode 100644 index 00000000..444294c5 --- /dev/null +++ b/local/recipes/system/redbear-hwutils/source/src/bin/redbear-phase-timer-check.rs @@ -0,0 +1,77 @@ +use std::path::Path; +use std::process; +use std::thread; +use std::time::Duration; + +use libredox::{flag, Fd}; +use redbear_hwutils::parse_args; +use syscall::data::TimeSpec; + +const PROGRAM: &str = "redbear-phase-timer-check"; +const USAGE: &str = "Usage: redbear-phase-timer-check\n\nRun the bounded timer-source proof check inside the guest."; + +fn require_path(path: &str) -> Result<(), String> { + if Path::new(path).exists() { + println!("present={path}"); + Ok(()) + } else { + Err(format!("missing {path}")) + } +} + +fn read_timespec(fd: &Fd) -> Result { + let mut time = TimeSpec::default(); + let bytes = libredox::call::read(fd.raw(), &mut time) + .map_err(|err| format!("failed to read monotonic time: {err}"))?; + if bytes < core::mem::size_of::() { + return Err(format!("short read from time scheme: {bytes} bytes")); + } + Ok(time) +} + +fn timespec_to_nanos(time: &TimeSpec) -> i128 { + i128::from(time.tv_sec) * 1_000_000_000i128 + i128::from(time.tv_nsec) +} + +fn run() -> Result<(), String> { + parse_args(PROGRAM, USAGE, std::env::args()).map_err(|err| { + if err.is_empty() { + process::exit(0); + } + err + })?; + + println!("=== Red Bear OS Timer Runtime Check ==="); + + let time_path = format!("/scheme/time/{}", flag::CLOCK_MONOTONIC); + require_path(&time_path)?; + + let time_fd = Fd::open(&time_path, flag::O_RDWR, 0) + .map_err(|err| format!("failed to open {time_path}: {err}"))?; + + let first = read_timespec(&time_fd)?; + thread::sleep(Duration::from_millis(50)); + let second = read_timespec(&time_fd)?; + + println!("monotonic_first_sec={}", first.tv_sec); + println!("monotonic_first_nsec={}", first.tv_nsec); + println!("monotonic_second_sec={}", second.tv_sec); + println!("monotonic_second_nsec={}", second.tv_nsec); + + let delta_ns = timespec_to_nanos(&second) - timespec_to_nanos(&first); + println!("monotonic_delta_ns={delta_ns}"); + + if delta_ns <= 0 { + return Err("monotonic timer did not advance".to_string()); + } + + println!("monotonic_progress=ok"); + Ok(()) +} + +fn main() { + if let Err(err) = run() { + eprintln!("{PROGRAM}: {err}"); + process::exit(1); + } +}