(
prepared_root: &MountedImageRoot,
configopts: &crate::install::InstallConfigOpts,
autoenroll: Option<SecurebootKeys>,
)
| 238 | /// Install systemd-boot using a pre-prepared boot root. |
| 239 | #[context("Installing bootloader")] |
| 240 | pub(crate) fn install_systemd_boot( |
| 241 | prepared_root: &MountedImageRoot, |
| 242 | configopts: &crate::install::InstallConfigOpts, |
| 243 | autoenroll: Option<SecurebootKeys>, |
| 244 | ) -> Result<()> { |
| 245 | println!("Installing bootloader via systemd-boot"); |
| 246 | |
| 247 | // We use the --root of the mounted target root, so we have the right /etc/os-release. |
| 248 | let root_path = prepared_root |
| 249 | .root_path() |
| 250 | .to_str() |
| 251 | .ok_or_else(|| anyhow::anyhow!("composefs tmpdir path is not UTF-8"))?; |
| 252 | let esp_path_in_root = format!("/{}", prepared_root.esp_subdir); |
| 253 | |
| 254 | let mut bootctl_args = vec![ |
| 255 | "install", |
| 256 | "--root", |
| 257 | root_path, |
| 258 | "--esp-path", |
| 259 | esp_path_in_root.as_str(), |
| 260 | // If we supported XBOOTLDR in the future, that'd go here with --boot-path. |
| 261 | ]; |
| 262 | |
| 263 | if configopts.generic_image { |
| 264 | bootctl_args.push("--no-variables"); |
| 265 | // `--random-seed` was only added to `bootctl install` in systemd 257. |
| 266 | let systemd_version = bootctl_systemd_version()?; |
| 267 | if systemd_version >= BOOTCTL_RANDOM_SEED_MIN_VERSION { |
| 268 | bootctl_args.extend(["--random-seed", "no"]); |
| 269 | } else { |
| 270 | tracing::debug!( |
| 271 | "Skipping --random-seed: requires systemd >= {BOOTCTL_RANDOM_SEED_MIN_VERSION}, found {systemd_version}" |
| 272 | ); |
| 273 | } |
| 274 | } |
| 275 | |
| 276 | Command::new("bootctl") |
| 277 | .args(bootctl_args) |
| 278 | // Skip partition-type GUID validation because e.g. osbuild |
| 279 | // may not provide the udev database. |
| 280 | .env("SYSTEMD_RELAX_ESP_CHECKS", "1") |
| 281 | // bootc doesn't use the entry-token file, but bootctl still tries to |
| 282 | // write it. Redirect into /tmp (a tmpfs mounted by MountedImageRoot) |
| 283 | // so the write succeeds and is automatically discarded. |
| 284 | .env("KERNEL_INSTALL_CONF_ROOT", KERNEL_INSTALL_CONF_ROOT) |
| 285 | .log_debug() |
| 286 | // Capture stderr so bootctl error messages appear in our error chain. |
| 287 | .run_capture_stderr()?; |
| 288 | |
| 289 | if let Some(SecurebootKeys { dir, keys }) = autoenroll { |
| 290 | let esp_dir = prepared_root.open_esp_dir()?; |
| 291 | let keys_path = prepared_root |
| 292 | .root_path() |
| 293 | .join(prepared_root.esp_subdir) |
| 294 | .join(SYSTEMD_KEY_DIR); |
| 295 | create_dir_all(&keys_path).with_context(|| { |
| 296 | format!("Creating secureboot key directory {}", keys_path.display()) |
| 297 | })?; |
no test coverage detected