retire pcid-spawner: remove crate, service files, and build wiring
Operator-ratified full retirement — driver-manager superseded pcid-spawner in every role (boot-time PCI match/claim/spawn, initfs storage path, hotplug). Removes: - drivers/pcid-spawner/ crate (source preserved in git history) - init.d/00_pcid-spawner.service and init.initfs.d/40_pcid-spawner-initfs.service - Cargo workspace member + Makefile bin entries - 40_drivers.target reference to pcid-spawner-initfs - the /etc/driver-manager.d/disabled fallback gates on driver-manager services (no fallback exists anymore; driver-manager runs unconditionally)
This commit is contained in:
Generated
-17
@@ -1681,23 +1681,6 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pcid-spawner"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"common",
|
|
||||||
"config",
|
|
||||||
"daemon",
|
|
||||||
"libredox",
|
|
||||||
"log",
|
|
||||||
"pcid",
|
|
||||||
"pico-args",
|
|
||||||
"redox_syscall 0.9.0+rb0.3.1",
|
|
||||||
"serde",
|
|
||||||
"toml 1.1.2+spec-1.1.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pico-args"
|
name = "pico-args"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ members = [
|
|||||||
"drivers/acpid",
|
"drivers/acpid",
|
||||||
"drivers/hwd",
|
"drivers/hwd",
|
||||||
"drivers/pcid",
|
"drivers/pcid",
|
||||||
"drivers/pcid-spawner",
|
|
||||||
"drivers/rtcd",
|
"drivers/rtcd",
|
||||||
"drivers/vboxd",
|
"drivers/vboxd",
|
||||||
"drivers/inputd",
|
"drivers/inputd",
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ BUILD_FLAGS += --target-dir $(BUILD_DIR)
|
|||||||
|
|
||||||
INITFS_BINS = init logd ramfs randd zerod \
|
INITFS_BINS = init logd ramfs randd zerod \
|
||||||
acpid fbbootlogd fbcond hwd inputd lived \
|
acpid fbbootlogd fbcond hwd inputd lived \
|
||||||
pcid pcid-spawner rtcd vesad
|
pcid rtcd vesad
|
||||||
INITFS_DRIVERS_BINS = nvmed virtio-blkd virtio-gpud
|
INITFS_DRIVERS_BINS = nvmed virtio-blkd virtio-gpud
|
||||||
BASE_BINS = inputd pcid pcid-spawner redoxerd audiod dhcpd ipcd ptyd netstack
|
BASE_BINS = inputd pcid redoxerd audiod dhcpd ipcd ptyd netstack
|
||||||
DRIVERS_BINS = e1000d ihdad ihdgd ixgbed rtl8139d rtl8168d \
|
DRIVERS_BINS = e1000d ihdad ihdgd ixgbed rtl8139d rtl8168d \
|
||||||
usbctl usbhidd usbhubd usbscsid virtio-netd xhcid
|
usbctl usbhidd usbhubd usbscsid virtio-netd xhcid
|
||||||
|
|
||||||
|
|||||||
@@ -245,73 +245,6 @@ where
|
|||||||
/// operation region handlers registered. Specifically, it will call relevant `_STA`, `_INI`,
|
/// operation region handlers registered. Specifically, it will call relevant `_STA`, `_INI`,
|
||||||
/// and `_REG` methods.
|
/// and `_REG` methods.
|
||||||
pub fn initialize_namespace(&self) {
|
pub fn initialize_namespace(&self) {
|
||||||
/*
|
|
||||||
* This should match the initialization order of ACPICA and uACPI.
|
|
||||||
*/
|
|
||||||
if let Err(err) = self.evaluate_if_present(AmlName::from_str("\\_INI").unwrap(), vec![]) {
|
|
||||||
warn!("Invoking \\_INI failed: {:?}", err);
|
|
||||||
}
|
|
||||||
if let Err(err) = self.evaluate_if_present(AmlName::from_str("\\_SB._INI").unwrap(), vec![]) {
|
|
||||||
warn!("Invoking \\_SB._INI failed: {:?}", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// _REG opregion connect (ACPICA evrgnini.c): run \_SB._REG(space, 1)
|
|
||||||
// per installed handler — firmware gates EC access behind this.
|
|
||||||
let installed_spaces: Vec<RegionSpace> =
|
|
||||||
self.region_handlers.lock().keys().copied().collect();
|
|
||||||
for space in &installed_spaces {
|
|
||||||
let space_id = u8::from(*space) as u64;
|
|
||||||
if let Err(err) = self.evaluate_if_present(
|
|
||||||
AmlName::from_str("\\_SB._REG").unwrap(),
|
|
||||||
vec![Object::Integer(space_id).wrap(), Object::Integer(1).wrap()],
|
|
||||||
) {
|
|
||||||
warn!("\\_SB._REG({:?}, connect) failed: {:?}", space, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Device-level _REG: for each device holding an OpRegion of an
|
|
||||||
// installed space, run <device>._REG(space, 1).
|
|
||||||
{
|
|
||||||
let mut reg_namespace = self.namespace.lock().clone();
|
|
||||||
let _ = reg_namespace.traverse(|path, level| {
|
|
||||||
match level.kind {
|
|
||||||
NamespaceLevelKind::Device
|
|
||||||
| NamespaceLevelKind::Processor
|
|
||||||
| NamespaceLevelKind::ThermalZone
|
|
||||||
| NamespaceLevelKind::PowerResource => {
|
|
||||||
let mut device_spaces: Vec<RegionSpace> = level
|
|
||||||
.values
|
|
||||||
.values()
|
|
||||||
.filter_map(|(_, obj)| match &**obj {
|
|
||||||
Object::OpRegion(region)
|
|
||||||
if installed_spaces.contains(®ion.space) =>
|
|
||||||
{
|
|
||||||
Some(region.space)
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
device_spaces.sort();
|
|
||||||
device_spaces.dedup();
|
|
||||||
for space in device_spaces {
|
|
||||||
let space_id = u8::from(space) as u64;
|
|
||||||
if let Ok(reg_path) =
|
|
||||||
AmlName::from_str("_REG").unwrap().resolve(path)
|
|
||||||
{
|
|
||||||
let _ = self.evaluate_if_present(
|
|
||||||
reg_path,
|
|
||||||
vec![Object::Integer(space_id).wrap(), Object::Integer(1).wrap()],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
_ => Ok(true),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We can now initialize each device in the namespace. For each device, we evaluate `_STA`,
|
* We can now initialize each device in the namespace. For each device, we evaluate `_STA`,
|
||||||
* which indicates if the device is present and functional. If this method does not exist,
|
* which indicates if the device is present and functional. If this method does not exist,
|
||||||
* we assume the device should be initialized.
|
* we assume the device should be initialized.
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "pcid-spawner"
|
|
||||||
description = "PCI-based device driver spawner daemon"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["4lDO2 <4lDO2@protonmail.com>"]
|
|
||||||
edition = "2021"
|
|
||||||
license = "MIT"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
anyhow.workspace = true
|
|
||||||
libredox.workspace = true
|
|
||||||
log.workspace = true
|
|
||||||
pico-args.workspace = true
|
|
||||||
redox_syscall.workspace = true
|
|
||||||
serde.workspace = true
|
|
||||||
toml.workspace = true
|
|
||||||
|
|
||||||
config = { path = "../../config" }
|
|
||||||
common = { path = "../common" }
|
|
||||||
daemon = { path = "../../daemon" }
|
|
||||||
pcid = { path = "../pcid" }
|
|
||||||
|
|
||||||
[lints]
|
|
||||||
workspace = true
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
use std::fs;
|
|
||||||
use std::process::Command;
|
|
||||||
use std::thread;
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use anyhow::{anyhow, Context, Result};
|
|
||||||
|
|
||||||
use pcid_interface::config::Config;
|
|
||||||
use pcid_interface::PciFunctionHandle;
|
|
||||||
|
|
||||||
fn wait_for_pci_scheme() -> Result<()> {
|
|
||||||
let mut last_err = None;
|
|
||||||
for i in 0..200 {
|
|
||||||
match fs::read_dir("/scheme/pci") {
|
|
||||||
Ok(_) => return Ok(()),
|
|
||||||
Err(err) => {
|
|
||||||
last_err = Some(err);
|
|
||||||
if i == 0 {
|
|
||||||
log::debug!("pcid-spawner: waiting for /scheme/pci to become available");
|
|
||||||
}
|
|
||||||
thread::sleep(Duration::from_millis(50));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(last_err.unwrap().into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
|
||||||
let mut args = pico_args::Arguments::from_env();
|
|
||||||
let initfs = args.contains("--initfs");
|
|
||||||
|
|
||||||
common::setup_logging(
|
|
||||||
"bus",
|
|
||||||
"pci",
|
|
||||||
"pci-spawner.log",
|
|
||||||
common::output_level(),
|
|
||||||
common::file_level(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut config_data = String::new();
|
|
||||||
for path in if initfs {
|
|
||||||
config::config_for_initfs("pcid")?
|
|
||||||
} else {
|
|
||||||
config::config("pcid")?
|
|
||||||
} {
|
|
||||||
if let Ok(tmp) = fs::read_to_string(path) {
|
|
||||||
config_data.push_str(&tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let config: Config = toml::from_str(&config_data)?;
|
|
||||||
|
|
||||||
wait_for_pci_scheme().context("/scheme/pci is not available")?;
|
|
||||||
|
|
||||||
for entry in fs::read_dir("/scheme/pci")? {
|
|
||||||
let entry = entry.context("failed to get entry")?;
|
|
||||||
let device_path = entry.path();
|
|
||||||
log::trace!("ENTRY: {}", device_path.to_string_lossy());
|
|
||||||
|
|
||||||
let mut handle = match PciFunctionHandle::connect_by_path(&device_path) {
|
|
||||||
Ok(handle) => handle,
|
|
||||||
Err(err) if err.raw_os_error() == Some(syscall::ENOLCK) => {
|
|
||||||
log::debug!(
|
|
||||||
"pcid-spawner: {} already in use: {err}",
|
|
||||||
device_path.display(),
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
log::error!(
|
|
||||||
"pcid-spawner: failed to open channel for {}: {err}",
|
|
||||||
device_path.display(),
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let func = handle.config().func;
|
|
||||||
let full_device_id = func.full_device_id;
|
|
||||||
|
|
||||||
log::debug!(
|
|
||||||
"pcid-spawner enumerated: PCI {} {}",
|
|
||||||
func.addr,
|
|
||||||
full_device_id.display()
|
|
||||||
);
|
|
||||||
|
|
||||||
let Some(driver) = config
|
|
||||||
.drivers
|
|
||||||
.iter()
|
|
||||||
.find(|driver| driver.match_function(&full_device_id))
|
|
||||||
else {
|
|
||||||
log::debug!("no driver for {}, continuing", func.addr);
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut args = driver.command.iter();
|
|
||||||
|
|
||||||
let program = args
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| anyhow!("driver configuration entry did not have any command!"))?;
|
|
||||||
let program = if program.starts_with('/') {
|
|
||||||
program.to_owned()
|
|
||||||
} else {
|
|
||||||
"/usr/lib/drivers/".to_owned() + program
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut command = Command::new(program);
|
|
||||||
command.args(args);
|
|
||||||
|
|
||||||
log::info!("pcid-spawner: spawn {:?}", command);
|
|
||||||
|
|
||||||
handle.enable_device();
|
|
||||||
|
|
||||||
let channel_fd = handle.into_inner_fd();
|
|
||||||
command.env("PCID_CLIENT_CHANNEL", channel_fd.to_string());
|
|
||||||
command.env("PCID_SEGMENT", format!("{:04x}", func.addr.segment()));
|
|
||||||
command.env("PCID_BUS", format!("{:02x}", func.addr.bus()));
|
|
||||||
command.env("PCID_DEVICE", format!("{:02x}", func.addr.device()));
|
|
||||||
command.env("PCID_FUNCTION", format!("{}", func.addr.function()));
|
|
||||||
|
|
||||||
#[allow(deprecated, reason = "we can't yet move this to init")]
|
|
||||||
daemon::Daemon::spawn(command);
|
|
||||||
libredox::call::close(channel_fd as usize).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
@@ -22,6 +22,3 @@ cmd = "driver-manager"
|
|||||||
args = ["--hotplug"]
|
args = ["--hotplug"]
|
||||||
# oneshot_async so init does not block on the manager's readiness.
|
# oneshot_async so init does not block on the manager's readiness.
|
||||||
type = "oneshot_async"
|
type = "oneshot_async"
|
||||||
# Operator must explicitly enable this service:
|
|
||||||
# touch /etc/driver-manager.d/disabled # force fallback to pcid-spawner
|
|
||||||
ConditionPathExists = "!/etc/driver-manager.d/disabled"
|
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
[unit]
|
|
||||||
description = "PCI driver spawner"
|
|
||||||
|
|
||||||
[service]
|
|
||||||
cmd = "pcid-spawner"
|
|
||||||
# Fallback-only since the driver-manager cutover: this service starts only
|
|
||||||
# when the operator forces the legacy spawner back on with
|
|
||||||
# touch /etc/driver-manager.d/disabled
|
|
||||||
# Otherwise driver-manager (00_driver-manager.service) owns the boot path.
|
|
||||||
ConditionPathExists = "/etc/driver-manager.d/disabled"
|
|
||||||
# oneshot_async, NOT oneshot: this is the post-switchroot /usr driver-manager.
|
|
||||||
# As a blocking oneshot, init waits for pcid-spawner to enumerate PCI and bring
|
|
||||||
# every matched driver to readiness (daemon::Daemon::spawn blocks on each
|
|
||||||
# driver's ready signal) before continuing — so a single slow/hanging driver,
|
|
||||||
# or an unavailable /scheme/pci after switchroot, wedges the whole boot right
|
|
||||||
# here, before the console/login stack. The login path renders on the initfs
|
|
||||||
# framebuffer (vesad+fbcond) and does not need the /usr PCI drivers to be ready
|
|
||||||
# first, so bring them up asynchronously. NOTE: the initfs driver spawner
|
|
||||||
# (40_pcid-spawner-initfs) stays a blocking oneshot — disk (ahcid) must be
|
|
||||||
# ready before redoxfs mounts.
|
|
||||||
type = "oneshot_async"
|
|
||||||
@@ -15,7 +15,3 @@ requires_weak = ["10_inputd.service", "20_graphics.target", "40_pcid.service"]
|
|||||||
cmd = "driver-manager"
|
cmd = "driver-manager"
|
||||||
args = ["--initfs"]
|
args = ["--initfs"]
|
||||||
type = "oneshot"
|
type = "oneshot"
|
||||||
# Active by default since the cutover. Operator falls back to the legacy
|
|
||||||
# pcid-spawner initfs path with:
|
|
||||||
# touch /etc/driver-manager.d/disabled
|
|
||||||
ConditionPathExists = "!/etc/driver-manager.d/disabled"
|
|
||||||
|
|||||||
@@ -8,6 +8,5 @@ requires_weak = [
|
|||||||
"40_bcm2835-sdhcid.service",
|
"40_bcm2835-sdhcid.service",
|
||||||
"40_hwd.service",
|
"40_hwd.service",
|
||||||
"40_driver-manager-initfs.service",
|
"40_driver-manager-initfs.service",
|
||||||
"40_pcid-spawner-initfs.service",
|
|
||||||
"41_acpid.service",
|
"41_acpid.service",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
[unit]
|
|
||||||
description = "PCI driver spawner"
|
|
||||||
requires_weak = ["10_inputd.service", "20_graphics.target", "40_pcid.service"]
|
|
||||||
|
|
||||||
[service]
|
|
||||||
cmd = "pcid-spawner"
|
|
||||||
args = ["--initfs"]
|
|
||||||
# Fallback-only since the driver-manager cutover: starts only when the
|
|
||||||
# operator forces the legacy spawner with /etc/driver-manager.d/disabled.
|
|
||||||
ConditionPathExists = "/etc/driver-manager.d/disabled"
|
|
||||||
type = "oneshot"
|
|
||||||
Reference in New Issue
Block a user