123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- /** @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;
- }
|