boot cleanup: netctl --boot, keymapd missing-dir, dm typo, pci errno, firmware-loader stub

- redbear-netctl: route --boot (and other manual commands) around clap so
  CommonArgs::parse no longer aborts with 'unexpected argument --boot'
  (12_netctl.service boot-time profile application was failing).
- redbear-keymapd: a missing /etc/keymaps is normal on mini (built-in
  keymaps cover the console) — log INFO, not ERROR, on NotFound.
- driver-manager: fix 'options loadeds' plural typo; log read_dir errno on
  PCI enumeration failure instead of an opaque IoError.
- redbear-mini: ship a 05_firmware-loader.service stub so the bluetooth
  units' weak dep resolves (was 'unit not found' x2 per boot).
This commit is contained in:
2026-07-31 03:23:53 +09:00
parent 7eefe35b6f
commit bcfb36633f
6 changed files with 67 additions and 8 deletions
+15
View File
@@ -503,6 +503,21 @@ args = ["--hotplug"]
type = "oneshot_async"
"""
# Stub: mini intentionally ships no firmware-loader (no firmware blobs except
# iwlwifi), but the bluetooth units (10_btusb / 11_btctl) declare a weak
# dependency on this unit. Without a stub, init logs
# "unit 05_firmware-loader.service not found" twice per boot.
[[files]]
path = "/etc/init.d/05_firmware-loader.service"
data = """
[unit]
description = "Firmware loader (stub: no firmware payload on live-mini)"
[service]
cmd = "true"
type = "oneshot"
"""
[[files]]
path = "/etc/init.d/00_ipcd.service"
data = """
@@ -5,6 +5,7 @@ edition = "2024"
description = "PCI bus backend for redox-driver-core"
[dependencies]
log = "0.4"
redox-driver-core = { path = "../../redox-driver-core/source" }
redox_syscall = { path = "../../../../../local/sources/syscall" }
@@ -29,7 +29,13 @@ impl Bus for PciBus {
}
fn enumerate_devices(&self) -> Result<Vec<DeviceInfo>, BusError> {
let dir = fs::read_dir(&self.pci_root).map_err(|_| BusError::IoError)?;
// Log the underlying io::Error: BusError::IoError alone hides the
// errno, which made the post-switchroot "enumeration failed: IoError"
// storm undiagnosable from boot logs.
let dir = fs::read_dir(&self.pci_root).map_err(|e| {
log::error!("pci: read_dir {} failed: {e}", self.pci_root);
BusError::IoError
})?;
let mut devices = Vec::new();
@@ -374,11 +374,12 @@ fn main() {
}
}
};
// NB: the plural-s used to be appended AFTER "loaded", producing the
// boot-log typo "0 driver(s) with options loadeds".
log::info!(
"policy: {} driver(s) with options loaded{}{}",
"policy: {} driver(s) with options loaded{}",
driver_options.len(),
if policy_disabled { " (SUPPRESSED)" } else { "" },
if driver_options.len() == 1 { "" } else { "s" }
);
// N9: capture the SharedDriverOptions so the SIGHUP worker can
// re-read it on operator reload. main.rs owns the live reference;
@@ -25,10 +25,20 @@ fn main() {
Err(_) => "/etc/keymaps".to_string(),
};
if let Err(e) = scheme.load_from_dir(&keymap_dir) {
log_msg(
"ERROR",
&format!("failed to load keymaps from {}: {}", keymap_dir, e),
);
// A missing keymap directory is the NORMAL state on minimal images
// (mini ships no /etc/keymaps; the built-in keymaps loaded above
// cover the console). Only a present-but-unreadable dir is an error.
if e.kind() == std::io::ErrorKind::NotFound {
log_msg(
"INFO",
&format!("no keymap dir at {}; using built-in keymaps", keymap_dir),
);
} else {
log_msg(
"ERROR",
&format!("failed to load keymaps from {}: {}", keymap_dir, e),
);
}
}
if let Ok(xkb_root) = env::var("XKB_CONFIG_ROOT") {
@@ -76,7 +76,33 @@ fn main() {
// --help and --version automatically and prints to stdout, then exits.
// For netctl specifically, the subcommands (list, status, scan, etc.)
// are not clap subcommands, so allow_external_subcommands is enabled.
let common = CommonArgs::parse();
//
// `--boot` (used by /etc/init.d/12_netctl.service) and the other manual
// commands must NOT go through clap: allow_external_subcommands covers
// unknown bare subcommands but a leading unknown FLAG like `--boot` makes
// clap abort with "unexpected argument" before run() ever sees it — which
// broke boot-time profile application. Detect manual-command invocations
// and give clap only the program name (defaults) in that case.
let manual_cmd = matches!(
std::env::args().nth(1).as_deref(),
Some(
"--boot"
| "list"
| "status"
| "scan"
| "retry"
| "start"
| "stop"
| "enable"
| "disable"
| "is-enabled"
)
);
let common = if manual_cmd {
CommonArgs::parse_from(["redbear-netctl"])
} else {
CommonArgs::parse()
};
common.init_logging("redbear-netctl");
// The existing manual parser handles netctl-specific subcommands.