Skip to content

Commit 5c1a16f

Browse files
committed
td-shim-interface: support large ffs header and section header
Add support for parsing ffs and sections that have size larger than 16MiB. Signed-off-by: Jiaqi Gao <[email protected]>
1 parent 0439e3e commit 5c1a16f

File tree

1 file changed

+97
-33
lines changed
  • td-shim-interface/src/td_uefi_pi

1 file changed

+97
-33
lines changed

td-shim-interface/src/td_uefi_pi/fv.rs

+97-33
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,6 @@ pub fn read_fv_header(fv_data: &[u8]) -> Option<FirmwareVolumeHeader> {
3838
Some(header)
3939
}
4040

41-
// Validate Ffs File header
42-
pub fn validate_ffs_file_header(header: FfsFileHeader) -> bool {
43-
// Do the sanity check for Ffs header.
44-
// Verify the header integrity,
45-
//
46-
if !header.validate_checksum() {
47-
return false;
48-
}
49-
true
50-
}
51-
5241
pub fn get_image_from_fv(
5342
fv_data: &[u8],
5443
fv_file_type: FvFileType,
@@ -58,10 +47,10 @@ pub fn get_image_from_fv(
5847

5948
let files = Files::parse(fv_data, fv_header.header_length as usize)?;
6049
for (file_header, file_data) in files {
61-
if !validate_ffs_file_header(file_header) {
50+
if !file_header.validate() {
6251
return None;
6352
}
64-
if file_header.r#type == fv_file_type {
53+
if file_header.r#type() == fv_file_type {
6554
return get_image_from_sections(file_data, section_type);
6655
}
6756
}
@@ -78,10 +67,10 @@ pub fn get_file_from_fv(
7867

7968
let files = Files::parse(fv_data, fv_header.header_length as usize)?;
8069
for (file_header, file_data) in files {
81-
if !validate_ffs_file_header(file_header) {
70+
if !file_header.validate() {
8271
return None;
8372
}
84-
if file_header.r#type == fv_file_type && &file_header.name == file_name.as_bytes() {
73+
if file_header.r#type() == fv_file_type && file_header.name() == file_name.as_bytes() {
8574
return Some(file_data);
8675
}
8776
}
@@ -93,14 +82,28 @@ fn get_image_from_sections(sections_data: &[u8], section_type: SectionType) -> O
9382
let sections = Sections::parse(sections_data, 0)?;
9483

9584
for (section_header, section_data) in sections {
96-
if section_header.r#type == section_type {
85+
if section_header.r#type() == section_type {
9786
return Some(section_data);
9887
}
9988
}
10089

10190
None
10291
}
10392

93+
enum CommonSectionHeaderType {
94+
Header(CommonSectionHeader),
95+
Header2(CommonSectionHeader2),
96+
}
97+
98+
impl CommonSectionHeaderType {
99+
fn r#type(&self) -> FvFileType {
100+
match self {
101+
Self::Header(header) => header.r#type,
102+
Self::Header2(header2) => header2.r#type,
103+
}
104+
}
105+
}
106+
104107
struct Sections<'a> {
105108
buffer: &'a [u8],
106109
}
@@ -118,17 +121,32 @@ impl<'a> Sections<'a> {
118121
}
119122

120123
impl<'a> Iterator for Sections<'a> {
121-
type Item = (CommonSectionHeader, &'a [u8]);
124+
type Item = (CommonSectionHeaderType, &'a [u8]);
122125

123126
fn next(&mut self) -> Option<Self::Item> {
124-
const HEADER_SIZE: usize = core::mem::size_of::<CommonSectionHeader>();
125127
let header: CommonSectionHeader = self.buffer.pread(0).ok()?;
126-
let section_size = header.size[0] as usize
127-
+ ((header.size[1] as usize) << 8)
128-
+ ((header.size[2] as usize) << 16);
129-
section_size.checked_sub(HEADER_SIZE)?;
128+
let is_large_section = header.size == [0xff, 0xff, 0xff];
129+
130+
let (section_size, section_header, header_size) = if is_large_section {
131+
let header2: CommonSectionHeader2 = self.buffer.pread(0).ok()?;
132+
(
133+
header2.extended_size as usize,
134+
CommonSectionHeaderType::Header2(header2),
135+
core::mem::size_of::<CommonSectionHeader2>(),
136+
)
137+
} else {
138+
(
139+
header.size[0] as usize
140+
+ ((header.size[1] as usize) << 8)
141+
+ ((header.size[2] as usize) << 16),
142+
CommonSectionHeaderType::Header(header),
143+
core::mem::size_of::<CommonSectionHeader>(),
144+
)
145+
};
146+
147+
section_size.checked_sub(header_size)?;
130148
self.buffer.len().checked_sub(section_size)?;
131-
let buf = &self.buffer[HEADER_SIZE..section_size];
149+
let buf = &self.buffer[header_size..section_size];
132150

133151
// Align to 4 bytes.
134152
let section_size = (section_size + 3) & !3;
@@ -138,7 +156,39 @@ impl<'a> Iterator for Sections<'a> {
138156
self.buffer = &self.buffer[0..0];
139157
}
140158

141-
Some((header, buf))
159+
Some((section_header, buf))
160+
}
161+
}
162+
163+
enum FfsFileHeaderType {
164+
Header(FfsFileHeader),
165+
Header2(FfsFileHeader2),
166+
}
167+
168+
impl FfsFileHeaderType {
169+
fn r#type(&self) -> FvFileType {
170+
match self {
171+
FfsFileHeaderType::Header(header) => header.r#type,
172+
FfsFileHeaderType::Header2(header2) => header2.r#type,
173+
}
174+
}
175+
176+
fn name(&self) -> &[u8] {
177+
match self {
178+
FfsFileHeaderType::Header(header) => &header.name,
179+
FfsFileHeaderType::Header2(header2) => &header2.name,
180+
}
181+
}
182+
183+
// Validate Ffs File header
184+
fn validate(&self) -> bool {
185+
// Do the sanity check for Ffs header.
186+
// Verify the header integrity,
187+
//
188+
match self {
189+
FfsFileHeaderType::Header(header) => ffs_header_validate_checksum(header.as_bytes()),
190+
FfsFileHeaderType::Header2(header2) => ffs_header_validate_checksum(header2.as_bytes()),
191+
}
142192
}
143193
}
144194

@@ -159,18 +209,32 @@ impl<'a> Files<'a> {
159209
}
160210

161211
impl<'a> Iterator for Files<'a> {
162-
type Item = (FfsFileHeader, &'a [u8]);
212+
type Item = (FfsFileHeaderType, &'a [u8]);
163213

164214
fn next(&mut self) -> Option<Self::Item> {
165-
const HEADER_SIZE: usize = core::mem::size_of::<FfsFileHeader>();
166-
167215
let header: FfsFileHeader = self.buffer.pread(0).ok()?;
168-
let data_size = header.size[0] as usize
169-
+ ((header.size[1] as usize) << 8)
170-
+ ((header.size[2] as usize) << 16);
171-
data_size.checked_sub(HEADER_SIZE)?;
216+
let is_large_file = header.attributes & FFS_ATTRIB_LARGE_FILE != 0;
217+
218+
let (data_size, ffs_header, header_size) = if is_large_file {
219+
let header2: FfsFileHeader2 = self.buffer.pread(0).ok()?;
220+
(
221+
header2.extended_size as usize,
222+
FfsFileHeaderType::Header2(header2),
223+
core::mem::size_of::<FfsFileHeader2>(),
224+
)
225+
} else {
226+
(
227+
header.size[0] as usize
228+
+ ((header.size[1] as usize) << 8)
229+
+ ((header.size[2] as usize) << 16),
230+
FfsFileHeaderType::Header(header),
231+
core::mem::size_of::<FfsFileHeader>(),
232+
)
233+
};
234+
235+
data_size.checked_sub(header_size)?;
172236
self.buffer.len().checked_sub(data_size)?;
173-
let buf = &self.buffer[HEADER_SIZE..data_size];
237+
let buf = &self.buffer[header_size..data_size];
174238

175239
// Align to 8 bytes.
176240
let data_size = (data_size + 7) & !7;
@@ -180,7 +244,7 @@ impl<'a> Iterator for Files<'a> {
180244
self.buffer = &self.buffer[0..0];
181245
}
182246

183-
Some((header, buf))
247+
Some((ffs_header, buf))
184248
}
185249
}
186250

0 commit comments

Comments
 (0)