Extend Red Bear runtime tooling
Red Bear OS Team
This commit is contained in:
@@ -7,3 +7,11 @@ template = "cargo"
|
||||
[package.files]
|
||||
"/usr/bin/lspci" = "lspci"
|
||||
"/usr/bin/lsusb" = "lsusb"
|
||||
"/usr/bin/redbear-bluetooth-battery-check" = "redbear-bluetooth-battery-check"
|
||||
"/usr/bin/redbear-phase4-wayland-check" = "redbear-phase4-wayland-check"
|
||||
"/usr/bin/redbear-phase5-network-check" = "redbear-phase5-network-check"
|
||||
"/usr/bin/redbear-phase5-wifi-check" = "redbear-phase5-wifi-check"
|
||||
"/usr/bin/redbear-phase5-wifi-capture" = "redbear-phase5-wifi-capture"
|
||||
"/usr/bin/redbear-phase5-wifi-run" = "redbear-phase5-wifi-run"
|
||||
"/usr/bin/redbear-phase5-wifi-analyze" = "redbear-phase5-wifi-analyze"
|
||||
"/usr/bin/redbear-phase5-wifi-link-check" = "redbear-phase5-wifi-link-check"
|
||||
|
||||
@@ -27,10 +27,34 @@ path = "src/bin/redbear-phase3-input-check.rs"
|
||||
name = "redbear-phase4-wayland-check"
|
||||
path = "src/bin/redbear-phase4-wayland-check.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "redbear-bluetooth-battery-check"
|
||||
path = "src/bin/redbear-bluetooth-battery-check.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "redbear-phase5-network-check"
|
||||
path = "src/bin/redbear-phase5-network-check.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "redbear-phase5-wifi-check"
|
||||
path = "src/bin/redbear-phase5-wifi-check.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "redbear-phase5-wifi-capture"
|
||||
path = "src/bin/redbear-phase5-wifi-capture.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "redbear-phase5-wifi-run"
|
||||
path = "src/bin/redbear-phase5-wifi-run.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "redbear-phase5-wifi-analyze"
|
||||
path = "src/bin/redbear-phase5-wifi-analyze.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "redbear-phase5-wifi-link-check"
|
||||
path = "src/bin/redbear-phase5-wifi-link-check.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "redbear-phase6-kde-check"
|
||||
path = "src/bin/redbear-phase6-kde-check.rs"
|
||||
@@ -39,7 +63,12 @@ path = "src/bin/redbear-phase6-kde-check.rs"
|
||||
name = "redbear-phase-iommu-check"
|
||||
path = "src/bin/redbear-phase-iommu-check.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "redbear-phase-dma-check"
|
||||
path = "src/bin/redbear-phase-dma-check.rs"
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
orbclient = "0.3"
|
||||
redox-driver-sys = { path = "../../../drivers/redox-driver-sys/source" }
|
||||
|
||||
+60
-5
@@ -15,6 +15,42 @@ fn require_path(path: &str) -> Result<(), String> {
|
||||
}
|
||||
}
|
||||
|
||||
fn require_wayland_smoke_marker() -> Result<(), String> {
|
||||
for path in [
|
||||
"/home/root/.qt6-bootstrap-minimal.ok",
|
||||
"/home/root/.qt6-plugin-minimal.ok",
|
||||
"/home/root/.qt6-wayland-smoke-minimal.ok",
|
||||
"/home/root/.qt6-wayland-smoke-offscreen.ok",
|
||||
"/home/root/.qt6-wayland-smoke-wayland.ok",
|
||||
] {
|
||||
let marker = Path::new(path);
|
||||
if !marker.exists() {
|
||||
return Err(format!(
|
||||
"missing required Qt smoke marker {}",
|
||||
marker.display()
|
||||
));
|
||||
}
|
||||
println!("{}", marker.display());
|
||||
}
|
||||
|
||||
let ok = Path::new("/home/root/.qt6-wayland-smoke.ok");
|
||||
if ok.exists() {
|
||||
println!("{}", ok.display());
|
||||
println!("qt6-wayland-smoke");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let err = Path::new("/home/root/.qt6-wayland-smoke.err");
|
||||
if err.exists() {
|
||||
return Err(format!(
|
||||
"qt6-wayland-smoke marker missing; failure marker present at {}",
|
||||
err.display()
|
||||
));
|
||||
}
|
||||
|
||||
Err("qt6-wayland-smoke did not leave a success marker".to_string())
|
||||
}
|
||||
|
||||
fn run() -> Result<(), String> {
|
||||
parse_args(PROGRAM, USAGE, std::env::args()).map_err(|err| {
|
||||
if err.is_empty() {
|
||||
@@ -27,16 +63,35 @@ fn run() -> Result<(), String> {
|
||||
require_path("/usr/bin/orbital-wayland")?;
|
||||
require_path("/usr/bin/wayland-session")?;
|
||||
require_path("/usr/bin/smallvil")?;
|
||||
require_path("/usr/bin/qt6-bootstrap-check")?;
|
||||
require_path("/usr/bin/qt6-plugin-check")?;
|
||||
require_path("/usr/bin/qt6-wayland-smoke")?;
|
||||
require_path("/home/root/.wayland-session.started")?;
|
||||
require_wayland_smoke_marker()?;
|
||||
|
||||
let status = Command::new("redbear-info")
|
||||
.arg("--json")
|
||||
.status()
|
||||
.output()
|
||||
.map_err(|err| format!("failed to run redbear-info --json: {err}"))?;
|
||||
if status.success() {
|
||||
Ok(())
|
||||
return if status.status.success() {
|
||||
let stdout = String::from_utf8_lossy(&status.stdout);
|
||||
if stdout.contains("virtio_net_present") {
|
||||
Ok(())
|
||||
} else {
|
||||
Err("redbear-info --json did not report virtio_net_present".to_string())
|
||||
}
|
||||
} else {
|
||||
Err(format!("redbear-info exited with status {status}"))
|
||||
}
|
||||
let stderr = String::from_utf8_lossy(&status.stderr);
|
||||
if stderr.trim().is_empty() {
|
||||
Err(format!("redbear-info exited with status {}", status.status))
|
||||
} else {
|
||||
Err(format!(
|
||||
"redbear-info exited with status {}: {}",
|
||||
status.status,
|
||||
stderr.trim()
|
||||
))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
+129
-4
@@ -2,6 +2,7 @@ use std::path::Path;
|
||||
use std::process::{self, Command};
|
||||
|
||||
use redbear_hwutils::parse_args;
|
||||
use serde_json::Value;
|
||||
|
||||
const PROGRAM: &str = "redbear-phase5-network-check";
|
||||
const USAGE: &str = "Usage: redbear-phase5-network-check\n\nShow the installed Phase 5 networking/session plumbing surface inside the guest.";
|
||||
@@ -15,6 +16,21 @@ fn require_path(path: &str) -> Result<(), String> {
|
||||
}
|
||||
}
|
||||
|
||||
fn require_json_field(value: &Value, field: &str) -> Result<(), String> {
|
||||
if value.get(field).is_some() {
|
||||
println!("{field}=present");
|
||||
Ok(())
|
||||
} else {
|
||||
Err(format!("redbear-info --json did not report {field}"))
|
||||
}
|
||||
}
|
||||
|
||||
fn optional_require_path(path: &str, label: &str) {
|
||||
if Path::new(path).exists() {
|
||||
println!("{label}=present");
|
||||
}
|
||||
}
|
||||
|
||||
fn run() -> Result<(), String> {
|
||||
parse_args(PROGRAM, USAGE, std::env::args()).map_err(|err| {
|
||||
if err.is_empty() {
|
||||
@@ -25,16 +41,108 @@ fn run() -> Result<(), String> {
|
||||
|
||||
println!("=== Red Bear OS Phase 5 Networking Check ===");
|
||||
require_path("/usr/bin/dbus-daemon")?;
|
||||
require_path("/usr/bin/netctl")?;
|
||||
require_path("/usr/bin/redbear-wifictl")?;
|
||||
|
||||
let info_status = Command::new("redbear-info")
|
||||
let info_output = Command::new("redbear-info")
|
||||
.arg("--json")
|
||||
.status()
|
||||
.output()
|
||||
.map_err(|err| format!("failed to run redbear-info --json: {err}"))?;
|
||||
if !info_status.success() {
|
||||
return Err(format!("redbear-info exited with status {info_status}"));
|
||||
if !info_output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&info_output.stderr);
|
||||
if stderr.trim().is_empty() {
|
||||
return Err(format!(
|
||||
"redbear-info exited with status {}",
|
||||
info_output.status
|
||||
));
|
||||
}
|
||||
return Err(format!(
|
||||
"redbear-info exited with status {}: {}",
|
||||
info_output.status,
|
||||
stderr.trim()
|
||||
));
|
||||
}
|
||||
|
||||
let info_stdout = String::from_utf8_lossy(&info_output.stdout);
|
||||
let info_json: Value = serde_json::from_str(&info_stdout)
|
||||
.map_err(|err| format!("failed to parse redbear-info --json output: {err}"))?;
|
||||
if info_stdout.contains("virtio_net_present") {
|
||||
println!("virtio_net_present");
|
||||
} else {
|
||||
return Err("redbear-info --json did not report virtio_net_present".to_string());
|
||||
}
|
||||
|
||||
let network = info_json
|
||||
.get("network")
|
||||
.ok_or_else(|| "redbear-info --json did not include network section".to_string())?;
|
||||
require_json_field(network, "wifi_control_state")?;
|
||||
require_json_field(network, "wifi_connect_result")?;
|
||||
require_json_field(network, "wifi_disconnect_result")?;
|
||||
|
||||
let _ = Command::new("netctl").arg("status").status();
|
||||
|
||||
let wifictl_output = Command::new("redbear-wifictl")
|
||||
.arg("--probe")
|
||||
.output()
|
||||
.map_err(|err| format!("failed to run redbear-wifictl --probe: {err}"))?;
|
||||
if !wifictl_output.status.success() {
|
||||
return Err(format!(
|
||||
"redbear-wifictl --probe exited with status {}",
|
||||
wifictl_output.status
|
||||
));
|
||||
}
|
||||
let wifictl_stdout = String::from_utf8_lossy(&wifictl_output.stdout);
|
||||
if wifictl_stdout.contains("interfaces=") {
|
||||
println!("WIFICTL_INTERFACES=present");
|
||||
} else {
|
||||
return Err("redbear-wifictl --probe did not report interfaces=".to_string());
|
||||
}
|
||||
if wifictl_stdout.contains("capabilities=") {
|
||||
println!("WIFICTL_CAPABILITIES=present");
|
||||
} else {
|
||||
return Err("redbear-wifictl --probe did not report capabilities=".to_string());
|
||||
}
|
||||
|
||||
let wifi_check_output = Command::new("redbear-phase5-wifi-check")
|
||||
.output()
|
||||
.map_err(|err| format!("failed to run redbear-phase5-wifi-check: {err}"))?;
|
||||
if !wifi_check_output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&wifi_check_output.stderr);
|
||||
if stderr.trim().is_empty() {
|
||||
return Err(format!(
|
||||
"redbear-phase5-wifi-check exited with status {}",
|
||||
wifi_check_output.status
|
||||
));
|
||||
}
|
||||
return Err(format!(
|
||||
"redbear-phase5-wifi-check exited with status {}: {}",
|
||||
wifi_check_output.status,
|
||||
stderr.trim()
|
||||
));
|
||||
}
|
||||
let wifi_check_stdout = String::from_utf8_lossy(&wifi_check_output.stdout);
|
||||
if wifi_check_stdout.contains("PASS: bounded Intel Wi-Fi runtime path exercised on target") {
|
||||
println!("PHASE5_WIFI_CHECK=pass");
|
||||
} else {
|
||||
return Err(
|
||||
"redbear-phase5-wifi-check did not report bounded Wi-Fi runtime success".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
if let Ok(ifaces) = std::fs::read_dir("/scheme/wifictl/ifaces") {
|
||||
for entry in ifaces.flatten() {
|
||||
let iface = entry.file_name().to_string_lossy().into_owned();
|
||||
optional_require_path(
|
||||
&format!("/scheme/wifictl/ifaces/{iface}/connect-result"),
|
||||
"WIFICTL_CONNECT_RESULT_NODE",
|
||||
);
|
||||
optional_require_path(
|
||||
&format!("/scheme/wifictl/ifaces/{iface}/disconnect-result"),
|
||||
"WIFICTL_DISCONNECT_RESULT_NODE",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if Path::new("/run/dbus/system_bus_socket").exists() {
|
||||
println!("DBUS_SYSTEM_BUS=present");
|
||||
} else {
|
||||
@@ -49,3 +157,20 @@ fn main() {
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn require_json_field_accepts_present_key() {
|
||||
let value: Value = serde_json::json!({"wifi_connect_result": "unknown"});
|
||||
assert!(require_json_field(&value, "wifi_connect_result").is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn require_json_field_rejects_missing_key() {
|
||||
let value: Value = serde_json::json!({"wifi_control_state": "present"});
|
||||
assert!(require_json_field(&value, "wifi_connect_result").is_err());
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,10 @@
|
||||
# - redbear-release: Branding and identity (os-release, hostname, motd)
|
||||
# - redox-driver-sys: Safe Rust driver infrastructure crate
|
||||
# - linux-kpi: Linux Kernel Programming Interface compatibility layer
|
||||
# - firmware-loader: AMD/Intel GPU firmware loading daemon
|
||||
# - redbear-iwlwifi: bounded Intel Wi-Fi driver-side package
|
||||
# - redbear-firmware: Linux-firmware-derived firmware bundle
|
||||
# - firmware-loader: firmware loading daemon used by GPU and Wi-Fi bring-up
|
||||
# - redbear-wifictl: Wi-Fi control daemon and scheme
|
||||
# - redox-drm: DRM display driver (AMD + Intel)
|
||||
# - evdevd: Event device daemon (input translation)
|
||||
# - udev-shim: udev-compatible device enumeration shim
|
||||
@@ -27,9 +30,12 @@ This package depends on all core Red Bear OS components.
|
||||
|
||||
Installed components:
|
||||
- redbear-release: OS branding and identity
|
||||
- redox-driver-sys: Driver infrastructure
|
||||
- linux-kpi: Linux kernel API compatibility
|
||||
- firmware-loader: GPU firmware daemon
|
||||
- redox-driver-sys: Driver infrastructure
|
||||
- linux-kpi: Linux kernel API compatibility
|
||||
- redbear-iwlwifi: Intel Wi-Fi driver-side package
|
||||
- redbear-firmware: Firmware bundle
|
||||
- firmware-loader: firmware daemon
|
||||
- redbear-wifictl: Wi-Fi control plane
|
||||
- redox-drm: DRM display driver (AMD + Intel)
|
||||
- evdevd: Input event translation
|
||||
- udev-shim: Device enumeration
|
||||
@@ -45,8 +51,11 @@ dependencies = [
|
||||
"redbear-release",
|
||||
"redox-driver-sys",
|
||||
"linux-kpi",
|
||||
"redbear-iwlwifi",
|
||||
"redbear-firmware",
|
||||
"redox-drm",
|
||||
"firmware-loader",
|
||||
"redbear-wifictl",
|
||||
"evdevd",
|
||||
"udev-shim",
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user