REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the UefiCpuPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Ray Ni <ray.ni@intel.com>
		
			
				
	
	
		
			332 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			332 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Implementation of MicrocodeLib.
 | 
						|
 | 
						|
  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include <Uefi/UefiBaseType.h>
 | 
						|
#include <Register/Intel/Cpuid.h>
 | 
						|
#include <Register/Intel/ArchitecturalMsr.h>
 | 
						|
#include <Register/Intel/Microcode.h>
 | 
						|
#include <Library/BaseLib.h>
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
#include <Ppi/ShadowMicrocode.h>
 | 
						|
 | 
						|
/**
 | 
						|
  Get microcode update signature of currently loaded microcode update.
 | 
						|
 | 
						|
  @return  Microcode signature.
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
EFIAPI
 | 
						|
GetProcessorMicrocodeSignature (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  MSR_IA32_BIOS_SIGN_ID_REGISTER  BiosSignIdMsr;
 | 
						|
 | 
						|
  AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID, 0);
 | 
						|
  AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, NULL);
 | 
						|
  BiosSignIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_BIOS_SIGN_ID);
 | 
						|
  return BiosSignIdMsr.Bits.MicrocodeUpdateSignature;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the processor signature and platform ID for current processor.
 | 
						|
 | 
						|
  @param MicrocodeCpuId  Return the processor signature and platform ID.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
GetProcessorMicrocodeCpuId (
 | 
						|
  EDKII_PEI_MICROCODE_CPU_ID  *MicrocodeCpuId
 | 
						|
  )
 | 
						|
{
 | 
						|
  MSR_IA32_PLATFORM_ID_REGISTER  PlatformIdMsr;
 | 
						|
 | 
						|
  ASSERT (MicrocodeCpuId != NULL);
 | 
						|
 | 
						|
  PlatformIdMsr.Uint64       = AsmReadMsr64 (MSR_IA32_PLATFORM_ID);
 | 
						|
  MicrocodeCpuId->PlatformId = (UINT8)PlatformIdMsr.Bits.PlatformId;
 | 
						|
  AsmCpuid (CPUID_VERSION_INFO, &MicrocodeCpuId->ProcessorSignature, NULL, NULL, NULL);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return the total size of the microcode entry.
 | 
						|
 | 
						|
  Logic follows pseudo code in SDM as below:
 | 
						|
 | 
						|
     N = 512
 | 
						|
     If (Update.DataSize != 00000000H)
 | 
						|
       N = Update.TotalSize / 4
 | 
						|
 | 
						|
  If Microcode is NULL, then ASSERT.
 | 
						|
 | 
						|
  @param Microcode  Pointer to the microcode entry.
 | 
						|
 | 
						|
  @return The microcode total size.
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
EFIAPI
 | 
						|
GetMicrocodeLength (
 | 
						|
  IN CPU_MICROCODE_HEADER  *Microcode
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32  TotalSize;
 | 
						|
 | 
						|
  ASSERT (Microcode != NULL);
 | 
						|
 | 
						|
  TotalSize = 2048;
 | 
						|
  if (Microcode->DataSize != 0) {
 | 
						|
    TotalSize = Microcode->TotalSize;
 | 
						|
  }
 | 
						|
 | 
						|
  return TotalSize;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Load the microcode to the processor.
 | 
						|
 | 
						|
  If Microcode is NULL, then ASSERT.
 | 
						|
 | 
						|
  @param Microcode  Pointer to the microcode entry.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
LoadMicrocode (
 | 
						|
  IN CPU_MICROCODE_HEADER  *Microcode
 | 
						|
  )
 | 
						|
{
 | 
						|
  ASSERT (Microcode != NULL);
 | 
						|
 | 
						|
  AsmWriteMsr64 (MSR_IA32_BIOS_UPDT_TRIG, (UINT64)(UINTN)(Microcode + 1));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Determine if a microcode patch matchs the specific processor signature and flag.
 | 
						|
 | 
						|
  @param[in]  ProcessorSignature    The processor signature field value in a
 | 
						|
                                    microcode patch.
 | 
						|
  @param[in]  ProcessorFlags        The processor flags field value in a
 | 
						|
                                    microcode patch.
 | 
						|
  @param[in]  MicrocodeCpuId        A pointer to an array of EDKII_PEI_MICROCODE_CPU_ID
 | 
						|
                                    structures.
 | 
						|
  @param[in]  MicrocodeCpuIdCount   Number of elements in MicrocodeCpuId array.
 | 
						|
 | 
						|
  @retval TRUE     The specified microcode patch matches to one of the MicrocodeCpuId.
 | 
						|
  @retval FALSE    The specified microcode patch doesn't match to any of the MicrocodeCpuId.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsProcessorMatchedMicrocode (
 | 
						|
  IN UINT32                      ProcessorSignature,
 | 
						|
  IN UINT32                      ProcessorFlags,
 | 
						|
  IN EDKII_PEI_MICROCODE_CPU_ID  *MicrocodeCpuId,
 | 
						|
  IN UINTN                       MicrocodeCpuIdCount
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  Index;
 | 
						|
 | 
						|
  if (MicrocodeCpuIdCount == 0) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < MicrocodeCpuIdCount; Index++) {
 | 
						|
    if ((ProcessorSignature == MicrocodeCpuId[Index].ProcessorSignature) &&
 | 
						|
        ((ProcessorFlags & (1 << MicrocodeCpuId[Index].PlatformId)) != 0))
 | 
						|
    {
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Detect whether specified processor can find matching microcode patch and load it.
 | 
						|
 | 
						|
  Microcode format is as below:
 | 
						|
  +----------------------------------------+-------------------------------------------------+
 | 
						|
  |          CPU_MICROCODE_HEADER          |                                                 |
 | 
						|
  +----------------------------------------+                                                 V
 | 
						|
  |              Update Data               |                                               CPU_MICROCODE_HEADER.Checksum
 | 
						|
  +----------------------------------------+-------+                                         ^
 | 
						|
  |  CPU_MICROCODE_EXTENDED_TABLE_HEADER   |       |                                         |
 | 
						|
  +----------------------------------------+       V                                         |
 | 
						|
  |      CPU_MICROCODE_EXTENDED_TABLE[0]   |  CPU_MICROCODE_EXTENDED_TABLE_HEADER.Checksum   |
 | 
						|
  |      CPU_MICROCODE_EXTENDED_TABLE[1]   |       ^                                         |
 | 
						|
  |                   ...                  |       |                                         |
 | 
						|
  +----------------------------------------+-------+-----------------------------------------+
 | 
						|
 | 
						|
  There may by multiple CPU_MICROCODE_EXTENDED_TABLE in this format.
 | 
						|
  The count of CPU_MICROCODE_EXTENDED_TABLE is indicated by ExtendedSignatureCount
 | 
						|
  of CPU_MICROCODE_EXTENDED_TABLE_HEADER structure.
 | 
						|
 | 
						|
  If Microcode is NULL, then ASSERT.
 | 
						|
 | 
						|
  @param Microcode            Pointer to a microcode entry.
 | 
						|
  @param MicrocodeLength      The total length of the microcode entry.
 | 
						|
  @param MinimumRevision      The microcode whose revision <= MinimumRevision is treated as invalid.
 | 
						|
                              Caller can supply value get from GetProcessorMicrocodeSignature() to check
 | 
						|
                              whether the microcode is newer than loaded one.
 | 
						|
                              Caller can supply 0 to treat any revision (except 0) microcode as valid.
 | 
						|
  @param MicrocodeCpuIds      Pointer to an array of processor signature and platform ID that represents
 | 
						|
                              a set of processors.
 | 
						|
                              Caller can supply zero-element array to skip the processor signature and
 | 
						|
                              platform ID check.
 | 
						|
  @param MicrocodeCpuIdCount  The number of elements in MicrocodeCpuIds.
 | 
						|
  @param VerifyChecksum       FALSE to skip all the checksum verifications.
 | 
						|
 | 
						|
  @retval TRUE  The microcode is valid.
 | 
						|
  @retval FALSE The microcode is invalid.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
EFIAPI
 | 
						|
IsValidMicrocode (
 | 
						|
  IN CPU_MICROCODE_HEADER        *Microcode,
 | 
						|
  IN UINTN                       MicrocodeLength,
 | 
						|
  IN UINT32                      MinimumRevision,
 | 
						|
  IN EDKII_PEI_MICROCODE_CPU_ID  *MicrocodeCpuIds,
 | 
						|
  IN UINTN                       MicrocodeCpuIdCount,
 | 
						|
  IN BOOLEAN                     VerifyChecksum
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                                Index;
 | 
						|
  UINT32                               DataSize;
 | 
						|
  UINT32                               TotalSize;
 | 
						|
  CPU_MICROCODE_EXTENDED_TABLE         *ExtendedTable;
 | 
						|
  CPU_MICROCODE_EXTENDED_TABLE_HEADER  *ExtendedTableHeader;
 | 
						|
  UINT32                               ExtendedTableLength;
 | 
						|
  UINT32                               Sum32;
 | 
						|
  BOOLEAN                              Match;
 | 
						|
 | 
						|
  ASSERT (Microcode != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // It's invalid when:
 | 
						|
  //   the input microcode buffer is so small that even cannot contain the header.
 | 
						|
  //   the input microcode buffer is so large that exceeds MAX_ADDRESS.
 | 
						|
  //
 | 
						|
  if ((MicrocodeLength < sizeof (CPU_MICROCODE_HEADER)) || (MicrocodeLength > (MAX_ADDRESS - (UINTN)Microcode))) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Per SDM, HeaderVersion and LoaderRevision should both be 1.
 | 
						|
  //
 | 
						|
  if ((Microcode->HeaderVersion != 1) || (Microcode->LoaderRevision != 1)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // The microcode revision should be larger than the minimum revision.
 | 
						|
  //
 | 
						|
  if (Microcode->UpdateRevision <= MinimumRevision) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  DataSize = Microcode->DataSize;
 | 
						|
  if (DataSize == 0) {
 | 
						|
    DataSize = 2000;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Per SDM, DataSize should be multiple of DWORDs.
 | 
						|
  //
 | 
						|
  if ((DataSize % 4) != 0) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  TotalSize = GetMicrocodeLength (Microcode);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check whether the whole microcode is within the buffer.
 | 
						|
  // TotalSize should be multiple of 1024.
 | 
						|
  //
 | 
						|
  if (((TotalSize % SIZE_1KB) != 0) || (TotalSize > MicrocodeLength)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // The summation of all DWORDs in microcode should be zero.
 | 
						|
  //
 | 
						|
  if (VerifyChecksum && (CalculateSum32 ((UINT32 *)Microcode, TotalSize) != 0)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  Sum32 = Microcode->ProcessorSignature.Uint32 + Microcode->ProcessorFlags + Microcode->Checksum;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check the processor signature and platform ID in the primary header.
 | 
						|
  //
 | 
						|
  Match = IsProcessorMatchedMicrocode (
 | 
						|
            Microcode->ProcessorSignature.Uint32,
 | 
						|
            Microcode->ProcessorFlags,
 | 
						|
            MicrocodeCpuIds,
 | 
						|
            MicrocodeCpuIdCount
 | 
						|
            );
 | 
						|
  if (Match) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  ExtendedTableLength = TotalSize - (DataSize + sizeof (CPU_MICROCODE_HEADER));
 | 
						|
  if ((ExtendedTableLength < sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER)) || ((ExtendedTableLength % 4) != 0)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Extended Table exist, check if the CPU in support list
 | 
						|
  //
 | 
						|
  ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *)((UINTN)(Microcode + 1) + DataSize);
 | 
						|
  if (ExtendedTableHeader->ExtendedSignatureCount > MAX_UINT32 / sizeof (CPU_MICROCODE_EXTENDED_TABLE)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ExtendedTableHeader->ExtendedSignatureCount * sizeof (CPU_MICROCODE_EXTENDED_TABLE)
 | 
						|
      > ExtendedTableLength - sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER))
 | 
						|
  {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check the extended table checksum
 | 
						|
  //
 | 
						|
  if (VerifyChecksum && (CalculateSum32 ((UINT32 *)ExtendedTableHeader, ExtendedTableLength) != 0)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  ExtendedTable = (CPU_MICROCODE_EXTENDED_TABLE *)(ExtendedTableHeader + 1);
 | 
						|
  for (Index = 0; Index < ExtendedTableHeader->ExtendedSignatureCount; Index++) {
 | 
						|
    if (VerifyChecksum &&
 | 
						|
        (ExtendedTable[Index].ProcessorSignature.Uint32 + ExtendedTable[Index].ProcessorFlag
 | 
						|
         + ExtendedTable[Index].Checksum != Sum32))
 | 
						|
    {
 | 
						|
      //
 | 
						|
      // The extended table entry is valid when the summation of Processor Signature, Processor Flags
 | 
						|
      // and Checksum equal to the coresponding summation from primary header. Because:
 | 
						|
      //    CalculateSum32 (Header + Update Binary) == 0
 | 
						|
      //    CalculateSum32 (Header + Update Binary)
 | 
						|
      //        - (Header.ProcessorSignature + Header.ProcessorFlag + Header.Checksum)
 | 
						|
      //        + (Extended.ProcessorSignature + Extended.ProcessorFlag + Extended.Checksum) == 0
 | 
						|
      // So,
 | 
						|
      //    (Header.ProcessorSignature + Header.ProcessorFlag + Header.Checksum)
 | 
						|
      //     == (Extended.ProcessorSignature + Extended.ProcessorFlag + Extended.Checksum)
 | 
						|
      //
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    Match = IsProcessorMatchedMicrocode (
 | 
						|
              ExtendedTable[Index].ProcessorSignature.Uint32,
 | 
						|
              ExtendedTable[Index].ProcessorFlag,
 | 
						|
              MicrocodeCpuIds,
 | 
						|
              MicrocodeCpuIdCount
 | 
						|
              );
 | 
						|
    if (Match) {
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 |