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]]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to