@@ -10,9 +10,10 @@ use log::trace;
10
10
use r_efi:: base:: Guid ;
11
11
use scroll:: Pwrite ;
12
12
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 ,
16
17
} ;
17
18
use td_layout:: mailbox:: TdxMpWakeupMailbox ;
18
19
use td_loader:: { elf, pe} ;
@@ -24,17 +25,15 @@ use td_shim::reset_vector::{ResetVectorHeader, ResetVectorParams};
24
25
use td_shim:: write_u24;
25
26
use td_shim_interface:: metadata:: { TdxMetadataGuid , TdxMetadataPtr } ;
26
27
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 ,
29
30
} ;
30
31
31
32
use crate :: metadata:: { default_metadata_sections, MetadataSections , TdxMetadata } ;
32
33
use crate :: { InputData , OutputFile } ;
33
34
34
35
pub const MAX_IPL_CONTENT_SIZE : usize =
35
36
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 > ( ) ;
38
37
pub const MAX_METADATA_CONFIG_SIZE : usize = 1024 * 1024 ;
39
38
40
39
pub const OVMF_TABLE_FOOTER_GUID : Guid = Guid :: from_fields (
@@ -73,80 +72,6 @@ impl Default for FvHeaderByte {
73
72
}
74
73
75
74
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
-
150
75
// Build internal payload header
151
76
pub fn build_tdx_ipl_fv_header ( ) -> Self {
152
77
let mut hdr = Self :: default ( ) ;
@@ -222,19 +147,117 @@ impl FvHeaderByte {
222
147
}
223
148
}
224
149
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 ;
226
248
pub type IplFvHeaderByte = FvHeaderByte ;
227
249
228
250
pub fn build_tdx_metadata (
229
251
path : Option < & str > ,
230
252
payload_type : PayloadType ,
253
+ is_large_payload : bool ,
231
254
) -> io:: Result < TdxMetadata > {
232
255
let sections = if let Some ( path) = path {
233
256
let metadata_config = fs:: read ( path) ?;
234
257
serde_json:: from_slice :: < MetadataSections > ( metadata_config. as_slice ( ) )
235
258
. map_err ( |e| io:: Error :: new ( io:: ErrorKind :: Other , e) ) ?
236
259
} else {
237
- default_metadata_sections ( payload_type)
260
+ default_metadata_sections ( payload_type, is_large_payload )
238
261
} ;
239
262
240
263
TdxMetadata :: new ( sections) . ok_or ( io:: Error :: new (
@@ -361,18 +384,32 @@ impl TdShimLinker {
361
384
"mailbox content" ,
362
385
) ?;
363
386
387
+ let mut is_large_payload = true ;
364
388
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) ;
368
405
output_file. seek_and_write (
369
- TD_SHIM_PAYLOAD_OFFSET as u64 ,
406
+ payload_offset as u64 ,
370
407
& payload_header. data ,
371
408
"payload header" ,
372
409
) ?;
373
410
374
411
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 ] ;
376
413
let reloc = pe:: relocate (
377
414
& payload_bin. data ,
378
415
& mut payload_reloc_buf,
@@ -386,9 +423,9 @@ impl TdShimLinker {
386
423
} else {
387
424
output_file. write ( & payload_bin. data , "payload content" ) ?;
388
425
}
389
- }
426
+ } ;
390
427
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 ) ?;
392
429
let pos = TD_SHIM_METADATA_OFFSET as u64 ;
393
430
output_file. seek_and_write ( pos, & metadata. to_vec ( ) , "metadata" ) ?;
394
431
@@ -409,18 +446,25 @@ impl TdShimLinker {
409
446
0x100000
410
447
) ;
411
448
let entry_point = ( reloc. 0 - 0x100000 ) as u32 ;
412
- let current_pos = output_file. current_pos ( ) ?;
413
449
let reset_vector_info = ResetVectorParams {
414
450
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 ,
416
452
img_size : ipl_bin. data . len ( ) as u32 ,
417
453
} ;
418
454
419
455
output_file. write ( & ipl_reloc_buf, "internal payload content" ) ?;
420
456
421
457
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
+ ) ?;
424
468
425
469
let current_pos = output_file. current_pos ( ) ?;
426
470
assert_eq ! ( current_pos, TD_SHIM_FIRMWARE_SIZE as u64 ) ;
0 commit comments