fix: commit remaining dirty files + phase4-5 checker updates

Wave C background task output: status doc + checker enhancements
This commit is contained in:
2026-04-29 15:17:15 +01:00
parent 2432691bb2
commit 58e91279ac
3 changed files with 213 additions and 16 deletions
@@ -24,6 +24,16 @@ const REDBEAR_KDE_SESSION_ENV_FILE: &str = "redbear-kde-session.env";
const REDBEAR_KDE_SESSION_READY_FILE: &str = "redbear-kde-session.ready";
#[cfg(target_os = "redox")]
const REDBEAR_KDE_SESSION_PANEL_READY_FILE: &str = "redbear-kde-session.panel-ready";
#[cfg(target_os = "redox")]
const KEY_KF6_LIBRARIES: &[&str] = &[
"/usr/lib/libKF6CoreAddons.so",
"/usr/lib/libKF6ConfigCore.so",
"/usr/lib/libKF6I18n.so",
"/usr/lib/libKF6WindowSystem.so",
"/usr/lib/libKF6Notifications.so",
"/usr/lib/libKF6Service.so",
"/usr/lib/libKF6WaylandClient.so",
];
#[cfg(target_os = "redox")]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -141,6 +151,7 @@ impl Report {
struct JsonReport {
overall_success: bool,
kf6_libs_present: bool,
kf6_library_versions: bool,
plasma_binaries_present: bool,
session_entry: bool,
session_environment: bool,
@@ -164,6 +175,7 @@ impl Report {
let report = JsonReport {
overall_success: !self.any_failed(),
kf6_libs_present: self.check_passed("KF6_LIBRARIES"),
kf6_library_versions: self.check_passed("KF6_LIBRARY_VERSIONS"),
plasma_binaries_present: self.check_passed("PLASMA_BINARIES"),
session_entry: self.check_passed("SESSION_ENTRY"),
session_environment: self.check_passed("SESSION_ENVIRONMENT"),
@@ -207,19 +219,10 @@ fn parse_args() -> Result<bool, String> {
#[cfg(target_os = "redox")]
fn check_kf6_libraries() -> Check {
let key_libs = [
"/usr/lib/libKF6CoreAddons.so",
"/usr/lib/libKF6ConfigCore.so",
"/usr/lib/libKF6I18n.so",
"/usr/lib/libKF6WindowSystem.so",
"/usr/lib/libKF6Notifications.so",
"/usr/lib/libKF6Service.so",
"/usr/lib/libKF6WaylandClient.so",
];
let mut found = 0usize;
let mut missing = Vec::new();
for lib in key_libs {
for lib in KEY_KF6_LIBRARIES {
if Path::new(lib).exists() {
found += 1;
} else {
@@ -231,7 +234,7 @@ fn check_kf6_libraries() -> Check {
if missing.is_empty() {
Check::pass(
"KF6_LIBRARIES",
format!("{found}/{} key KF6 libraries found", key_libs.len()),
format!("{found}/{} key KF6 libraries found", KEY_KF6_LIBRARIES.len()),
)
} else {
let preview = missing
@@ -242,17 +245,93 @@ fn check_kf6_libraries() -> Check {
.join(", ");
Check::pass(
"KF6_LIBRARIES",
format!("{found}/{} found, missing: {preview}", key_libs.len()),
format!("{found}/{} found, missing: {preview}", KEY_KF6_LIBRARIES.len()),
)
}
} else {
Check::fail(
"KF6_LIBRARIES",
format!("only {found}/{} key KF6 libraries found", key_libs.len()),
format!(
"only {found}/{} key KF6 libraries found",
KEY_KF6_LIBRARIES.len()
),
)
}
}
#[cfg(target_os = "redox")]
fn library_display_name(path: &str) -> &str {
path.rsplit('/').next().unwrap_or(path)
}
#[cfg(target_os = "redox")]
fn detect_shared_library_version(path: &Path) -> Result<String, String> {
let resolved = fs::canonicalize(path)
.map_err(|err| format!("failed to resolve {}: {err}", path.display()))?;
let file_name = resolved
.file_name()
.and_then(|name| name.to_str())
.ok_or_else(|| format!("failed to read resolved file name for {}", path.display()))?;
file_name
.rsplit_once(".so.")
.map(|(_, version)| version.to_string())
.ok_or_else(|| {
format!(
"resolved library {} does not contain a version suffix",
resolved.display()
)
})
}
#[cfg(target_os = "redox")]
fn check_kf6_library_versions() -> Check {
let mut versions = BTreeMap::<String, Vec<String>>::new();
let mut unresolved = Vec::new();
for lib in KEY_KF6_LIBRARIES {
let lib_path = Path::new(lib);
if !lib_path.exists() {
continue;
}
match detect_shared_library_version(lib_path) {
Ok(version) => versions
.entry(version)
.or_default()
.push(library_display_name(lib).to_string()),
Err(err) => unresolved.push(err),
}
}
let detected = versions.values().map(Vec::len).sum::<usize>();
if detected >= 6 {
let mut detail_parts = versions
.iter()
.map(|(version, libs)| format!("{version} [{}]", libs.join(", ")))
.collect::<Vec<_>>();
if !unresolved.is_empty() {
detail_parts.push(format!("unresolved: {}", unresolved.join("; ")));
}
Check::pass(
"KF6_LIBRARY_VERSIONS",
format!(
"detected version suffixes for {detected}/{} key KF6 libraries: {}",
KEY_KF6_LIBRARIES.len(),
detail_parts.join(" | ")
),
)
} else {
let detail = if unresolved.is_empty() {
String::from("no versioned KF6 libraries could be resolved")
} else {
unresolved.join("; ")
};
Check::fail("KF6_LIBRARY_VERSIONS", detail)
}
}
#[cfg(target_os = "redox")]
fn check_plasma_binaries() -> Check {
let required = [
@@ -631,6 +710,7 @@ fn run() -> Result<(), String> {
let mut report = Report::new(json_mode);
report.add(check_kf6_libraries());
report.add(check_kf6_library_versions());
report.add(check_plasma_binaries());
report.add(check_session_entry());
report.add(check_session_environment());
@@ -4,6 +4,11 @@
use std::process;
#[cfg(target_os = "redox")]
use redbear_hwutils::{PciLocation, lookup_pci_device_name, lookup_pci_vendor_name, parse_pci_location};
#[cfg(target_os = "redox")]
use redox_driver_sys::pci::parse_device_info_from_config_space;
const PROGRAM: &str = "redbear-phase5-gpu-check";
const USAGE: &str = "Usage: redbear-phase5-gpu-check [--json]\n\n\
Phase 5 hardware GPU preflight check. Validates DRM device registration,\n\
@@ -120,6 +125,7 @@ impl Report {
#[derive(serde::Serialize)]
struct JsonReport {
drm_device: bool,
gpu_pci_vendor: bool,
gpu_firmware: bool,
mesa_dri: bool,
display_modes: bool,
@@ -138,6 +144,11 @@ impl Report {
.iter()
.find(|c| c.name == "GPU_FIRMWARE")
.map_or(false, |c| c.result == CheckResult::Pass);
let pci_vendor = self
.checks
.iter()
.find(|c| c.name == "GPU_PCI_VENDOR")
.map_or(false, |c| c.result == CheckResult::Pass);
let mesa = self
.checks
.iter()
@@ -176,6 +187,7 @@ impl Report {
std::io::stdout(),
&JsonReport {
drm_device: drm,
gpu_pci_vendor: pci_vendor,
gpu_firmware: firmware,
mesa_dri: mesa,
display_modes: modes,
@@ -256,6 +268,101 @@ fn check_drm_device() -> Check {
Check::fail("DRM_DEVICE", "no DRM device found at /scheme/drm/card0")
}
#[cfg(target_os = "redox")]
#[derive(Clone, Debug)]
struct GpuPciDevice {
location: PciLocation,
vendor_id: u16,
device_id: u16,
}
#[cfg(target_os = "redox")]
fn collect_gpu_pci_devices() -> Result<Vec<GpuPciDevice>, String> {
let entries = std::fs::read_dir("/scheme/pci")
.map_err(|err| format!("failed to read /scheme/pci: {err}"))?;
let mut devices = Vec::new();
for entry in entries.flatten() {
let file_name = entry.file_name();
let Some(file_name) = file_name.to_str() else {
continue;
};
let Some(location) = parse_pci_location(file_name) else {
continue;
};
let config_path = format!("{}/config", location.scheme_path());
let config = match std::fs::read(&config_path) {
Ok(config) => config,
Err(_) => continue,
};
if config.len() < 64 {
continue;
}
let Some(info) = parse_device_info_from_config_space(
redox_driver_sys::pci::PciLocation {
segment: location.segment,
bus: location.bus,
device: location.device,
function: location.function,
},
&config,
) else {
continue;
};
if info.class_code != 0x03 {
continue;
}
devices.push(GpuPciDevice {
location,
vendor_id: info.vendor_id,
device_id: info.device_id,
});
}
devices.sort_by_key(|device| device.location);
Ok(devices)
}
#[cfg(target_os = "redox")]
fn format_gpu_pci_device(device: &GpuPciDevice) -> String {
let vendor = lookup_pci_vendor_name(device.vendor_id)
.unwrap_or_else(|| format!("vendor {:04x}", device.vendor_id));
let device_name = lookup_pci_device_name(device.vendor_id, device.device_id)
.unwrap_or_else(|| format!("device {:04x}", device.device_id));
format!(
"{} {} ({})",
device.location, vendor, device_name
)
}
#[cfg(target_os = "redox")]
fn check_gpu_pci_vendor() -> Check {
match collect_gpu_pci_devices() {
Ok(devices) if devices.is_empty() => Check::fail(
"GPU_PCI_VENDOR",
"no display-class PCI device found under /scheme/pci",
),
Ok(devices) => {
let preview = devices
.iter()
.take(3)
.map(format_gpu_pci_device)
.collect::<Vec<_>>()
.join(", ");
Check::pass(
"GPU_PCI_VENDOR",
&format!("detected {} GPU PCI device(s): {preview}", devices.len()),
)
}
Err(err) => Check::fail("GPU_PCI_VENDOR", &err),
}
}
#[cfg(target_os = "redox")]
fn check_gpu_firmware() -> Check {
let firmware_dirs = ["/lib/firmware/amdgpu", "/lib/firmware/i915"];
@@ -509,6 +616,7 @@ fn check_cs_ioctl_protocol() -> Check {
fn check_hardware_rendering_ready(report: &Report) -> Check {
let required = [
"DRM_DEVICE",
"GPU_PCI_VENDOR",
"GPU_FIRMWARE",
"MESA_DRI",
"DISPLAY_MODES",
@@ -557,6 +665,7 @@ fn run() -> Result<(), String> {
let json_mode = parse_args()?;
let mut report = Report::new(json_mode);
report.add(check_drm_device());
report.add(check_gpu_pci_vendor());
report.add(check_gpu_firmware());
report.add(check_mesa_dri_hardware());
report.add(check_display_modes());