|
5 | 5 | */ |
6 | 6 |
|
7 | 7 | use std::cell::RefCell; |
| 8 | +use std::collections::BTreeMap; |
8 | 9 | use std::os::unix::io::AsRawFd; |
9 | 10 | use std::path::{Path, PathBuf}; |
10 | 11 | use std::process::Command; |
@@ -328,6 +329,7 @@ impl Component for Efi { |
328 | 329 | meta: updatemeta.clone(), |
329 | 330 | filetree: Some(updatef), |
330 | 331 | adopted_from: Some(meta.version), |
| 332 | + firmware: BTreeMap::new(), |
331 | 333 | })) |
332 | 334 | } |
333 | 335 |
|
@@ -372,15 +374,70 @@ impl Component for Efi { |
372 | 374 | .arg(destpath) |
373 | 375 | .current_dir(format!("/proc/self/fd/{}", src_root.as_raw_fd())) |
374 | 376 | .run()?; |
| 377 | + |
| 378 | + let mut found_firmware = BTreeMap::new(); |
| 379 | + // Scan and install supplemental firmware |
| 380 | + let firmware_base_dir_path = Path::new("usr/lib/efi/firmware"); |
| 381 | + if src_root.exists(firmware_base_dir_path)? { |
| 382 | + let firmware_base_dir = src_root.sub_dir(firmware_base_dir_path)?; |
| 383 | + for pkg_entry in firmware_base_dir.list_dir(".")?.flatten() { |
| 384 | + if firmware_base_dir.get_file_type(&pkg_entry)? != openat::SimpleType::Dir { |
| 385 | + continue; |
| 386 | + } |
| 387 | + let pkg_name = pkg_entry.file_name().to_string_lossy().to_string(); |
| 388 | + let pkg_dir = firmware_base_dir.sub_dir(pkg_entry.file_name())?; |
| 389 | + |
| 390 | + let mut versions: Vec<_> = pkg_dir.list_dir(".")?.filter_map(Result::ok).collect(); |
| 391 | + versions.sort_by_key(|e| e.file_name().to_owned()); |
| 392 | + |
| 393 | + if let Some(ver_entry) = versions.pop() { |
| 394 | + let ver_dir = pkg_dir.sub_dir(ver_entry.file_name())?; |
| 395 | + let meta_path = Path::new("EFI.json"); |
| 396 | + |
| 397 | + if ver_dir.exists(meta_path)? { |
| 398 | + log::debug!( |
| 399 | + "Found supplemental firmware: {}/{}", |
| 400 | + pkg_name, |
| 401 | + ver_entry.file_name().to_string_lossy() |
| 402 | + ); |
| 403 | + let firmware_meta: ContentMetadata = |
| 404 | + serde_json::from_reader(ver_dir.open_file(meta_path)?)?; |
| 405 | + let payload_src_dir = ver_dir.sub_dir("EFI")?; |
| 406 | + let firmware_filetree = |
| 407 | + crate::filetree::FileTree::new_from_dir(&payload_src_dir)?; |
| 408 | + // copy all by applying a diff with a empty filetree |
| 409 | + let empty_filetree = filetree::FileTree { |
| 410 | + children: Default::default(), |
| 411 | + }; |
| 412 | + let diff = empty_filetree.diff(&firmware_filetree)?; |
| 413 | + filetree::apply_diff(&payload_src_dir, destd, &diff, None) |
| 414 | + .context("applying supplemental firmware")?; |
| 415 | + |
| 416 | + found_firmware.insert( |
| 417 | + pkg_name.clone(), |
| 418 | + Box::new(InstalledContent { |
| 419 | + meta: firmware_meta, |
| 420 | + filetree: Some(firmware_filetree), |
| 421 | + adopted_from: None, |
| 422 | + firmware: BTreeMap::new(), |
| 423 | + }), |
| 424 | + ); |
| 425 | + } |
| 426 | + } |
| 427 | + } |
| 428 | + } |
| 429 | + |
375 | 430 | if update_firmware { |
376 | | - if let Some(vendordir) = self.get_efi_vendor(&src_root)? { |
| 431 | + if let Some(vendordir) = self.get_efi_vendor(src_root)? { |
377 | 432 | self.update_firmware(device, destd, &vendordir)? |
378 | 433 | } |
379 | 434 | } |
| 435 | + |
380 | 436 | Ok(InstalledContent { |
381 | 437 | meta, |
382 | 438 | filetree: Some(ft), |
383 | 439 | adopted_from: None, |
| 440 | + firmware: found_firmware, |
384 | 441 | }) |
385 | 442 | } |
386 | 443 |
|
@@ -424,6 +481,7 @@ impl Component for Efi { |
424 | 481 | meta: updatemeta, |
425 | 482 | filetree: Some(updatef), |
426 | 483 | adopted_from, |
| 484 | + firmware: BTreeMap::new(), |
427 | 485 | }) |
428 | 486 | } |
429 | 487 |
|
|
0 commit comments