public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v7] IntelSiliconPkg: FIT based shadow microcode PPI support.
@ 2020-02-19 11:03 Siyuan, Fu
  2020-02-19 11:25 ` Ni, Ray
  0 siblings, 1 reply; 2+ messages in thread
From: Siyuan, Fu @ 2020-02-19 11:03 UTC (permalink / raw)
  To: devel; +Cc: Michael D Kinney, Ray Ni, Rangasai V Chaganty

V7 Change:
Add check for FIT type 0 count.
Move all FIT table check to function IsValidFitTable().
V6 Changes:
Add missing EFIAPI for ShadowMicrocode().
Check FIT table version and checksum before use.
Merge ShadowMicrocodePatchByFit() to ShadowMicrocode().
V5 Changes:
Add FIT address check to see if it's in valid firmware region.
V4 Changes:
Adjust EDKII_MICROCODE_SHADOW_INFO_HOB structure definition for
better alignment and understanding.
Add EFI_MICROCODE_STORAGE_TYPE_FLASH_CONTEXT structure definition.
Fix a typo in EFI_MICROCODE_STORAGE_TYPE_FLASH_GUID.
Merge ShadowMicrocodePei.h header into c file.
Correct file header description and copy right year.
V3 Changes:
Remove the feature PCD PcdCpuShadowMicrocodeByFit because the
whole FIT microcode shadow code is moved to this PEIM so platform
could disable this feature by not include PEIM now.
V2 Changes:
Rename EDKII_PEI_CPU_MICROCODE_ID to EDKII_PEI_MICROCODE_CPU_ID.

This patch adds a platform PEIM for FIT based shadow microcode PPI
support. A detailed design doc can be found here:
https://edk2.groups.io/g/devel/files/Designs/2020/0214/Support%20
the%202nd%20Microcode%20FV%20Flash%20Region.pdf

TEST: Tested on FIT enabled platform.
BZ: https://tianocore.acgmultimedia.com/show_bug.cgi?id=2449

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
Signed-off-by: Siyuan Fu <siyuan.fu@intel.com>
---
 .../ShadowMicrocode/ShadowMicrocodePei.c      | 491 ++++++++++++++++++
 .../ShadowMicrocode/ShadowMicrocodePei.inf    |  43 ++
 .../Include/Guid/MicrocodeShadowInfoHob.h     |  64 +++
 .../Intel/IntelSiliconPkg/IntelSiliconPkg.dec |   8 +-
 .../Intel/IntelSiliconPkg/IntelSiliconPkg.dsc |   3 +-
 5 files changed, 607 insertions(+), 2 deletions(-)
 create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.c
 create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.inf
 create mode 100644 Silicon/Intel/IntelSiliconPkg/Include/Guid/MicrocodeShadowInfoHob.h

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.c b/Silicon/Intel/IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.c
new file mode 100644
index 0000000000..7e4084247e
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.c
@@ -0,0 +1,491 @@
+/** @file
+  FIT based microcode shadow PEIM.
+
+Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Ppi/ShadowMicrocode.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <IndustryStandard/FirmwareInterfaceTable.h>
+#include <Register/Intel/Microcode.h>
+#include <Register/Intel/Cpuid.h>
+#include <Guid/MicrocodeShadowInfoHob.h>
+//
+// Data structure for microcode patch information
+//
+typedef struct {
+  UINTN    Address;
+  UINTN    Size;
+} MICROCODE_PATCH_INFO;
+
+/**
+  Shadow microcode update patches to memory.
+
+  The function is used for shadowing microcode update patches to a continuous memory.
+  It shall allocate memory buffer and only shadow the microcode patches for those
+  processors specified by MicrocodeCpuId array. The checksum verification may be
+  skiped in this function so the caller must perform checksum verification before
+  using the microcode patches in returned memory buffer.
+
+  @param[in]  This                 The PPI instance pointer.
+  @param[in]  CpuIdCount           Number of elements in MicrocodeCpuId array.
+  @param[in]  MicrocodeCpuId       A pointer to an array of EDKII_PEI_MICROCODE_CPU_ID
+                                   structures.
+  @param[out] BufferSize           Pointer to receive the total size of Buffer.
+  @param[out] Buffer               Pointer to receive address of allocated memory
+                                   with microcode patches data in it.
+
+  @retval EFI_SUCCESS              The microcode has been shadowed to memory.
+  @retval EFI_OUT_OF_RESOURCES     The operation fails due to lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+ShadowMicrocode (
+  IN  EDKII_PEI_SHADOW_MICROCODE_PPI        *This,
+  IN  UINTN                                 CpuIdCount,
+  IN  EDKII_PEI_MICROCODE_CPU_ID            *MicrocodeCpuId,
+  OUT UINTN                                 *BufferSize,
+  OUT VOID                                  **Buffer
+  );
+
+
+EDKII_PEI_SHADOW_MICROCODE_PPI   mPeiShadowMicrocodePpi = {
+  ShadowMicrocode
+};
+
+
+EFI_PEI_PPI_DESCRIPTOR           mPeiShadowMicrocodePpiList[] = {
+  {
+    EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+    &gEdkiiPeiShadowMicrocodePpiGuid,
+    &mPeiShadowMicrocodePpi
+  }
+};
+
+/**
+  Determine if a microcode patch matchs the specific processor signature and flag.
+
+  @param[in]  CpuIdCount            Number of elements in MicrocodeCpuId array.
+  @param[in]  MicrocodeCpuId        A pointer to an array of EDKII_PEI_MICROCODE_CPU_ID
+                                    structures.
+  @param[in]  ProcessorSignature    The processor signature field value
+                                    supported by a microcode patch.
+  @param[in]  ProcessorFlags        The prcessor flags field value supported by
+                                    a microcode patch.
+
+  @retval TRUE     The specified microcode patch will be loaded.
+  @retval FALSE    The specified microcode patch will not be loaded.
+**/
+BOOLEAN
+IsProcessorMatchedMicrocodePatch (
+  IN  UINTN                           CpuIdCount,
+  IN  EDKII_PEI_MICROCODE_CPU_ID      *MicrocodeCpuId,
+  IN UINT32                           ProcessorSignature,
+  IN UINT32                           ProcessorFlags
+  )
+{
+  UINTN          Index;
+
+  for (Index = 0; Index < CpuIdCount; Index++) {
+    if ((ProcessorSignature == MicrocodeCpuId[Index].ProcessorSignature) &&
+        (ProcessorFlags & (1 << MicrocodeCpuId[Index].PlatformId)) != 0) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  Check the 'ProcessorSignature' and 'ProcessorFlags' of the microcode
+  patch header with the CPUID and PlatformID of the processors within
+  system to decide if it will be copied into memory.
+
+  @param[in]  CpuIdCount            Number of elements in MicrocodeCpuId array.
+  @param[in]  MicrocodeCpuId        A pointer to an array of EDKII_PEI_MICROCODE_CPU_ID
+                                    structures.
+  @param[in]  MicrocodeEntryPoint   The pointer to the microcode patch header.
+
+  @retval TRUE     The specified microcode patch need to be loaded.
+  @retval FALSE    The specified microcode patch dosen't need to be loaded.
+**/
+BOOLEAN
+IsMicrocodePatchNeedLoad (
+  IN  UINTN                         CpuIdCount,
+  IN  EDKII_PEI_MICROCODE_CPU_ID    *MicrocodeCpuId,
+  CPU_MICROCODE_HEADER              *MicrocodeEntryPoint
+  )
+{
+  BOOLEAN                                NeedLoad;
+  UINTN                                  DataSize;
+  UINTN                                  TotalSize;
+  CPU_MICROCODE_EXTENDED_TABLE_HEADER    *ExtendedTableHeader;
+  UINT32                                 ExtendedTableCount;
+  CPU_MICROCODE_EXTENDED_TABLE           *ExtendedTable;
+  UINTN                                  Index;
+
+  //
+  // Check the 'ProcessorSignature' and 'ProcessorFlags' in microcode patch header.
+  //
+  NeedLoad = IsProcessorMatchedMicrocodePatch (
+               CpuIdCount,
+               MicrocodeCpuId,
+               MicrocodeEntryPoint->ProcessorSignature.Uint32,
+               MicrocodeEntryPoint->ProcessorFlags
+               );
+
+  //
+  // If the Extended Signature Table exists, check if the processor is in the
+  // support list
+  //
+  DataSize  = MicrocodeEntryPoint->DataSize;
+  TotalSize = (DataSize == 0) ? 2048 : MicrocodeEntryPoint->TotalSize;
+  if ((!NeedLoad) && (DataSize != 0) &&
+      (TotalSize - DataSize > sizeof (CPU_MICROCODE_HEADER) +
+                              sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER))) {
+    ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint)
+                            + DataSize + sizeof (CPU_MICROCODE_HEADER));
+    ExtendedTableCount  = ExtendedTableHeader->ExtendedSignatureCount;
+    ExtendedTable       = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);
+
+    for (Index = 0; Index < ExtendedTableCount; Index ++) {
+      //
+      // Check the 'ProcessorSignature' and 'ProcessorFlag' of the Extended
+      // Signature Table entry with the CPUID and PlatformID of the processors
+      // within system to decide if it will be copied into memory
+      //
+      NeedLoad = IsProcessorMatchedMicrocodePatch (
+                   CpuIdCount,
+                   MicrocodeCpuId,
+                   ExtendedTable->ProcessorSignature.Uint32,
+                   ExtendedTable->ProcessorFlag
+                   );
+      if (NeedLoad) {
+        break;
+      }
+      ExtendedTable ++;
+    }
+  }
+
+  return NeedLoad;
+}
+
+/**
+  Actual worker function that shadows the required microcode patches into memory.
+
+  @param[in]       Patches          The pointer to an array of information on
+                                    the microcode patches that will be loaded
+                                    into memory.
+  @param[in]       PatchCount       The number of microcode patches that will
+                                    be loaded into memory.
+  @param[in]       TotalLoadSize    The total size of all the microcode patches
+                                    to be loaded.
+  @param[out] BufferSize            Pointer to receive the total size of Buffer.
+  @param[out] Buffer                Pointer to receive address of allocated memory
+                                    with microcode patches data in it.
+**/
+VOID
+ShadowMicrocodePatchWorker (
+  IN  MICROCODE_PATCH_INFO       *Patches,
+  IN  UINTN                      PatchCount,
+  IN  UINTN                      TotalLoadSize,
+  OUT UINTN                      *BufferSize,
+  OUT VOID                       **Buffer
+  )
+{
+  UINTN                                     Index;
+  VOID                                      *MicrocodePatchInRam;
+  UINT8                                     *Walker;
+  EDKII_MICROCODE_SHADOW_INFO_HOB           *MicrocodeShadowHob;
+  UINTN                                     HobDataLength;
+  UINT64                                    *MicrocodeAddressInMemory;
+  EFI_MICROCODE_STORAGE_TYPE_FLASH_CONTEXT  *Flashcontext;
+
+  ASSERT ((Patches != NULL) && (PatchCount != 0));
+
+  //
+  // Init microcode shadow info HOB content.
+  //
+  HobDataLength = sizeof (EDKII_MICROCODE_SHADOW_INFO_HOB) +
+                  sizeof (UINT64) * PatchCount * 2;
+  MicrocodeShadowHob  = AllocatePool (HobDataLength);
+  if (MicrocodeShadowHob == NULL) {
+    ASSERT (FALSE);
+    return;
+  }
+  MicrocodeShadowHob->MicrocodeCount = PatchCount;
+  CopyGuid (
+    &MicrocodeShadowHob->StorageType,
+    &gEdkiiMicrocodeStorageTypeFlashGuid
+    );
+  MicrocodeAddressInMemory = (UINT64 *) (MicrocodeShadowHob + 1);
+  Flashcontext = (EFI_MICROCODE_STORAGE_TYPE_FLASH_CONTEXT *) (MicrocodeAddressInMemory + PatchCount);
+
+  //
+  // Allocate memory for microcode shadow operation.
+  //
+  MicrocodePatchInRam = AllocatePages (EFI_SIZE_TO_PAGES (TotalLoadSize));
+  if (MicrocodePatchInRam == NULL) {
+    ASSERT (FALSE);
+    return;
+  }
+
+  //
+  // Shadow all the required microcode patches into memory
+  //
+  for (Walker = MicrocodePatchInRam, Index = 0; Index < PatchCount; Index++) {
+    CopyMem (
+      Walker,
+      (VOID *) Patches[Index].Address,
+      Patches[Index].Size
+      );
+    MicrocodeAddressInMemory[Index] = (UINT64) Walker;
+    Flashcontext->MicrocodeAddressInFlash[Index]  = (UINT64) Patches[Index].Address;
+    Walker += Patches[Index].Size;
+  }
+
+  //
+  // Update the microcode patch related fields in CpuMpData
+  //
+  *Buffer     = (VOID *) (UINTN) MicrocodePatchInRam;
+  *BufferSize = TotalLoadSize;
+
+  BuildGuidDataHob (
+    &gEdkiiMicrocodeShadowInfoHobGuid,
+    MicrocodeShadowHob,
+    HobDataLength
+    );
+
+  DEBUG ((
+    DEBUG_INFO,
+    "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n",
+    __FUNCTION__, *Buffer, *BufferSize
+    ));
+
+  return;
+}
+
+/**
+  Check if FIT table content is valid according to FIT BIOS specification.
+
+**/
+BOOLEAN
+IsValidFitTable (
+  IN  UINT64               FitPointer
+  )
+{
+  UINT64                            FitEnding;
+  FIRMWARE_INTERFACE_TABLE_ENTRY    *FitEntry;
+  UINT32                            EntryNum;
+  UINT32                            Type0Count;
+  UINT32                            Index;
+
+  //
+  // The entire FIT table must reside with in the firmware address range
+  // of (4GB-16MB) to (4GB-40h).
+  //
+  if ((FitPointer < (SIZE_4GB - SIZE_16MB)) || (FitPointer >= (SIZE_4GB - 0x40))) {
+    //
+    // Invalid FIT address, treat it as no FIT table.
+    //
+    DEBUG ((DEBUG_ERROR, "Error: Invalid FIT pointer 0x%p.\n", FitPointer));
+    return FALSE;
+  }
+
+  //
+  // Check FIT header.
+  //
+  FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *) (UINTN) FitPointer;
+  if ((FitEntry[0].Type != FIT_TYPE_00_HEADER) ||
+      (FitEntry[0].Address != FIT_TYPE_00_SIGNATURE)) {
+    DEBUG ((DEBUG_ERROR, "Error: Invalid FIT header.\n"));
+    return FALSE;
+  }
+
+  //
+  // Check FIT version.
+  //
+  if (FitEntry[0].Version != FIT_TYPE_VERSION) {
+    DEBUG ((DEBUG_ERROR, "Error: Unsupported FIT version.\n"));
+    return FALSE;
+  }
+
+  //
+  // Check FIT ending address in valid range.
+  //
+  EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;
+  FitEnding = FitPointer + sizeof (FIRMWARE_INTERFACE_TABLE_ENTRY) * EntryNum;
+  if (FitEnding  > (SIZE_4GB - 0x40)) {
+    DEBUG ((DEBUG_ERROR, "Error: FIT table exceeds valid range.\n"));
+    return FALSE;
+  }
+
+  //
+  // Calculate FIT checksum if Checksum Valid bit is set.
+  //
+  if (FitEntry[0].C_V &&
+      CalculateSum8 ((UINT8*) FitEntry, sizeof (FIRMWARE_INTERFACE_TABLE_ENTRY) * EntryNum) != 0) {
+    DEBUG ((DEBUG_ERROR, "Error: Invalid FIT checksum.\n"));
+    return FALSE;
+  }
+
+  //
+  // Check type 0 entry count.
+  //
+  Type0Count = 0;
+  for (Index = 0; Index < EntryNum; Index++) {
+    if (FitEntry[Index].Type == FIT_TYPE_00_HEADER) {
+      Type0Count++;
+    }
+  }
+  if (Type0Count != 1) {
+    DEBUG ((DEBUG_ERROR, "Error: There can be only one Type 0 entry in FIT.\n"));
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+
+/**
+  Shadow microcode update patches to memory.
+
+  The function is used for shadowing microcode update patches to a continuous memory.
+  It shall allocate memory buffer and only shadow the microcode patches for those
+  processors specified by MicrocodeCpuId array. The checksum verification may be
+  skiped in this function so the caller must perform checksum verification before
+  using the microcode patches in returned memory buffer.
+
+  @param[in]  This                 The PPI instance pointer.
+  @param[in]  CpuIdCount           Number of elements in MicrocodeCpuId array.
+  @param[in]  MicrocodeCpuId       A pointer to an array of EDKII_PEI_MICROCODE_CPU_ID
+                                   structures.
+  @param[out] BufferSize           Pointer to receive the total size of Buffer.
+  @param[out] Buffer               Pointer to receive address of allocated memory
+                                   with microcode patches data in it.
+
+  @retval EFI_SUCCESS              The microcode has been shadowed to memory.
+  @retval EFI_OUT_OF_RESOURCES     The operation fails due to lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+ShadowMicrocode (
+  IN  EDKII_PEI_SHADOW_MICROCODE_PPI        *This,
+  IN  UINTN                                 CpuIdCount,
+  IN  EDKII_PEI_MICROCODE_CPU_ID            *MicrocodeCpuId,
+  OUT UINTN                                 *BufferSize,
+  OUT VOID                                  **Buffer
+  )
+{
+  UINT64                            FitPointer;
+  FIRMWARE_INTERFACE_TABLE_ENTRY    *FitEntry;
+  UINT32                            EntryNum;
+  UINT32                            Index;
+  MICROCODE_PATCH_INFO              *PatchInfoBuffer;
+  UINTN                             MaxPatchNumber;
+  CPU_MICROCODE_HEADER              *MicrocodeEntryPoint;
+  UINTN                             PatchCount;
+  UINTN                             TotalSize;
+  UINTN                             TotalLoadSize;
+
+  if (BufferSize == NULL || Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (CpuIdCount != 0 && MicrocodeCpuId == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  FitPointer = *(UINT64 *) (UINTN) FIT_POINTER_ADDRESS;
+  if (!IsValidFitTable (FitPointer)) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Calculate microcode entry number
+  //
+  FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *) (UINTN) FitPointer;
+  EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;
+  MaxPatchNumber = 0;
+  for (Index = 0; Index < EntryNum; Index++) {
+    if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {
+      MaxPatchNumber++;
+    }
+  }
+  if (MaxPatchNumber == 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  PatchInfoBuffer = AllocatePool (MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO));
+  if (PatchInfoBuffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Fill up microcode patch info buffer according to FIT table.
+  //
+  PatchCount = 0;
+  TotalLoadSize = 0;
+  for (Index = 0; Index < EntryNum; Index++) {
+    if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {
+      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (UINTN) FitEntry[Index].Address;
+      TotalSize = (MicrocodeEntryPoint->DataSize == 0) ? 2048 : MicrocodeEntryPoint->TotalSize;
+      if (IsMicrocodePatchNeedLoad (CpuIdCount, MicrocodeCpuId, MicrocodeEntryPoint)) {
+        PatchInfoBuffer[PatchCount].Address     = (UINTN) MicrocodeEntryPoint;
+        PatchInfoBuffer[PatchCount].Size        = TotalSize;
+        TotalLoadSize += TotalSize;
+        PatchCount++;
+      }
+    }
+  }
+
+  if (PatchCount != 0) {
+    DEBUG ((
+      DEBUG_INFO,
+      "%a: 0x%x microcode patches will be loaded into memory, with size 0x%x.\n",
+      __FUNCTION__, PatchCount, TotalLoadSize
+      ));
+
+    ShadowMicrocodePatchWorker (PatchInfoBuffer, PatchCount, TotalLoadSize, BufferSize, Buffer);
+  }
+
+  FreePool (PatchInfoBuffer);
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Platform Init PEI module entry point
+
+  @param[in]  FileHandle           Not used.
+  @param[in]  PeiServices          General purpose services available to every PEIM.
+
+  @retval     EFI_SUCCESS          The function completes successfully
+  @retval     EFI_OUT_OF_RESOURCES Insufficient resources to create database
+**/
+EFI_STATUS
+EFIAPI
+ShadowMicrocodePeimInit (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  EFI_STATUS                       Status;
+
+  //
+  // Install EDKII Shadow Microcode PPI
+  //
+  Status = PeiServicesInstallPpi(mPeiShadowMicrocodePpiList);
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.inf b/Silicon/Intel/IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.inf
new file mode 100644
index 0000000000..019400ab31
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.inf
@@ -0,0 +1,43 @@
+### @file
+# FIT based microcode shadow PEIM.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = ShadowMicrocodePei
+  FILE_GUID                      = 8af4cf68-ebe4-4b21-a008-0cb3da277be5
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = PEIM
+  ENTRY_POINT                    = ShadowMicrocodePeimInit
+
+[Sources]
+  ShadowMicrocodePei.c
+
+[LibraryClasses]
+  PeimEntryPoint
+  DebugLib
+  MemoryAllocationLib
+  BaseMemoryLib
+  HobLib
+  PeiServicesLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+  IntelSiliconPkg/IntelSiliconPkg.dec
+
+[Ppis]
+  gEdkiiPeiShadowMicrocodePpiGuid                     ## PRODUCES
+
+[Guids]
+  gEdkiiMicrocodeShadowInfoHobGuid
+  gEdkiiMicrocodeStorageTypeFlashGuid
+
+[Depex]
+  TRUE
diff --git a/Silicon/Intel/IntelSiliconPkg/Include/Guid/MicrocodeShadowInfoHob.h b/Silicon/Intel/IntelSiliconPkg/Include/Guid/MicrocodeShadowInfoHob.h
new file mode 100644
index 0000000000..d1a9d79a51
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Include/Guid/MicrocodeShadowInfoHob.h
@@ -0,0 +1,64 @@
+/** @file
+  The definition for Microcode Shadow Info Hob.
+
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+
+#ifndef _MICROCODE_SHADOW_INFO_HOB_H_
+#define _MICROCODE_SHADOW_INFO_HOB_H_
+
+///
+/// The Global ID of a GUIDed HOB used to pass microcode shadow info to DXE Driver.
+///
+#define EDKII_MICROCODE_SHADOW_INFO_HOB_GUID \
+  { \
+    0x658903f9, 0xda66, 0x460d, { 0x8b, 0xb0, 0x9d, 0x2d, 0xdf, 0x65, 0x44, 0x59 } \
+  }
+
+extern EFI_GUID gEdkiiMicrocodeShadowInfoHobGuid;
+
+typedef struct {
+  //
+  // An EFI_GUID that defines the contents of StorageContext.
+  //
+  GUID      StorageType;
+  //
+  // Number of the microcode patches which have been
+  // relocated to memory.
+  //
+  UINT64    MicrocodeCount;
+  //
+  // An array with MicrocodeCount elements that stores
+  // the shadowed microcode patch address in memory.
+  //
+  UINT64    MicrocodeAddrInMemory[];
+  //
+  // A buffer which contains details about the storage information
+  // specific to StorageType.
+  //
+  // UINT8  StorageContext[];
+} EDKII_MICROCODE_SHADOW_INFO_HOB;
+
+//
+// An EDKII_MICROCODE_SHADOW_INFO_HOB with StorageType set to below GUID will have
+// the StorageContext of a EFI_MICROCODE_STORAGE_TYPE_FLASH_CONTEXT strucutre.
+//
+#define EFI_MICROCODE_STORAGE_TYPE_FLASH_GUID \
+  { \
+    0x2cba01b3, 0xd391, 0x4598, { 0x8d, 0x89, 0xb7, 0xfc, 0x39, 0x22, 0xfd, 0x71 } \
+  }
+
+extern EFI_GUID gEdkiiMicrocodeStorageTypeFlashGuid;
+
+typedef struct {
+  //
+  // An array with MicrocodeCount elements that stores the original
+  // microcode patch address on flash. The address is placed in same
+  // order as the microcode patches in MicrocodeAddrInMemory.
+  //
+  UINT64  MicrocodeAddressInFlash[];
+} EFI_MICROCODE_STORAGE_TYPE_FLASH_CONTEXT;
+
+#endif
diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
index 22ebf19c4e..3c49fb289c 100644
--- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
+++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
@@ -3,7 +3,7 @@
 #
 # This package provides common open source Intel silicon modules.
 #
-# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
@@ -48,6 +48,12 @@
   ## HOB GUID to get memory information after MRC is done. The hob data will be used to set the PMR ranges
   gVtdPmrInfoDataHobGuid = {0x6fb61645, 0xf168, 0x46be, { 0x80, 0xec, 0xb5, 0x02, 0x38, 0x5e, 0xe7, 0xe7 } }
 
+  ## Include/Guid/MicrocodeShadowInfoHob.h
+  gEdkiiMicrocodeShadowInfoHobGuid = { 0x658903f9, 0xda66, 0x460d, { 0x8b, 0xb0, 0x9d, 0x2d, 0xdf, 0x65, 0x44, 0x59 } }
+
+  ## Include/Guid/MicrocodeShadowInfoHob.h
+  gEdkiiMicrocodeStorageTypeFlashGuid = { 0x2cba01b3, 0xd391, 0x4598, { 0x8d, 0x89, 0xb7, 0xfc, 0x39, 0x22, 0xfd, 0x71 } }
+
 [Ppis]
   gEdkiiVTdInfoPpiGuid = { 0x8a59fcb3, 0xf191, 0x400c, { 0x97, 0x67, 0x67, 0xaf, 0x2b, 0x25, 0x68, 0x4a } }
 
diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dsc b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dsc
index 0a6509d8b3..f995883691 100644
--- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dsc
+++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dsc
@@ -1,7 +1,7 @@
 ## @file
 # This package provides common open source Intel silicon modules.
 #
-# Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2017 - 2020, Intel Corporation. All rights reserved.<BR>
 #
 #    SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -84,6 +84,7 @@
   IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
   IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf
   IntelSiliconPkg/Feature/Capsule/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf
+  IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.inf
   IntelSiliconPkg/Library/PeiDxeSmmBootMediaLib/PeiFirmwareBootMediaLib.inf
   IntelSiliconPkg/Library/PeiDxeSmmBootMediaLib/DxeSmmFirmwareBootMediaLib.inf
 
-- 
2.19.1.windows.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v7] IntelSiliconPkg: FIT based shadow microcode PPI support.
  2020-02-19 11:03 [PATCH v7] IntelSiliconPkg: FIT based shadow microcode PPI support Siyuan, Fu
@ 2020-02-19 11:25 ` Ni, Ray
  0 siblings, 0 replies; 2+ messages in thread
From: Ni, Ray @ 2020-02-19 11:25 UTC (permalink / raw)
  To: Fu, Siyuan, devel@edk2.groups.io; +Cc: Kinney, Michael D, Chaganty, Rangasai V

Reviewed-by: Ray Ni <ray.ni@intel.com>

> -----Original Message-----
> From: Fu, Siyuan <siyuan.fu@intel.com>
> Sent: Wednesday, February 19, 2020 7:04 PM
> To: devel@edk2.groups.io
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>
> Subject: [PATCH v7] IntelSiliconPkg: FIT based shadow microcode PPI support.
> 
> V7 Change:
> Add check for FIT type 0 count.
> Move all FIT table check to function IsValidFitTable().
> V6 Changes:
> Add missing EFIAPI for ShadowMicrocode().
> Check FIT table version and checksum before use.
> Merge ShadowMicrocodePatchByFit() to ShadowMicrocode().
> V5 Changes:
> Add FIT address check to see if it's in valid firmware region.
> V4 Changes:
> Adjust EDKII_MICROCODE_SHADOW_INFO_HOB structure definition for
> better alignment and understanding.
> Add EFI_MICROCODE_STORAGE_TYPE_FLASH_CONTEXT structure definition.
> Fix a typo in EFI_MICROCODE_STORAGE_TYPE_FLASH_GUID.
> Merge ShadowMicrocodePei.h header into c file.
> Correct file header description and copy right year.
> V3 Changes:
> Remove the feature PCD PcdCpuShadowMicrocodeByFit because the
> whole FIT microcode shadow code is moved to this PEIM so platform
> could disable this feature by not include PEIM now.
> V2 Changes:
> Rename EDKII_PEI_CPU_MICROCODE_ID to EDKII_PEI_MICROCODE_CPU_ID.
> 
> This patch adds a platform PEIM for FIT based shadow microcode PPI
> support. A detailed design doc can be found here:
> https://edk2.groups.io/g/devel/files/Designs/2020/0214/Support%20
> the%202nd%20Microcode%20FV%20Flash%20Region.pdf
> 
> TEST: Tested on FIT enabled platform.
> BZ: https://tianocore.acgmultimedia.com/show_bug.cgi?id=2449
> 
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
> Signed-off-by: Siyuan Fu <siyuan.fu@intel.com>
> ---
>  .../ShadowMicrocode/ShadowMicrocodePei.c      | 491 ++++++++++++++++++
>  .../ShadowMicrocode/ShadowMicrocodePei.inf    |  43 ++
>  .../Include/Guid/MicrocodeShadowInfoHob.h     |  64 +++
>  .../Intel/IntelSiliconPkg/IntelSiliconPkg.dec |   8 +-
>  .../Intel/IntelSiliconPkg/IntelSiliconPkg.dsc |   3 +-
>  5 files changed, 607 insertions(+), 2 deletions(-)
>  create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.c
>  create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.inf
>  create mode 100644 Silicon/Intel/IntelSiliconPkg/Include/Guid/MicrocodeShadowInfoHob.h
> 
> diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.c
> b/Silicon/Intel/IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.c
> new file mode 100644
> index 0000000000..7e4084247e
> --- /dev/null
> +++ b/Silicon/Intel/IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.c
> @@ -0,0 +1,491 @@
> +/** @file
> +  FIT based microcode shadow PEIM.
> +
> +Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <PiPei.h>
> +#include <Ppi/ShadowMicrocode.h>
> +#include <Library/PeiServicesLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <IndustryStandard/FirmwareInterfaceTable.h>
> +#include <Register/Intel/Microcode.h>
> +#include <Register/Intel/Cpuid.h>
> +#include <Guid/MicrocodeShadowInfoHob.h>
> +//
> +// Data structure for microcode patch information
> +//
> +typedef struct {
> +  UINTN    Address;
> +  UINTN    Size;
> +} MICROCODE_PATCH_INFO;
> +
> +/**
> +  Shadow microcode update patches to memory.
> +
> +  The function is used for shadowing microcode update patches to a continuous memory.
> +  It shall allocate memory buffer and only shadow the microcode patches for those
> +  processors specified by MicrocodeCpuId array. The checksum verification may be
> +  skiped in this function so the caller must perform checksum verification before
> +  using the microcode patches in returned memory buffer.
> +
> +  @param[in]  This                 The PPI instance pointer.
> +  @param[in]  CpuIdCount           Number of elements in MicrocodeCpuId array.
> +  @param[in]  MicrocodeCpuId       A pointer to an array of EDKII_PEI_MICROCODE_CPU_ID
> +                                   structures.
> +  @param[out] BufferSize           Pointer to receive the total size of Buffer.
> +  @param[out] Buffer               Pointer to receive address of allocated memory
> +                                   with microcode patches data in it.
> +
> +  @retval EFI_SUCCESS              The microcode has been shadowed to memory.
> +  @retval EFI_OUT_OF_RESOURCES     The operation fails due to lack of resources.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ShadowMicrocode (
> +  IN  EDKII_PEI_SHADOW_MICROCODE_PPI        *This,
> +  IN  UINTN                                 CpuIdCount,
> +  IN  EDKII_PEI_MICROCODE_CPU_ID            *MicrocodeCpuId,
> +  OUT UINTN                                 *BufferSize,
> +  OUT VOID                                  **Buffer
> +  );
> +
> +
> +EDKII_PEI_SHADOW_MICROCODE_PPI   mPeiShadowMicrocodePpi = {
> +  ShadowMicrocode
> +};
> +
> +
> +EFI_PEI_PPI_DESCRIPTOR           mPeiShadowMicrocodePpiList[] = {
> +  {
> +    EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
> +    &gEdkiiPeiShadowMicrocodePpiGuid,
> +    &mPeiShadowMicrocodePpi
> +  }
> +};
> +
> +/**
> +  Determine if a microcode patch matchs the specific processor signature and flag.
> +
> +  @param[in]  CpuIdCount            Number of elements in MicrocodeCpuId array.
> +  @param[in]  MicrocodeCpuId        A pointer to an array of EDKII_PEI_MICROCODE_CPU_ID
> +                                    structures.
> +  @param[in]  ProcessorSignature    The processor signature field value
> +                                    supported by a microcode patch.
> +  @param[in]  ProcessorFlags        The prcessor flags field value supported by
> +                                    a microcode patch.
> +
> +  @retval TRUE     The specified microcode patch will be loaded.
> +  @retval FALSE    The specified microcode patch will not be loaded.
> +**/
> +BOOLEAN
> +IsProcessorMatchedMicrocodePatch (
> +  IN  UINTN                           CpuIdCount,
> +  IN  EDKII_PEI_MICROCODE_CPU_ID      *MicrocodeCpuId,
> +  IN UINT32                           ProcessorSignature,
> +  IN UINT32                           ProcessorFlags
> +  )
> +{
> +  UINTN          Index;
> +
> +  for (Index = 0; Index < CpuIdCount; Index++) {
> +    if ((ProcessorSignature == MicrocodeCpuId[Index].ProcessorSignature) &&
> +        (ProcessorFlags & (1 << MicrocodeCpuId[Index].PlatformId)) != 0) {
> +      return TRUE;
> +    }
> +  }
> +
> +  return FALSE;
> +}
> +
> +/**
> +  Check the 'ProcessorSignature' and 'ProcessorFlags' of the microcode
> +  patch header with the CPUID and PlatformID of the processors within
> +  system to decide if it will be copied into memory.
> +
> +  @param[in]  CpuIdCount            Number of elements in MicrocodeCpuId array.
> +  @param[in]  MicrocodeCpuId        A pointer to an array of EDKII_PEI_MICROCODE_CPU_ID
> +                                    structures.
> +  @param[in]  MicrocodeEntryPoint   The pointer to the microcode patch header.
> +
> +  @retval TRUE     The specified microcode patch need to be loaded.
> +  @retval FALSE    The specified microcode patch dosen't need to be loaded.
> +**/
> +BOOLEAN
> +IsMicrocodePatchNeedLoad (
> +  IN  UINTN                         CpuIdCount,
> +  IN  EDKII_PEI_MICROCODE_CPU_ID    *MicrocodeCpuId,
> +  CPU_MICROCODE_HEADER              *MicrocodeEntryPoint
> +  )
> +{
> +  BOOLEAN                                NeedLoad;
> +  UINTN                                  DataSize;
> +  UINTN                                  TotalSize;
> +  CPU_MICROCODE_EXTENDED_TABLE_HEADER    *ExtendedTableHeader;
> +  UINT32                                 ExtendedTableCount;
> +  CPU_MICROCODE_EXTENDED_TABLE           *ExtendedTable;
> +  UINTN                                  Index;
> +
> +  //
> +  // Check the 'ProcessorSignature' and 'ProcessorFlags' in microcode patch header.
> +  //
> +  NeedLoad = IsProcessorMatchedMicrocodePatch (
> +               CpuIdCount,
> +               MicrocodeCpuId,
> +               MicrocodeEntryPoint->ProcessorSignature.Uint32,
> +               MicrocodeEntryPoint->ProcessorFlags
> +               );
> +
> +  //
> +  // If the Extended Signature Table exists, check if the processor is in the
> +  // support list
> +  //
> +  DataSize  = MicrocodeEntryPoint->DataSize;
> +  TotalSize = (DataSize == 0) ? 2048 : MicrocodeEntryPoint->TotalSize;
> +  if ((!NeedLoad) && (DataSize != 0) &&
> +      (TotalSize - DataSize > sizeof (CPU_MICROCODE_HEADER) +
> +                              sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER))) {
> +    ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint)
> +                            + DataSize + sizeof (CPU_MICROCODE_HEADER));
> +    ExtendedTableCount  = ExtendedTableHeader->ExtendedSignatureCount;
> +    ExtendedTable       = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);
> +
> +    for (Index = 0; Index < ExtendedTableCount; Index ++) {
> +      //
> +      // Check the 'ProcessorSignature' and 'ProcessorFlag' of the Extended
> +      // Signature Table entry with the CPUID and PlatformID of the processors
> +      // within system to decide if it will be copied into memory
> +      //
> +      NeedLoad = IsProcessorMatchedMicrocodePatch (
> +                   CpuIdCount,
> +                   MicrocodeCpuId,
> +                   ExtendedTable->ProcessorSignature.Uint32,
> +                   ExtendedTable->ProcessorFlag
> +                   );
> +      if (NeedLoad) {
> +        break;
> +      }
> +      ExtendedTable ++;
> +    }
> +  }
> +
> +  return NeedLoad;
> +}
> +
> +/**
> +  Actual worker function that shadows the required microcode patches into memory.
> +
> +  @param[in]       Patches          The pointer to an array of information on
> +                                    the microcode patches that will be loaded
> +                                    into memory.
> +  @param[in]       PatchCount       The number of microcode patches that will
> +                                    be loaded into memory.
> +  @param[in]       TotalLoadSize    The total size of all the microcode patches
> +                                    to be loaded.
> +  @param[out] BufferSize            Pointer to receive the total size of Buffer.
> +  @param[out] Buffer                Pointer to receive address of allocated memory
> +                                    with microcode patches data in it.
> +**/
> +VOID
> +ShadowMicrocodePatchWorker (
> +  IN  MICROCODE_PATCH_INFO       *Patches,
> +  IN  UINTN                      PatchCount,
> +  IN  UINTN                      TotalLoadSize,
> +  OUT UINTN                      *BufferSize,
> +  OUT VOID                       **Buffer
> +  )
> +{
> +  UINTN                                     Index;
> +  VOID                                      *MicrocodePatchInRam;
> +  UINT8                                     *Walker;
> +  EDKII_MICROCODE_SHADOW_INFO_HOB           *MicrocodeShadowHob;
> +  UINTN                                     HobDataLength;
> +  UINT64                                    *MicrocodeAddressInMemory;
> +  EFI_MICROCODE_STORAGE_TYPE_FLASH_CONTEXT  *Flashcontext;
> +
> +  ASSERT ((Patches != NULL) && (PatchCount != 0));
> +
> +  //
> +  // Init microcode shadow info HOB content.
> +  //
> +  HobDataLength = sizeof (EDKII_MICROCODE_SHADOW_INFO_HOB) +
> +                  sizeof (UINT64) * PatchCount * 2;
> +  MicrocodeShadowHob  = AllocatePool (HobDataLength);
> +  if (MicrocodeShadowHob == NULL) {
> +    ASSERT (FALSE);
> +    return;
> +  }
> +  MicrocodeShadowHob->MicrocodeCount = PatchCount;
> +  CopyGuid (
> +    &MicrocodeShadowHob->StorageType,
> +    &gEdkiiMicrocodeStorageTypeFlashGuid
> +    );
> +  MicrocodeAddressInMemory = (UINT64 *) (MicrocodeShadowHob + 1);
> +  Flashcontext = (EFI_MICROCODE_STORAGE_TYPE_FLASH_CONTEXT *) (MicrocodeAddressInMemory + PatchCount);
> +
> +  //
> +  // Allocate memory for microcode shadow operation.
> +  //
> +  MicrocodePatchInRam = AllocatePages (EFI_SIZE_TO_PAGES (TotalLoadSize));
> +  if (MicrocodePatchInRam == NULL) {
> +    ASSERT (FALSE);
> +    return;
> +  }
> +
> +  //
> +  // Shadow all the required microcode patches into memory
> +  //
> +  for (Walker = MicrocodePatchInRam, Index = 0; Index < PatchCount; Index++) {
> +    CopyMem (
> +      Walker,
> +      (VOID *) Patches[Index].Address,
> +      Patches[Index].Size
> +      );
> +    MicrocodeAddressInMemory[Index] = (UINT64) Walker;
> +    Flashcontext->MicrocodeAddressInFlash[Index]  = (UINT64) Patches[Index].Address;
> +    Walker += Patches[Index].Size;
> +  }
> +
> +  //
> +  // Update the microcode patch related fields in CpuMpData
> +  //
> +  *Buffer     = (VOID *) (UINTN) MicrocodePatchInRam;
> +  *BufferSize = TotalLoadSize;
> +
> +  BuildGuidDataHob (
> +    &gEdkiiMicrocodeShadowInfoHobGuid,
> +    MicrocodeShadowHob,
> +    HobDataLength
> +    );
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n",
> +    __FUNCTION__, *Buffer, *BufferSize
> +    ));
> +
> +  return;
> +}
> +
> +/**
> +  Check if FIT table content is valid according to FIT BIOS specification.
> +
> +**/
> +BOOLEAN
> +IsValidFitTable (
> +  IN  UINT64               FitPointer
> +  )
> +{
> +  UINT64                            FitEnding;
> +  FIRMWARE_INTERFACE_TABLE_ENTRY    *FitEntry;
> +  UINT32                            EntryNum;
> +  UINT32                            Type0Count;
> +  UINT32                            Index;
> +
> +  //
> +  // The entire FIT table must reside with in the firmware address range
> +  // of (4GB-16MB) to (4GB-40h).
> +  //
> +  if ((FitPointer < (SIZE_4GB - SIZE_16MB)) || (FitPointer >= (SIZE_4GB - 0x40))) {
> +    //
> +    // Invalid FIT address, treat it as no FIT table.
> +    //
> +    DEBUG ((DEBUG_ERROR, "Error: Invalid FIT pointer 0x%p.\n", FitPointer));
> +    return FALSE;
> +  }
> +
> +  //
> +  // Check FIT header.
> +  //
> +  FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *) (UINTN) FitPointer;
> +  if ((FitEntry[0].Type != FIT_TYPE_00_HEADER) ||
> +      (FitEntry[0].Address != FIT_TYPE_00_SIGNATURE)) {
> +    DEBUG ((DEBUG_ERROR, "Error: Invalid FIT header.\n"));
> +    return FALSE;
> +  }
> +
> +  //
> +  // Check FIT version.
> +  //
> +  if (FitEntry[0].Version != FIT_TYPE_VERSION) {
> +    DEBUG ((DEBUG_ERROR, "Error: Unsupported FIT version.\n"));
> +    return FALSE;
> +  }
> +
> +  //
> +  // Check FIT ending address in valid range.
> +  //
> +  EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;
> +  FitEnding = FitPointer + sizeof (FIRMWARE_INTERFACE_TABLE_ENTRY) * EntryNum;
> +  if (FitEnding  > (SIZE_4GB - 0x40)) {
> +    DEBUG ((DEBUG_ERROR, "Error: FIT table exceeds valid range.\n"));
> +    return FALSE;
> +  }
> +
> +  //
> +  // Calculate FIT checksum if Checksum Valid bit is set.
> +  //
> +  if (FitEntry[0].C_V &&
> +      CalculateSum8 ((UINT8*) FitEntry, sizeof (FIRMWARE_INTERFACE_TABLE_ENTRY) * EntryNum) != 0) {
> +    DEBUG ((DEBUG_ERROR, "Error: Invalid FIT checksum.\n"));
> +    return FALSE;
> +  }
> +
> +  //
> +  // Check type 0 entry count.
> +  //
> +  Type0Count = 0;
> +  for (Index = 0; Index < EntryNum; Index++) {
> +    if (FitEntry[Index].Type == FIT_TYPE_00_HEADER) {
> +      Type0Count++;
> +    }
> +  }
> +  if (Type0Count != 1) {
> +    DEBUG ((DEBUG_ERROR, "Error: There can be only one Type 0 entry in FIT.\n"));
> +    return FALSE;
> +  }
> +
> +  return TRUE;
> +}
> +
> +
> +/**
> +  Shadow microcode update patches to memory.
> +
> +  The function is used for shadowing microcode update patches to a continuous memory.
> +  It shall allocate memory buffer and only shadow the microcode patches for those
> +  processors specified by MicrocodeCpuId array. The checksum verification may be
> +  skiped in this function so the caller must perform checksum verification before
> +  using the microcode patches in returned memory buffer.
> +
> +  @param[in]  This                 The PPI instance pointer.
> +  @param[in]  CpuIdCount           Number of elements in MicrocodeCpuId array.
> +  @param[in]  MicrocodeCpuId       A pointer to an array of EDKII_PEI_MICROCODE_CPU_ID
> +                                   structures.
> +  @param[out] BufferSize           Pointer to receive the total size of Buffer.
> +  @param[out] Buffer               Pointer to receive address of allocated memory
> +                                   with microcode patches data in it.
> +
> +  @retval EFI_SUCCESS              The microcode has been shadowed to memory.
> +  @retval EFI_OUT_OF_RESOURCES     The operation fails due to lack of resources.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ShadowMicrocode (
> +  IN  EDKII_PEI_SHADOW_MICROCODE_PPI        *This,
> +  IN  UINTN                                 CpuIdCount,
> +  IN  EDKII_PEI_MICROCODE_CPU_ID            *MicrocodeCpuId,
> +  OUT UINTN                                 *BufferSize,
> +  OUT VOID                                  **Buffer
> +  )
> +{
> +  UINT64                            FitPointer;
> +  FIRMWARE_INTERFACE_TABLE_ENTRY    *FitEntry;
> +  UINT32                            EntryNum;
> +  UINT32                            Index;
> +  MICROCODE_PATCH_INFO              *PatchInfoBuffer;
> +  UINTN                             MaxPatchNumber;
> +  CPU_MICROCODE_HEADER              *MicrocodeEntryPoint;
> +  UINTN                             PatchCount;
> +  UINTN                             TotalSize;
> +  UINTN                             TotalLoadSize;
> +
> +  if (BufferSize == NULL || Buffer == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (CpuIdCount != 0 && MicrocodeCpuId == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  FitPointer = *(UINT64 *) (UINTN) FIT_POINTER_ADDRESS;
> +  if (!IsValidFitTable (FitPointer)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Calculate microcode entry number
> +  //
> +  FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *) (UINTN) FitPointer;
> +  EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;
> +  MaxPatchNumber = 0;
> +  for (Index = 0; Index < EntryNum; Index++) {
> +    if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {
> +      MaxPatchNumber++;
> +    }
> +  }
> +  if (MaxPatchNumber == 0) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  PatchInfoBuffer = AllocatePool (MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO));
> +  if (PatchInfoBuffer == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // Fill up microcode patch info buffer according to FIT table.
> +  //
> +  PatchCount = 0;
> +  TotalLoadSize = 0;
> +  for (Index = 0; Index < EntryNum; Index++) {
> +    if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {
> +      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (UINTN) FitEntry[Index].Address;
> +      TotalSize = (MicrocodeEntryPoint->DataSize == 0) ? 2048 : MicrocodeEntryPoint->TotalSize;
> +      if (IsMicrocodePatchNeedLoad (CpuIdCount, MicrocodeCpuId, MicrocodeEntryPoint)) {
> +        PatchInfoBuffer[PatchCount].Address     = (UINTN) MicrocodeEntryPoint;
> +        PatchInfoBuffer[PatchCount].Size        = TotalSize;
> +        TotalLoadSize += TotalSize;
> +        PatchCount++;
> +      }
> +    }
> +  }
> +
> +  if (PatchCount != 0) {
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "%a: 0x%x microcode patches will be loaded into memory, with size 0x%x.\n",
> +      __FUNCTION__, PatchCount, TotalLoadSize
> +      ));
> +
> +    ShadowMicrocodePatchWorker (PatchInfoBuffer, PatchCount, TotalLoadSize, BufferSize, Buffer);
> +  }
> +
> +  FreePool (PatchInfoBuffer);
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Platform Init PEI module entry point
> +
> +  @param[in]  FileHandle           Not used.
> +  @param[in]  PeiServices          General purpose services available to every PEIM.
> +
> +  @retval     EFI_SUCCESS          The function completes successfully
> +  @retval     EFI_OUT_OF_RESOURCES Insufficient resources to create database
> +**/
> +EFI_STATUS
> +EFIAPI
> +ShadowMicrocodePeimInit (
> +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
> +  IN CONST EFI_PEI_SERVICES     **PeiServices
> +  )
> +{
> +  EFI_STATUS                       Status;
> +
> +  //
> +  // Install EDKII Shadow Microcode PPI
> +  //
> +  Status = PeiServicesInstallPpi(mPeiShadowMicrocodePpiList);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return Status;
> +}
> diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.inf
> b/Silicon/Intel/IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.inf
> new file mode 100644
> index 0000000000..019400ab31
> --- /dev/null
> +++ b/Silicon/Intel/IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.inf
> @@ -0,0 +1,43 @@
> +### @file
> +# FIT based microcode shadow PEIM.
> +#
> +# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +###
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010017
> +  BASE_NAME                      = ShadowMicrocodePei
> +  FILE_GUID                      = 8af4cf68-ebe4-4b21-a008-0cb3da277be5
> +  VERSION_STRING                 = 1.0
> +  MODULE_TYPE                    = PEIM
> +  ENTRY_POINT                    = ShadowMicrocodePeimInit
> +
> +[Sources]
> +  ShadowMicrocodePei.c
> +
> +[LibraryClasses]
> +  PeimEntryPoint
> +  DebugLib
> +  MemoryAllocationLib
> +  BaseMemoryLib
> +  HobLib
> +  PeiServicesLib
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  UefiCpuPkg/UefiCpuPkg.dec
> +  IntelSiliconPkg/IntelSiliconPkg.dec
> +
> +[Ppis]
> +  gEdkiiPeiShadowMicrocodePpiGuid                     ## PRODUCES
> +
> +[Guids]
> +  gEdkiiMicrocodeShadowInfoHobGuid
> +  gEdkiiMicrocodeStorageTypeFlashGuid
> +
> +[Depex]
> +  TRUE
> diff --git a/Silicon/Intel/IntelSiliconPkg/Include/Guid/MicrocodeShadowInfoHob.h
> b/Silicon/Intel/IntelSiliconPkg/Include/Guid/MicrocodeShadowInfoHob.h
> new file mode 100644
> index 0000000000..d1a9d79a51
> --- /dev/null
> +++ b/Silicon/Intel/IntelSiliconPkg/Include/Guid/MicrocodeShadowInfoHob.h
> @@ -0,0 +1,64 @@
> +/** @file
> +  The definition for Microcode Shadow Info Hob.
> +
> +  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +
> +#ifndef _MICROCODE_SHADOW_INFO_HOB_H_
> +#define _MICROCODE_SHADOW_INFO_HOB_H_
> +
> +///
> +/// The Global ID of a GUIDed HOB used to pass microcode shadow info to DXE Driver.
> +///
> +#define EDKII_MICROCODE_SHADOW_INFO_HOB_GUID \
> +  { \
> +    0x658903f9, 0xda66, 0x460d, { 0x8b, 0xb0, 0x9d, 0x2d, 0xdf, 0x65, 0x44, 0x59 } \
> +  }
> +
> +extern EFI_GUID gEdkiiMicrocodeShadowInfoHobGuid;
> +
> +typedef struct {
> +  //
> +  // An EFI_GUID that defines the contents of StorageContext.
> +  //
> +  GUID      StorageType;
> +  //
> +  // Number of the microcode patches which have been
> +  // relocated to memory.
> +  //
> +  UINT64    MicrocodeCount;
> +  //
> +  // An array with MicrocodeCount elements that stores
> +  // the shadowed microcode patch address in memory.
> +  //
> +  UINT64    MicrocodeAddrInMemory[];
> +  //
> +  // A buffer which contains details about the storage information
> +  // specific to StorageType.
> +  //
> +  // UINT8  StorageContext[];
> +} EDKII_MICROCODE_SHADOW_INFO_HOB;
> +
> +//
> +// An EDKII_MICROCODE_SHADOW_INFO_HOB with StorageType set to below GUID will have
> +// the StorageContext of a EFI_MICROCODE_STORAGE_TYPE_FLASH_CONTEXT strucutre.
> +//
> +#define EFI_MICROCODE_STORAGE_TYPE_FLASH_GUID \
> +  { \
> +    0x2cba01b3, 0xd391, 0x4598, { 0x8d, 0x89, 0xb7, 0xfc, 0x39, 0x22, 0xfd, 0x71 } \
> +  }
> +
> +extern EFI_GUID gEdkiiMicrocodeStorageTypeFlashGuid;
> +
> +typedef struct {
> +  //
> +  // An array with MicrocodeCount elements that stores the original
> +  // microcode patch address on flash. The address is placed in same
> +  // order as the microcode patches in MicrocodeAddrInMemory.
> +  //
> +  UINT64  MicrocodeAddressInFlash[];
> +} EFI_MICROCODE_STORAGE_TYPE_FLASH_CONTEXT;
> +
> +#endif
> diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> index 22ebf19c4e..3c49fb289c 100644
> --- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> +++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> @@ -3,7 +3,7 @@
>  #
>  # This package provides common open source Intel silicon modules.
>  #
> -# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
>  ##
> @@ -48,6 +48,12 @@
>    ## HOB GUID to get memory information after MRC is done. The hob data will be used to set the PMR ranges
>    gVtdPmrInfoDataHobGuid = {0x6fb61645, 0xf168, 0x46be, { 0x80, 0xec, 0xb5, 0x02, 0x38, 0x5e, 0xe7, 0xe7 } }
> 
> +  ## Include/Guid/MicrocodeShadowInfoHob.h
> +  gEdkiiMicrocodeShadowInfoHobGuid = { 0x658903f9, 0xda66, 0x460d, { 0x8b, 0xb0, 0x9d, 0x2d, 0xdf, 0x65, 0x44, 0x59 } }
> +
> +  ## Include/Guid/MicrocodeShadowInfoHob.h
> +  gEdkiiMicrocodeStorageTypeFlashGuid = { 0x2cba01b3, 0xd391, 0x4598, { 0x8d, 0x89, 0xb7, 0xfc, 0x39, 0x22, 0xfd, 0x71 } }
> +
>  [Ppis]
>    gEdkiiVTdInfoPpiGuid = { 0x8a59fcb3, 0xf191, 0x400c, { 0x97, 0x67, 0x67, 0xaf, 0x2b, 0x25, 0x68, 0x4a } }
> 
> diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dsc b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dsc
> index 0a6509d8b3..f995883691 100644
> --- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dsc
> +++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dsc
> @@ -1,7 +1,7 @@
>  ## @file
>  # This package provides common open source Intel silicon modules.
>  #
> -# Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2017 - 2020, Intel Corporation. All rights reserved.<BR>
>  #
>  #    SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
> @@ -84,6 +84,7 @@
>    IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
>    IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf
>    IntelSiliconPkg/Feature/Capsule/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf
> +  IntelSiliconPkg/Feature/ShadowMicrocode/ShadowMicrocodePei.inf
>    IntelSiliconPkg/Library/PeiDxeSmmBootMediaLib/PeiFirmwareBootMediaLib.inf
>    IntelSiliconPkg/Library/PeiDxeSmmBootMediaLib/DxeSmmFirmwareBootMediaLib.inf
> 
> --
> 2.19.1.windows.1


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-02-19 11:25 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-02-19 11:03 [PATCH v7] IntelSiliconPkg: FIT based shadow microcode PPI support Siyuan, Fu
2020-02-19 11:25 ` Ni, Ray

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox