* [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