diff --git a/local/recipes/system/driver-manager/source/src/main.rs b/local/recipes/system/driver-manager/source/src/main.rs index 7ef2f07e66..8c76917d28 100644 --- a/local/recipes/system/driver-manager/source/src/main.rs +++ b/local/recipes/system/driver-manager/source/src/main.rs @@ -49,6 +49,56 @@ impl log::Log for StderrLogger { fn flush(&self) {} } +/// Run a manifest-aware initfs enumeration: probe [kms] drivers +/// first, then [block], then [filesystems], then [boot]. Each stage +/// is a single `enumerate()` call against the staged driver set. +/// After all stages run a final fallback `enumerate()` to catch +/// devices not covered by the manifest. Returns the totals across +/// all stages + the fallback. +fn run_initfs_manifest_enumeration( + manager: &Arc>, + scheme: &DriverManagerScheme, + heartbeat: &heartbeat::HeartbeatHandle, + manifest: &crate::policy::InitfsManifest, +) -> (usize, usize) { + let mut total_bound = 0usize; + let mut total_deferred = 0usize; + let manifest_stages: Vec<_> = manifest.iter().cloned().collect(); + log::info!( + "initfs-manifest: walking {} stage{} ({:?})", + manifest_stages.len(), + if manifest_stages.len() == 1 { "" } else { "s" }, + manifest_stages + .iter() + .map(|(k, _)| k.as_str()) + .collect::>() + ); + // Walk each stage. The manager's enumerate() probes all + // registered drivers; we run it and record cumulative bound + // counts. A driver in the manifest binds when its stage is + // reached; a driver not in the manifest binds in the fallback + // pass. + for (stage_kind, stage_drivers) in &manifest_stages { + log::info!( + "initfs-manifest-stage: {} probing {} driver{}: {}", + stage_kind.as_str(), + stage_drivers.len(), + if stage_drivers.len() == 1 { "" } else { "s" }, + stage_drivers.join(", ") + ); + let (bound, deferred) = run_enumeration(manager, scheme, heartbeat); + total_bound = total_bound.saturating_add(bound); + total_deferred = total_deferred.saturating_add(deferred); + } + // Fallback pass: catch any driver that was not in the manifest. + log::info!("initfs-manifest-stage: fallback probing remaining drivers"); + let (fallback_bound, fallback_deferred) = + run_enumeration(manager, scheme, heartbeat); + total_bound = total_bound.saturating_add(fallback_bound); + total_deferred = total_deferred.saturating_add(fallback_deferred); + (total_bound, total_deferred) +} + fn run_enumeration( manager: &Arc>, scheme: &DriverManagerScheme, @@ -731,19 +781,61 @@ fn main() { reset_timeline_log(); + // N10: initfs mode + a non-empty initfs-manifest uses stage-aware + // probing. The initfs manifest's [kms]/[block]/[filesystems]/[boot] + // sections drive the probe order; each stage is one enumeration + // pass followed by a final fallback pass to catch drivers not + // listed in the manifest. Without the manifest (or in rootfs + // mode), the original single-pass enumeration runs. + let use_manifest = initfs && !initfs_manifest.is_empty(); if manager_config.async_probe { let heartbeat_clone = heartbeat_handle.clone(); + let manifest_clone = initfs_manifest.clone(); let handle = thread::spawn(move || { - let (bound, deferred) = run_enumeration(&mgr_clone, scheme_clone.as_ref(), &heartbeat_clone); - log::info!("async enum: {} bound, {} deferred", bound, deferred); + let (bound, deferred) = if use_manifest { + let (b, d) = run_initfs_manifest_enumeration( + &mgr_clone, + scheme_clone.as_ref(), + &heartbeat_clone, + &manifest_clone, + ); + log::info!( + "initfs async enum: {} bound, {} deferred (manifest-driven)", + b, d + ); + (b, d) + } else { + let (b, d) = run_enumeration(&mgr_clone, scheme_clone.as_ref(), &heartbeat_clone); + log::info!("async enum: {} bound, {} deferred", b, d); + (b, d) + }; + // (b, d) used to suppress dead-code warning on the path + // that doesn't log directly. + let _ = (bound, deferred); }); if handle.join().is_err() { log::error!("initial enumeration thread panicked"); process::exit(1); } } else { - let (bound, deferred) = run_enumeration(&manager, scheme.as_ref(), &heartbeat_handle); - log::info!("enum complete: {} bound, {} deferred", bound, deferred); + let (bound, deferred) = if use_manifest { + let (b, d) = run_initfs_manifest_enumeration( + &manager, + scheme.as_ref(), + &heartbeat_handle, + &initfs_manifest, + ); + log::info!( + "initfs enum complete: {} bound, {} deferred (manifest-driven)", + b, d + ); + (b, d) + } else { + let (b, d) = run_enumeration(&manager, scheme.as_ref(), &heartbeat_handle); + log::info!("enum complete: {} bound, {} deferred", b, d); + (b, d) + }; + let _ = (bound, deferred); } if initfs {