Skip to content

Commit 3781502

Browse files
committed
feat(efi::update)update extended payload path
efi::update is updated to read from path created by extend_payload_to_esp and update the firmware.
1 parent cba4de8 commit 3781502

File tree

1 file changed

+106
-4
lines changed

1 file changed

+106
-4
lines changed

src/efi.rs

Lines changed: 106 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -462,15 +462,117 @@ impl Component for Efi {
462462
anyhow::bail!("Failed to find all esp devices");
463463
};
464464

465-
for esp in esp_devices {
466-
let destpath = &self.ensure_mounted_esp(rootcxt.path.as_ref(), Path::new(&esp))?;
465+
for esp in esp_devices.iter() {
466+
let destpath = &self.ensure_mounted_esp(rootcxt.path.as_ref(), Path::new(esp))?;
467467
let destdir = openat::Dir::open(&destpath.join("EFI")).context("opening EFI dir")?;
468468
validate_esp_fstype(&destdir)?;
469469
log::trace!("applying diff: {}", &diff);
470470
filetree::apply_diff(&updated, &destdir, &diff, None)
471471
.context("applying filesystem changes")?;
472+
}
472473

473-
// Do the sync before unmount
474+
// update firmware
475+
let mut updated_firmware = BTreeMap::new();
476+
let firmware_base_dir_path = Path::new("usr/lib/efi/firmware");
477+
478+
let available_payloads = {
479+
let mut payloads = BTreeMap::new();
480+
if rootcxt.sysroot.exists(firmware_base_dir_path)? {
481+
let firmware_base_dir = rootcxt.sysroot.sub_dir(firmware_base_dir_path)?;
482+
for pkg_entry in firmware_base_dir.list_dir(".")?.flatten() {
483+
if firmware_base_dir.get_file_type(&pkg_entry)? == openat::SimpleType::Dir {
484+
let pkg_name = pkg_entry.file_name().to_string_lossy().to_string();
485+
payloads.insert(pkg_name, pkg_entry.file_name().to_owned());
486+
}
487+
}
488+
}
489+
payloads
490+
};
491+
492+
let old_keys: std::collections::HashSet<_> = current.firmware.keys().collect();
493+
let new_keys: std::collections::HashSet<_> = available_payloads.keys().collect();
494+
let all_keys: std::collections::HashSet<_> = old_keys.union(&new_keys).collect();
495+
496+
// determine if it should be added, updated, or removed.
497+
for pkg_name in all_keys {
498+
let old_payload = current.firmware.get(*pkg_name);
499+
let new_payload_path = available_payloads.get(*pkg_name);
500+
501+
let (diff, src_dir, new_content) = match (old_payload, new_payload_path) {
502+
// Payload exists in both old state and new source.
503+
(Some(old), Some(new_path)) => {
504+
let new_ver_dir = rootcxt
505+
.sysroot
506+
.sub_dir(firmware_base_dir_path)?
507+
.sub_dir(new_path.as_os_str())?;
508+
let new_payload_dir = new_ver_dir.sub_dir("EFI")?;
509+
let new_ft = crate::filetree::FileTree::new_from_dir(&new_payload_dir)?;
510+
let old_ft = old.filetree.as_ref().unwrap_or(&new_ft);
511+
let diff = old_ft.diff(&new_ft)?;
512+
513+
let meta: ContentMetadata =
514+
serde_json::from_reader(new_ver_dir.open_file("EFI.json")?)?;
515+
let content = Box::new(InstalledContent {
516+
meta,
517+
filetree: Some(new_ft),
518+
adopted_from: None,
519+
firmware: BTreeMap::new(),
520+
});
521+
(diff, Some(new_payload_dir), Some(content))
522+
}
523+
// add as old payload is none
524+
(None, Some(new_path)) => {
525+
let new_ver_dir = rootcxt
526+
.sysroot
527+
.sub_dir(firmware_base_dir_path)?
528+
.sub_dir(new_path.as_os_str())?;
529+
let new_payload_dir = new_ver_dir.sub_dir("EFI")?;
530+
let new_ft = crate::filetree::FileTree::new_from_dir(&new_payload_dir)?;
531+
let empty_ft = crate::filetree::FileTree {
532+
children: BTreeMap::new(),
533+
};
534+
let diff = empty_ft.diff(&new_ft)?;
535+
536+
let meta: ContentMetadata =
537+
serde_json::from_reader(new_ver_dir.open_file("EFI.json")?)?;
538+
let content = Box::new(InstalledContent {
539+
meta,
540+
filetree: Some(new_ft),
541+
adopted_from: None,
542+
firmware: BTreeMap::new(),
543+
});
544+
(diff, Some(new_payload_dir), Some(content))
545+
}
546+
// remove payload if not in new source
547+
(Some(old), None) => {
548+
let empty_ft = crate::filetree::FileTree {
549+
children: BTreeMap::new(),
550+
};
551+
let old_ft = old.filetree.as_ref().unwrap_or(&empty_ft);
552+
let diff = old_ft.diff(&empty_ft)?;
553+
(diff, None, None)
554+
}
555+
// Should not happen.
556+
(None, None) => continue,
557+
};
558+
559+
//apply the above diffs
560+
for esp in esp_devices.iter() {
561+
let destpath = &self.ensure_mounted_esp(rootcxt.path.as_ref(), Path::new(esp))?;
562+
let destdir = openat::Dir::open(destpath)?;
563+
let src_dir = src_dir.as_ref().unwrap_or(&destdir);
564+
filetree::apply_diff(src_dir, &destdir, &diff, None)
565+
.context(format!("applying firmware diff for {}", pkg_name))?;
566+
}
567+
568+
if let Some(content) = new_content {
569+
updated_firmware.insert(pkg_name.to_string(), content);
570+
}
571+
}
572+
573+
for esp in esp_devices.iter() {
574+
let destpath = &self.ensure_mounted_esp(rootcxt.path.as_ref(), Path::new(esp))?;
575+
let destdir = openat::Dir::open(destpath)?;
474576
destdir.syncfs()?;
475577
drop(destdir);
476578
self.unmount().context("unmount after update")?;
@@ -481,7 +583,7 @@ impl Component for Efi {
481583
meta: updatemeta,
482584
filetree: Some(updatef),
483585
adopted_from,
484-
firmware: BTreeMap::new(),
586+
firmware: updated_firmware,
485587
})
486588
}
487589

0 commit comments

Comments
 (0)