Longlong,
Your code creates a big buffer that holds microcode data for all threads.
MicrocodeCpu[i] = MicrocodePatchHob->MicrocodePatchAddress +
MicrocodePatchHob->ProcessorSpecificPatchOffset[i]
BigBuffer = GetMicrocodeBuffer (MicrocodeOfCpu[0]) + GetMicrocodeBuffer
(MicrocodeOfCpu[1]) + ...
HashValue = Hash (BigBuffer)
I am not sure if we can do like below:
BigBuffer = <Entire microcode buffer pointed by
MicrocodePatchHob->MicrocodePatchAddress> + <array content of
MicrocodePatchHob->ProcessorSpecificPatchOffset[]>
HashValue = Hash (BigBuffer)
The second approach doesn't require sorting, one-by-one-copying.
Thanks,
Ray
-----Original Message-----
From: Yang, Longlong <[email protected]>
Sent: Thursday, October 28, 2021 3:21 PM
To: [email protected]
Cc: Yang, Longlong <[email protected]>; Dong, Eric <[email protected]>;
Ni, Ray <[email protected]>; Kumar, Rahul1 <[email protected]>; Yao, Jiewen
<[email protected]>; Xu, Min M <[email protected]>; Zhang, Qi1
<[email protected]>
Subject: [PATCH 1/1] UefiCpuPkg: Extend measurement of microcode patches to TPM
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3683
TCG specification says BIOS should extend measurement of microcode to TPM.
However, reference BIOS is not doing this. This patch consumes
gEdkiiMicrocodePatchHobGuid to checkout all applied microcode patches, then all
applied microcode patches are packed in order to form a single binary blob
which is measured with event type EV_CPU_MICROCODE to PCR[1] in TPM.
Cc: Eric Dong <[email protected]>
Cc: Ray Ni <[email protected]>
Cc: Rahul Kumar <[email protected]>
Cc: Jiewen Yao <[email protected]>
Cc: Min M Xu <[email protected]>
Cc: Qi Zhang <[email protected]>
Signed-off-by: Longlong Yang <[email protected]>
---
.../MicrocodeMeasurementDxe.c | 254 ++++++++++++++++++
.../MicrocodeMeasurementDxe.inf | 58 ++++
.../MicrocodeMeasurementDxe.uni | 15 ++
.../MicrocodeMeasurementDxeExtra.uni | 12 +
UefiCpuPkg/UefiCpuPkg.dsc | 2 +
5 files changed, 341 insertions(+)
create mode 100644 UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.c
create mode 100644
UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.inf
create mode 100644
UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.uni
create mode 100644
UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxeExtra.uni
diff --git a/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.c
b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.c
new file mode 100644
index 000000000000..1898a2bff023
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.c
@@ -0,0 +1,254 @@
+/** @file
+ This driver measures Microcode Patches to TPM.
+
+Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Guid/EventGroup.h>
+#include <Guid/MicrocodePatchHob.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h> #include <Library/UefiLib.h>
+#include <Library/BaseLib.h> #include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h> #include
+<Library/UefiBootServicesTableLib.h>
+#include <Library/PrintLib.h>
+#include <Library/SortLib.h>
+#include <Library/HobLib.h>
+#include <Library/MicrocodeLib.h>
+#include <Library/TpmMeasurementLib.h>
+
+
+#define CPU_MICROCODE_MEASUREMENT_DESCRIPTION "Microcode Measurement"
+#define CPU_MICROCODE_MEASUREMENT_EVENT_LOG_DESCRIPTION_LEN
+sizeof(CPU_MICROCODE_MEASUREMENT_DESCRIPTION)
+
+#pragma pack(1)
+typedef struct {
+ UINTN Address;
+ UINTN Size;
+} MICROCODE_PATCH_TYPE;
+
+typedef struct {
+ UINT8 Description[CPU_MICROCODE_MEASUREMENT_EVENT_LOG_DESCRIPTION_LEN];
+ UINTN NumberOfMicrocodePatchesMeasured;
+ UINTN SizeOfMicrocodePatchesMeasured;
+} CPU_MICROCODE_MEASUREMENT_EVENT_LOG;
+#pragma pack()
+
+STATIC BOOLEAN mMicrocodeMeasured = FALSE;
+
+/**
+ The function is called by PerformQuickSort to compare the order of
+ addresses of two microcode patch in RAM.
+
+ @param[in] MicrocodePatch1 The pointer to the first microcode patch type
structure.
+ @param[in] MicrocodePatch2 The pointer to the second microcode patch type
structure.
+
+ @return 0 The address of MicrocodePatch1 in RAM equal to
that of MicrocodePatch2.
+ @return <0 The address of MicrocodePatch1 in RAM is less
than that of MicrocodePatch2.
+ @return >0 The address of MicrocodePatch1 in RAM is
greater than that of MicrocodePatch2.
+**/
+INTN
+EFIAPI
+MicrocodePatchesListSortFunction (
+ IN CONST VOID *MicrocodePatch1,
+ IN CONST VOID *MicrocodePatch2
+ )
+{
+ return ((MICROCODE_PATCH_TYPE*)MicrocodePatch2)->Address -
+((MICROCODE_PATCH_TYPE*)MicrocodePatch1)->Address;
+}
+
+/**
+ Callback function, called after signaling of the Ready to Boot Event.
+ Measure microcode patches binary blob with event type
+EV_CPU_MICROCODE
+ to PCR[1] in TPM.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+MeasureMicrocodePatches (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PCRIndex;
+ UINT32 EventType;
+ CPU_MICROCODE_MEASUREMENT_EVENT_LOG EventLog;
+ UINT32 EventLogSize;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ EDKII_MICROCODE_PATCH_HOB *MicrocodePatchHob;
+ UINTN SumOfAllPatchesSizeInMicrocodePatchHob;
+ UINT32 Index;
+ MICROCODE_PATCH_TYPE *MicrocodePatchesList;
+ UINTN LastPackedMicrocodeAddress;
+ UINT8 *MicrocodePatchesBlob;
+ UINT64 MicrocodePatchesBlobSize;
+
+
+ PCRIndex = 1;
+ EventType = EV_CPU_MICROCODE;
+ AsciiSPrint (
+ (CHAR8 *)EventLog.Description,
+ CPU_MICROCODE_MEASUREMENT_EVENT_LOG_DESCRIPTION_LEN,
+ CPU_MICROCODE_MEASUREMENT_DESCRIPTION
+ );
+ EventLog.NumberOfMicrocodePatchesMeasured = 0;
+ EventLog.SizeOfMicrocodePatchesMeasured = 0;
+ EventLogSize = sizeof
(CPU_MICROCODE_MEASUREMENT_EVENT_LOG);
+ SumOfAllPatchesSizeInMicrocodePatchHob = 0;
+ LastPackedMicrocodeAddress = 0;
+ MicrocodePatchesBlob = NULL;
+ MicrocodePatchesBlobSize = 0;
+
+
+ if (TRUE == mMicrocodeMeasured) {
+ DEBUG((DEBUG_INFO, "INFO: mMicrocodeMeasured = TRUE, Skip.\n"));
+ return;
+ }
+
+ GuidHob = GetFirstGuidHob (&gEdkiiMicrocodePatchHobGuid); if (NULL
+ == GuidHob) {
+ DEBUG((DEBUG_ERROR, "ERROR: GetFirstGuidHob (&gEdkiiMicrocodePatchHobGuid)
failed.\n"));
+ return;
+ }
+
+ MicrocodePatchHob = GET_GUID_HOB_DATA (GuidHob); DEBUG ((DEBUG_INFO,
+ "INFO: Got MicrocodePatchHob with microcode patches starting
+ address:0x%x, microcode patches region size:0x%x, processor
+ count:0x%x\n", MicrocodePatchHob->MicrocodePatchAddress,
+ MicrocodePatchHob->MicrocodePatchRegionSize,
+ MicrocodePatchHob->ProcessorCount));
+
+ //
+ // Extract all microcode patches to a list from MicrocodePatchHob //
+ MicrocodePatchesList = AllocatePool (MicrocodePatchHob->ProcessorCount
+ * sizeof (MICROCODE_PATCH_TYPE)); if (NULL == MicrocodePatchesList) {
+ DEBUG ((DEBUG_ERROR, "ERROR: AllocatePool to MicrocodePatchesList
Failed!\n"));
+ return;
+ }
+ for (Index = 0; Index < MicrocodePatchHob->ProcessorCount; Index++) {
+ if (MAX_UINT64 == MicrocodePatchHob->ProcessorSpecificPatchOffset[Index]) {
+ //
+ // If no microcode patch was found in a slot, set the address of the
microcode patch
+ // in that slot to MAX_UINTN, and the size to 0, thus indicates no patch
in that slot.
+ //
+ MicrocodePatchesList[Index].Address = MAX_UINTN;
+ MicrocodePatchesList[Index].Size = 0;
+
+ DEBUG ((DEBUG_INFO, "INFO: Processor#%d: detected no microcode patch\n",
Index));
+ } else {
+ MicrocodePatchesList[Index].Address =
(UINTN)(MicrocodePatchHob->MicrocodePatchAddress +
MicrocodePatchHob->ProcessorSpecificPatchOffset[Index]);
+ MicrocodePatchesList[Index].Size =
((CPU_MICROCODE_HEADER*)((UINTN)(MicrocodePatchHob->MicrocodePatchAddress +
MicrocodePatchHob->ProcessorSpecificPatchOffset[Index])))->TotalSize;
+ SumOfAllPatchesSizeInMicrocodePatchHob +=
+ MicrocodePatchesList[Index].Size;
+
+ DEBUG ((DEBUG_INFO, "INFO: Processor#%d: Microcode patch address: 0x%x,
size: 0x%x\n", Index, MicrocodePatchesList[Index].Address,
MicrocodePatchesList[Index].Size));
+ }
+ }
+
+ //
+ // The order matters when packing all applied microcode patches to a single
binary blob.
+ // Therefore it is a must to do sorting before packing.
+ // NOTE: We assumed that the order of address of every microcode
+ patch in RAM is the same // with the order of those in the Microcode
+ Firmware Volume. If any future updates made // this assumption untenable,
then there needs a new solution to measure microcode patches.
+ //
+ PerformQuickSort (
+ MicrocodePatchesList,
+ MicrocodePatchHob->ProcessorCount,
+ sizeof (MICROCODE_PATCH_TYPE),
+ MicrocodePatchesListSortFunction
+ );
+ for (Index = 0; Index < MicrocodePatchHob->ProcessorCount; Index++) {
+ DEBUG ((DEBUG_INFO, "INFO: After sorting: Processor#%d: Microcode
+ patch address: 0x%x, size: 0x%x\n", Index,
+ MicrocodePatchesList[Index].Address,
+ MicrocodePatchesList[Index].Size));
+ }
+
+ MicrocodePatchesBlob = AllocateZeroPool
+ (SumOfAllPatchesSizeInMicrocodePatchHob);
+ if (NULL == MicrocodePatchesBlob) {
+ DEBUG ((DEBUG_ERROR, "ERROR: AllocateZeroPool to MicrocodePatchesBlob
failed!\n"));
+ FreePool (MicrocodePatchesList);
+ return;
+ }
+
+ //
+ // LastPackedMicrocodeAddress is used to skip duplicate microcode patch.
+ //
+ for (Index = 0; Index < MicrocodePatchHob->ProcessorCount; Index++) {
+ if (MicrocodePatchesList[Index].Address != LastPackedMicrocodeAddress &&
+ MicrocodePatchesList[Index].Address != MAX_UINTN) {
+
+ CopyMem (
+ (VOID *)(MicrocodePatchesBlob + MicrocodePatchesBlobSize),
+ (VOID *)(MicrocodePatchesList[Index].Address),
+ (UINTN)(MicrocodePatchesList[Index].Size)
+ );
+ MicrocodePatchesBlobSize +=
MicrocodePatchesList[Index].Size;
+ LastPackedMicrocodeAddress =
MicrocodePatchesList[Index].Address;
+ EventLog.NumberOfMicrocodePatchesMeasured += 1;
+ EventLog.SizeOfMicrocodePatchesMeasured +=
MicrocodePatchesList[Index].Size;
+
+ }
+ }
+
+ if (0 == MicrocodePatchesBlobSize) {
+ DEBUG ((DEBUG_INFO, "INFO: No microcode patch was ever applied!"));
+ FreePool (MicrocodePatchesList);
+ FreePool (MicrocodePatchesBlob);
+ return;
+ }
+
+ Status = TpmMeasureAndLogData (
+ PCRIndex, // PCRIndex
+ EventType, // EventType
+ &EventLog, // EventLog
+ EventLogSize, // LogLen
+ MicrocodePatchesBlob, // HashData
+ MicrocodePatchesBlobSize // HashDataLen
+ );
+ if (!EFI_ERROR (Status)) {
+ mMicrocodeMeasured = TRUE;
+ gBS->CloseEvent (Event);
+ } else {
+ FreePool (MicrocodePatchesList);
+ FreePool (MicrocodePatchesBlob);
+ DEBUG ((DEBUG_ERROR, "ERROR: TpmMeasureAndLogData failed with
+ %a!\n", Status)); }
+
+ return;
+}
+
+/**
+
+ Driver to produce microcode measurement.
+
+ @param ImageHandle Module's image handle
+ @param SystemTable Pointer of EFI_SYSTEM_TABLE
+
+ @return EFI_SUCCESS This function always complete successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+MicrocodeMeasurementDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_EVENT Event;
+
+ //
+ // Measure Microcode patches
+ //
+ EfiCreateEventReadyToBootEx (
+ TPL_CALLBACK,
+ MeasureMicrocodePatches,
+ NULL,
+ &Event
+ );
+
+ return EFI_SUCCESS;
+}
diff --git a/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.inf
b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.inf
new file mode 100644
index 000000000000..4b03339b431b
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.inf
@@ -0,0 +1,58 @@
+## @file
+# This driver measures microcode patches to TPM.
+#
+# This driver consumes gEdkiiMicrocodePatchHobGuid, packs all unique #
+microcode patch found in gEdkiiMicrocodePatchHobGuid to a binary blob,
+# and measures the binary blob to TPM.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> # #
+SPDX-License-Identifier: BSD-2-Clause-Patent # ##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = MicrocodeMeasurementDxe
+ MODULE_UNI_FILE = MicrocodeMeasurementDxe.uni
+ FILE_GUID = 0A32A803-ACDF-4C89-8293-91011548CD91
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = MicrocodeMeasurementDriverEntryPoint
+
+#
+# The following information is for reference only and not required by the
build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64
+#
+
+[Sources]
+ MicrocodeMeasurementDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ BaseLib
+ UefiLib
+ UefiDriverEntryPoint
+ DebugLib
+ PrintLib
+ SortLib
+ HobLib
+ MicrocodeLib
+ TpmMeasurementLib
+
+[Guids]
+ gEdkiiMicrocodePatchHobGuid ## CONSUMES ## HOB
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ MicrocodeMeasurementDxeExtra.uni
+
+[Depex]
+ TRUE
diff --git a/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.uni
b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.uni
new file mode 100644
index 000000000000..5a21e955fbbf
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.uni
@@ -0,0 +1,15 @@
+// /** @file
+// This driver measures microcode patches to TPM.
+//
+// This driver consumes gEdkiiMicrocodePatchHobGuid, packs all uniquemicrocode
patch found in gEdkiiMicrocodePatchHobGuid to a binary blob, and measures the
binary blob to TPM.
+//
+// Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> //
+// SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "This driver measures
Microcode Patches to TPM."
+
+#string STR_MODULE_DESCRIPTION #language en-US "This driver consumes
gEdkiiMicrocodePatchHobGuid, packs all microcode patch found in
gEdkiiMicrocodePatchHobGuid to a binary blob, and measure the binary blob to
TPM."
diff --git
a/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxeExtra.uni
b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxeExtra.uni
new file mode 100644
index 000000000000..6990cee8c6fd
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxeExtra.uni
@@ -0,0 +1,12 @@
+// /** @file
+// MicrocodeMeasurementDxe Localized Strings and Content
+//
+// Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Microcode Patches Measurement DXE Driver"
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index 870b45284087..06d55f780a9c 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -61,6 +61,7 @@
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
+ SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
[LibraryClasses.common.SEC]
PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
@@ -119,6 +120,7 @@
UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.inf
UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf
+ UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.inf
[Components.IA32, Components.X64]
UefiCpuPkg/CpuDxe/CpuDxe.inf
--
2.31.1.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#83079): https://edk2.groups.io/g/devel/message/83079
Mute This Topic: https://groups.io/mt/86757841/21656
Group Owner: [email protected]
Unsubscribe: https://edk2.groups.io/g/devel/unsub [[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-