2 Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
3 SPDX-License-Identifier: BSD-2-Clause-Patent
7 #include <Library/BaseLib.h>
8 #include <Library/BaseMemoryLib.h>
9 #include <Library/DebugLib.h>
10 #include <Guid/VariableFormat.h>
11 #include <Guid/SystemNvDataGuid.h>
12 #include <IndustryStandard/Tpm20.h>
13 #include <IndustryStandard/UefiTcgPlatform.h>
14 #include <Library/HobLib.h>
15 #include <Library/PrintLib.h>
16 #include <Library/TpmMeasurementLib.h>
18 #include "PeilessStartupInternal.h"
22 #define HANDOFF_TABLE_DESC "TdxTable"
24 UINT8 TableDescriptionSize
;
25 UINT8 TableDescription
[sizeof (HANDOFF_TABLE_DESC
)];
26 UINT64 NumberOfTables
;
27 EFI_CONFIGURATION_TABLE TableEntry
[1];
28 } TDX_HANDOFF_TABLE_POINTERS2
;
30 #define FV_HANDOFF_TABLE_DESC "Fv(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)"
32 UINT8 BlobDescriptionSize
;
33 UINT8 BlobDescription
[sizeof (FV_HANDOFF_TABLE_DESC
)];
34 EFI_PHYSICAL_ADDRESS BlobBase
;
36 } FV_HANDOFF_TABLE_POINTERS2
;
41 Check padding data all bit should be 1.
43 @param[in] Buffer - A pointer to buffer header
44 @param[in] BufferSize - Buffer size
46 @retval TRUE - The padding data is valid.
47 @retval TRUE - The padding data is invalid.
58 for (index
= 0; index
< BufferSize
; index
++) {
59 if (Buffer
[index
] != 0xFF) {
68 Check the integrity of CFV data.
70 @param[in] TdxCfvBase - A pointer to CFV header
71 @param[in] TdxCfvSize - CFV data size
73 @retval TRUE - The CFV data is valid.
74 @retval FALSE - The CFV data is invalid.
86 UINT32 VariableOffset
;
87 UINT32 VariableOffsetBeforeAlign
;
88 EFI_FIRMWARE_VOLUME_HEADER
*CfvFvHeader
;
89 VARIABLE_STORE_HEADER
*CfvVariableStoreHeader
;
90 AUTHENTICATED_VARIABLE_HEADER
*VariableHeader
;
92 static EFI_GUID FvHdrGUID
= EFI_SYSTEM_NV_DATA_FV_GUID
;
93 static EFI_GUID VarStoreHdrGUID
= EFI_AUTHENTICATED_VARIABLE_GUID
;
97 if (TdxCfvBase
== NULL
) {
98 DEBUG ((DEBUG_ERROR
, "TDX CFV: CFV pointer is NULL\n"));
103 // Verify the header zerovetor, filesystemguid,
104 // revision, signature, attributes, fvlength, checksum
105 // HeaderLength cannot be an odd number
107 CfvFvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)TdxCfvBase
;
109 if ((!IsZeroBuffer (CfvFvHeader
->ZeroVector
, 16)) ||
110 (!CompareGuid (&FvHdrGUID
, &CfvFvHeader
->FileSystemGuid
)) ||
111 (CfvFvHeader
->Signature
!= EFI_FVH_SIGNATURE
) ||
112 (CfvFvHeader
->Attributes
!= 0x4feff) ||
113 (CfvFvHeader
->Revision
!= EFI_FVH_REVISION
) ||
114 (CfvFvHeader
->FvLength
!= TdxCfvSize
)
117 DEBUG ((DEBUG_ERROR
, "TDX CFV: Basic FV headers were invalid\n"));
122 // Verify the header checksum
124 Checksum
= CalculateSum16 ((VOID
*)CfvFvHeader
, CfvFvHeader
->HeaderLength
);
127 DEBUG ((DEBUG_ERROR
, "TDX CFV: FV checksum was invalid\n"));
132 // Verify the header signature, size, format, state
134 CfvVariableStoreHeader
= (VARIABLE_STORE_HEADER
*)(TdxCfvBase
+ CfvFvHeader
->HeaderLength
);
135 if ((!CompareGuid (&VarStoreHdrGUID
, &CfvVariableStoreHeader
->Signature
)) ||
136 (CfvVariableStoreHeader
->Format
!= VARIABLE_STORE_FORMATTED
) ||
137 (CfvVariableStoreHeader
->State
!= VARIABLE_STORE_HEALTHY
) ||
138 (CfvVariableStoreHeader
->Size
> (CfvFvHeader
->FvLength
- CfvFvHeader
->HeaderLength
)) ||
139 (CfvVariableStoreHeader
->Size
< sizeof (VARIABLE_STORE_HEADER
))
142 DEBUG ((DEBUG_ERROR
, "TDX CFV: Variable Store header was invalid\n"));
147 // Verify the header startId, state
148 // Verify data to the end
150 VariableBase
= (UINTN
)TdxCfvBase
+ CfvFvHeader
->HeaderLength
+ sizeof (VARIABLE_STORE_HEADER
);
151 while (VariableOffset
< (CfvVariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
))) {
152 VariableHeader
= (AUTHENTICATED_VARIABLE_HEADER
*)(VariableBase
+ VariableOffset
);
153 if (VariableHeader
->StartId
!= VARIABLE_DATA
) {
154 if (!CheckPaddingData ((UINT8
*)VariableHeader
, CfvVariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
) - VariableOffset
)) {
155 DEBUG ((DEBUG_ERROR
, "TDX CFV: Variable header was invalid\n"));
159 VariableOffset
= CfvVariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
161 if (!((VariableHeader
->State
== VAR_IN_DELETED_TRANSITION
) ||
162 (VariableHeader
->State
== VAR_DELETED
) ||
163 (VariableHeader
->State
== VAR_HEADER_VALID_ONLY
) ||
164 (VariableHeader
->State
== VAR_ADDED
)))
166 DEBUG ((DEBUG_ERROR
, "TDX CFV: Variable header was invalid\n"));
170 VariableOffset
+= sizeof (AUTHENTICATED_VARIABLE_HEADER
) + VariableHeader
->NameSize
+ VariableHeader
->DataSize
;
171 // Verify VariableOffset should be less than or equal CfvVariableStoreHeader->Size - sizeof(VARIABLE_STORE_HEADER)
172 if (VariableOffset
> (CfvVariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
))) {
173 DEBUG ((DEBUG_ERROR
, "TDX CFV: Variable header was invalid\n"));
177 VariableOffsetBeforeAlign
= VariableOffset
;
179 VariableOffset
= (VariableOffset
+ 3) & (UINTN
)(~3);
181 if (!CheckPaddingData ((UINT8
*)(VariableBase
+ VariableOffsetBeforeAlign
), VariableOffset
- VariableOffsetBeforeAlign
)) {
182 DEBUG ((DEBUG_ERROR
, "TDX CFV: Variable header was invalid\n"));
192 Measure the Hoblist passed from the VMM.
194 @param[in] VmmHobList The Hoblist pass the firmware
196 @retval EFI_SUCCESS Fv image is measured successfully
197 or it has been already measured.
198 @retval Others Other errors as indicated
203 IN CONST VOID
*VmmHobList
206 EFI_PEI_HOB_POINTERS Hob
;
207 TDX_HANDOFF_TABLE_POINTERS2 HandoffTables
;
210 if (!TdIsEnabled ()) {
212 return EFI_UNSUPPORTED
;
215 Hob
.Raw
= (UINT8
*)VmmHobList
;
218 // Parse the HOB list until end of list.
220 while (!END_OF_HOB_LIST (Hob
)) {
221 Hob
.Raw
= GET_NEXT_HOB (Hob
);
225 // Init the log event for HOB measurement
228 HandoffTables
.TableDescriptionSize
= sizeof (HandoffTables
.TableDescription
);
229 CopyMem (HandoffTables
.TableDescription
, HANDOFF_TABLE_DESC
, sizeof (HandoffTables
.TableDescription
));
230 HandoffTables
.NumberOfTables
= 1;
231 CopyGuid (&(HandoffTables
.TableEntry
[0].VendorGuid
), &gUefiOvmfPkgTokenSpaceGuid
);
232 HandoffTables
.TableEntry
[0].VendorTable
= (VOID
*)VmmHobList
;
234 Status
= TpmMeasureAndLogData (
236 EV_EFI_HANDOFF_TABLES2
, // EventType
237 (VOID
*)&HandoffTables
, // EventData
238 sizeof (HandoffTables
), // EventSize
239 (UINT8
*)(UINTN
)VmmHobList
, // HashData
240 (UINTN
)((UINT8
*)Hob
.Raw
- (UINT8
*)VmmHobList
) // HashDataLen
243 if (EFI_ERROR (Status
)) {
251 Get the FvName from the FV header.
253 Causion: The FV is untrusted input.
255 @param[in] FvBase Base address of FV image.
256 @param[in] FvLength Length of FV image.
258 @return FvName pointer
259 @retval NULL FvName is NOT found
263 IN EFI_PHYSICAL_ADDRESS FvBase
,
267 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
268 EFI_FIRMWARE_VOLUME_EXT_HEADER
*FvExtHeader
;
270 if (FvBase
>= MAX_ADDRESS
) {
274 if (FvLength
>= MAX_ADDRESS
- FvBase
) {
278 if (FvLength
< sizeof (EFI_FIRMWARE_VOLUME_HEADER
)) {
282 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)FvBase
;
283 if (FvHeader
->ExtHeaderOffset
< sizeof (EFI_FIRMWARE_VOLUME_HEADER
)) {
287 if (FvHeader
->ExtHeaderOffset
+ sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER
) > FvLength
) {
291 FvExtHeader
= (EFI_FIRMWARE_VOLUME_EXT_HEADER
*)(UINTN
)(FvBase
+ FvHeader
->ExtHeaderOffset
);
293 return &FvExtHeader
->FvName
;
299 @param[in] FvBase Base address of FV image.
300 @param[in] FvLength Length of FV image.
301 @param[in] PcrIndex Index of PCR
303 @retval EFI_SUCCESS Fv image is measured successfully
304 or it has been already measured.
305 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
306 @retval EFI_DEVICE_ERROR The command was unsuccessful.
312 IN EFI_PHYSICAL_ADDRESS FvBase
,
318 FV_HANDOFF_TABLE_POINTERS2 FvBlob2
;
322 // Init the log event for FV measurement
324 FvBlob2
.BlobDescriptionSize
= sizeof (FvBlob2
.BlobDescription
);
325 CopyMem (FvBlob2
.BlobDescription
, FV_HANDOFF_TABLE_DESC
, sizeof (FvBlob2
.BlobDescription
));
326 FvName
= GetFvName (FvBase
, FvLength
);
327 if (FvName
!= NULL
) {
328 AsciiSPrint ((CHAR8
*)FvBlob2
.BlobDescription
, sizeof (FvBlob2
.BlobDescription
), "Fv(%g)", FvName
);
331 FvBlob2
.BlobBase
= FvBase
;
332 FvBlob2
.BlobLength
= FvLength
;
334 Status
= TpmMeasureAndLogData (
336 EV_EFI_PLATFORM_FIRMWARE_BLOB2
, // EventType
337 (VOID
*)&FvBlob2
, // EventData
338 sizeof (FvBlob2
), // EventSize
339 (UINT8
*)(UINTN
)FvBase
, // HashData
340 (UINTN
)(FvLength
) // HashDataLen
343 if (EFI_ERROR (Status
)) {
344 DEBUG ((DEBUG_ERROR
, "The FV which failed to be measured starts at: 0x%x\n", FvBase
));