td_shim_interface/td_uefi_pi/pi/
fv.rs1use core::mem::size_of;
32use core::ptr::slice_from_raw_parts;
33use r_efi::efi::Guid;
34use scroll::{Pread, Pwrite};
35
36pub type FvbAttributes2 = u32;
37pub const FVH_REVISION: u8 = 2;
38
39fn sum8(data: &[u8]) -> u8 {
41 let mut sum = 0u8;
42 let cnt = data.len();
43 for item in data.iter().take(cnt) {
44 sum = sum.wrapping_add(*item);
45 }
46 sum
47}
48
49fn sum16(data: &[u8]) -> u16 {
51 let mut sum = 0u16;
52 let cnt = data.len() / 2;
53 for i in 0..cnt {
54 sum = sum.wrapping_add((data[i * 2 + 1] as u16) << 8 | data[i * 2] as u16);
55 }
56 if cnt * 2 == data.len() - 1 {
57 sum = sum.wrapping_add(data[cnt * 2] as u16)
58 }
59 sum
60}
61
62pub const FVH_SIGNATURE: u32 = 0x4856465F; #[repr(C)]
71#[derive(Copy, Clone, Debug, Pread, Pwrite, Default)]
72pub struct FirmwareVolumeHeader {
73 pub zero_vector: [u8; 16],
74 pub file_system_guid: [u8; 16], pub fv_length: u64,
76 pub signature: u32,
77 pub attributes: FvbAttributes2,
78 pub header_length: u16,
79 pub checksum: u16,
80 pub ext_header_offset: u16,
81 pub reserved: u8,
82 pub revision: u8,
83}
84
85impl FirmwareVolumeHeader {
86 pub fn as_bytes(&self) -> &[u8] {
87 unsafe { &*slice_from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) }
88 }
89
90 pub fn update_checksum(&mut self) {
92 self.checksum = 0;
94 self.checksum = (u16::MAX - sum16(self.as_bytes())).wrapping_add(1);
95 }
96
97 pub fn validate_checksum(&self) -> bool {
99 sum16(self.as_bytes()) == 0
100 }
101}
102
103#[repr(C)]
111#[derive(Copy, Clone, Debug, Pread, Pwrite, Default)]
112pub struct FvBlockMap {
113 pub num_blocks: u32,
114 pub length: u32,
115}
116
117impl FvBlockMap {
118 pub fn as_bytes(&self) -> &[u8] {
119 unsafe { &*slice_from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) }
120 }
121}
122
123#[repr(C)]
130#[derive(Copy, Clone, Debug, Pread, Pwrite, Default)]
131pub struct FirmwareVolumeExtHeader {
132 pub fv_name: [u8; 16], pub ext_header_size: u32,
134}
135
136impl FirmwareVolumeExtHeader {
137 pub fn as_bytes(&self) -> &[u8] {
138 unsafe { &*slice_from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) }
139 }
140}
141
142#[repr(C)]
147#[derive(Copy, Clone, Debug)]
148pub struct FirmwareVolumeExtEntry {
149 pub ext_entry_size: u16,
150 pub ext_entry_type: u32,
151}
152
153impl FirmwareVolumeExtEntry {
154 pub fn as_bytes(&self) -> &[u8] {
155 unsafe { &*slice_from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) }
156 }
157}
158
159pub const FIRMWARE_FILE_SYSTEM2_GUID: r_efi::base::Guid = r_efi::base::Guid::from_fields(
161 0x8c8ce578,
162 0x8a3d,
163 0x4f1c,
164 0x99,
165 0x35,
166 &[0x89, 0x61, 0x85, 0xc3, 0x2d, 0xd3],
167);
168
169pub const FIRMWARE_FILE_SYSTEM3_GUID: r_efi::base::Guid = r_efi::base::Guid::from_fields(
171 0x5473c07a,
172 0x3dcb,
173 0x4dca,
174 0xbd,
175 0x6f,
176 &[0x1e, 0x96, 0x89, 0xe7, 0x34, 0x9a],
177);
178
179pub type FvFileType = u8;
181
182pub const FV_FILETYPE_RAW: u8 = 0x01;
183pub const FV_FILETYPE_FREEFORM: u8 = 0x02;
184pub const FV_FILETYPE_SECURITY_CORE: u8 = 0x03;
185pub const FV_FILETYPE_PEI_CORE: u8 = 0x04;
186pub const FV_FILETYPE_DXE_CORE: u8 = 0x05;
187pub const FV_FILETYPE_PEIM: u8 = 0x06;
188pub const FV_FILETYPE_DRIVER: u8 = 0x07;
189pub const FV_FILETYPE_COMBINED_PEIM_DRIVER: u8 = 0x08;
190pub const FV_FILETYPE_APPLICATION: u8 = 0x09;
191pub const FV_FILETYPE_MM: u8 = 0x0A;
192pub const FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: u8 = 0x0B;
193pub const FV_FILETYPE_COMBINED_MM_DXE: u8 = 0x0C;
194pub const FV_FILETYPE_MM_CORE: u8 = 0x0D;
195pub const FV_FILETYPE_MM_STANDALONE: u8 = 0x0E;
196pub const FV_FILETYPE_MM_CORE_STANDALONE: u8 = 0x0F;
197pub const FV_FILETYPE_FFS_PAD: u8 = 0xF0;
198
199pub const FFS_ATTRIB_LARGE_FILE: u8 = 0x01;
203pub const FFS_ATTRIB_DATA_ALIGNMENT2: u8 = 0x02;
204pub const FFS_ATTRIB_FIXED: u8 = 0x04;
205pub const FFS_ATTRIB_DATA_ALIGNMENT: u8 = 0x38;
206pub const FFS_ATTRIB_CHECKSUM: u8 = 0x40;
207pub const FFS_FIXED_CHECKSUM: u8 = 0xAA;
212
213pub const EFI_FILE_HEADER_CONSTRUCTION: u8 = 0x01;
215pub const EFI_FILE_HEADER_VALID: u8 = 0x02;
216pub const EFI_FILE_DATA_VALID: u8 = 0x04;
217pub const EFI_FILE_MARKED_FOR_UPDATE: u8 = 0x08;
218pub const EFI_FILE_DELETED: u8 = 0x10;
219pub const EFI_FILE_HEADER_INVALID: u8 = 0x20;
220
221pub type FfsFileAttributes = u8;
222pub type FfsFileState = u8;
223
224#[repr(C)]
225#[derive(Copy, Clone, Debug, Pread, Pwrite, Default)]
226pub struct Checksum {
227 pub header: u8,
228 pub file: u8,
229}
230
231#[repr(C)]
241#[derive(Copy, Clone, Debug, Pread, Pwrite, Default)]
242pub struct FfsFileHeader {
243 pub name: [u8; 16], pub integrity_check: Checksum,
245 pub r#type: FvFileType,
246 pub attributes: FfsFileAttributes,
247 pub size: [u8; 3],
248 pub state: FfsFileState,
249}
250
251impl FfsFileHeader {
252 pub fn as_bytes(&self) -> &[u8] {
253 unsafe { &*slice_from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) }
254 }
255
256 pub fn update_checksum(&mut self) {
258 self.integrity_check.header = 0;
260 self.integrity_check.file = 0;
261 self.state = 0;
262 self.integrity_check.header = (u8::MAX - sum8(self.as_bytes())).wrapping_add(1);
263
264 self.integrity_check.file = FFS_FIXED_CHECKSUM;
265 self.state = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
266 }
267
268 pub fn validate_checksum(&self) -> bool {
270 let sum = sum8(self.as_bytes());
271 sum ^ ((EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID)
272 + FFS_FIXED_CHECKSUM)
273 == 0
274 }
275}
276
277#[repr(C)]
287#[derive(Copy, Clone, Debug)]
288pub struct FfsFileHeader2 {
289 pub name: Guid,
290 pub integrity_check: u16,
291 pub r#type: FvFileType,
292 pub attributes: FfsFileAttributes,
293 pub size: [u8; 3],
294 pub state: FfsFileState,
295 pub extended_size: u32,
296}
297
298impl FfsFileHeader2 {
299 pub fn as_bytes(&self) -> &[u8] {
300 unsafe { &*slice_from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) }
301 }
302}
303
304pub type SectionType = u8;
306
307pub const SECTION_ALL: u8 = 0x00;
308
309pub const SECTION_COMPRESSION: u8 = 0x01;
310pub const SECTION_GUID_DEFINED: u8 = 0x02;
311pub const SECTION_DISPOSABLE: u8 = 0x03;
312
313pub const SECTION_PE32: u8 = 0x10;
314pub const SECTION_PIC: u8 = 0x11;
315pub const SECTION_TE: u8 = 0x12;
316pub const SECTION_DXE_DEPEX: u8 = 0x13;
317pub const SECTION_VERSION: u8 = 0x14;
318pub const SECTION_USER_INTERFACE: u8 = 0x15;
319pub const SECTION_COMPATIBILITY16: u8 = 0x16;
320pub const SECTION_FIRMWARE_VOLUME_IMAGE: u8 = 0x17;
321pub const SECTION_FREEFORM_SUBTYPE_GUID: u8 = 0x18;
322pub const SECTION_RAW: u8 = 0x19;
323pub const SECTION_PEI_DEPEX: u8 = 0x1B;
324pub const SECTION_MM_DEPEX: u8 = 0x1C;
325
326#[repr(C)]
328#[derive(Copy, Clone, Debug, Pread, Pwrite, Default)]
329pub struct CommonSectionHeader {
330 pub size: [u8; 3],
331 pub r#type: SectionType,
332}
333
334impl CommonSectionHeader {
335 pub fn as_bytes(&self) -> &[u8] {
336 unsafe { &*slice_from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) }
337 }
338}
339
340#[repr(C)]
342#[derive(Copy, Clone, Debug)]
343pub struct CommonSectionHeader2 {
344 pub size: [u8; 3],
345 pub r#type: SectionType,
346 pub extended_size: u32,
347}
348
349impl CommonSectionHeader2 {
350 pub fn as_bytes(&self) -> &[u8] {
351 unsafe { &*slice_from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) }
352 }
353}
354
355#[cfg(test)]
356mod tests {
357 use super::*;
358
359 #[test]
360 fn test_fvh_checksum() {
361 let mut header = FirmwareVolumeHeader::default();
362 header.attributes = 0x4feff;
363 header.revision = FVH_REVISION;
364 header.signature = FVH_SIGNATURE;
365 header.header_length = size_of::<FirmwareVolumeHeader>() as u16;
366 header.fv_length = 0x1000;
367 header.checksum = 0x3fef;
368 header.update_checksum();
369
370 assert_eq!(header.checksum, 0x6010);
371 assert!(header.validate_checksum());
372
373 header.checksum = 0x3fe6;
374 assert!(!header.validate_checksum());
375
376 header.update_checksum();
377 assert_eq!(header.checksum, 0x6010);
378 assert!(header.validate_checksum());
379 }
380
381 #[test]
382 fn test_ffsh_checksum() {
383 let mut header = FfsFileHeader::default();
384 header.r#type = FV_FILETYPE_FFS_PAD;
385
386 header.update_checksum();
387 assert_eq!(header.integrity_check.header, 0x10);
388 assert!(header.validate_checksum());
389
390 header.name = *Guid::from_fields(
391 0x00000001,
392 0x0000,
393 0x0000,
394 0x00,
395 0x00,
396 &[0x02, 0x00, 0x00, 0x00, 0x00, 0x01],
397 )
398 .as_bytes();
399 assert!(!header.validate_checksum());
400 header.update_checksum();
401 assert_eq!(header.integrity_check.header, 0xC);
402 assert!(header.validate_checksum());
403 }
404
405 #[test]
406 fn test_update_checksum() {
407 let mut header = FfsFileHeader::default();
408 header.update_checksum();
409
410 let mut header = FirmwareVolumeHeader::default();
411 header.update_checksum();
412 }
413}