Skip to content

Commit 2898860

Browse files
authored
Merge pull request #1633 from Johan-Liebert1/efivars
efivars: Parse efivar as UTF-16 LE bytes
2 parents 1a99caf + 2d877c7 commit 2898860

File tree

2 files changed

+64
-11
lines changed

2 files changed

+64
-11
lines changed

crates/lib/src/bootc_composefs/status.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::{
1212
grub_menuconfig::{parse_grub_menuentry_file, MenuEntry},
1313
},
1414
spec::{BootEntry, BootOrder, Host, HostSpec, ImageReference, ImageStatus},
15+
utils::{read_uefi_var, EfiError},
1516
};
1617

1718
use std::str::FromStr;
@@ -32,7 +33,6 @@ use crate::composefs_consts::{
3233
COMPOSEFS_STAGED_DEPLOYMENT_FNAME, COMPOSEFS_TRANSIENT_STATE_DIR, ORIGIN_KEY_BOOT,
3334
ORIGIN_KEY_BOOT_TYPE, STATE_DIR_RELATIVE,
3435
};
35-
use crate::install::EFIVARFS;
3636
use crate::spec::Bootloader;
3737

3838
/// A parsed composefs command line
@@ -153,16 +153,9 @@ async fn get_container_manifest_and_config(
153153

154154
#[context("Getting bootloader")]
155155
fn get_bootloader() -> Result<Bootloader> {
156-
let efivarfs = match Dir::open_ambient_dir(EFIVARFS, ambient_authority()) {
157-
Ok(dir) => dir,
158-
// Most likely using BIOS
159-
Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(Bootloader::Grub),
160-
Err(e) => Err(e).context(format!("Opening {EFIVARFS}"))?,
161-
};
162-
163156
const EFI_LOADER_INFO: &str = "LoaderInfo-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f";
164157

165-
match efivarfs.read_to_string(EFI_LOADER_INFO) {
158+
match read_uefi_var(EFI_LOADER_INFO) {
166159
Ok(loader) => {
167160
if loader.to_lowercase().contains("systemd-boot") {
168161
return Ok(Bootloader::Systemd);
@@ -171,9 +164,12 @@ fn get_bootloader() -> Result<Bootloader> {
171164
return Ok(Bootloader::Grub);
172165
}
173166

174-
Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(Bootloader::Grub),
167+
Err(efi_error) => match efi_error {
168+
EfiError::SystemNotUEFI => return Ok(Bootloader::Grub),
169+
EfiError::MissingVar => return Ok(Bootloader::Grub),
175170

176-
Err(e) => Err(e).context(format!("Opening {EFI_LOADER_INFO}"))?,
171+
e => return Err(anyhow::anyhow!("Failed to read EfiLoaderInfo: {e:?}")),
172+
},
177173
}
178174
}
179175

crates/lib/src/utils.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,63 @@ pub(crate) fn digested_pullspec(image: &str, digest: &str) -> String {
188188
format!("{image}@{digest}")
189189
}
190190

191+
#[cfg(feature = "composefs-backend")]
192+
#[derive(Debug)]
193+
pub enum EfiError {
194+
SystemNotUEFI,
195+
MissingVar,
196+
#[allow(dead_code)]
197+
InvalidData(&'static str),
198+
#[allow(dead_code)]
199+
Io(std::io::Error),
200+
}
201+
202+
#[cfg(feature = "composefs-backend")]
203+
impl From<std::io::Error> for EfiError {
204+
fn from(e: std::io::Error) -> Self {
205+
EfiError::Io(e)
206+
}
207+
}
208+
209+
#[cfg(feature = "composefs-backend")]
210+
pub fn read_uefi_var(var_name: &str) -> Result<String, EfiError> {
211+
use crate::install::EFIVARFS;
212+
use cap_std_ext::cap_std::ambient_authority;
213+
214+
let efivarfs = match Dir::open_ambient_dir(EFIVARFS, ambient_authority()) {
215+
Ok(dir) => dir,
216+
Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Err(EfiError::SystemNotUEFI),
217+
Err(e) => Err(e)?,
218+
};
219+
220+
match efivarfs.read(var_name) {
221+
Ok(loader_bytes) => {
222+
if loader_bytes.len() % 2 != 0 {
223+
return Err(EfiError::InvalidData(
224+
"EFI var length is not valid UTF-16 LE",
225+
));
226+
}
227+
228+
// EFI vars are UTF-16 LE
229+
let loader_u16_bytes: Vec<u16> = loader_bytes
230+
.chunks_exact(2)
231+
.map(|x| u16::from_le_bytes([x[0], x[1]]))
232+
.collect();
233+
234+
let loader = String::from_utf16(&loader_u16_bytes)
235+
.map_err(|_| EfiError::InvalidData("EFI var is not UTF-16"))?;
236+
237+
return Ok(loader);
238+
}
239+
240+
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
241+
return Err(EfiError::MissingVar);
242+
}
243+
244+
Err(e) => Err(e)?,
245+
}
246+
}
247+
191248
/// Computes a relative path from `from` to `to`.
192249
///
193250
/// Both `from` and `to` must be absolute paths.

0 commit comments

Comments
 (0)