From 6df5f998ef3e20e074e5fba0a1642191bcf6f385 Mon Sep 17 00:00:00 2001 From: Dishendra Deshmukh Date: Mon, 24 Aug 2026 00:30:16 +0530 Subject: [PATCH] hii: account for efivarfs attributes when reading varstores efivarfs prepends a 4-byte attributes field to each variable payload. VariableStore::read_bytes() allocated only the HII-declared payload size while extract_efi_data() skipped the attributes field, leaving the final four payload bytes unavailable. Read the attributes field together with the complete VarStore payload. Signed-off-by: Dishendra Deshmukh --- src/lib/hii/forms.rs | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/lib/hii/forms.rs b/src/lib/hii/forms.rs index 4b64773..7c41730 100644 --- a/src/lib/hii/forms.rs +++ b/src/lib/hii/forms.rs @@ -43,6 +43,13 @@ use crate::hii::efivarfs::EfivarsMountGuard; use crate::hii::package::Guid; const DUMMY_OPCODE: u8 = 0xFFu8; // doesn't correspond to any known IFROpCode +const EFIVARFS_HEADER_SIZE: usize = std::mem::size_of::(); + +fn read_efivarfs_bytes(reader: &mut R, payload_size: usize) -> Result> { + let mut bytes = vec![0u8; EFIVARFS_HEADER_SIZE + payload_size]; + reader.read_exact(&mut bytes)?; + Ok(bytes) +} // UEFI Spec v2.9 Page 1844 #[derive(BinRead, Debug, PartialEq, Copy, Clone)] @@ -496,10 +503,9 @@ trait VariableStore { "failed to open sysfs efivars '{}' to get varstore bytes", self.store_filename() ))?; - let mut buf = vec![0u8; self.size().into()]; - debug!("buffer size: {}",self.size()); - // only read as much as we require - file.read_exact(&mut buf).context(format!( + debug!("buffer size: {}", self.size()); + // efivarfs prepends a 4-byte attributes field to the variable payload. + let buf = read_efivarfs_bytes(&mut file, self.size().into()).context(format!( "failed to read bytes from sysfs efivars '{}' of size specified by varstore in hiidb", self.store_filename() ))?; @@ -1798,3 +1804,21 @@ where Ok(answer) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn read_efivarfs_bytes_includes_attributes_and_complete_payload() { + let payload = 95u16.to_le_bytes(); + let mut efivarfs_data = 7u32.to_le_bytes().to_vec(); + efivarfs_data.extend_from_slice(&payload); + + let mut reader = Cursor::new(&efivarfs_data); + let bytes = read_efivarfs_bytes(&mut reader, payload.len()).unwrap(); + + assert_eq!(bytes, efivarfs_data); + assert_eq!(extract_efi_data::(0, &bytes).unwrap(), 95); + } +}