1882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao/** @file 2882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao SetImage instance to update Microcode. 3882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 4882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Caution: This module requires additional review when modified. 5882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao This module will have external input - capsule image. 6882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao This external input must be validated carefully to avoid security issue like 7882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao buffer overflow, integer overflow. 8882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 9882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao MicrocodeWrite() and VerifyMicrocode() will receive untrusted input and do basic validation. 10882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 11882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> 12882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao This program and the accompanying materials 13882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao are licensed and made available under the terms and conditions of the BSD License 14882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao which accompanies this distribution. The full text of the license may be found at 15882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao http://opensource.org/licenses/bsd-license.php 16882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 17882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 18882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 19882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 20882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao**/ 21882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 22882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao#include "MicrocodeUpdate.h" 23882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 24882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao/** 25882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Get Microcode Region. 26882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 27882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @param[out] MicrocodePatchAddress The address of Microcode 28882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @param[out] MicrocodePatchRegionSize The region size of Microcode 29882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 30882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @retval TRUE The Microcode region is returned. 31882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @retval FALSE No Microcode region. 32882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao**/ 33882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoBOOLEAN 34882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoGetMicrocodeRegion ( 352ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao OUT VOID **MicrocodePatchAddress, 362ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao OUT UINTN *MicrocodePatchRegionSize 37882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ) 38882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao{ 392ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao *MicrocodePatchAddress = (VOID *)(UINTN)PcdGet64(PcdCpuMicrocodePatchAddress); 402ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao *MicrocodePatchRegionSize = (UINTN)PcdGet64(PcdCpuMicrocodePatchRegionSize); 41882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 422ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao if ((*MicrocodePatchAddress == NULL) || (*MicrocodePatchRegionSize == 0)) { 43882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return FALSE; 44882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 45882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 46882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return TRUE; 47882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao} 48882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 49882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao/** 50882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Get Microcode update signature of currently loaded Microcode update. 51882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 52882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @return Microcode signature. 53882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 54882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao**/ 55882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoUINT32 56882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoGetCurrentMicrocodeSignature ( 57882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao VOID 58882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ) 59882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao{ 60882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao UINT64 Signature; 61882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 62882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao AsmWriteMsr64(MSR_IA32_BIOS_SIGN_ID, 0); 63882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao AsmCpuid(CPUID_VERSION_INFO, NULL, NULL, NULL, NULL); 64882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Signature = AsmReadMsr64(MSR_IA32_BIOS_SIGN_ID); 65882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return (UINT32)RShiftU64(Signature, 32); 66882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao} 67882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 68882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao/** 69882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Get current processor signature. 70882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 71882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @return current processor signature. 72882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao**/ 73882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoUINT32 74882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoGetCurrentProcessorSignature ( 75882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao VOID 76882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ) 77882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao{ 78882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao UINT32 RegEax; 79882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao AsmCpuid(CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL); 80882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return RegEax; 81882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao} 82882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 83882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao/** 84882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Get current platform ID. 85882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 86882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @return current platform ID. 87882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao**/ 88882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoUINT8 89882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoGetCurrentPlatformId ( 90882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao VOID 91882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ) 92882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao{ 93882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao UINT8 PlatformId; 94882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 95882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao PlatformId = (UINT8)AsmMsrBitFieldRead64(MSR_IA32_PLATFORM_ID, 50, 52); 96882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return PlatformId; 97882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao} 98882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 99882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao/** 100882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Load new Microcode. 101882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 102882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @param[in] Address The address of new Microcode. 103882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 104882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @return Loaded Microcode signature. 105882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 106882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao**/ 107882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoUINT32 108882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoLoadMicrocode ( 109882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao IN UINT64 Address 110882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ) 111882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao{ 112882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao AsmWriteMsr64(MSR_IA32_BIOS_UPDT_TRIG, Address); 113882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return GetCurrentMicrocodeSignature(); 114882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao} 115882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 116882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao/** 11731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao Load Microcode on an Application Processor. 11831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao The function prototype for invoking a function on an Application Processor. 11931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao 12031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @param[in,out] Buffer The pointer to private data buffer. 12131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao**/ 12231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen YaoVOID 12331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen YaoEFIAPI 12431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen YaoMicrocodeLoadAp ( 12531d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao IN OUT VOID *Buffer 12631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ) 12731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao{ 12831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao MICROCODE_LOAD_BUFFER *MicrocodeLoadBuffer; 12931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao 13031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao MicrocodeLoadBuffer = Buffer; 13131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao MicrocodeLoadBuffer->Revision = LoadMicrocode (MicrocodeLoadBuffer->Address); 13231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao} 13331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao 13431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao/** 13531d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao Load new Microcode on this processor 1362ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 13731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @param[in] MicrocodeFmpPrivate The Microcode driver private data 13831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @param[in] CpuIndex The index of the processor. 13931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @param[in] Address The address of new Microcode. 14031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao 14131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @return Loaded Microcode signature. 1422ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 1432ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao**/ 14431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen YaoUINT32 14531d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen YaoLoadMicrocodeOnThis ( 14631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate, 14731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao IN UINTN CpuIndex, 14831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao IN UINT64 Address 1492ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao ) 1502ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao{ 15131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao EFI_STATUS Status; 15231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao EFI_MP_SERVICES_PROTOCOL *MpService; 15331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao MICROCODE_LOAD_BUFFER MicrocodeLoadBuffer; 1542ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 15531d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao if (CpuIndex == MicrocodeFmpPrivate->BspIndex) { 15631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao return LoadMicrocode (Address); 15731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao } else { 15831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao MpService = MicrocodeFmpPrivate->MpService; 15931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao MicrocodeLoadBuffer.Address = Address; 16031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao MicrocodeLoadBuffer.Revision = 0; 16131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao Status = MpService->StartupThisAP ( 16231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao MpService, 16331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao MicrocodeLoadAp, 16431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao CpuIndex, 16531d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao NULL, 16631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao 0, 16731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao &MicrocodeLoadBuffer, 16831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao NULL 16931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ); 17031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ASSERT_EFI_ERROR(Status); 17131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao return MicrocodeLoadBuffer.Revision; 1722ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 17331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao} 17431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao 17531d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao/** 17631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao Collect processor information. 17731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao The function prototype for invoking a function on an Application Processor. 17831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao 17931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @param[in,out] Buffer The pointer to private data buffer. 18031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao**/ 18131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen YaoVOID 18231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen YaoEFIAPI 18331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen YaoCollectProcessorInfo ( 18431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao IN OUT VOID *Buffer 18531d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ) 18631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao{ 18731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao PROCESSOR_INFO *ProcessorInfo; 18831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao 18931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ProcessorInfo = Buffer; 19031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ProcessorInfo->ProcessorSignature = GetCurrentProcessorSignature(); 19131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ProcessorInfo->PlatformId = GetCurrentPlatformId(); 19231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ProcessorInfo->MicrocodeRevision = GetCurrentMicrocodeSignature(); 1932ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao} 1942ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 1952ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao/** 196882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Get current Microcode information. 197882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 19831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao The ProcessorInformation (BspIndex/ProcessorCount/ProcessorInfo) 19931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao in MicrocodeFmpPrivate must be initialized. 20031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao 20131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao The MicrocodeInformation (DescriptorCount/ImageDescriptor/MicrocodeInfo) 20231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao in MicrocodeFmpPrivate may not be avaiable in this function. 2032ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 2042ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @param[in] MicrocodeFmpPrivate The Microcode driver private data 2052ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @param[in] DescriptorCount The count of Microcode ImageDescriptor allocated. 2062ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @param[out] ImageDescriptor Microcode ImageDescriptor 2072ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @param[out] MicrocodeInfo Microcode information 208882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 209882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @return Microcode count 210882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao**/ 211882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoUINTN 212882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoGetMicrocodeInfo ( 2132ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate, 2142ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao IN UINTN DescriptorCount, OPTIONAL 215882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor, OPTIONAL 2162ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao OUT MICROCODE_INFO *MicrocodeInfo OPTIONAL 217882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ) 218882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao{ 2192ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao VOID *MicrocodePatchAddress; 2202ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao UINTN MicrocodePatchRegionSize; 221882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao CPU_MICROCODE_HEADER *MicrocodeEntryPoint; 222882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao UINTN MicrocodeEnd; 223882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao UINTN TotalSize; 224882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao UINTN Count; 225882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao UINT64 ImageAttributes; 2262ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao BOOLEAN IsInUse; 22731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao EFI_STATUS Status; 22831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao UINT32 AttemptStatus; 22931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao UINTN TargetCpuIndex; 230882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 2312ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress; 2322ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize; 2332ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 2342ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao DEBUG((DEBUG_INFO, "Microcode Region - 0x%x - 0x%x\n", MicrocodePatchAddress, MicrocodePatchRegionSize)); 235882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 236882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Count = 0; 237882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 2382ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao MicrocodeEnd = (UINTN)MicrocodePatchAddress + MicrocodePatchRegionSize; 239882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (UINTN) MicrocodePatchAddress; 240882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao do { 241882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (MicrocodeEntryPoint->HeaderVersion == 0x1 && MicrocodeEntryPoint->LoaderRevision == 0x1) { 242882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 243882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // It is the microcode header. It is not the padding data between microcode patches 244882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // becasue the padding data should not include 0x00000001 and it should be the repeated 245882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // byte format (like 0xXYXYXYXY....). 246882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 247882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (MicrocodeEntryPoint->DataSize == 0) { 248882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao TotalSize = 2048; 249882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } else { 250882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao TotalSize = MicrocodeEntryPoint->TotalSize; 251882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 252882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 25331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao TargetCpuIndex = (UINTN)-1; 25431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao Status = VerifyMicrocode(MicrocodeFmpPrivate, MicrocodeEntryPoint, TotalSize, FALSE, &AttemptStatus, NULL, &TargetCpuIndex); 25531d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao if (!EFI_ERROR(Status)) { 25631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao IsInUse = TRUE; 25731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ASSERT (TargetCpuIndex < MicrocodeFmpPrivate->ProcessorCount); 25831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao MicrocodeFmpPrivate->ProcessorInfo[TargetCpuIndex].MicrocodeIndex = Count; 25931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao } else { 26031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao IsInUse = FALSE; 26131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao } 2622ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 263882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (ImageDescriptor != NULL && DescriptorCount > Count) { 264882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ImageDescriptor[Count].ImageIndex = (UINT8)(Count + 1); 265882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao CopyGuid (&ImageDescriptor[Count].ImageTypeId, &gMicrocodeFmpImageTypeIdGuid); 266882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ImageDescriptor[Count].ImageId = LShiftU64(MicrocodeEntryPoint->ProcessorFlags, 32) + MicrocodeEntryPoint->ProcessorSignature.Uint32; 267882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ImageDescriptor[Count].ImageIdName = NULL; 268882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ImageDescriptor[Count].Version = MicrocodeEntryPoint->UpdateRevision; 269882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ImageDescriptor[Count].VersionName = NULL; 270882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ImageDescriptor[Count].Size = TotalSize; 271882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ImageAttributes = IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | IMAGE_ATTRIBUTE_RESET_REQUIRED; 2722ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao if (IsInUse) { 273882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ImageAttributes |= IMAGE_ATTRIBUTE_IN_USE; 274882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 275882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ImageDescriptor[Count].AttributesSupported = ImageAttributes | IMAGE_ATTRIBUTE_IN_USE; 276882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ImageDescriptor[Count].AttributesSetting = ImageAttributes; 277882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ImageDescriptor[Count].Compatibilities = 0; 278882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ImageDescriptor[Count].LowestSupportedImageVersion = MicrocodeEntryPoint->UpdateRevision; // do not support rollback 279882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ImageDescriptor[Count].LastAttemptVersion = 0; 280882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ImageDescriptor[Count].LastAttemptStatus = 0; 281882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ImageDescriptor[Count].HardwareInstance = 0; 282882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 2832ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao if (MicrocodeInfo != NULL && DescriptorCount > Count) { 2842ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao MicrocodeInfo[Count].MicrocodeEntryPoint = MicrocodeEntryPoint; 2852ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao MicrocodeInfo[Count].TotalSize = TotalSize; 2862ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao MicrocodeInfo[Count].InUse = IsInUse; 2872ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 288882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } else { 289882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 290882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // It is the padding data between the microcode patches for microcode patches alignment. 291882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // Because the microcode patch is the multiple of 1-KByte, the padding data should not 292882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode 293882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to 294882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // find the next possible microcode patch header. 295882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 296882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB); 297882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao continue; 298882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 299882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 300882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Count++; 301882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ASSERT(Count < 0xFF); 302882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 303882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 304882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // Get the next patch. 305882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 306882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + TotalSize); 307882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd)); 308882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 309882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return Count; 310882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao} 311882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 312882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao/** 31331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao Return matched processor information. 31431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao 31531d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @param[in] MicrocodeFmpPrivate The Microcode driver private data 31631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @param[in] ProcessorSignature The processor signature to be matched 31731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @param[in] ProcessorFlags The processor flags to be matched 31831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @param[in, out] TargetCpuIndex On input, the index of target CPU which tries to match the Microcode. (UINTN)-1 means to try all. 31931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao On output, the index of target CPU which matches the Microcode. 32031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao 32131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @return matched processor information. 32231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao**/ 32331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen YaoPROCESSOR_INFO * 32431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen YaoGetMatchedProcessor ( 32531d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate, 32631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao IN UINT32 ProcessorSignature, 32731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao IN UINT32 ProcessorFlags, 32831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao IN OUT UINTN *TargetCpuIndex 32931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ) 33031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao{ 33131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao UINTN Index; 33231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao 33331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao if (*TargetCpuIndex != (UINTN)-1) { 33431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao Index = *TargetCpuIndex; 33531d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao if ((ProcessorSignature == MicrocodeFmpPrivate->ProcessorInfo[Index].ProcessorSignature) && 33631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ((ProcessorFlags & (1 << MicrocodeFmpPrivate->ProcessorInfo[Index].PlatformId)) != 0)) { 33731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao return &MicrocodeFmpPrivate->ProcessorInfo[Index]; 33831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao } else { 33931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao return NULL; 34031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao } 34131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao } 34231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao 34331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao for (Index = 0; Index < MicrocodeFmpPrivate->ProcessorCount; Index++) { 34431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao if ((ProcessorSignature == MicrocodeFmpPrivate->ProcessorInfo[Index].ProcessorSignature) && 34531d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ((ProcessorFlags & (1 << MicrocodeFmpPrivate->ProcessorInfo[Index].PlatformId)) != 0)) { 34631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao *TargetCpuIndex = Index; 34731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao return &MicrocodeFmpPrivate->ProcessorInfo[Index]; 34831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao } 34931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao } 35031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao return NULL; 35131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao} 35231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao 35331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao/** 354882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Verify Microcode. 355882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 356882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Caution: This function may receive untrusted input. 357882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 35831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @param[in] MicrocodeFmpPrivate The Microcode driver private data 35931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @param[in] Image The Microcode image buffer. 36031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @param[in] ImageSize The size of Microcode image buffer in bytes. 36131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @param[in] TryLoad Try to load Microcode or not. 36231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. 36331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more 36431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao details for the aborted operation. The buffer is allocated by this function 36531d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao with AllocatePool(), and it is the caller's responsibility to free it with a 36631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao call to FreePool(). 36731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @param[in, out] TargetCpuIndex On input, the index of target CPU which tries to match the Microcode. (UINTN)-1 means to try all. 36831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao On output, the index of target CPU which matches the Microcode. 369882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 370882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @retval EFI_SUCCESS The Microcode image passes verification. 371882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @retval EFI_VOLUME_CORRUPTED The Microcode image is corrupt. 372882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @retval EFI_INCOMPATIBLE_VERSION The Microcode image version is incorrect. 373882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @retval EFI_UNSUPPORTED The Microcode ProcessorSignature or ProcessorFlags is incorrect. 374882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @retval EFI_SECURITY_VIOLATION The Microcode image fails to load. 375882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao**/ 376882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoEFI_STATUS 377882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoVerifyMicrocode ( 37831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate, 37931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao IN VOID *Image, 38031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao IN UINTN ImageSize, 38131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao IN BOOLEAN TryLoad, 38231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao OUT UINT32 *LastAttemptStatus, 38331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao OUT CHAR16 **AbortReason, OPTIONAL 38431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao IN OUT UINTN *TargetCpuIndex 385882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ) 386882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao{ 387882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao UINTN Index; 388882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao CPU_MICROCODE_HEADER *MicrocodeEntryPoint; 389882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao UINTN TotalSize; 390882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao UINTN DataSize; 391882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao UINT32 CurrentRevision; 39231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao PROCESSOR_INFO *ProcessorInfo; 393882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao UINT32 CheckSum32; 394882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao UINTN ExtendedTableLength; 395882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao UINT32 ExtendedTableCount; 396882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable; 397882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader; 398882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao BOOLEAN CorrectMicrocode; 399882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 400882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 401882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // Check HeaderVersion 402882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 403882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao MicrocodeEntryPoint = Image; 404882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (MicrocodeEntryPoint->HeaderVersion != 0x1) { 405882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on HeaderVersion\n")); 406882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT; 407882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (AbortReason != NULL) { 408882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *AbortReason = AllocateCopyPool(sizeof(L"InvalidHeaderVersion"), L"InvalidHeaderVersion"); 409882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 410882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return EFI_INCOMPATIBLE_VERSION; 411882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 412882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 413882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // Check LoaderRevision 414882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 415882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (MicrocodeEntryPoint->LoaderRevision != 0x1) { 416882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on LoaderRevision\n")); 417882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT; 418882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (AbortReason != NULL) { 419882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *AbortReason = AllocateCopyPool(sizeof(L"InvalidLoaderVersion"), L"InvalidLoaderVersion"); 420882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 421882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return EFI_INCOMPATIBLE_VERSION; 422882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 423882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 424882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // Check Size 425882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 426882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (MicrocodeEntryPoint->DataSize == 0) { 427882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao TotalSize = 2048; 428882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } else { 429882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao TotalSize = MicrocodeEntryPoint->TotalSize; 430882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 431882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (TotalSize <= sizeof(CPU_MICROCODE_HEADER)) { 432882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao DEBUG((DEBUG_ERROR, "VerifyMicrocode - TotalSize too small\n")); 433882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT; 434882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (AbortReason != NULL) { 435882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *AbortReason = AllocateCopyPool(sizeof(L"InvalidTotalSize"), L"InvalidTotalSize"); 436882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 437882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return EFI_VOLUME_CORRUPTED; 438882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 439882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (TotalSize != ImageSize) { 440882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on TotalSize\n")); 441882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT; 442882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (AbortReason != NULL) { 443882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *AbortReason = AllocateCopyPool(sizeof(L"InvalidTotalSize"), L"InvalidTotalSize"); 444882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 445882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return EFI_VOLUME_CORRUPTED; 446882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 447882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 448882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // Check CheckSum32 449882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 450882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (MicrocodeEntryPoint->DataSize == 0) { 451882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao DataSize = 2048 - sizeof(CPU_MICROCODE_HEADER); 452882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } else { 453882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao DataSize = MicrocodeEntryPoint->DataSize; 454882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 455882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (DataSize > TotalSize - sizeof(CPU_MICROCODE_HEADER)) { 456882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao DEBUG((DEBUG_ERROR, "VerifyMicrocode - DataSize too big\n")); 457882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT; 458882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (AbortReason != NULL) { 459882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *AbortReason = AllocateCopyPool(sizeof(L"InvalidDataSize"), L"InvalidDataSize"); 460882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 461882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return EFI_VOLUME_CORRUPTED; 462882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 463882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if ((DataSize & 0x3) != 0) { 464882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao DEBUG((DEBUG_ERROR, "VerifyMicrocode - DataSize not aligned\n")); 465882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT; 466882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (AbortReason != NULL) { 467882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *AbortReason = AllocateCopyPool(sizeof(L"InvalidDataSize"), L"InvalidDataSize"); 468882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 469882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return EFI_VOLUME_CORRUPTED; 470882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 471882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao CheckSum32 = CalculateSum32((UINT32 *)MicrocodeEntryPoint, DataSize + sizeof(CPU_MICROCODE_HEADER)); 472882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (CheckSum32 != 0) { 473882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on CheckSum32\n")); 474882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT; 475882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (AbortReason != NULL) { 476882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *AbortReason = AllocateCopyPool(sizeof(L"InvalidChecksum"), L"InvalidChecksum"); 477882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 478882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return EFI_VOLUME_CORRUPTED; 479882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 480882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 481882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 482882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // Check ProcessorSignature/ProcessorFlags 483882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 48431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao 48531d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ProcessorInfo = GetMatchedProcessor (MicrocodeFmpPrivate, MicrocodeEntryPoint->ProcessorSignature.Uint32, MicrocodeEntryPoint->ProcessorFlags, TargetCpuIndex); 48631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao if (ProcessorInfo == NULL) { 48731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao CorrectMicrocode = FALSE; 488882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ExtendedTableLength = TotalSize - (DataSize + sizeof(CPU_MICROCODE_HEADER)); 489882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (ExtendedTableLength != 0) { 490882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 491882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // Extended Table exist, check if the CPU in support list 492882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 493882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *)((UINT8 *)(MicrocodeEntryPoint) + DataSize + sizeof(CPU_MICROCODE_HEADER)); 494882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 495882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // Calculate Extended Checksum 496882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 497882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if ((ExtendedTableLength > sizeof(CPU_MICROCODE_EXTENDED_TABLE_HEADER)) && ((ExtendedTableLength & 0x3) != 0)) { 498882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao CheckSum32 = CalculateSum32((UINT32 *)ExtendedTableHeader, ExtendedTableLength); 499882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (CheckSum32 == 0) { 500882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 501882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // Checksum correct 502882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 503882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount; 504882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (ExtendedTableCount <= (ExtendedTableLength - sizeof(CPU_MICROCODE_EXTENDED_TABLE_HEADER)) / sizeof(CPU_MICROCODE_EXTENDED_TABLE)) { 505882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ExtendedTable = (CPU_MICROCODE_EXTENDED_TABLE *)(ExtendedTableHeader + 1); 506882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao for (Index = 0; Index < ExtendedTableCount; Index++) { 507882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao CheckSum32 = CalculateSum32((UINT32 *)ExtendedTable, sizeof(CPU_MICROCODE_EXTENDED_TABLE)); 508882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (CheckSum32 == 0) { 509882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 510882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // Verify Header 511882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 51231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ProcessorInfo = GetMatchedProcessor (MicrocodeFmpPrivate, ExtendedTable->ProcessorSignature.Uint32, ExtendedTable->ProcessorFlag, TargetCpuIndex); 51331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao if (ProcessorInfo != NULL) { 514882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 515882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // Find one 516882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 517882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao CorrectMicrocode = TRUE; 518882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao break; 519882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 520882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 521882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ExtendedTable++; 522882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 523882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 524882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 525882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 526882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 527882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (!CorrectMicrocode) { 5282ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao if (TryLoad) { 5292ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on CurrentProcessorSignature/ProcessorFlags\n")); 5302ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 531882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION; 532882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (AbortReason != NULL) { 53331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao *AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessSignature/ProcessorFlags"), L"UnsupportedProcessSignature/ProcessorFlags"); 534882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 535882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return EFI_UNSUPPORTED; 536882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 537882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 538882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 539882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 540882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // Check UpdateRevision 541882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 54231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao CurrentRevision = ProcessorInfo->MicrocodeRevision; 54331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao if ((MicrocodeEntryPoint->UpdateRevision < CurrentRevision) || 54431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao (TryLoad && (MicrocodeEntryPoint->UpdateRevision == CurrentRevision))) { 5452ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao if (TryLoad) { 5462ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on UpdateRevision\n")); 5472ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 548882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION; 549882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (AbortReason != NULL) { 550882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *AbortReason = AllocateCopyPool(sizeof(L"IncorrectRevision"), L"IncorrectRevision"); 551882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 552882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return EFI_INCOMPATIBLE_VERSION; 553882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 554882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 555882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 556882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // try load MCU 557882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 558882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (TryLoad) { 55931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao CurrentRevision = LoadMicrocodeOnThis(MicrocodeFmpPrivate, ProcessorInfo->CpuIndex, (UINTN)MicrocodeEntryPoint + sizeof(CPU_MICROCODE_HEADER)); 560882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (MicrocodeEntryPoint->UpdateRevision != CurrentRevision) { 561882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on LoadMicrocode\n")); 562882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR; 563882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (AbortReason != NULL) { 564882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *AbortReason = AllocateCopyPool(sizeof(L"InvalidData"), L"InvalidData"); 565882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 566882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return EFI_SECURITY_VIOLATION; 567882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 568882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 569882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 570882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return EFI_SUCCESS; 571882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao} 572882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 573882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao/** 5742ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao Get next Microcode entrypoint. 575882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 5762ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @param[in] MicrocodeFmpPrivate The Microcode driver private data 5772ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @param[in] MicrocodeEntryPoint Current Microcode entrypoint 5782ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 5792ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @return next Microcode entrypoint. 5802ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao**/ 5812ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen YaoCPU_MICROCODE_HEADER * 5822ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen YaoGetNextMicrocode ( 5832ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate, 5842ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao IN CPU_MICROCODE_HEADER *MicrocodeEntryPoint 5852ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao ) 5862ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao{ 5872ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao UINTN Index; 5882ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 5892ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao for (Index = 0; Index < MicrocodeFmpPrivate->DescriptorCount; Index++) { 5902ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao if (MicrocodeEntryPoint == MicrocodeFmpPrivate->MicrocodeInfo[Index].MicrocodeEntryPoint) { 5912ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao if (Index == (UINTN)MicrocodeFmpPrivate->DescriptorCount - 1) { 5922ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // it is last one 5932ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao return NULL; 594882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } else { 5952ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // return next one 5962ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao return MicrocodeFmpPrivate->MicrocodeInfo[Index + 1].MicrocodeEntryPoint; 597882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 598882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 5992ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 600882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 6012ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao ASSERT(FALSE); 602882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return NULL; 603882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao} 604882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 605882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao/** 606882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Get current Microcode used region size. 607882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 6082ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @param[in] MicrocodeFmpPrivate The Microcode driver private data 6092ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 610882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @return current Microcode used region size. 611882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao**/ 612882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoUINTN 613882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoGetCurrentMicrocodeUsedRegionSize ( 6142ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate 615882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ) 616882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao{ 6172ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao if (MicrocodeFmpPrivate->DescriptorCount == 0) { 618882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return 0; 619882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 620882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 6212ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao return (UINTN)MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeFmpPrivate->DescriptorCount - 1].MicrocodeEntryPoint 6222ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao + (UINTN)MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeFmpPrivate->DescriptorCount - 1].TotalSize 6232ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao - (UINTN)MicrocodeFmpPrivate->MicrocodePatchAddress; 624882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao} 625882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 626882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao/** 627882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Update Microcode. 628882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 629882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @param[in] Address The flash address of Microcode. 630882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @param[in] Image The Microcode image buffer. 631882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @param[in] ImageSize The size of Microcode image buffer in bytes. 632882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. 633882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 634882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @retval EFI_SUCCESS The Microcode image is updated. 635882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao @retval EFI_WRITE_PROTECTED The flash device is read only. 636882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao**/ 637882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoEFI_STATUS 638882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoUpdateMicrocode ( 639882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao IN UINT64 Address, 640882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao IN VOID *Image, 641882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao IN UINTN ImageSize, 642882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao OUT UINT32 *LastAttemptStatus 643882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ) 644882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao{ 645882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao EFI_STATUS Status; 646882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 647882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao DEBUG((DEBUG_INFO, "PlatformUpdate:")); 648882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao DEBUG((DEBUG_INFO, " Address - 0x%lx,", Address)); 649882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao DEBUG((DEBUG_INFO, " Legnth - 0x%x\n", ImageSize)); 650882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 651882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Status = MicrocodeFlashWrite ( 652882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Address, 653882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao Image, 654882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ImageSize 655882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ); 656882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (!EFI_ERROR(Status)) { 657882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS; 658882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } else { 659882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; 660882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 661882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return Status; 662882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao} 663882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 664882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao/** 6652ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao Update Microcode flash region. 666882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 6672ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @param[in] MicrocodeFmpPrivate The Microcode driver private data 66831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao @param[in] TargetMicrocodeEntryPoint Target Microcode entrypoint to be updated 6692ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @param[in] Image The Microcode image buffer. 6702ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @param[in] ImageSize The size of Microcode image buffer in bytes. 6712ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. 672882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 6732ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @retval EFI_SUCCESS The Microcode image is written. 6742ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @retval EFI_WRITE_PROTECTED The flash device is read only. 675882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao**/ 676882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen YaoEFI_STATUS 6772ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen YaoUpdateMicrocodeFlashRegion ( 6782ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate, 67931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao IN CPU_MICROCODE_HEADER *TargetMicrocodeEntryPoint, 6802ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao IN VOID *Image, 6812ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao IN UINTN ImageSize, 6822ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao OUT UINT32 *LastAttemptStatus 683882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao ) 684882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao{ 6852ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao VOID *MicrocodePatchAddress; 6862ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao UINTN MicrocodePatchRegionSize; 68731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao UINTN TargetTotalSize; 688882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao UINTN UsedRegionSize; 6892ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao EFI_STATUS Status; 6902ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao VOID *MicrocodePatchScratchBuffer; 6912ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao UINT8 *ScratchBufferPtr; 6922ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao UINTN ScratchBufferSize; 6932ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao UINTN RestSize; 6942ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao UINTN AvailableSize; 6952ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao VOID *NextMicrocodeEntryPoint; 6962ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao MICROCODE_INFO *MicrocodeInfo; 6972ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao UINTN MicrocodeCount; 6982ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao UINTN Index; 6992ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 7002ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao DEBUG((DEBUG_INFO, "UpdateMicrocodeFlashRegion: Image - 0x%x, size - 0x%x\n", Image, ImageSize)); 701882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 7022ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress; 7032ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize; 7042ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 7052ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao MicrocodePatchScratchBuffer = AllocateZeroPool (MicrocodePatchRegionSize); 7062ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao if (MicrocodePatchScratchBuffer == NULL) { 7072ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao DEBUG((DEBUG_ERROR, "Fail to allocate Microcode Scratch buffer\n")); 7082ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES; 7092ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao return EFI_OUT_OF_RESOURCES; 710882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 7112ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao ScratchBufferPtr = MicrocodePatchScratchBuffer; 7122ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao ScratchBufferSize = 0; 713882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 7142ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 71531d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao // Target data collection 7162ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 71731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao TargetTotalSize = 0; 7182ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao AvailableSize = 0; 7192ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao NextMicrocodeEntryPoint = NULL; 72031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao if (TargetMicrocodeEntryPoint != NULL) { 72131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao if (TargetMicrocodeEntryPoint->DataSize == 0) { 72231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao TargetTotalSize = 2048; 723882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } else { 72431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao TargetTotalSize = TargetMicrocodeEntryPoint->TotalSize; 725882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 72631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao DEBUG((DEBUG_INFO, " TargetTotalSize - 0x%x\n", TargetTotalSize)); 72731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao NextMicrocodeEntryPoint = GetNextMicrocode(MicrocodeFmpPrivate, TargetMicrocodeEntryPoint); 7282ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao DEBUG((DEBUG_INFO, " NextMicrocodeEntryPoint - 0x%x\n", NextMicrocodeEntryPoint)); 7292ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao if (NextMicrocodeEntryPoint != NULL) { 73031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ASSERT ((UINTN)NextMicrocodeEntryPoint >= ((UINTN)TargetMicrocodeEntryPoint + TargetTotalSize)); 73131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao AvailableSize = (UINTN)NextMicrocodeEntryPoint - (UINTN)TargetMicrocodeEntryPoint; 7322ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } else { 73331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao AvailableSize = (UINTN)MicrocodePatchAddress + MicrocodePatchRegionSize - (UINTN)TargetMicrocodeEntryPoint; 7342ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 7352ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao DEBUG((DEBUG_INFO, " AvailableSize - 0x%x\n", AvailableSize)); 7362ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 73731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ASSERT (AvailableSize >= TargetTotalSize); 7382ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao UsedRegionSize = GetCurrentMicrocodeUsedRegionSize(MicrocodeFmpPrivate); 7392ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao DEBUG((DEBUG_INFO, " UsedRegionSize - 0x%x\n", UsedRegionSize)); 74031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ASSERT (UsedRegionSize >= TargetTotalSize); 74131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao if (TargetMicrocodeEntryPoint != NULL) { 74231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ASSERT ((UINTN)MicrocodePatchAddress + UsedRegionSize >= ((UINTN)TargetMicrocodeEntryPoint + TargetTotalSize)); 7432ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 7442ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 7452ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // Total Size means the Microcode data size. 74631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao // Available Size means the Microcode data size plus the pad till (1) next Microcode or (2) the end. 7472ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 7482ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // (1) 7492ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+-----------+-----+------+===================+ 7502ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // | MCU1 | Microcode | PAD | MCU2 | Empty | 7512ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+-----------+-----+------+===================+ 7522ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // | TotalSize | 7532ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // |<-AvailableSize->| 7542ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // |<- UsedRegionSize ->| 7552ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 7562ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // (2) 7572ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+-----------+===================+ 7582ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // | MCU | Microcode | Empty | 7592ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+-----------+===================+ 7602ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // | TotalSize | 7612ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // |<- AvailableSize ->| 7622ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // |<-UsedRegionSize->| 7632ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 7642ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 7652ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 7662ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // Update based on policy 7672ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 7682ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 7692ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 7702ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 1. If there is enough space to update old one in situ, replace old microcode in situ. 7712ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 7722ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao if (AvailableSize >= ImageSize) { 7732ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao DEBUG((DEBUG_INFO, "Replace old microcode in situ\n")); 7742ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 7752ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+------------+------+===================+ 7762ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // |Other1| Old Image |Other2| Empty | 7772ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+------------+------+===================+ 7782ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 7792ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+---------+--+------+===================+ 7802ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // |Other1|New Image|FF|Other2| Empty | 7812ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+---------+--+------+===================+ 7822ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 7832ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 1.1. Copy new image 7842ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao CopyMem (ScratchBufferPtr, Image, ImageSize); 7852ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao ScratchBufferSize += ImageSize; 78631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize; 7872ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 1.2. Pad 0xFF 7882ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao RestSize = AvailableSize - ImageSize; 7892ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao if (RestSize > 0) { 7902ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao SetMem (ScratchBufferPtr, RestSize, 0xFF); 7912ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao ScratchBufferSize += RestSize; 79231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize; 7932ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 79431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao Status = UpdateMicrocode((UINTN)TargetMicrocodeEntryPoint, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus); 7952ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao return Status; 796882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 797882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 798882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 7992ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 2. If there is enough space to remove old one and add new one, reorg and replace old microcode. 8002ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 80131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao if (MicrocodePatchRegionSize - (UsedRegionSize - TargetTotalSize) >= ImageSize) { 80231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao if (TargetMicrocodeEntryPoint == NULL) { 8032ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao DEBUG((DEBUG_INFO, "Append new microcode\n")); 8042ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 8052ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+------------+------+===================+ 8062ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // |Other1| Other |Other2| Empty | 8072ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+------------+------+===================+ 8082ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 8092ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+------------+------+-----------+=======+ 8102ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // |Other1| Other |Other2| New Image | Empty | 8112ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+------------+------+-----------+=======+ 8122ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 8132ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao Status = UpdateMicrocode((UINTN)MicrocodePatchAddress + UsedRegionSize, Image, ImageSize, LastAttemptStatus); 8142ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } else { 8152ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao DEBUG((DEBUG_INFO, "Reorg and replace old microcode\n")); 8162ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 8172ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+------------+------+===================+ 8182ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // |Other1| Old Image |Other2| Empty | 8192ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+------------+------+===================+ 8202ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 8212ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+---------------+------+================+ 8222ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // |Other1| New Image |Other2| Empty | 8232ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+---------------+------+================+ 8242ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 8252ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 2.1. Copy new image 82631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao CopyMem (ScratchBufferPtr, Image, ImageSize); 8272ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao ScratchBufferSize += ImageSize; 82831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize; 8292ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 2.2. Copy rest images after the old image. 8302ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao if (NextMicrocodeEntryPoint != 0) { 8312ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao RestSize = (UINTN)MicrocodePatchAddress + UsedRegionSize - ((UINTN)NextMicrocodeEntryPoint); 83231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao CopyMem (ScratchBufferPtr, (UINT8 *)TargetMicrocodeEntryPoint + TargetTotalSize, RestSize); 8332ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao ScratchBufferSize += RestSize; 83431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize; 8352ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 83631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao Status = UpdateMicrocode((UINTN)TargetMicrocodeEntryPoint, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus); 8372ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 8382ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao return Status; 8392ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 8402ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 8412ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 8422ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 3. The new image can be put in MCU region, but not all others can be put. 8432ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // So all the unused MCU is removed. 8442ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 8452ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao if (MicrocodePatchRegionSize >= ImageSize) { 8462ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 8472ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+------------+------+===================+ 8482ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // |Other1| Old Image |Other2| Empty | 8492ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +------+------------+------+===================+ 8502ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 8512ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +-------------------------------------+--------+ 8522ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // | New Image | Other | 8532ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // +-------------------------------------+--------+ 8542ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 8552ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao DEBUG((DEBUG_INFO, "Add new microcode from beginning\n")); 8562ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 8572ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao MicrocodeCount = MicrocodeFmpPrivate->DescriptorCount; 8582ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao MicrocodeInfo = MicrocodeFmpPrivate->MicrocodeInfo; 8592ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 8602ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 3.1. Copy new image 86131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao CopyMem (ScratchBufferPtr, Image, ImageSize); 8622ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao ScratchBufferSize += ImageSize; 86331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize; 8642ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 3.2. Copy some others to rest buffer 8652ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao for (Index = 0; Index < MicrocodeCount; Index++) { 8662ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao if (!MicrocodeInfo[Index].InUse) { 8672ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao continue; 8682ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 86931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao if (MicrocodeInfo[Index].MicrocodeEntryPoint == TargetMicrocodeEntryPoint) { 8702ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao continue; 8712ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 8722ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao if (MicrocodeInfo[Index].TotalSize <= MicrocodePatchRegionSize - ScratchBufferSize) { 8732ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao CopyMem (ScratchBufferPtr, MicrocodeInfo[Index].MicrocodeEntryPoint, MicrocodeInfo[Index].TotalSize); 8742ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao ScratchBufferSize += MicrocodeInfo[Index].TotalSize; 87531d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize; 8762ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 8772ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 8782ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 3.3. Pad 0xFF 8792ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao RestSize = MicrocodePatchRegionSize - ScratchBufferSize; 8802ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao if (RestSize > 0) { 8812ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao SetMem (ScratchBufferPtr, RestSize, 0xFF); 8822ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao ScratchBufferSize += RestSize; 88331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize; 8842ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 8852ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao Status = UpdateMicrocode((UINTN)MicrocodePatchAddress, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus); 8862ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao return Status; 8872ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao } 8882ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 8892ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 8902ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 4. The new image size is bigger than the whole MCU region. 8912ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 8922ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao DEBUG((DEBUG_ERROR, "Microcode too big\n")); 8932ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES; 8942ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao Status = EFI_OUT_OF_RESOURCES; 8952ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 8962ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao return Status; 8972ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao} 8982ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 8992ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao/** 9002ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao Write Microcode. 9012ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 9022ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao Caution: This function may receive untrusted input. 9032ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 9042ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @param[in] MicrocodeFmpPrivate The Microcode driver private data 9052ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @param[in] Image The Microcode image buffer. 9062ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @param[in] ImageSize The size of Microcode image buffer in bytes. 9072ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. 9082ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. 9092ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more 9102ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao details for the aborted operation. The buffer is allocated by this function 9112ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao with AllocatePool(), and it is the caller's responsibility to free it with a 9122ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao call to FreePool(). 9132ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 9142ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @retval EFI_SUCCESS The Microcode image is written. 9152ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @retval EFI_VOLUME_CORRUPTED The Microcode image is corrupt. 9162ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @retval EFI_INCOMPATIBLE_VERSION The Microcode image version is incorrect. 9172ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @retval EFI_SECURITY_VIOLATION The Microcode image fails to load. 9182ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao @retval EFI_WRITE_PROTECTED The flash device is read only. 9192ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao**/ 9202ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen YaoEFI_STATUS 9212ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen YaoMicrocodeWrite ( 9222ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate, 9232ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao IN VOID *Image, 9242ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao IN UINTN ImageSize, 9252ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao OUT UINT32 *LastAttemptVersion, 9262ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao OUT UINT32 *LastAttemptStatus, 9272ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao OUT CHAR16 **AbortReason 9282ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao ) 9292ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao{ 9302ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao EFI_STATUS Status; 9312ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao VOID *AlignedImage; 93231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao CPU_MICROCODE_HEADER *TargetMicrocodeEntryPoint; 93331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao UINTN TargetCpuIndex; 93431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao UINTN TargetMicrcodeIndex; 9352ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao 9362ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao // 937882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // MCU must be 16 bytes aligned 938882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao // 939882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao AlignedImage = AllocateCopyPool(ImageSize, Image); 940882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (AlignedImage == NULL) { 941882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao DEBUG((DEBUG_ERROR, "Fail to allocate aligned image\n")); 942882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES; 943882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return EFI_OUT_OF_RESOURCES; 944882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 945882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 946882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao *LastAttemptVersion = ((CPU_MICROCODE_HEADER *)Image)->UpdateRevision; 94731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao TargetCpuIndex = (UINTN)-1; 94831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao Status = VerifyMicrocode(MicrocodeFmpPrivate, AlignedImage, ImageSize, TRUE, LastAttemptStatus, AbortReason, &TargetCpuIndex); 949882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao if (EFI_ERROR(Status)) { 950882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao DEBUG((DEBUG_ERROR, "Fail to verify Microcode Region\n")); 951882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao FreePool(AlignedImage); 952882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return Status; 953882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao } 954882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao DEBUG((DEBUG_INFO, "Pass VerifyMicrocode\n")); 955882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 95631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao DEBUG((DEBUG_INFO, " TargetCpuIndex - 0x%x\n", TargetCpuIndex)); 95731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ASSERT (TargetCpuIndex < MicrocodeFmpPrivate->ProcessorCount); 95831d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao TargetMicrcodeIndex = MicrocodeFmpPrivate->ProcessorInfo[TargetCpuIndex].MicrocodeIndex; 95931d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao DEBUG((DEBUG_INFO, " TargetMicrcodeIndex - 0x%x\n", TargetMicrcodeIndex)); 96031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao if (TargetMicrcodeIndex != (UINTN)-1) { 96131d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao ASSERT (TargetMicrcodeIndex < MicrocodeFmpPrivate->DescriptorCount); 96231d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao TargetMicrocodeEntryPoint = MicrocodeFmpPrivate->MicrocodeInfo[TargetMicrcodeIndex].MicrocodeEntryPoint; 96331d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao } else { 96431d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao TargetMicrocodeEntryPoint = NULL; 96531d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao } 96631d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao DEBUG((DEBUG_INFO, " TargetMicrocodeEntryPoint - 0x%x\n", TargetMicrocodeEntryPoint)); 96731d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao 9682ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao Status = UpdateMicrocodeFlashRegion( 9692ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao MicrocodeFmpPrivate, 97031d060d94e65c41ccca2b68f7908c0c3b4ac3df4Jiewen Yao TargetMicrocodeEntryPoint, 9712ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao AlignedImage, 9722ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao ImageSize, 9732ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao LastAttemptStatus 9742ed658240c1f3ca10aa65dbbf74f4cf297145d8cJiewen Yao ); 975882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 976882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao FreePool(AlignedImage); 977882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 978882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao return Status; 979882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao} 980882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 981882668595c32e9e0adeaaf0bd0062f88b464fc18Jiewen Yao 982