Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ccb5634

Browse files
committedMay 10, 2024·
td-shim-tools: support large payload
Use `FfsFileHeader2` and `CommonSectionHeader2` for payload FV. If payload binary is larger than the `Payload` region size, then it will be treated as a large payload and it will be packaged in the start of the image and loaded into physical memory as indicated by metadata. Signed-off-by: Jiaqi Gao <[email protected]>
1 parent a6936d7 commit ccb5634

File tree

2 files changed

+179
-110
lines changed

2 files changed

+179
-110
lines changed
 

‎td-shim-tools/src/linker.rs

+138-94
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ use log::trace;
1010
use r_efi::base::Guid;
1111
use scroll::Pwrite;
1212
use td_layout::build_time::{
13-
TD_SHIM_FIRMWARE_BASE, TD_SHIM_FIRMWARE_SIZE, TD_SHIM_IPL_OFFSET, TD_SHIM_IPL_SIZE,
14-
TD_SHIM_MAILBOX_OFFSET, TD_SHIM_METADATA_OFFSET, TD_SHIM_PAYLOAD_BASE, TD_SHIM_PAYLOAD_OFFSET,
15-
TD_SHIM_PAYLOAD_SIZE, TD_SHIM_RESET_VECTOR_SIZE, TD_SHIM_SEC_CORE_INFO_OFFSET,
13+
TD_SHIM_FIRMWARE_SIZE, TD_SHIM_IPL_BASE, TD_SHIM_IPL_OFFSET, TD_SHIM_IPL_SIZE,
14+
TD_SHIM_LARGE_PAYLOAD_OFFSET, TD_SHIM_LARGE_PAYLOAD_SIZE, TD_SHIM_MAILBOX_OFFSET,
15+
TD_SHIM_METADATA_OFFSET, TD_SHIM_PAYLOAD_BASE, TD_SHIM_PAYLOAD_OFFSET, TD_SHIM_PAYLOAD_SIZE,
16+
TD_SHIM_RESET_VECTOR_OFFSET, TD_SHIM_RESET_VECTOR_SIZE, TD_SHIM_SEC_CORE_INFO_OFFSET,
1617
};
1718
use td_layout::mailbox::TdxMpWakeupMailbox;
1819
use td_loader::{elf, pe};
@@ -24,17 +25,15 @@ use td_shim::reset_vector::{ResetVectorHeader, ResetVectorParams};
2425
use td_shim::write_u24;
2526
use td_shim_interface::metadata::{TdxMetadataGuid, TdxMetadataPtr};
2627
use td_shim_interface::td_uefi_pi::pi::fv::{
27-
FfsFileHeader, FVH_REVISION, FVH_SIGNATURE, FV_FILETYPE_DXE_CORE, FV_FILETYPE_SECURITY_CORE,
28-
SECTION_PE32,
28+
CommonSectionHeader2, FfsFileHeader, FfsFileHeader2, FFS_ATTRIB_LARGE_FILE, FVH_REVISION,
29+
FVH_SIGNATURE, FV_FILETYPE_DXE_CORE, FV_FILETYPE_SECURITY_CORE, SECTION_PE32,
2930
};
3031

3132
use crate::metadata::{default_metadata_sections, MetadataSections, TdxMetadata};
3233
use crate::{InputData, OutputFile};
3334

3435
pub const MAX_IPL_CONTENT_SIZE: usize =
3536
TD_SHIM_IPL_SIZE as usize - size_of::<IplFvHeaderByte>() - size_of::<ResetVectorHeader>();
36-
pub const MAX_PAYLOAD_CONTENT_SIZE: usize =
37-
TD_SHIM_PAYLOAD_SIZE as usize - size_of::<FvHeaderByte>();
3837
pub const MAX_METADATA_CONFIG_SIZE: usize = 1024 * 1024;
3938

4039
pub const OVMF_TABLE_FOOTER_GUID: Guid = Guid::from_fields(
@@ -73,80 +72,6 @@ impl Default for FvHeaderByte {
7372
}
7473

7574
impl FvHeaderByte {
76-
pub fn build_tdx_payload_fv_header() -> Self {
77-
let mut hdr = Self::default();
78-
let fv_header_size = (size_of::<FvHeader>()) as usize;
79-
80-
let mut tdx_payload_fv_header = FvHeader::default();
81-
tdx_payload_fv_header.fv_header.fv_length = TD_SHIM_PAYLOAD_SIZE as u64;
82-
tdx_payload_fv_header.fv_header.signature = FVH_SIGNATURE;
83-
tdx_payload_fv_header.fv_header.header_length = size_of::<FvHeader>() as u16;
84-
tdx_payload_fv_header.fv_header.revision = FVH_REVISION;
85-
tdx_payload_fv_header.fv_header.update_checksum();
86-
87-
tdx_payload_fv_header.fv_block_map[0].num_blocks = (TD_SHIM_PAYLOAD_SIZE as u32) / 0x1000;
88-
tdx_payload_fv_header.fv_block_map[0].length = 0x1000;
89-
tdx_payload_fv_header.fv_ext_header.fv_name.copy_from_slice(
90-
Guid::from_fields(
91-
0x7cb8bdc9,
92-
0xf8eb,
93-
0x4f34,
94-
0xaa,
95-
0xea,
96-
&[0x3e, 0xe4, 0xaf, 0x65, 0x16, 0xa1],
97-
)
98-
.as_bytes(),
99-
);
100-
tdx_payload_fv_header.fv_ext_header.ext_header_size = 0x14;
101-
// Safe to unwrap() because space is enough.
102-
let res = hdr.data.pwrite(tdx_payload_fv_header, 0).unwrap();
103-
assert_eq!(res, 120);
104-
105-
let mut tdx_payload_fv_ffs_header = FvFfsFileHeader::default();
106-
tdx_payload_fv_ffs_header.ffs_header.name.copy_from_slice(
107-
Guid::from_fields(
108-
0xa8f75d7c,
109-
0x8b85,
110-
0x49b6,
111-
0x91,
112-
0x3e,
113-
&[0xaf, 0x99, 0x61, 0x55, 0x73, 0x08],
114-
)
115-
.as_bytes(),
116-
);
117-
tdx_payload_fv_ffs_header.ffs_header.r#type = FV_FILETYPE_DXE_CORE;
118-
tdx_payload_fv_ffs_header.ffs_header.attributes = 0x00;
119-
write_u24(
120-
TD_SHIM_PAYLOAD_SIZE - fv_header_size as u32,
121-
&mut tdx_payload_fv_ffs_header.ffs_header.size,
122-
);
123-
tdx_payload_fv_ffs_header.ffs_header.update_checksum();
124-
// Safe to unwrap() because space is enough.
125-
let res = hdr
126-
.data
127-
.pwrite(tdx_payload_fv_ffs_header, fv_header_size)
128-
.unwrap();
129-
assert_eq!(res, 24);
130-
131-
let mut tdx_payload_fv_ffs_section_header = FvFfsSectionHeader::default();
132-
write_u24(
133-
TD_SHIM_PAYLOAD_SIZE - fv_header_size as u32 - size_of::<FvFfsFileHeader>() as u32,
134-
&mut tdx_payload_fv_ffs_section_header.section_header.size,
135-
);
136-
tdx_payload_fv_ffs_section_header.section_header.r#type = SECTION_PE32;
137-
// Safe to unwrap() because space is enough.
138-
let res = hdr
139-
.data
140-
.pwrite(
141-
tdx_payload_fv_ffs_section_header,
142-
fv_header_size + size_of::<FvFfsFileHeader>(),
143-
)
144-
.unwrap();
145-
assert_eq!(res, 4);
146-
147-
hdr
148-
}
149-
15075
// Build internal payload header
15176
pub fn build_tdx_ipl_fv_header() -> Self {
15277
let mut hdr = Self::default();
@@ -222,19 +147,117 @@ impl FvHeaderByte {
222147
}
223148
}
224149

225-
pub type PayloadFvHeaderByte = FvHeaderByte;
150+
#[repr(C, align(4))]
151+
pub struct FvHeader2Byte {
152+
pub data: [u8; size_of::<FvHeader>()
153+
+ size_of::<FfsFileHeader2>()
154+
+ size_of::<CommonSectionHeader2>()],
155+
}
156+
157+
impl Default for FvHeader2Byte {
158+
fn default() -> Self {
159+
Self {
160+
data: [0u8; size_of::<FvHeader>()
161+
+ size_of::<FfsFileHeader2>()
162+
+ size_of::<CommonSectionHeader2>()],
163+
}
164+
}
165+
}
166+
167+
impl FvHeader2Byte {
168+
pub fn build_tdx_payload_fv_header(is_large_payload: bool) -> Self {
169+
let mut hdr = Self::default();
170+
let fv_header_size = (size_of::<FvHeader>()) as usize;
171+
172+
let mut tdx_payload_fv_header = FvHeader::default();
173+
let payload_region_size = if is_large_payload {
174+
TD_SHIM_LARGE_PAYLOAD_SIZE
175+
} else {
176+
TD_SHIM_PAYLOAD_SIZE
177+
};
178+
tdx_payload_fv_header.fv_header.fv_length = payload_region_size as u64;
179+
tdx_payload_fv_header.fv_header.signature = FVH_SIGNATURE;
180+
tdx_payload_fv_header.fv_header.header_length = size_of::<FvHeader>() as u16;
181+
tdx_payload_fv_header.fv_header.revision = FVH_REVISION;
182+
tdx_payload_fv_header.fv_header.update_checksum();
183+
184+
tdx_payload_fv_header.fv_block_map[0].num_blocks = payload_region_size / 0x1000;
185+
tdx_payload_fv_header.fv_block_map[0].length = 0x1000;
186+
tdx_payload_fv_header.fv_ext_header.fv_name.copy_from_slice(
187+
Guid::from_fields(
188+
0x7cb8bdc9,
189+
0xf8eb,
190+
0x4f34,
191+
0xaa,
192+
0xea,
193+
&[0x3e, 0xe4, 0xaf, 0x65, 0x16, 0xa1],
194+
)
195+
.as_bytes(),
196+
);
197+
tdx_payload_fv_header.fv_ext_header.ext_header_size = 0x14;
198+
// Safe to unwrap() because space is enough.
199+
let res = hdr.data.pwrite(tdx_payload_fv_header, 0).unwrap();
200+
assert_eq!(res, 120);
201+
202+
let mut tdx_payload_fv_ffs_header = FfsFileHeader2::default();
203+
tdx_payload_fv_ffs_header.name.copy_from_slice(
204+
Guid::from_fields(
205+
0xa8f75d7c,
206+
0x8b85,
207+
0x49b6,
208+
0x91,
209+
0x3e,
210+
&[0xaf, 0x99, 0x61, 0x55, 0x73, 0x08],
211+
)
212+
.as_bytes(),
213+
);
214+
tdx_payload_fv_ffs_header.r#type = FV_FILETYPE_DXE_CORE;
215+
tdx_payload_fv_ffs_header.attributes = FFS_ATTRIB_LARGE_FILE;
216+
tdx_payload_fv_ffs_header.extended_size =
217+
payload_region_size as u32 - fv_header_size as u32;
218+
tdx_payload_fv_ffs_header.update_checksum();
219+
// Safe to unwrap() because space is enough.
220+
let res = hdr
221+
.data
222+
.pwrite(tdx_payload_fv_ffs_header, fv_header_size)
223+
.unwrap();
224+
assert_eq!(res, 28);
225+
226+
let mut tdx_payload_fv_ffs_section_header = CommonSectionHeader2::default();
227+
tdx_payload_fv_ffs_section_header
228+
.size
229+
.copy_from_slice(&[0xff, 0xff, 0xff]);
230+
tdx_payload_fv_ffs_section_header.extended_size =
231+
TD_SHIM_PAYLOAD_SIZE - fv_header_size as u32 - size_of::<FfsFileHeader2>() as u32;
232+
tdx_payload_fv_ffs_section_header.r#type = SECTION_PE32;
233+
// Safe to unwrap() because space is enough.
234+
let res = hdr
235+
.data
236+
.pwrite(
237+
tdx_payload_fv_ffs_section_header,
238+
fv_header_size + size_of::<FfsFileHeader2>(),
239+
)
240+
.unwrap();
241+
assert_eq!(res, 8);
242+
243+
hdr
244+
}
245+
}
246+
247+
pub type PayloadFvHeaderByte = FvHeader2Byte;
226248
pub type IplFvHeaderByte = FvHeaderByte;
227249

228250
pub fn build_tdx_metadata(
229251
path: Option<&str>,
230252
payload_type: PayloadType,
253+
is_large_payload: bool,
231254
) -> io::Result<TdxMetadata> {
232255
let sections = if let Some(path) = path {
233256
let metadata_config = fs::read(path)?;
234257
serde_json::from_slice::<MetadataSections>(metadata_config.as_slice())
235258
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?
236259
} else {
237-
default_metadata_sections(payload_type)
260+
default_metadata_sections(payload_type, is_large_payload)
238261
};
239262

240263
TdxMetadata::new(sections).ok_or(io::Error::new(
@@ -361,18 +384,32 @@ impl TdShimLinker {
361384
"mailbox content",
362385
)?;
363386

387+
let mut is_large_payload = true;
364388
if let Some(payload_name) = payload_name {
365-
let payload_bin =
366-
InputData::new(payload_name, 0..=MAX_PAYLOAD_CONTENT_SIZE, "payload")?;
367-
let payload_header = PayloadFvHeaderByte::build_tdx_payload_fv_header();
389+
let max_payload_size = core::cmp::max(TD_SHIM_PAYLOAD_SIZE, TD_SHIM_LARGE_PAYLOAD_SIZE)
390+
as usize
391+
- size_of::<FvHeaderByte>();
392+
let payload_bin = InputData::new(payload_name, 0..=max_payload_size, "payload")?;
393+
394+
// If the payload image size greater than the size of payload region, it will be loaded
395+
// into the large payload region.
396+
// is_large_payload = payload_bin.as_bytes().len()
397+
// > TD_SHIM_PAYLOAD_SIZE as usize - size_of::<FvHeaderByte>();
398+
let payload_offset = if is_large_payload {
399+
TD_SHIM_LARGE_PAYLOAD_OFFSET
400+
} else {
401+
TD_SHIM_PAYLOAD_OFFSET
402+
};
403+
404+
let payload_header = PayloadFvHeaderByte::build_tdx_payload_fv_header(is_large_payload);
368405
output_file.seek_and_write(
369-
TD_SHIM_PAYLOAD_OFFSET as u64,
406+
payload_offset as u64,
370407
&payload_header.data,
371408
"payload header",
372409
)?;
373410

374411
if self.payload_relocation {
375-
let mut payload_reloc_buf = vec![0x0u8; MAX_PAYLOAD_CONTENT_SIZE];
412+
let mut payload_reloc_buf = vec![0x0u8; max_payload_size];
376413
let reloc = pe::relocate(
377414
&payload_bin.data,
378415
&mut payload_reloc_buf,
@@ -386,9 +423,9 @@ impl TdShimLinker {
386423
} else {
387424
output_file.write(&payload_bin.data, "payload content")?;
388425
}
389-
}
426+
};
390427

391-
let metadata = build_tdx_metadata(metadata_name, self.payload_type)?;
428+
let metadata = build_tdx_metadata(metadata_name, self.payload_type, is_large_payload)?;
392429
let pos = TD_SHIM_METADATA_OFFSET as u64;
393430
output_file.seek_and_write(pos, &metadata.to_vec(), "metadata")?;
394431

@@ -409,18 +446,25 @@ impl TdShimLinker {
409446
0x100000
410447
);
411448
let entry_point = (reloc.0 - 0x100000) as u32;
412-
let current_pos = output_file.current_pos()?;
413449
let reset_vector_info = ResetVectorParams {
414450
entry_point,
415-
img_base: TD_SHIM_FIRMWARE_BASE + current_pos as u32,
451+
img_base: TD_SHIM_IPL_BASE + size_of::<IplFvHeaderByte>() as u32,
416452
img_size: ipl_bin.data.len() as u32,
417453
};
418454

419455
output_file.write(&ipl_reloc_buf, "internal payload content")?;
420456

421457
let reset_vector_header = ResetVectorHeader::build_tdx_reset_vector_header();
422-
output_file.write(reset_vector_header.as_bytes(), "reset vector header")?;
423-
output_file.write(&reset_vector_bin.data, "reset vector content")?;
458+
output_file.seek_and_write(
459+
TD_SHIM_RESET_VECTOR_OFFSET as u64 - size_of::<ResetVectorHeader>() as u64,
460+
reset_vector_header.as_bytes(),
461+
"reset vector header",
462+
)?;
463+
output_file.seek_and_write(
464+
TD_SHIM_RESET_VECTOR_OFFSET as u64,
465+
&reset_vector_bin.data,
466+
"reset vector content",
467+
)?;
424468

425469
let current_pos = output_file.current_pos()?;
426470
assert_eq!(current_pos, TD_SHIM_FIRMWARE_SIZE as u64);

‎td-shim-tools/src/metadata.rs

+41-16
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ use serde::de::Error;
66
use serde::{de, Deserialize};
77
use std::{mem::size_of, vec::Vec};
88
use td_layout::build_time::*;
9+
use td_layout::runtime::exec::LARGE_PAYLOAD_BASE;
910
use td_layout::runtime::*;
1011
use td_shim_interface::metadata::{
11-
TdxMetadataDescriptor, TDX_METADATA_GUID, TDX_METADATA_SECTION_TYPE_BFV,
12-
TDX_METADATA_SECTION_TYPE_CFV, TDX_METADATA_SECTION_TYPE_PAYLOAD,
13-
TDX_METADATA_SECTION_TYPE_PAYLOAD_PARAM, TDX_METADATA_SECTION_TYPE_PERM_MEM,
14-
TDX_METADATA_SECTION_TYPE_TD_HOB, TDX_METADATA_SECTION_TYPE_TD_INFO,
15-
TDX_METADATA_SECTION_TYPE_TEMP_MEM, TDX_METADATA_SIGNATURE, TDX_METADATA_VERSION,
12+
TdxMetadataDescriptor, TDX_METADATA_ATTRIBUTES_EXTENDMR, TDX_METADATA_GUID,
13+
TDX_METADATA_SECTION_TYPE_BFV, TDX_METADATA_SECTION_TYPE_CFV,
14+
TDX_METADATA_SECTION_TYPE_PAYLOAD, TDX_METADATA_SECTION_TYPE_PAYLOAD_PARAM,
15+
TDX_METADATA_SECTION_TYPE_PERM_MEM, TDX_METADATA_SECTION_TYPE_TD_HOB,
16+
TDX_METADATA_SECTION_TYPE_TD_INFO, TDX_METADATA_SECTION_TYPE_TEMP_MEM, TDX_METADATA_SIGNATURE,
17+
TDX_METADATA_VERSION,
1618
};
1719
use td_shim_interface::td_uefi_pi::pi::guid::Guid;
1820

@@ -101,8 +103,6 @@ impl MetadataSections {
101103
}
102104

103105
fn basic_metadata_sections(payload_type: PayloadType) -> MetadataSections {
104-
use td_shim_interface::metadata::TDX_METADATA_ATTRIBUTES_EXTENDMR;
105-
106106
let mut metadata_sections = MetadataSections::new();
107107

108108
// BFV
@@ -182,7 +182,10 @@ fn basic_metadata_sections(payload_type: PayloadType) -> MetadataSections {
182182
metadata_sections
183183
}
184184

185-
pub fn default_metadata_sections(payload_type: PayloadType) -> MetadataSections {
185+
pub fn default_metadata_sections(
186+
payload_type: PayloadType,
187+
is_large_payload: bool,
188+
) -> MetadataSections {
186189
let mut metadata_sections = basic_metadata_sections(payload_type);
187190

188191
if payload_type == PayloadType::Linux {
@@ -226,16 +229,38 @@ pub fn default_metadata_sections(payload_type: PayloadType) -> MetadataSections
226229
attributes: 0,
227230
});
228231

229-
if cfg!(feature = "exec-payload-section") {
230-
println!("default_metadata_sections_exec_payload");
232+
if cfg!(feature = "exec-payload-section") || is_large_payload {
233+
let (data_offset, raw_data_size, memory_address) = if is_large_payload {
234+
(
235+
TD_SHIM_LARGE_PAYLOAD_OFFSET,
236+
TD_SHIM_LARGE_PAYLOAD_SIZE,
237+
LARGE_PAYLOAD_BASE as u64,
238+
)
239+
} else {
240+
(
241+
TD_SHIM_PAYLOAD_OFFSET,
242+
TD_SHIM_PAYLOAD_SIZE,
243+
TD_SHIM_PAYLOAD_BASE as u64,
244+
)
245+
};
246+
247+
let (r#type, attributes) = if cfg!(feature = "exec-payload-section") {
248+
(TDX_METADATA_SECTION_TYPE_PAYLOAD, 0)
249+
} else {
250+
(
251+
TDX_METADATA_SECTION_TYPE_BFV,
252+
TDX_METADATA_ATTRIBUTES_EXTENDMR,
253+
)
254+
};
255+
231256
// payload image
232257
metadata_sections.add(TdxMetadataSection {
233-
data_offset: TD_SHIM_PAYLOAD_OFFSET,
234-
raw_data_size: TD_SHIM_PAYLOAD_SIZE,
235-
memory_address: TD_SHIM_PAYLOAD_BASE as u64,
236-
memory_data_size: TD_SHIM_PAYLOAD_SIZE as u64,
237-
r#type: TDX_METADATA_SECTION_TYPE_PAYLOAD,
238-
attributes: 0,
258+
data_offset,
259+
raw_data_size,
260+
memory_address,
261+
memory_data_size: raw_data_size as u64,
262+
r#type,
263+
attributes,
239264
});
240265
}
241266
}

0 commit comments

Comments
 (0)
Please sign in to comment.