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