diff --git a/blsforme/src/entry.rs b/blsforme/src/entry.rs index 286c3ed..df17ecc 100644 --- a/blsforme/src/entry.rs +++ b/blsforme/src/entry.rs @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: MPL-2.0 +use std::path::PathBuf; + use crate::{AuxiliaryFile, Kernel, Schema}; /// An entry corresponds to a single kernel, and may have a supplemental @@ -10,6 +12,8 @@ use crate::{AuxiliaryFile, Kernel, Schema}; pub struct Entry<'a> { pub(crate) kernel: &'a Kernel, + pub(crate) sysroot: Option, + // Additional cmdline #[allow(dead_code)] cmdline: Option, @@ -18,7 +22,11 @@ pub struct Entry<'a> { impl<'a> Entry<'a> { /// New entry for the given kernel pub fn new(kernel: &'a Kernel) -> Self { - Self { kernel, cmdline: None } + Self { + kernel, + cmdline: None, + sysroot: None, + } } /// With the following cmdline @@ -29,6 +37,14 @@ impl<'a> Entry<'a> { } } + /// With the given system root + pub fn with_sysroot(self, sysroot: impl Into) -> Self { + Self { + sysroot: Some(sysroot.into()), + ..self + } + } + /// Return an entry ID, suitable for `.conf` generation pub fn id(&self, schema: &Schema) -> String { // TODO: For BLS schema, grab something even uniquer (TM) diff --git a/blsforme/src/manager.rs b/blsforme/src/manager.rs index 8a466ba..196d899 100644 --- a/blsforme/src/manager.rs +++ b/blsforme/src/manager.rs @@ -39,7 +39,9 @@ pub struct Manager<'a> { mounts: Mounts, - cmdline: String, + cmdline: Vec, + + system_excluded_snippets: Vec, } impl<'a> Manager<'a> { @@ -51,7 +53,7 @@ impl<'a> Manager<'a> { log::info!("root = {:?}", root.cmd_line()); // Right now we assume `rw` for the rootfs - let mut cmdline = vec![root.cmd_line(), "rw".to_string()]; + let cmdline = [root.cmd_line(), "rw".to_string()]; let mut local_cmdline = vec![]; let etc_cmdline_d = config.root.path().join("etc").join("kernel").join("cmdline.d"); @@ -83,30 +85,6 @@ impl<'a> Manager<'a> { } } - // Merge the system-wide cmdline with the rootfs cmdline - if let Ok(it) = fs::read_dir( - config - .root - .path() - .join("usr") - .join("lib") - .join("kernel") - .join("cmdline.d"), - ) { - log::trace!("reading system cmdline.d entries"); - let entries = it - .filter_map(|p| p.ok()) - .filter(|d| { - if let Some(name) = d.file_name().to_str() { - !system_excludes.contains(&name.to_string()) - } else { - true - } - }) - .filter_map(|p| cmdline_snippet(p.path()).ok()); - cmdline.extend(entries); - } - // Grab parent disk, establish disk environment setup let disk_parent = probe.get_device_parent(root.path); let boot_env = BootEnvironment::new(&probe, disk_parent, config)?; @@ -140,12 +118,11 @@ impl<'a> Manager<'a> { } } - let cmdline_string = cmdline + let cmdline_joined = cmdline .iter() .chain(local_cmdline.iter()) .cloned() - .collect::>() - .join(" "); + .collect::>(); Ok(Self { config, @@ -153,7 +130,8 @@ impl<'a> Manager<'a> { bootloader_assets: vec![], boot_env, mounts, - cmdline: cmdline_string, + cmdline: cmdline_joined, + system_excluded_snippets: system_excludes, }) } @@ -240,7 +218,28 @@ impl<'a> Manager<'a> { // Install every kernel that was passed to us for entry in self.entries.iter() { - bootloader.install(&self.cmdline, entry)?; + let root_dir = entry + .sysroot + .clone() + .unwrap_or_else(|| self.config.root.path().to_path_buf()); + let mut cmdline = self.cmdline.clone(); + + // Merge the system-wide cmdline with the rootfs cmdline + if let Ok(it) = fs::read_dir(root_dir.join("usr").join("lib").join("kernel").join("cmdline.d")) { + log::trace!("reading system cmdline.d entries"); + let entries = it + .filter_map(|p| p.ok()) + .filter(|d| { + if let Some(name) = d.file_name().to_str() { + !self.system_excluded_snippets.contains(&name.to_string()) + } else { + true + } + }) + .filter_map(|p| cmdline_snippet(p.path()).ok()); + cmdline.extend(entries); + } + bootloader.install(&cmdline.join(" "), entry)?; } Ok(())