TianoCore EDK2 master
Loading...
Searching...
No Matches
MicrocodeMeasurementDxe.c
Go to the documentation of this file.
1
12#include <Guid/EventGroup.h>
14#include <Library/DebugLib.h>
16#include <Library/UefiLib.h>
17#include <Library/BaseLib.h>
21#include <Library/HobLib.h>
24
25#define CPU_MICROCODE_MEASUREMENT_DESCRIPTION "Microcode Measurement"
26#define CPU_MICROCODE_MEASUREMENT_EVENT_LOG_DESCRIPTION_LEN sizeof (CPU_MICROCODE_MEASUREMENT_DESCRIPTION)
27
28#pragma pack(1)
29typedef struct {
30 UINT8 Description[CPU_MICROCODE_MEASUREMENT_EVENT_LOG_DESCRIPTION_LEN];
31 UINTN NumberOfMicrocodePatchesMeasured;
32 UINTN SizeOfMicrocodePatchesMeasured;
34#pragma pack()
35
50INTN
51EFIAPI
53 IN CONST VOID *Offset1,
54 IN CONST VOID *Offset2
55 )
56{
57 if (*(UINT64 *)(Offset1) > *(UINT64 *)(Offset2)) {
58 return 1;
59 } else if (*(UINT64 *)(Offset1) < *(UINT64 *)(Offset2)) {
60 return -1;
61 } else {
62 return 0;
63 }
64}
65
74VOID
76 IN UINT64 *Offsets,
77 IN OUT UINTN *Count
78 )
79{
80 UINTN Index;
81 UINTN NewCount;
82 UINT64 LastOffset;
83 UINT64 QuickSortBuffer;
84
85 //
86 // The order matters when packing all applied microcode patches to a single binary blob.
87 // Therefore it is a must to do sorting before packing.
88 // NOTE: Since microcode patches are sorted by their addresses in memory, the order of
89 // addresses in memory of all the microcode patches before sorting is required to be the
90 // same in every boot flow. If any future updates made this assumption untenable, then
91 // there needs a new solution to measure microcode patches.
92 //
93 QuickSort (
94 Offsets,
95 *Count,
96 sizeof (UINT64),
98 (VOID *)&QuickSortBuffer
99 );
100
101 NewCount = 0;
102 LastOffset = MAX_UINT64;
103 for (Index = 0; Index < *Count; Index++) {
104 //
105 // When MAX_UINT64 element is met, all following elements are MAX_UINT64.
106 //
107 if (Offsets[Index] == MAX_UINT64) {
108 break;
109 }
110
111 //
112 // Remove duplicated offsets
113 //
114 if (Offsets[Index] != LastOffset) {
115 LastOffset = Offsets[Index];
116 Offsets[NewCount] = Offsets[Index];
117 NewCount++;
118 }
119 }
120
121 *Count = NewCount;
122}
123
133VOID
134EFIAPI
136 IN EFI_EVENT Event,
137 IN VOID *Context
138 )
139{
140 EFI_STATUS Status;
141 UINT32 PCRIndex;
142 UINT32 EventType;
144 UINT32 EventLogSize;
145 EFI_HOB_GUID_TYPE *GuidHob;
146 EDKII_MICROCODE_PATCH_HOB *MicrocodePatchHob;
147 UINT64 *Offsets;
148 UINTN Count;
149 UINTN Index;
150 UINTN TotalMicrocodeSize;
151 UINT8 *MicrocodePatchesBlob;
152
153 PCRIndex = 1;
154 EventType = EV_CPU_MICROCODE;
156 (CHAR8 *)(EventLog.Description),
157 CPU_MICROCODE_MEASUREMENT_EVENT_LOG_DESCRIPTION_LEN,
158 CPU_MICROCODE_MEASUREMENT_DESCRIPTION
159 );
160 EventLog.NumberOfMicrocodePatchesMeasured = 0;
161 EventLog.SizeOfMicrocodePatchesMeasured = 0;
162 EventLogSize = sizeof (CPU_MICROCODE_MEASUREMENT_EVENT_LOG);
163 Offsets = NULL;
164 TotalMicrocodeSize = 0;
165 Count = 0;
166
167 GuidHob = GetFirstGuidHob (&gEdkiiMicrocodePatchHobGuid);
168 if (NULL == GuidHob) {
169 DEBUG ((DEBUG_ERROR, "ERROR: GetFirstGuidHob (&gEdkiiMicrocodePatchHobGuid) failed.\n"));
170 return;
171 }
172
173 MicrocodePatchHob = GET_GUID_HOB_DATA (GuidHob);
174 DEBUG (
175 (DEBUG_INFO,
176 "INFO: Got MicrocodePatchHob with microcode patches starting address:0x%x, microcode patches region size:0x%x, processor count:0x%x\n",
177 MicrocodePatchHob->MicrocodePatchAddress, MicrocodePatchHob->MicrocodePatchRegionSize,
178 MicrocodePatchHob->ProcessorCount)
179 );
180
181 Offsets = AllocateCopyPool (
182 MicrocodePatchHob->ProcessorCount * sizeof (UINT64),
183 MicrocodePatchHob->ProcessorSpecificPatchOffset
184 );
185 Count = MicrocodePatchHob->ProcessorCount;
186
187 RemoveDuplicateAndInvalidOffset (Offsets, &Count);
188
189 if (0 == Count) {
190 DEBUG ((DEBUG_INFO, "INFO: No microcode patch is ever applied, skip the measurement of microcode!\n"));
191 FreePool (Offsets);
192 return;
193 }
194
195 for (Index = 0; Index < Count; Index++) {
196 TotalMicrocodeSize +=
197 GetMicrocodeLength ((CPU_MICROCODE_HEADER *)((UINTN)(MicrocodePatchHob->MicrocodePatchAddress + Offsets[Index])));
198 }
199
200 EventLog.NumberOfMicrocodePatchesMeasured = Count;
201 EventLog.SizeOfMicrocodePatchesMeasured = TotalMicrocodeSize;
202
203 MicrocodePatchesBlob = AllocateZeroPool (TotalMicrocodeSize);
204 if (NULL == MicrocodePatchesBlob) {
205 DEBUG ((DEBUG_ERROR, "ERROR: AllocateZeroPool to MicrocodePatchesBlob failed!\n"));
206 FreePool (Offsets);
207 return;
208 }
209
210 TotalMicrocodeSize = 0;
211 for (Index = 0; Index < Count; Index++) {
212 CopyMem (
213 (VOID *)(MicrocodePatchesBlob + TotalMicrocodeSize),
214 (VOID *)((UINTN)(MicrocodePatchHob->MicrocodePatchAddress + Offsets[Index])),
216 (CPU_MICROCODE_HEADER *)((UINTN)(MicrocodePatchHob->MicrocodePatchAddress +
217 Offsets[Index]))
218 ))
219 );
220 TotalMicrocodeSize +=
221 GetMicrocodeLength ((CPU_MICROCODE_HEADER *)((UINTN)(MicrocodePatchHob->MicrocodePatchAddress + Offsets[Index])));
222 }
223
224 Status = TpmMeasureAndLogData (
225 PCRIndex, // PCRIndex
226 EventType, // EventType
227 &EventLog, // EventLog
228 EventLogSize, // LogLen
229 MicrocodePatchesBlob, // HashData
230 TotalMicrocodeSize // HashDataLen
231 );
232 if (!EFI_ERROR (Status)) {
233 gBS->CloseEvent (Event);
234 DEBUG (
235 (DEBUG_INFO,
236 "INFO: %d Microcode patches are successfully extended to TPM! The total size measured to TPM is 0x%x\n",
237 Count,
238 TotalMicrocodeSize)
239 );
240 } else {
241 DEBUG ((DEBUG_ERROR, "ERROR: TpmMeasureAndLogData failed with status %r!\n", Status));
242 }
243
244 FreePool (Offsets);
245 FreePool (MicrocodePatchesBlob);
246 return;
247}
248
262EFIAPI
264 IN EFI_HANDLE ImageHandle,
265 IN EFI_SYSTEM_TABLE *SystemTable
266 )
267{
268 EFI_EVENT Event;
269
270 //
271 // Measure Microcode patches
272 //
274 TPL_CALLBACK,
276 NULL,
277 &Event
278 );
279
280 return EFI_SUCCESS;
281}
UINT64 UINTN
INT64 INTN
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition: HobLib.c:215
VOID EFIAPI QuickSort(IN OUT VOID *BufferToSort, IN CONST UINTN Count, IN CONST UINTN ElementSize, IN BASE_SORT_COMPARE CompareFunction, OUT VOID *BufferOneElement)
Definition: QuickSort.c:36
RETURN_STATUS EFIAPI AsciiStrCpyS(OUT CHAR8 *Destination, IN UINTN DestMax, IN CONST CHAR8 *Source)
Definition: SafeString.c:1797
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
UINT32 EFIAPI GetMicrocodeLength(IN CPU_MICROCODE_HEADER *Microcode)
Definition: MicrocodeLib.c:73
EFI_STATUS EFIAPI MicrocodeMeasurementDriverEntryPoint(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
INTN EFIAPI MicrocodePatchOffsetCompareFunction(IN CONST VOID *Offset1, IN CONST VOID *Offset2)
VOID EFIAPI MeasureMicrocodePatches(IN EFI_EVENT Event, IN VOID *Context)
VOID RemoveDuplicateAndInvalidOffset(IN UINT64 *Offsets, IN OUT UINTN *Count)
EFI_STATUS EFIAPI TpmMeasureAndLogData(IN UINT32 PcrIndex, IN UINT32 EventType, IN VOID *EventLog, IN UINT32 LogLen, IN VOID *HashData, IN UINT64 HashDataLen)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI EfiCreateEventReadyToBootEx(IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL, IN VOID *NotifyContext OPTIONAL, OUT EFI_EVENT *ReadyToBootEvent)
Definition: UefiNotTiano.c:164