mirror of
https://github.com/edera-dev/sprout.git
synced 2026-11-04 22:02:20 +00:00
54 lines
2.0 KiB
Rust
54 lines
2.0 KiB
Rust
use alloc::{format, string::String};
|
|||
|
|
use anyhow::{Context, Result};
|
||
|
|
use edera_sprout_bls::BootCounter;
|
||
|
|
use uefi::{
|
||
|
|
CString16, Handle,
|
||
|
|
fs::{FileSystem, PathBuf},
|
||
|
|
proto::media::fs::SimpleFileSystem,
|
||
|
|
};
|
||
|
|
|
||
|
|
/// Where the boot counter of an entry is stored, so that a try can be consumed when the
|
||
|
|
/// entry is booted.
|
||
|
|
#[derive(Clone)]
|
||
|
|
pub struct BootCounterTarget {
|
||
|
|
/// The counter as it is currently encoded in the file name.
|
||
|
|
pub counter: BootCounter,
|
||
|
|
/// The handle of the filesystem that holds the entry file.
|
||
|
|
pub filesystem: Handle,
|
||
|
|
/// The directory that holds the entry file.
|
||
|
|
pub directory: PathBuf,
|
||
|
|
/// The entry id, which is the file name without the counter and extension.
|
||
|
|
pub id: String,
|
||
|
|
/// The current file name, including the counter and the extension.
|
||
|
|
pub file_name: String,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl BootCounterTarget {
|
||
|
|
/// Consumes one try by renaming the entry file, such as `foo+3.conf` to `foo+2-1.conf`.
|
||
|
|
/// Returns the path of the renamed file.
|
||
|
|
pub fn consume(&self) -> Result<PathBuf> {
|
||
|
|
// The extension is taken from the current file name, as it may be in any case.
|
||
|
|
let extension = &self.file_name[self.file_name.len() - ".conf".len()..];
|
||
|
|
let new_name = format!(
|
||
|
|
"{}{}",
|
||
|
|
self.counter.decremented().render(&self.id),
|
||
|
|
extension
|
||
|
|
);
|
||
|
|
|
||
|
|
let mut from = self.directory.clone();
|
||
|
|
from.push(PathBuf::from(
|
||
|
|
CString16::try_from(self.file_name.as_str()).context("invalid entry file name")?,
|
||
|
|
));
|
||
|
|
let mut to = self.directory.clone();
|
||
|
|
to.push(PathBuf::from(
|
||
|
|
CString16::try_from(new_name.as_str()).context("invalid new entry file name")?,
|
||
|
|
));
|
||
|
|
|
||
|
|
let fs = uefi::boot::open_protocol_exclusive::<SimpleFileSystem>(self.filesystem)
|
||
|
|
.context("unable to open the entry filesystem")?;
|
||
|
|
let mut fs = FileSystem::new(fs);
|
||
|
|
fs.rename(&from, &to)
|
||
|
|
.context("unable to rename the entry file")?;
|
||
|
|
Ok(to)
|
||
|
|
}
|
||
|
|
}
|