summaryrefslogtreecommitdiff
path: root/Core/EM/SecurityPkg/SecSMIFlash
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/SecurityPkg/SecSMIFlash')
-rw-r--r--Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.c1810
-rw-r--r--Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.cif16
-rw-r--r--Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.dxs67
-rw-r--r--Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.mak108
-rw-r--r--Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.sdl74
-rw-r--r--Core/EM/SecurityPkg/SecSMIFlash/VerifyFwCapsule.c790
6 files changed, 2865 insertions, 0 deletions
diff --git a/Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.c b/Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.c
new file mode 100644
index 0000000..170461a
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.c
@@ -0,0 +1,1810 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SecureFlashPkg/SecureSmiFlash/SecSMIFlash.c 61 9/10/14 5:03p Alexp $
+//
+// $Revision: 61 $
+//
+// $Date: 9/10/14 5:03p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureFlashPkg/SecureSmiFlash/SecSMIFlash.c $
+//
+// 61 9/10/14 5:03p Alexp
+// EIP176297: Harden external parameter checks in SW SMI API
+// Fixes are made to address:
+// #7. Arbitrary SMRAM overwrite in SetFlUpdMethod()
+// #8. Integer overflow leading to buffer overflow in
+// LoadFwImage in SecSMIFlash SMI handler
+//
+// 60 8/04/14 11:59a Alexp
+// 1. Use internal RomLayout map to process Flash Erase/Write requests.
+// Issue- new RomMap may be different - exposing rom holes in wrong
+// places
+// 2. SetFlUpdMethod() - SecSmiFlash.RomLayout is updated to a map from a
+// new image but not used.
+// Later may compare the maps to find inconsistencies.
+// 3. BeforeSecureUpdate() - bug in calculating the flash range within
+// RomArea
+//
+// 59 7/29/14 12:07p Alexp
+// Add a code to erase existing CapsuleUpdate and FlashUdate vars
+// Fixes the case when vars exist with different attributes which prevent
+// SecSmiFlash to set new valid var.
+//
+// 57 7/03/14 10:16a Alexp
+// EIP176297: Harden external parameter checks in SW SMI API
+//
+// 56 6/11/14 10:16a Alexp
+// EIP#168391:The power button does not work with failed NVRAM
+// - harden SmiS5CapsuleCallback()
+// - memory allocation for gpEfiCapsuleHdr changed from runtime memory to
+// SMRAM.
+//
+// 55 3/20/14 3:20p Alexp
+// 1. EIP#159507 : S3 resume time improvement: Use EfiReservedMemoryType
+// instead of EfiACPIMemoryNVS for large buffer allocations.
+// FwCapsule buffer to be allocated below 4GB.
+// 2. Allow gpPubKeyHndl to be accessed from externally linked code
+//
+// 54 1/24/14 4:02p Alexp
+// SetFlUpdMethod()
+// 1. Set SecSmiFlash.RomLayout only for Runtime and Capsule update
+// 2. removed dummy code " SecSmiFlash.pFwCapsule =
+// SecSmiFlash.pFwCapsule"
+//
+// 53 10/11/13 2:50p Alexp
+//
+// 52 6/21/13 10:56a Alexp
+// EIP#125800: add more error checking in release mode inside
+// InSmmFunction()
+//
+// 51 6/12/13 3:52p Alexp
+// CapsuleValidate() made external function in SecSmiFlash API
+//
+// 50 6/06/13 4:03p Alexp
+// EIP#125800 : Privilege escalation into SMM via Secure SMI Flash SMM
+// driver via GetFlUpdPolicy and SetFlUpdMethod - BugID 305294
+// add IsAddressInSmram() checks inside exposed API functions
+//
+// 49 4/23/13 2:49p Alexp
+// GetFlUpdPolicy() to return FwKey up to 256 bytes.
+//
+//
+// 47 2/26/13 6:14p Alexp
+// Set data size for Capsule Upd variable as
+// size of (EFI_PHYSICAL_ADDRESS)
+//
+//
+// 45 12/28/12 2:19p Alexp
+// fix "cppcheck: code style issues
+//
+// 42 11/21/12 10:42a Alexp
+// Replace direct calls to Hash() in CryptoLib with API calls
+//
+// 41 11/13/12 3:26p Alexp
+// 1. Calculate offset to RomLayout table within FwCapsHdr instead of
+// using hardwired location. Pkcs#7
+// cert will differ in size and offset may change
+// 2. Remove assert after GetKey function.
+//
+// 40 11/09/12 5:44p Alexp
+// fixed branch for FWCAPSULE_2_0_SUPPORT
+//
+// 39 10/18/12 10:17a Alexp
+// Bug fix: make allocation of HashCtx buffer not to be dependent on
+// CAPSULE_RECOVERY support.
+//
+// 38 8/28/12 4:12p Alexp
+// fix spelling
+//
+// 37 8/22/12 9:40a Alexp
+// Allow to insrtall SecSmi Flash handler if RomLayout map not detected
+// during module Init
+//
+// 36 8/16/12 11:31a Alexp
+// use global pSmmBase ptr in InSmmFunction()
+//
+// 35 7/25/12 6:21p Alexp
+// replaced custom Capsule module defined _EFI_CAPSULE_BLOCK_DESCRIPTOR_
+// with generic UEFI EFI_CAPSULE_BLOCK_DESCRIPTOR structure
+//
+// 34 6/26/12 9:49a Alexp
+// include GetRomLayout under
+// #if RUNTIME_SECURE_UPDATE_FLOW == 1
+//
+// 33 6/12/12 5:33p Alexp
+// EIP74625:New Capsule PPI required by latest Intel's MRC code
+// -Fw Capsule upload supports new Capsule_2_0 format without extra
+// CapHdr in the Mailbox
+// EIP90678: MonotonicCounter variable guid changed
+// -Use AMI_GLOBAL_VARIABLE_GUID
+//
+// 30 5/21/12 4:55p Alexp
+// keep a pointer to FwCaps Hdr withing Capsule image. Streamlines
+// creation of Capsule Mailbox.
+//
+// 29 5/18/12 5:27p Alexp
+// 1. Replace Hash PPI calls with calls to Crypto lib functions.
+// 2. Enforce flash update security by replacing SMM Flash protocol
+// Write/Erase functions with local functions
+// 3. Include RomLayout map pointer to SecSmiFlash protocol table. Local
+// RomMap table is replaced with new one from valid FwCapsule image
+//
+// 28 2/29/12 4:15p Alexp
+// Removed "gAmiSig->GetKey" from driver entry point. Will use VerifyKey
+// instead. FW Key may be stored as a Hash in FW Key file storage.
+//
+// 27 2/16/12 9:38a Alexp
+// SetFlUpdMethod() - removed condition #if NEW_BIOS_MEM_ALLOC != 0 left
+// out from older logic
+//
+// 26 2/03/12 2:42p Alexp
+// Use SHA256 Hash for Hash table
+//
+// 25 1/27/12 12:14p Alexp
+// move defines for HASH_TBL_... to SecSmiFlash header file
+//
+// 23 1/13/12 4:18p Alexp
+// Replace "AFU_FLASH_PAGE_SIZE" with "FLASH_BLOCK_SIZE"
+//
+// 22 1/10/12 6:22p Alexp
+// 1. Always perform Hash match for new bios data block with one
+// calculated during Capsule verification
+// 2. Flash block available for hashing is determined by SDL token
+// FLASH_BLOCK_SIZE and not by AFU interface
+//
+// 21 12/16/11 1:19p Alexp
+// Bug fix: UpdateCapsule()
+// While preparing MailBox discriptor, the pointer gpCapsuleMailboxPtr
+// went outside of allocated memory pEfiCapsuleHdr
+//
+// 19 12/01/11 3:34p Alexp
+// 1.SmiS5CapsuleCallback-> Introduce a call to Chipset defined
+// SBLib_ResetSystem(WarmReset)
+// Call is included based on the SDL switch CSLIB_WARM_RESET_SUPPORTED
+// It replaces sample oimplementation of WarmReset via S3 & RTC wake up
+// 2. SetFlUpdMethod-> Add temp w/a for AFU rev 3.0. Wrong image size(0)
+// is reported by AFU in pSessionBlock->FlUpdBlock.ImageSize
+// 3. Updated conditional statements to match newly defined SDL tokens:
+// INSTALL_SECURE_FLASH_SW_SMI_HNDL and CSLIB_WARM_RESET_SUPPORTED
+//
+// 17 11/30/11 8:11p Alexp
+// 1. Replaced dependencies from WARM_REBOOT flag to generic
+// FWCAPSULE_RECOVERY_SUPPORT
+// 2. SetFlUpdMethod() corercted behavior of some AFU implementations for
+// CApsule Set mode. Size should have been provided
+// 3. Memory for Capsule Mailbox allocation moved form "EfiRuntime" to
+// more appropriate "AcpiNvs"
+//
+// 16 11/11/11 12:50p Alexp
+// fixed InSmmFunction() when building without FWCAPSULE_RECOVERY_SUPPORT
+//
+// 15 11/03/11 6:45p Alexp
+// skip SecSMIFlashSMIHandler() if OFBD Secure Flash module is active
+//
+// 14 10/17/11 11:25a Alexp
+// update Hdr & Footer. Clear BIOS buffer
+//
+// 13 10/11/11 12:28p Alexp
+// add OFBD dependency
+//
+// 12 9/30/11 4:39p Alexp
+// add porting notes
+//
+// 11 8/24/11 6:51p Alexp
+// replaced CAPSULE_SUPPORT check to FWCAPSULE_RECOVERY_SUPPORT
+//
+// 10 8/24/11 11:30a Alexp
+// Clear Capsule update capability in gFlUpdatePolicy.FlashUpdate if no
+// Capsule Driver or WarmReboot tokens are defined
+//
+// 9 8/09/11 7:45p Alexp
+//
+// 8 8/09/11 9:54a Alexp
+// bug fix: NEW #if NEW_BIOS_MEM_ALLOC != 0, OLD: #if NEW_BIOS_MEM_ALLOC
+//
+// 7 8/08/11 7:23p Alexp
+// SetFlashUpdateVar - assign Attributes to SetVar via CounterHi variable.
+// old init method "A | B | C" had wrong Attributes passed to the SetVar
+//
+// 6 8/06/11 11:35a Alexp
+// LoadImage-> clear out FSHndl. Need to be set to valid value only if
+// image Verification complete inside SetFlMethod
+//
+// 5 8/05/11 3:43p Alexp
+// hardwire Flash Upd policy (staticly provided from SDL tokens)
+//
+// 4 7/21/11 3:13p Alexp
+// removed mistakenly put while(1){} statement at the end of
+// SmiS5CapsuleCallback()
+//
+// 3 7/20/11 7:20p Alexp
+// removed dependency on Capsule module.
+//
+// 2 7/20/11 6:22p Alexp
+// include sample implementation to enter S3 on AMD chipsets
+//
+// 1 7/01/11 4:41p Alexp
+//
+// 1 7/01/11 4:37p Alexp
+//
+// 10 6/24/11 4:32p Alexp
+// move around debug comments
+//
+// 9 6/24/11 2:09p Alexp
+// SetFlUpd: abort if capsule size passed by AFU is greater then allocated
+// buffer in gRomFileSize
+//
+// 8 6/23/11 7:08p Alexp
+// SetFlashUpd: update local buffer with Ptr to AFU allocated buffer with
+// rom image
+//
+// 14 6/20/11 2:10p Alexp
+// // AFU updates the address in CapsuleMailboxPtr if
+// SetFlashMethod: update for the case if AFU provided address in memory
+// for new BIOS image
+//
+// 7 6/17/11 5:47p Alexp
+// bug fix: GetKey expects valid buffer size on input
+//
+// 6 6/01/11 12:35p Alexp
+// fix FSHandle init value
+//
+// 5 5/25/11 8:31p Alexp
+// forse Implemented flag to "1" if SecSMIFlash supported. ASFU would
+// check for combination, Version>-12 and this flag to determine if SecSMI
+// Flash API is supported
+//
+// 4 5/17/11 12:58p Alexp
+// add build switch for location of temp BIOS image
+//
+// 3 5/12/11 7:58p Alexp
+//
+// 2 5/10/11 5:10p Alexp
+// Hash guids are defined globally
+//
+// 1 5/10/11 10:01a Alexp
+//
+// 13 5/06/11 11:59a Alexp
+//
+// 12 5/02/11 3:22p Alexp
+// merged capsule hdr and mailbox into one mem allocation unit
+//
+// 11 4/28/11 6:21p Alexp
+// tbd: in release mode get FW pub key may fail
+//
+// 10 4/28/11 10:45a Alexp
+// update Capsule mailbox format. Add extra Efi Capsule Hdr that will be
+// discarded by CApsul PEI service while coalescing the Capsule into a Hob
+//
+// 8 4/22/11 4:36p Alexp
+// temp debug: init MC field in FlashUpd var with 0 if MC Var is missing.
+//
+// 7 4/19/11 6:42p Alexp
+// tested Reboot and Online flash. Recovery flow fails.
+//
+// 6 4/18/11 7:22p Alexp
+// working version. Need to review HashTable as it may not be practical if
+// block sizes do not mach BLOCK_SIZE
+//
+// 5 4/13/11 7:14p Alexp
+// locate RomMap for easy location of Fid.ffs for VersionControl
+// Create HashTable for uplaoded Fw Image. Used for runtime updates only
+// generate FSHandle for future use
+//
+// 4 4/11/11 2:10p Alexp
+// -Revision 12 and upper to support "Installed" field in Flash Info as
+// bit mask
+// -Add support for new CApsule SigningCert header
+// - Replace PKpub with new FW Sign key as a root Platform key to verify
+// Capsule Sig with
+//
+// 3 4/05/11 6:38p Alexp
+// use GetVariable to get PK Pub key
+//
+// 2 3/11/11 6:51p Alexp
+//
+// 1 3/10/11 4:59p Alexp
+//
+// 1 3/03/11 6:34p Alexp
+//
+//**********************************************************************
+
+#include <Token.h>
+#include <AmiDxeLib.h>
+#include <Protocol\SmiFlash.h>
+#include <Protocol\SmmBase.h>
+#include <Protocol\SmmSwDispatch.h>
+#include <Protocol\SmmSxDispatch.h>
+#include <Protocol\DevicePath.h>
+#include <Protocol\LoadedImage.h>
+#include <AmiSmm.h>
+//PI 1.1 ++
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)
+#include <Protocol\SmmAccess2.h>
+#else
+#include <Protocol\SmmAccess.h>
+#endif
+
+#if FWCAPSULE_RECOVERY_SUPPORT == 1
+#include <Capsule.h>
+#endif
+
+#include <AmiHobs.h>
+
+#include <Protocol\SecSmiFlash.h>
+#include <Protocol\FlashProtocol.h>
+
+//----------------------------------------------------------------------
+// Module defined global variables
+static EFI_GUID gSwSmiCpuTriggerGuid = SW_SMI_CPU_TRIGGER_GUID;
+static EFI_GUID gEfiSmmSwDispatchProtocolGuid = EFI_SMM_SW_DISPATCH_PROTOCOL_GUID;
+static EFI_GUID gEfiSmmSxDispatchProtocolGuid = EFI_SMM_SX_DISPATCH_PROTOCOL_GUID;
+//extern EFI_GUID gEfiSmmSxDispatchProtocolGuid = EFI_SMM_SX_DISPATCH_PROTOCOL_GUID;
+
+// AMI_GLOBAL_VARIABLE_GUID must be defined in AmiLib.h (Core 4.6.5.4 +)
+#if defined(AMI_GLOBAL_VARIABLE_GUID)
+static EFI_GUID gAmiGlobalVariableGuid = AMI_GLOBAL_VARIABLE_GUID;
+#else
+static EFI_GUID gAmiGlobalVariableGuid = EFI_GLOBAL_VARIABLE;
+#endif
+
+static EFI_GUID FlashUpdGuid = FLASH_UPDATE_GUID;
+
+EFI_GUID gFWCapsuleGuid = APTIO_FW_CAPSULE_GUID;
+EFI_GUID gPRKeyGuid = PR_KEY_GUID;
+EFI_GUID gFwCapFfsGuid = AMI_FW_CAPSULE_FFS_GUID;
+
+static FLASH_UPD_POLICY FlUpdatePolicy = {FlashUpdatePolicy, BBUpdatePolicy};
+
+EFI_SHA256_HASH *gHashTbl = NULL;
+UINT8 gHashDB[SHA256_DIGEST_SIZE];
+CRYPT_HANDLE gpPubKeyHndl;
+
+AMI_DIGITAL_SIGNATURE_PROTOCOL *gAmiSig;
+
+#if FWCAPSULE_RECOVERY_SUPPORT == 1
+static EFI_GUID CapsuleVendorGuid = EFI_CAPSULE_AMI_GUID;
+EFI_CAPSULE_BLOCK_DESCRIPTOR *gpEfiCapsuleHdr = NULL;
+#endif
+
+// BIOS allocates the space in AcpiNVS for new BIOS image to be uploaded by Flash tool
+// Alternatively the buffer may be reserved within the SMM TSEG. Check NEW_BIOS_MEM_ALLOC Token
+// AFU would have to execute a sequence of SW SMI calls to load new BIOS image to mem
+UINTN gFwCapMaxSize = FWCAPSULE_IMAGE_SIZE;
+UINT32 *pFwCapsuleLowMem = NULL;
+
+static EFI_SMRAM_DESCRIPTOR *mSmramRanges;
+static UINTN mSmramRangeCount;
+//----------------------------------------------------------------------
+// Flash Upd Protocol defines
+//----------------------------------------------------------------------
+typedef EFI_STATUS (EFIAPI *FLASH_READ_WRITE)(
+ VOID* FlashAddress, UINTN Size, VOID* DataBuffer
+);
+typedef EFI_STATUS (EFIAPI *FLASH_ERASE)(
+ VOID* FlashAddress, UINTN Size
+);
+
+FLASH_PROTOCOL *Flash;
+
+FLASH_READ_WRITE pFlashWrite; // Original Ptr inside FlashAPI
+FLASH_ERASE pFlashErase;
+
+static UINT32 Flash4GBMapStart;
+ROM_AREA *RomLayout = NULL;
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+// UpFront Function definitions
+BOOLEAN SupportUpdateCapsuleReset (
+ VOID
+);
+EFI_STATUS CapsuleValidate (
+ IN OUT UINT8 **pFwCapsule,
+ IN OUT APTIO_FW_CAPSULE_HEADER **pFwCapsuleHdr
+);
+EFI_STATUS LoadFwImage(
+ IN OUT FUNC_BLOCK *pFuncBlock
+);
+EFI_STATUS GetFlUpdPolicy(
+ IN OUT FLASH_POLICY_INFO_BLOCK *InfoBlock
+);
+EFI_STATUS SetFlUpdMethod(
+ IN OUT FUNC_FLASH_SESSION_BLOCK *pSessionBlock
+);
+EFI_STATUS FindCapHdrFFS(
+ IN VOID *pCapsule,
+ OUT UINT8 **pFfsData
+);
+BOOLEAN IsAddressInSmram (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+);
+
+//----------------------------------------------------------------------
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: SecSmiFlash
+//
+// Description:
+//
+// Input:
+//
+// Output:
+//
+// Returns:
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_SEC_SMI_FLASH_PROTOCOL SecSmiFlash = {
+ LoadFwImage,
+ GetFlUpdPolicy,
+ SetFlUpdMethod,
+ CapsuleValidate,
+ 0,// pFwImageLowMem
+ 0,// RomLayout,
+ 0,// gSha256HashTbl,
+ 0,// FSHandle
+};
+
+#if FWCAPSULE_RECOVERY_SUPPORT == 1
+
+#if CSLIB_WARM_RESET_SUPPORTED == 0
+
+//#if (defined x64_BUILD && x64_BUILD == 1)
+//VOID flushcaches();
+void DisableCacheInCR0();
+//#endif
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: ReadRtcIndexedRegister
+//
+// DESCRIPTION: Used to read RTC register indexed by the argument
+//
+// Input:
+// IN UINT8 Index Index of the register to read
+//
+//
+// Output:
+// UINT8 Current value of the register
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8 ReadRtcIndexedRegister(IN UINT8 Index){
+
+ UINT8 Byte = IoRead8(0x70) & 0x80; // preserve bit 7
+ IoWrite8(0x70, Index | Byte);
+ Byte = IoRead8(0x71);
+ return Byte;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: ReadRtcIndexedRegister
+//
+// DESCRIPTION: Used to write to RTC register indexed by the argument
+//
+// Input:
+// IN UINT8 Index Index of the register to write to
+//
+// IN UINT8 Value Value to write to the RTC register
+//
+// Output:
+// VOID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID WriteRtcIndexedRegister(IN UINT8 Index, IN UINT8 Value){
+
+ IoWrite8(0x70,Index | (IoRead8(0x70) & 0x80));
+ IoWrite8(0x71,Value);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: S3RTCresume
+//
+// Description: This function puts system into ACPI S3 State.
+// if token ENABLE_RTC_ONE_SECOND_WAKEUP = 1, then it setups RTC
+// 1 second alarm as well.
+//
+// Input: None
+//
+// Output: None, system will enter ACPI S3 State.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID S3RTCresume (VOID)
+{
+ UINT32 IoData;
+ UINT8 Hour, Minute, Second;
+ BOOLEAN inBCD = TRUE;
+
+ //flush caches befor going to S3
+//#if (defined x64_BUILD && x64_BUILD == 1)
+// flushcaches();
+ DisableCacheInCR0();
+//#else
+// _asm wbinvd
+//#endif
+
+ // determine if RTC is in BCD mode
+ if( ReadRtcIndexedRegister(0xB) & 0x4 ) // bit 2
+ inBCD = FALSE;
+ // wait for time update to complete before reading the values
+ while( ReadRtcIndexedRegister(0xA) & 0x80 ); // while bit 7 is set the
+ // time update is in progress
+ //read current hour, minute, second
+ Hour = ReadRtcIndexedRegister(0x4);
+ Minute = ReadRtcIndexedRegister(0x2);
+ Second = ReadRtcIndexedRegister(0x0);
+
+ //convert second to decimal from BCD and increment by 1
+ if(inBCD)
+ Second = (Second >> 4) * 10 + (Second & 0x0F);
+ Second += 2;
+
+ if(Second > 59){
+ Second -= 60;
+ if(inBCD)
+ Minute = (Minute >> 4) * 10 + (Minute & 0x0F);
+ Minute++;
+ if(Minute > 59){
+ Minute = 0;
+ if(inBCD)
+ Hour = (Hour >> 4) * 10 + (Hour & 0x0F);
+ Hour++;
+ // check 24 hour mode/12 hour mode
+ if( ReadRtcIndexedRegister(0xB) & 0x2 ) {// bit 1 1=24hour else 12 hour
+ if(Hour > 23)
+ Hour = 0;
+ } else {
+ if(Hour > 11)
+ Hour = 0;
+ }
+
+ if(inBCD)
+ Hour = Hour % 10 + ( (Hour / 10) << 4 ) ;
+ }
+ if(inBCD)
+ Minute = Minute % 10 + ( (Minute / 10) << 4 ) ;
+ }
+
+ //convert from decimal to BCD
+ if(inBCD)
+ Second = Second % 10 + ( (Second / 10) << 4 ) ;
+
+ //set the alarm
+
+ WriteRtcIndexedRegister(0x5, Hour);
+ WriteRtcIndexedRegister(0x3, Minute);
+ WriteRtcIndexedRegister(0x1, Second);
+ //enable the alarm
+ WriteRtcIndexedRegister(0xB, ( ReadRtcIndexedRegister(0xB) | ((UINT8)( 1 << 5 )) ));
+
+// ========== PORTING REQUIRED ===========================================================
+// Current implementation to simulate the Warm Reboot may not be sufficient on some platforms.
+// S3 transition may require additional Chipset/Platform coding.
+// If needed add any necessary OEM hooks to be able to put the system into S3 at the end of this handler
+//========================================================================================
+
+ //set RTC_EN bit in PM1_EN to wake up from the alarm
+ IoWrite16(PM_BASE_ADDRESS + 0x02, ( IoRead16(PM_BASE_ADDRESS + 0x02) | (1 << 10) ));
+
+ //Disable Sleep SMI to avoid SMI re-entrance.
+// IoWrite16(PM_BASE_ADDRESS + 0x30, ( IoRead16(PM_BASE_ADDRESS + 0x30) & (~BIT4) ));
+
+ //modify power management control register to reflect S3
+ IoData = IoRead32(PM_BASE_ADDRESS + 0x04);
+ //following code is applicable to Intel PCH only.
+ IoData &= ~(0x1C00);
+ IoData |= 0x1400; //Suspend to RAM
+/*
+ // AMD w/a to enter S3 state
+ IoData |= 0x2C00; //Suspend to RAM
+ {
+ UINT8 Temp8;
+ IoWrite8(0xCD6, 0x004);
+ Temp8 = IoRead8(0xCD7);
+ Temp8 &= ~(BIT7);
+ IoWrite8(0xCD6, 0x004);
+ IoWrite8(0xCD7, Temp8);
+ IoWrite8(0xCD6, 0x007);
+ IoWrite8(0xCD7, BIT7);
+ }
+}
+*/
+ IoWrite32(PM_BASE_ADDRESS + 0x04, IoData );
+}
+//#else
+//extern SBLib_ResetSystem( IN EFI_RESET_TYPE ResetType );
+#endif
+extern SBLib_ResetSystem( IN EFI_RESET_TYPE ResetType );
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: SmiS5CapsuleCallback
+//
+// DESCRIPTION: SMI handler to perform capsule reset (bounce from S5 to S3)
+// ========== PORTING REQUIRED ===========================================================
+// Current implementation to simulate the Warm Reboot may not be sufficient on some platforms.
+// S3 transition may require additional Chipset/Platform coding.
+// If needed add any necessary OEM hooks to be able to put the system into S3 at the end of this handler
+//========================================================================================
+//
+// Input:
+// IN EFI_HANDLE DispatchHandle Handle of SMI dispatch
+// protocol
+// IN EFI_SMM_SX_DISPATCH_CONTEXT* DispatchContext Pointer to SMI dispatch
+// context structure
+//
+// Output:
+// VOID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SmiS5CapsuleCallback ( IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext
+){
+ EFI_PHYSICAL_ADDRESS IoData;
+ UINTN Size;
+ EFI_CAPSULE_HEADER *CapsuleHeader;
+ AMI_FLASH_UPDATE_BLOCK FlUpdateBlock;
+
+ TRACE((TRACE_ALWAYS,"SecSMI. S5 Trap\n"));
+
+ //
+ //Check if the Capsule update is supported by platform policy
+ //
+ if (!SupportUpdateCapsuleReset())
+ return;
+
+ Size=sizeof(AMI_FLASH_UPDATE_BLOCK);
+ if(EFI_ERROR(pRS->GetVariable(FLASH_UPDATE_VAR,&FlashUpdGuid, NULL, &Size, &FlUpdateBlock)) ||
+ FlUpdateBlock.FlashOpType != FlCapsule)
+ return;
+
+ // verify the FW capsule is in memory.
+ Size = sizeof(EFI_PHYSICAL_ADDRESS);
+ if(EFI_ERROR(pRS->GetVariable(CAPSULE_UPDATE_VAR,&CapsuleVendorGuid, NULL, &Size, &IoData)))
+ return;
+
+ if(IoData != (EFI_PHYSICAL_ADDRESS)gpEfiCapsuleHdr ||
+ !IsAddressInSmram((EFI_PHYSICAL_ADDRESS)IoData, sizeof(EFI_PHYSICAL_ADDRESS)))
+ return;
+
+ CapsuleHeader = (EFI_CAPSULE_HEADER*)gpEfiCapsuleHdr[0].DataBlock;
+ //
+ // Compare GUID with APTIO_FW_CAPSULE_GUID
+ //
+ if (guidcmp (&CapsuleHeader->CapsuleGuid, &gFWCapsuleGuid))
+ return;
+
+#if CSLIB_WARM_RESET_SUPPORTED == 1
+ SBLib_ResetSystem(EfiResetWarm);
+#else
+ S3RTCresume();
+#endif
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SupportUpdateCapsuleReset
+//
+// Description: This function returns platform policy capability for capsule update via a system reset.
+//
+// Input: None
+//
+// Output: TRUE - memory can be preserved across reset
+// FALSE - memory integrity across reset is not guaranteed
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN SupportUpdateCapsuleReset (
+ VOID
+)
+{
+ //
+ //If the platform has a way to guarantee the memory integrity across a system reset, return
+ //TRUE, else FALSE.
+ //
+ if( (FlUpdatePolicy.FlashUpdate & FlCapsule) ||
+ (FlUpdatePolicy.BBUpdate & FlCapsule))
+ return TRUE;
+
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UpdateCapsule
+//
+// Description: This code prepares Capsule Update EFI Variable
+//
+// Input:
+// IN EFI_CAPSULE_HEADER **CapsuleHeaderArray - array of pointers to capsule headers passed in
+//
+// Output: EFI_SUCCESS - capsule processed successfully
+// EFI_INVALID_PARAMETER - CapsuleCount is less than 1,CapsuleGuid is not supported
+// EFI_DEVICE_ERROR - capsule processing failed
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS UpdateCapsule (
+ IN FUNC_FLASH_SESSION_BLOCK *pSessionBlock,
+ IN APTIO_FW_CAPSULE_HEADER *pFwCapsuleHdr
+){
+ EFI_STATUS Status;
+ EFI_CAPSULE_HEADER *pEfiCapsuleHdr = NULL;
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *pCapsuleMailboxPtr;
+ UINT32 Attributes, Index;
+
+ //
+ //Compare GUID with APTIO_FW_CAPSULE_GUID
+ //
+ if (!pFwCapsuleHdr ||
+ guidcmp (&pFwCapsuleHdr->CapHdr.CapsuleGuid, &gFWCapsuleGuid)
+ )
+ return EFI_DEVICE_ERROR;
+
+ pCapsuleMailboxPtr = gpEfiCapsuleHdr;
+ Index = 0;
+#if !defined(FWCAPSULE_2_0_SUPPORT) || FWCAPSULE_2_0_SUPPORT == 0
+ pEfiCapsuleHdr = (EFI_CAPSULE_HEADER*)&pCapsuleMailboxPtr[4];
+// New Capsule PPI supports single CapHdr.
+// construct dummy EfiCapHdr struct within pEfiCapsuleHdr as 1st element to be linked from Mailbox
+ MemCpy((VOID*)pEfiCapsuleHdr, &gFWCapsuleGuid, sizeof(EFI_GUID));
+ pEfiCapsuleHdr->Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
+ pEfiCapsuleHdr->HeaderSize = sizeof(EFI_CAPSULE_HEADER);
+ pEfiCapsuleHdr->CapsuleImageSize = pFwCapsuleHdr->CapHdr.CapsuleImageSize + sizeof(EFI_CAPSULE_HEADER);
+ // create ScatterGather list: use pre-allocated runtime memory
+ pCapsuleMailboxPtr[Index].Length = pEfiCapsuleHdr->HeaderSize;
+ pCapsuleMailboxPtr[Index].DataBlock = (EFI_PHYSICAL_ADDRESS)pEfiCapsuleHdr;
+ Index++;
+#endif
+ pCapsuleMailboxPtr[Index].Length = pFwCapsuleHdr->CapHdr.HeaderSize;
+ pCapsuleMailboxPtr[Index].DataBlock = (EFI_PHYSICAL_ADDRESS)pFwCapsuleHdr;
+ pCapsuleMailboxPtr[Index+1].Length = pFwCapsuleHdr->CapHdr.CapsuleImageSize-pFwCapsuleHdr->CapHdr.HeaderSize;
+ if((UINT32*)pFwCapsuleLowMem == (UINT32*)pFwCapsuleHdr) {
+ // Fw Cap Hdr is on top of Payload
+
+ pCapsuleMailboxPtr[Index+1].DataBlock = pCapsuleMailboxPtr[Index].DataBlock+pCapsuleMailboxPtr[Index].Length;
+ } else {
+ // Fw Cap Hdr is embedded inside Payload
+ pCapsuleMailboxPtr[Index+1].DataBlock = (EFI_PHYSICAL_ADDRESS)pFwCapsuleLowMem;
+ }
+ pCapsuleMailboxPtr[Index+2].Length = 0;
+ pCapsuleMailboxPtr[Index+2].DataBlock = 0;
+ //
+ //Check if the platform supports update capsule across a system reset
+ //
+ if (!SupportUpdateCapsuleReset()) {
+ return EFI_UNSUPPORTED;
+ }
+ // Erase prev copy
+ Status = pRS->SetVariable ( CAPSULE_UPDATE_VAR, &CapsuleVendorGuid,0,0,NULL);
+ Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS;
+ Status = pRS->SetVariable ( CAPSULE_UPDATE_VAR, &CapsuleVendorGuid,
+ Attributes, sizeof(EFI_PHYSICAL_ADDRESS),(VOID*)&pCapsuleMailboxPtr);
+
+ if(!EFI_ERROR(Status))
+ return Status;
+
+ return EFI_DEVICE_ERROR;
+}
+
+#endif //#if FWCAPSULE_RECOVERY_SUPPORT == 1
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetFlashUpdateVar
+//
+// Description: This code finds if the capsule needs reset to update, if no, update immediately.
+//
+// Input:
+// IN EFI_CAPSULE_HEADER **CapsuleHeaderArray - array of pointers to capsule headers passed in
+// IN UINTN CapsuleCount - number of capsule
+// IN EFI_PHYSICAL_ADDRESS ScatterGatherList - physical address of datablock list points to capsule
+//
+// Output: EFI_SUCCESS - capsule processed successfully
+// EFI_INVALID_PARAMETER - CapsuleCount is less than 1,CapsuleGuid is not supported
+// EFI_DEVICE_ERROR - capsule processing failed
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS SetFlashUpdateVar (
+ IN FUNC_FLASH_SESSION_BLOCK *pSessionBlock
+){
+ EFI_STATUS Status;
+ UINTN Size;
+ UINT32 CounterHi;
+
+ if(pSessionBlock->FlUpdBlock.FlashOpType == FlRecovery &&
+ pSessionBlock->FlUpdBlock.FwImage.AmiRomFileName[0] == 0
+ )
+ return EFI_DEVICE_ERROR;
+
+ CounterHi = 0;
+ Size = sizeof(UINT32);
+// MonotonicCounter is a boot time service, hence the variable may have restricted access in runtime
+ if(EFI_ERROR(pRS->GetVariable(L"MonotonicCounter", &gAmiGlobalVariableGuid,
+ NULL, &Size, &CounterHi))
+ )
+// return Status;//EFI_DEVICE_ERROR;
+//SetMode should set FlashUpd even if no MC var detected.
+ CounterHi=0xffffffff;
+
+ pSessionBlock->FlUpdBlock.MonotonicCounter = CounterHi;
+ CounterHi = (EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_RUNTIME_ACCESS |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS);
+ // Erase prev copy
+ Status = pRS->SetVariable ( FLASH_UPDATE_VAR, &FlashUpdGuid,0,0,NULL);
+ Status = pRS->SetVariable ( FLASH_UPDATE_VAR, &FlashUpdGuid, CounterHi,
+ sizeof(AMI_FLASH_UPDATE_BLOCK), (VOID*) &pSessionBlock->FlUpdBlock
+ );
+
+ if(!EFI_ERROR(Status))
+ return Status;
+
+ return EFI_DEVICE_ERROR;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: GetFlUpdPolicy
+//
+// Description:
+//
+// Input:
+//
+// Output:
+//
+// Returns:
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetFlUpdPolicy(
+ IN OUT FLASH_POLICY_INFO_BLOCK *InfoBlock
+)
+{
+ UINT32 KeySize = DEFAULT_RSA_KEY_MODULUS_LEN;
+
+//TRACE((TRACE_ALWAYS,"SecSMI. GetPolicy. %X_%X\n",FlUpdatePolicy.FlashUpdate, FlUpdatePolicy.BBUpdate));
+
+ if(IsAddressInSmram((EFI_PHYSICAL_ADDRESS)InfoBlock, sizeof(FLASH_POLICY_INFO_BLOCK)))
+ return EFI_DEVICE_ERROR;
+
+ MemCpy(&InfoBlock->FlUpdPolicy, &FlUpdatePolicy, sizeof(FLASH_UPD_POLICY));
+ MemSet(&InfoBlock->PKpub, KeySize, 0xFF);
+ if(gpPubKeyHndl.BlobSize < KeySize)
+ KeySize = gpPubKeyHndl.BlobSize;
+ MemCpy(&InfoBlock->PKpub, gpPubKeyHndl.Blob, KeySize);
+
+ InfoBlock->ErrorCode = 0;
+
+ return EFI_SUCCESS;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: SetFlUpdMethod
+//
+// Description:
+//
+// Input:
+//
+// Output:
+//
+// Returns:
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS SetFlUpdMethod(
+ IN OUT FUNC_FLASH_SESSION_BLOCK *pSessionBlock
+)
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+#if RUNTIME_SECURE_UPDATE_FLOW == 1
+ UINT32 HashBlock;
+ UINT32 BlockSize;
+ UINT8 *BlockAddr;
+#endif
+ UINT32 *FSHandl;
+ APTIO_FW_CAPSULE_HEADER *pFwCapsuleHdr;
+
+//TRACE((TRACE_ALWAYS,"SecSMI. SetFlash\nSize : %X\n",pSessionBlock->FlUpdBlock.ImageSize));
+
+ if(IsAddressInSmram((EFI_PHYSICAL_ADDRESS)pSessionBlock, sizeof(FUNC_FLASH_SESSION_BLOCK)))
+ return EFI_DEVICE_ERROR;
+
+//if(pSessionBlock->FlUpdBlock.FlashOpType == FlRecovery)
+//TRACE((TRACE_ALWAYS,"File Name: %s\n",pSessionBlock->FlUpdBlock.FwImage.AmiRomFileName));
+//else
+//TRACE((TRACE_ALWAYS,"Image Adr: %X\n",pSessionBlock->FlUpdBlock.FwImage.CapsuleMailboxPtr[0]));
+
+//TRACE((TRACE_ALWAYS,"ROMmap : %X\n",pSessionBlock->FlUpdBlock.ROMSection));
+//TRACE((TRACE_ALWAYS,"FlOpType : %X\n",pSessionBlock->FlUpdBlock.FlashOpType));
+// Verify if chosen Flash method is compatible with FlUpd Policy
+ if(((pSessionBlock->FlUpdBlock.ROMSection & (1<<BOOT_BLOCK)) && (pSessionBlock->FlUpdBlock.FlashOpType & FlUpdatePolicy.BBUpdate)) ||
+ (!(pSessionBlock->FlUpdBlock.ROMSection & (1<<BOOT_BLOCK))&& (pSessionBlock->FlUpdBlock.FlashOpType & FlUpdatePolicy.FlashUpdate))
+ ){
+
+//TRACE((TRACE_ALWAYS,"Buff Adr : %X\nBuff Size: %X\n",pFwCapsuleLowMem, gRomFileSize));
+//!!! make sure Flash blocks BOOT_BLOCK, MAIN_, NV_ and EC_ are matching enum types in FlashUpd.h
+ // Get Flash Update mode
+ switch(pSessionBlock->FlUpdBlock.FlashOpType)
+ {
+#if FWCAPSULE_RECOVERY_SUPPORT == 1
+ case FlCapsule:
+#endif
+ case FlRuntime:
+ // common for FlRuntime or Capsule
+ if(pSessionBlock->FlUpdBlock.ImageSize > gFwCapMaxSize)
+ break; // suspecting buffer overrun.
+
+ SecSmiFlash.pFwCapsule = pFwCapsuleLowMem;
+ // AFU updates the address in CapsuleMailboxPtr if
+ // it's capable of allocating large buffer to load entire FW Capsule image
+ if(pSessionBlock->FlUpdBlock.FwImage.CapsuleMailboxPtr[0] != 0 )
+ {
+ if(IsAddressInSmram((EFI_PHYSICAL_ADDRESS)pSessionBlock->FlUpdBlock.FwImage.CapsuleMailboxPtr[0],
+ pSessionBlock->FlUpdBlock.ImageSize))
+ return EFI_DEVICE_ERROR;
+#if NEW_BIOS_MEM_ALLOC != 2
+ if(SecSmiFlash.pFwCapsule != NULL) {
+ // prevent leaking of the SMM code to the external buffer
+ if(!IsAddressInSmram((EFI_PHYSICAL_ADDRESS)SecSmiFlash.pFwCapsule, sizeof(UINTN)))
+ return EFI_DEVICE_ERROR;
+
+ MemCpy((UINT8*)SecSmiFlash.pFwCapsule,
+ (UINT8*)pSessionBlock->FlUpdBlock.FwImage.CapsuleMailboxPtr[0],
+ pSessionBlock->FlUpdBlock.ImageSize);
+ }
+ else
+#endif
+ SecSmiFlash.pFwCapsule = (UINT32*)pSessionBlock->FlUpdBlock.FwImage.CapsuleMailboxPtr[0];
+ }
+ // else AFU must've uploaded the image to designated SMM space using LoadFw command
+
+ // verify we got a capsule at pFwCapsuleLowMem, update a ptr to FwCapHdr within Payload image
+ Status = CapsuleValidate((UINT8**)&(SecSmiFlash.pFwCapsule), &pFwCapsuleHdr);
+ if(!pFwCapsuleHdr ||
+ EFI_ERROR(Status)) break;
+ // capture RomLayout from new Secure Image if it's loaded in memory and validated
+ SecSmiFlash.RomLayout = (ROM_AREA *)(UINTN)((UINT32)pFwCapsuleHdr+pFwCapsuleHdr->RomLayoutOffset);
+ if(pSessionBlock->FlUpdBlock.FlashOpType == FlRuntime)
+ {
+#if RUNTIME_SECURE_UPDATE_FLOW == 1
+ // Fill in gShaHashTbl Hash Table
+ BlockSize = FLASH_BLOCK_SIZE;
+ BlockAddr = (UINT8*)SecSmiFlash.pFwCapsule;
+ for(HashBlock = 0; HashBlock < SEC_FLASH_HASH_TBL_BLOCK_COUNT; HashBlock++)
+ {
+
+ Status = gAmiSig->Hash(gAmiSig, &gEfiHashAlgorithmSha256Guid,
+ 1, &BlockAddr, (const UINTN*)&BlockSize, gHashTbl[HashBlock]);
+ if (EFI_ERROR(Status)) break;
+ BlockAddr+= (UINTN)(BlockSize);
+ }
+#endif
+ // done for Runtime Upd
+ break;
+ }
+ // Set Capsule EFI Var if Capsule(Verify Capsule Mailbox points to FW_CAPSULE)
+ pSessionBlock->FlUpdBlock.ImageSize = pFwCapsuleHdr->CapHdr.CapsuleImageSize;
+#if FWCAPSULE_RECOVERY_SUPPORT == 1
+ Status = UpdateCapsule (pSessionBlock, pFwCapsuleHdr);
+ if(EFI_ERROR(Status)) break;
+#endif
+ // common for Recovery or Capsule
+ case FlRecovery:
+ // Set FlUpd EFI Var (Get MC, verify RecFileName)
+ Status = SetFlashUpdateVar (pSessionBlock);
+ break;
+
+ default:
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+
+ // Set Error Status
+ if (Status != EFI_SUCCESS) {
+ SecSmiFlash.FSHandle = 0;
+ SecSmiFlash.pFwCapsule = NULL;
+ SecSmiFlash.RomLayout = RomLayout; // back to default RomLayout
+ pSessionBlock->FSHandle = 0;
+ pSessionBlock->ErrorCode = 1;
+
+ return EFI_DEVICE_ERROR;
+ }
+ // FSHandle is updated if Capsule validation passed.
+ // Create FSHandle as 1st 4 bytes of gHashTbl. It must be different each time
+ // SetMethod is called with new Image
+ FSHandl = (UINT32*)gHashTbl;
+ SecSmiFlash.FSHandle = *FSHandl; // should be unique per Capsule;
+ pSessionBlock->FSHandle = SecSmiFlash.FSHandle;
+ pSessionBlock->ErrorCode = 0;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: LoadFwImage
+//
+// Description: Routine is called in a loop by the Flash tool.
+// Depending on the OS environment, Flash tool passes either an entire
+// Flash Image into SMM buffer or block by block.
+// E.g AFUDOS could allocate a contiguous buffer for the entire ROM buffer,
+// while certain OSes (Linux) may only allocate limited buffer sizes
+//
+// Input: FUNC_BLOCK -> Address, size
+//
+// Output: FUNC_BLOCK -> Status
+//
+// Returns:
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS LoadFwImage(
+ IN OUT FUNC_BLOCK *pFuncBlock
+)
+{
+ if(IsAddressInSmram((EFI_PHYSICAL_ADDRESS)pFuncBlock, sizeof(FUNC_BLOCK)))
+ return EFI_DEVICE_ERROR;
+
+ // prevent leaking of the SMM code to the external buffer
+ if(IsAddressInSmram((EFI_PHYSICAL_ADDRESS)pFuncBlock->BufAddr, pFuncBlock->BlockSize))
+ return EFI_DEVICE_ERROR;
+
+ pFuncBlock->ErrorCode = 1;
+
+ SecSmiFlash.FSHandle = 0; // clear out Hndl. Will be set to valid number in SetFlashMethod
+ SecSmiFlash.pFwCapsule = NULL;
+ SecSmiFlash.RomLayout = RomLayout; // back to default RomLayout
+
+//TRACE((TRACE_ALWAYS,"SecSMI. LoadImage at %X, size %X\n",(UINT32)pFwCapsuleLowMem + pFuncBlock->BlockAddr, pFuncBlock->BlockSize));
+
+ if(pFwCapsuleLowMem == NULL)
+ return EFI_DEVICE_ERROR;
+
+// assuming the address in 0 based offset in new ROM image
+ if((UINT64)((UINT32)pFwCapsuleLowMem + pFuncBlock->BlockAddr + pFuncBlock->BlockSize) >
+ (UINT64)((UINT32)pFwCapsuleLowMem + gFwCapMaxSize)
+ )
+ return EFI_DEVICE_ERROR;
+
+ MemCpy((VOID*)((UINT32)pFwCapsuleLowMem+pFuncBlock->BlockAddr),
+ (UINT8*)pFuncBlock->BufAddr, pFuncBlock->BlockSize);
+
+ pFuncBlock->ErrorCode = (UINT8)MemCmp(
+ (VOID*)((UINT32)pFwCapsuleLowMem+pFuncBlock->BlockAddr),
+ (VOID*)pFuncBlock->BufAddr, pFuncBlock->BlockSize);
+
+ pFuncBlock->ErrorCode = 0;
+
+ return EFI_SUCCESS;
+}
+// End Secured Flash Update API
+
+#if RUNTIME_SECURE_UPDATE_FLOW == 1
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: BeforeSecureUpdate
+//
+// Description: Verifies if the Update range is protected by Signature
+// 1. return Success if flash region is inside unSigned RomArea
+// 2. if region is signed - compare its hash with pre-calculated Hash in smm
+// and return pointer to internal DataBuffer
+//
+// Input:
+// VOID* FlashAddress Pointer to address of a flash
+//
+// Output: Status
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+EFI_STATUS BeforeSecureUpdate (
+ VOID* FlashAddress, UINTN Size, UINT8 **DataBuffer
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ ROM_AREA *Area;
+ UINT8 *BuffAddr;
+ UINT8 *PageAddr;
+ UINT8 HashCounter;
+ UINTN PageSize;
+ UINTN PageCount;
+ UINT32 *FSHandl;
+
+ // enforce write protection if RomArea undefined
+ if ( RomLayout == NULL )
+ Status = EFI_WRITE_PROTECTED;
+
+ for (Area = RomLayout; Area && Area->Size!=0; Area++)
+ {
+ if(Area->Address == 0) // construct an Address field if not initialized
+ Area->Address = (UINT64)((0xFFFFFFFF - FLASH_SIZE) + 1)+Area->Offset;
+//TRACE((-1, "RomArea %8X(%8X) + Size %8X = %8X, Attr %X\n",Area->Address,Area->Offset, Area->Size, (UINT64)((UINTN)Area->Address+Area->Size), Area->Attributes));
+ if(
+ (((UINT64)FlashAddress >= (UINT64)(Area->Address)) &&
+ ((UINT64)FlashAddress < (UINT64)(Area->Address+Area->Size)))
+ ||
+ (((UINT64)(Area->Address) >= (UINT64)FlashAddress) &&
+ ((UINT64)(Area->Address) < (UINT64)((UINT64)FlashAddress + Size))) )
+ {
+ if (Area->Attributes & ROM_AREA_FV_SIGNED)
+ {
+ Status = EFI_WRITE_PROTECTED;
+ break;
+ }
+//TRACE((-1, "\nSignAttr %x(%x)\nRomArea %8X, Size %8X, (%8X)\nFlsAddr %8X, Size %8X, (%8X)\n", Area->Attributes, (Area->Attributes & ROM_AREA_FV_SIGNED),
+// Area->Address, Area->Size, (UINT64)((UINTN)Area->Address+Area->Size),
+// (UINTN)FlashAddress, Size, (UINT64)((UINTN)FlashAddress+Size)));
+ }
+ }
+//if(Status != EFI_WRITE_PROTECTED) {
+// TRACE((-1, "SpiOffs %8X, Size %8X, (%8X)\n", (0-(UINTN)FlashAddress), Size, (0-(EFI_PHYSICAL_ADDRESS)((UINTN)FlashAddress+Size))));
+//}
+ if(Status == EFI_WRITE_PROTECTED &&
+ (FlUpdatePolicy.FlashUpdate & FlRuntime)
+ ){
+ // check Verify status by comparing FSHandl with gHashTbl[0]
+ // should be unique per Capsule;
+ FSHandl = (UINT32*)gHashTbl;
+ if(SecSmiFlash.FSHandle == 0 ||
+ SecSmiFlash.FSHandle != *FSHandl)
+ return Status; // EFI_WRITE_PROTECTED
+
+ PageSize = FLASH_BLOCK_SIZE;
+ PageCount=( (UINTN)FlashAddress - Flash4GBMapStart) / PageSize;
+
+ if(SecSmiFlash.pFwCapsule != NULL)
+ {
+ // Flash Write -> Update ptr to internal Acpi NVS or SMM Buffer
+ BuffAddr = (UINT8*)SecSmiFlash.pFwCapsule;
+ PageAddr = (UINT8*)((UINTN)BuffAddr + (PageSize * PageCount));
+ BuffAddr = (UINT8*)((UINTN)BuffAddr + ((UINTN)FlashAddress - Flash4GBMapStart));
+
+ Status = EFI_SUCCESS;
+ HashCounter = 2; // addr may rollover to next flash page
+ while(HashCounter-- && PageCount < SEC_FLASH_HASH_TBL_BLOCK_COUNT)
+ {
+ // compare calculated block hash with corresponding hash from the Hw Hash Table
+ // if no match -> make Size=0 to skip Flash Write Op
+ Status = gAmiSig->Hash(gAmiSig, &gEfiHashAlgorithmSha256Guid,
+ 1, (const UINT8**)&PageAddr, (const UINTN*)&PageSize, gHashDB);
+ if(EFI_ERROR(Status) ||
+ MemCmp(gHashDB, SecSmiFlash.HashTbl[PageCount], SHA256_DIGEST_SIZE)
+ ){
+//TRACE((-1, "Hash Err! FlashBuff = %8X, Data = %8X, BlockAddr=%x, BlockSize=%x\n", BuffAddr, *((UINT32*)BuffAddr), PageAddr, Size));
+ return EFI_WRITE_PROTECTED;
+ }
+ // repeat Hash check on next Flash Block if Write Block overlaps the Flash Block boundary
+ PageCount++;
+ PageAddr = (UINT8*)((UINTN)PageAddr + PageSize);
+ if((BuffAddr+Size) <= PageAddr)
+ break;
+ }
+ // Erase
+ if(DataBuffer != NULL)
+ *DataBuffer = BuffAddr;
+ }
+ }
+
+ return Status;
+}
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: SecureFlashWrite
+//
+// Description: Allows to write to flash device is Secure Capsule is loaded into memory
+// Function replacing Flash->Write API call
+//
+// Input: VOID* FlashAddress, UINTN Size, VOID* DataBuffer
+//
+//
+// Output: EFI_SUCCESS
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+EFI_STATUS SecureFlashWrite (
+ VOID* FlashAddress, UINTN Size, VOID* DataBuffer
+)
+{
+ EFI_STATUS Status;
+ UINT8 *CurrBuff;
+
+ CurrBuff = (UINT8*)DataBuffer;
+ Status = BeforeSecureUpdate(FlashAddress, Size, &CurrBuff);
+//TRACE((-1, "SecSMIFlash Write %X, BuffAddr=%X(%X) Lock Status=%r\n", FlashAddress, DataBuffer, CurrBuff, Status));
+ if(!EFI_ERROR(Status))
+ return pFlashWrite(FlashAddress, Size, CurrBuff);
+
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: SecureFlashErase
+//
+// Description: Allows erase of flash device is Secure Capsule is loaded into memory
+// Function replacing Flash->Erase API call
+//
+// Input: NON
+//
+//
+// Output: EFI_SUCCESS
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+EFI_STATUS SecureFlashErase (
+ VOID* FlashAddress, UINTN Size
+)
+{
+ EFI_STATUS Status;
+
+ Status = BeforeSecureUpdate(FlashAddress, Size, NULL);
+//TRACE((-1, "SecSMIFlash Erase %X - %X Lock Status=%r\n", FlashAddress, Size, Status));
+ if(!EFI_ERROR(Status))
+ return pFlashErase(FlashAddress, Size);
+
+ return Status;//EFI_SUCCESS;
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: GetFwCapFfs
+//
+// Description: Loads binary from RAW section of X firwmare volume
+//
+// Input:
+// NameGuid - The guid of binary file
+// Buffer - Returns a pointer to allocated memory. Caller must free it when done.
+// Size - Returns the size of the binary loaded into the buffer.
+//
+// Output: Buffer - returns a pointer to allocated memory. Caller
+// must free it when done.
+// Size - returns the size of the binary loaded into the
+// buffer.
+// EFI_NOT_FOUND - Can't find the binary.
+// EFI_LOAD_ERROR - Load fail.
+// EFI_SUCCESS - Load success.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+GetFwCapFfs (
+ IN EFI_GUID *NameGuid,
+ IN OUT VOID **Buffer,
+ IN OUT UINTN *Size
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ UINTN Index;
+ EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
+ EFI_HANDLE *HandleBuff;
+ UINT32 AuthenticationStatus;
+
+ *Buffer=0;
+ *Size=0;
+ Status = pBS->LocateHandleBuffer (ByProtocol,&gEfiFirmwareVolumeProtocolGuid,NULL,&HandleCount,&HandleBuff);
+ if (EFI_ERROR (Status) || HandleCount == 0) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Find desired image in all Fvs
+ //
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = pBS->HandleProtocol (HandleBuff[Index],&gEfiFirmwareVolumeProtocolGuid,&Fv);
+
+ if (EFI_ERROR (Status)) {
+ continue;//return EFI_LOAD_ERROR;
+ }
+ //
+ // Try a raw file
+ //
+ Status = Fv->ReadSection (
+ Fv,
+ NameGuid, //&gFwCapFfsGuid,
+ EFI_SECTION_FREEFORM_SUBTYPE_GUID,//EFI_SECTION_RAW
+ 0, //Instance
+ Buffer,
+ Size,
+ &AuthenticationStatus
+ );
+
+ if (Status == EFI_SUCCESS) break;
+ }
+
+ pBS->FreePool(HandleBuff);
+
+ if (Index >= HandleCount) {
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: GetRomLayout
+//
+// Description:
+//
+// Input:
+// IN EFI_HANDLE ImageHandle Image Handle
+// IN EFI_SYSTEM_TABLE *SystemTable Pointer to System Table
+//
+// Output: EFI_STATUS
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+EFI_STATUS GetRomLayout(
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ EFI_SMM_BASE_PROTOCOL *SmmBase,
+ OUT ROM_AREA **RomLayout
+)
+{
+ EFI_STATUS Status;
+ static EFI_GUID HobListGuid = HOB_LIST_GUID;
+ static EFI_GUID AmiRomLayoutHobGuid = AMI_ROM_LAYOUT_HOB_GUID;
+ ROM_LAYOUT_HOB *RomLayoutHob;
+ UINTN RomLayoutSize=0, Size;
+ ROM_AREA *Area;
+ APTIO_FW_CAPSULE_HEADER *FwCapHdr;
+ UINT8* pFwCapHdr=NULL;
+
+// 1. Try to locate RomLayout from embedded CapHdr Ffs
+ Status = GetFwCapFfs(&gFwCapFfsGuid, &pFwCapHdr, &Size);
+ if(!EFI_ERROR(Status))
+ {
+ // Skip over Section GUID
+ FwCapHdr = (APTIO_FW_CAPSULE_HEADER*)pFwCapHdr;
+ (UINT8*)FwCapHdr += sizeof (EFI_GUID);
+ Size -= sizeof (EFI_GUID);
+ *RomLayout = (ROM_AREA *)(UINTN)((UINT32)FwCapHdr+FwCapHdr->RomLayoutOffset);
+ RomLayoutSize = sizeof(ROM_AREA);
+ for (Area=*RomLayout; Area->Size!=0 && RomLayoutSize<=(Size - FwCapHdr->RomLayoutOffset); Area++)
+ {
+ RomLayoutSize+=sizeof(ROM_AREA);
+ }
+// TRACE((-1, "Get Rom Map from the FwCap FFS at %X(size 0x%X)\nRomLayout offs %X(size 0x%X)\n", FwCapHdr, Size, FwCapHdr->RomLayoutOffset, RomLayoutSize));
+ Area=*RomLayout;
+ }
+ else
+ {
+// 2. Backup: Use primary RomLayout from Rom Layout HOB.
+// This one does not yet report the Rom Hole regions
+ //----- Get HobList -------------------------------------
+ RomLayoutHob = GetEfiConfigurationTable(SystemTable, &HobListGuid);
+ if (RomLayoutHob!=NULL)
+ {
+ // -------- Get RomLayoutHob ----------------------
+ if (!EFI_ERROR(
+ FindNextHobByGuid(&AmiRomLayoutHobGuid, &RomLayoutHob)
+ ))
+ {
+ RomLayoutSize = RomLayoutHob->Header.Header.HobLength
+ - sizeof(ROM_LAYOUT_HOB);
+
+ Area=(ROM_AREA*)((UINT8*)RomLayoutHob+1);
+ //TRACE((-1, "Get Default Rom Map from the Hob at %X\n", Area));
+ }
+ }
+ }
+ if(RomLayoutSize)
+ {
+ //---Allocate memory in SMRAM for RomLayout---
+ *RomLayout = NULL;
+ Status = pSmst->SmmAllocatePool(EfiRuntimeServicesData, RomLayoutSize,(void **)RomLayout);
+ if (EFI_ERROR(Status) || *RomLayout == NULL)
+ return EFI_NOT_FOUND;
+
+ pBS->CopyMem( *RomLayout, Area, RomLayoutSize);
+
+ if(pFwCapHdr)
+ pBS->FreePool(pFwCapHdr);
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+#endif //#if RUNTIME_SECURE_UPDATE_FLOW == 1
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IsAddressInSmram
+//
+// Description: CThis function check if the address is in SMRAM
+//
+// Input:
+// Address - the buffer address to be checked.
+// Range - the buffer length to be checked
+//
+// Output:
+// TRUE this address is in SMRAM.
+// FALSE this address is NOT in SMRAM.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN IsAddressInSmram (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+)
+{
+ UINTN Index;
+//TRACE((TRACE_ALWAYS,"Addr in SMRAM %X_%X\n",Buffer, Length));
+ for (Index = 0; Index < mSmramRangeCount; Index ++) {
+ if (((Buffer >= mSmramRanges[Index].CpuStart) && (Buffer < mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize)) ||
+ ((mSmramRanges[Index].CpuStart >= Buffer) && (mSmramRanges[Index].CpuStart < Buffer + Length))) {
+//TRACE((TRACE_ALWAYS,"TRUE\n"));
+ return TRUE;
+ }
+ }
+//TRACE((TRACE_ALWAYS,"FALSE\n"));
+ return FALSE;
+}
+
+// !!! do not install if OFBD SecFlash is installed
+#if INSTALL_SECURE_FLASH_SW_SMI_HNDL == 1
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: SecSMIFlashSMIHandler
+//
+// Description:
+//
+// Input:
+//
+// Output:
+//
+// Returns:
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SecSMIFlashSMIHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext
+)
+{
+ EFI_SMM_CPU_SAVE_STATE *pCpuSaveState;
+ SW_SMI_CPU_TRIGGER *SwSmiCpuTrigger;
+ UINT8 Data;
+ UINT64 pCommBuff;
+ UINT32 HighBufferAddress = 0;
+ UINT32 LowBufferAddress = 0;
+ UINTN i;
+ UINTN Cpu = pSmst->CurrentlyExecutingCpu - 1;
+
+ for (i = 0; i < pSmst->NumberOfTableEntries; ++i) {
+ if (guidcmp(&pSmst->SmmConfigurationTable[i].VendorGuid,&gSwSmiCpuTriggerGuid) == 0) {
+ break;
+ }
+ }
+
+ //If found table, check for the CPU that caused the software Smi.
+ if (i != pSmst->NumberOfTableEntries) {
+ SwSmiCpuTrigger = pSmst->SmmConfigurationTable[i].VendorTable;
+ Cpu = SwSmiCpuTrigger->Cpu;
+ }
+
+ //
+ // Found Invalid CPU number, return
+ //
+ if(Cpu == (UINTN) -1) {
+ return;
+ }
+
+ Data = (UINT8)DispatchContext->SwSmiInputValue;
+
+ pCpuSaveState = pSmst->CpuSaveState;
+ HighBufferAddress = pCpuSaveState[Cpu].Ia32SaveState.ECX;
+ LowBufferAddress = pCpuSaveState[Cpu].Ia32SaveState.EBX;
+ pCommBuff = HighBufferAddress;
+ pCommBuff = Shl64(pCommBuff, 32);
+ pCommBuff += LowBufferAddress;
+
+//TRACE((-1, "Sec SW SMI Flash Hook == 0x%x\n", Data));
+
+ switch(Data)
+ {
+ case SecSMIflash_Load: // 0x1d Send Flash Block to memory
+ LoadFwImage((FUNC_BLOCK *)pCommBuff);
+ break;
+
+ case SecSMIflash_GetPolicy: // 0x1e Get Fl Upd Policy
+ GetFlUpdPolicy((FLASH_POLICY_INFO_BLOCK *)pCommBuff);
+ break;
+
+ case SecSMIflash_SetFlash: // 0x1f Set Flash method
+ SetFlUpdMethod((FUNC_FLASH_SESSION_BLOCK *)pCommBuff);
+ break;
+ }
+}
+#endif
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: InSmmFunction
+//
+// Description:
+//
+// Input:
+//
+// Output:
+//
+// Returns:
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS InSmmFunction(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
+{
+#if INSTALL_SECURE_FLASH_SW_SMI_HNDL == 1
+ EFI_SMM_SW_DISPATCH_PROTOCOL *pSwDispatch = NULL;
+ EFI_SMM_SW_DISPATCH_CONTEXT SwContext;
+ UINTN Index;
+#endif
+#if FWCAPSULE_RECOVERY_SUPPORT == 1
+ EFI_SMM_SX_DISPATCH_CONTEXT SxDispatchContext;
+ EFI_SMM_SX_DISPATCH_PROTOCOL *SxDispatchProtocol;
+#endif
+
+ EFI_HANDLE Handle = NULL;
+ EFI_HANDLE DummyHandle = NULL;
+ EFI_STATUS Status;
+
+ UINTN Size = 0;
+ UINT8 MinSMIPort = SecSMIflash_Load; //0x1d
+ //UINT8 MinSMIPort = SecSMIflash_GetPolicy; //0x1e;
+ UINT8 MaxSMIPort = SecSMIflash_SetFlash; //0x1f;
+
+//PI 1.1 ++
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)
+ EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;
+#else
+ EFI_SMM_ACCESS_PROTOCOL *SmmAccess;
+#endif
+
+ InitAmiSmmLib( ImageHandle, SystemTable );
+
+ Status = pBS->LocateProtocol(&gAmiSmmDigitalSignatureProtocolGuid, NULL, &gAmiSig);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR(Status)) return Status;
+
+// Test if Root Platform Key is available,else - don't install Flash Upd security measures.
+ gpPubKeyHndl.Blob = NULL;
+ gpPubKeyHndl.BlobSize = 0;
+ Status = gAmiSig->GetKey(gAmiSig, &gpPubKeyHndl, &gPRKeyGuid, gpPubKeyHndl.BlobSize, 0);
+//TRACE((TRACE_ALWAYS,"GetKey %r (%x, %d bytes)\n",Status, gpPubKeyHndl.Blob,gpPubKeyHndl.BlobSize));
+ if (EFI_ERROR(Status) || gpPubKeyHndl.Blob == NULL) {
+ if(Status == EFI_BUFFER_TOO_SMALL)
+ return EFI_SUCCESS;
+ return Status;
+ }
+ //
+ // Get SMRAM information
+ //
+//PI 1.1 ++
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)
+ Status = pBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR(Status)) return Status;
+#else
+ Status = pBS->LocateProtocol(&gEfiSmmAccessProtocolGuid, NULL, &SmmAccess);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) return Status;
+#endif
+ Size = 0;
+ Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+ if (Size==0) return EFI_NOT_FOUND;
+ Status = pSmst->SmmAllocatePool (EfiRuntimeServicesData,Size,(VOID **)&mSmramRanges);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR(Status)) return Status;
+ Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges);
+ if (EFI_ERROR(Status)) return Status;
+ mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);
+ //
+ // Allocate scratch buffer to hold entire Signed BIOS image for Secure Capsule and Runtime Flash Updates
+ // AFU would have to execute a sequence of SW SMI calls to push entire BIOS image to SMM
+ //
+ //NEW_BIOS_MEM_ALLOC == 2 AFU will allocate a buffer and provide pointer via SET_FLASH_METHOD API call.
+ //
+#if NEW_BIOS_MEM_ALLOC == 0
+ //
+ // Alternatively the buffer may be reserved within the SMM TSEG memory
+ //
+ Status = pSmmBase->SmmAllocatePool(pSmmBase, EfiRuntimeServicesData, gFwCapMaxSize, (void**)&pFwCapsuleLowMem);
+
+//TRACE((TRACE_ALWAYS,"SecSmiFlash: Alloc 0x%X bytes in SMM, %r\n",gRomFileSize, Status));
+#else
+#if NEW_BIOS_MEM_ALLOC == 1
+ //
+ // The buffer allocated in OS reserved memory below 4GB
+ //
+// Status = pST->BootServices->AllocatePool(EfiReservedMemoryType, gRomFileSize, &pFwCapsuleLowMem);
+ pFwCapsuleLowMem = (UINT32*)0xFFFFFFFF;
+ Status = pST->BootServices->AllocatePages(AllocateMaxAddress, EfiReservedMemoryType,
+ EFI_SIZE_TO_PAGES(gFwCapMaxSize), (EFI_PHYSICAL_ADDRESS*)&pFwCapsuleLowMem);
+//TRACE((TRACE_ALWAYS,"SecSmiFlash: AllocatePages=%X,(0x%x) %r\n",pFwCapsuleLowMem,gRomFileSize, Status));
+#endif
+#endif
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) return Status;
+#if NEW_BIOS_MEM_ALLOC < 2
+ MemSet((void*)pFwCapsuleLowMem, gFwCapMaxSize, 0 );
+#endif
+ //
+ // Allocate space to hold a Hash table for all Flash blocks
+ //
+ Size = SEC_FLASH_HASH_TBL_SIZE;
+ Status = pSmmBase->SmmAllocatePool(pSmmBase, EfiRuntimeServicesData, Size, (void**)&gHashTbl);
+ if (EFI_ERROR(Status)) return Status;
+ MemSet((void*)gHashTbl, Size, 0xdb );
+
+#if FWCAPSULE_RECOVERY_SUPPORT == 0
+ FlUpdatePolicy.FlashUpdate &=~FlCapsule;
+ FlUpdatePolicy.BBUpdate &=~FlCapsule;
+#else
+ //
+ // Reserve pool in smm runtime memory for capsule's mailbox list
+ //
+ Size = 4*sizeof(EFI_CAPSULE_BLOCK_DESCRIPTOR) + sizeof(EFI_CAPSULE_HEADER); // (4*16)+28
+ Status = pSmmBase->SmmAllocatePool(pSmmBase, EfiRuntimeServicesData, Size, (void**)&gpEfiCapsuleHdr);
+//TRACE((TRACE_ALWAYS,"Mailbox: AllocatePages=%X,(0x%x) %r\n",gpEfiCapsuleHdr,Size, Status));
+ if (EFI_ERROR(Status)) return Status;
+ MemSet((void*)gpEfiCapsuleHdr, Size, 0 );
+
+ //
+ // Install callback on S5 Sleep Type SMI. Needed to transition to S3 if Capsule's mailbox ie pending
+ // Locate the Sx Dispatch Protocol
+ //
+ // gEfiSmmSxDispatch2ProtocolGuid
+ Status = pBS->LocateProtocol (&gEfiSmmSxDispatchProtocolGuid,NULL,&SxDispatchProtocol);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR(Status)) return Status;
+ //
+ // Register the callback for S5 entry
+ //
+ if (SxDispatchProtocol && SupportUpdateCapsuleReset()) {
+ SxDispatchContext.Type = SxS5;
+ SxDispatchContext.Phase = SxEntry;
+ Status = SxDispatchProtocol->Register (SxDispatchProtocol,SmiS5CapsuleCallback,&SxDispatchContext,&Handle);
+ ASSERT_EFI_ERROR (Status);
+ }
+ if (EFI_ERROR(Status)) goto Done;
+#endif
+#if RUNTIME_SECURE_UPDATE_FLOW == 1
+/*
+AFU For Rom Holes in Runtime/Capsule upd
+ 1. Read full ROM image to ROM buffer
+ 2. Merge Rom Hole from input file to ROM buffer
+ 3. call "LoadImage" for full BIOS
+ 3. call "SetFlash" with Runtime update (NVRAM block should be unsigned!!!)
+ 4. calls to upd Rom hole -erase,write should pass
+*/
+ Status = GetRomLayout(SystemTable, pSmmBase, &RomLayout);
+//TRACE((TRACE_ALWAYS,"SecSmiFlash: Get Rom Layout ptr=%X, %r\n",RomLayout, Status));
+ // Rom Layout HOB may not be found in Recovery mode and if FW does not include built in FwCapsule Hdr file
+// if (EFI_ERROR(Status)) goto Done;
+ //
+ // Trap the original Flash Driver API calls to enforce
+ // Flash Write protection in SMM at the driver API level
+ //
+ Status = pBS->LocateProtocol(&gFlashSmmProtocolGuid, NULL, &Flash);
+//TRACE((TRACE_ALWAYS,"SecSmiFlash: Flash Protocol Fixup %X->%X\n",Flash->Write,SecureFlashWrite));
+ if (EFI_ERROR(Status)) goto Done;
+
+ // preserve org Flash API
+ pFlashWrite = Flash->Write;
+ pFlashErase = Flash->Erase;
+ // replace with local functions
+ Flash->Erase = SecureFlashErase;
+ Flash->Write = SecureFlashWrite;
+ // Calculate the flash mapping start address. This is calculated
+ // as follows:
+ // 1. Find the total size of the flash (FLASH_BLOCK_SIZE * NUMBER_OF_BLOCKS)
+ // 2. Subtract the total flash size from 4GB
+ Flash4GBMapStart = 0xFFFFFFFF - (FLASH_BLOCK_SIZE * NUMBER_OF_BLOCKS);
+ Flash4GBMapStart ++;
+#endif
+ //
+ // Install Secure SMI Flash Protocol
+ //
+ SecSmiFlash.pFwCapsule = pFwCapsuleLowMem;
+ SecSmiFlash.HashTbl = gHashTbl;
+ SecSmiFlash.RomLayout = RomLayout;
+// SecSmiFlash.FSHandle = 0;
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &DummyHandle,
+ &gSecureSMIFlashProtocolGuid,&SecSmiFlash,
+ NULL
+ );
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) return Status;
+
+ //
+ // Install SW SMI callbacks for 3 SecSMI Flash functions
+ // !!! do not install if OFBD SecFlash is installed
+ //
+#if INSTALL_SECURE_FLASH_SW_SMI_HNDL == 1
+ Status = pBS->LocateProtocol(&gEfiSmmSwDispatchProtocolGuid, NULL, &pSwDispatch);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) return EFI_SUCCESS;
+
+ for(Index=MinSMIPort;Index<=MaxSMIPort;Index++)
+ {
+ SwContext.SwSmiInputValue = Index;
+ Status = pSwDispatch->Register(pSwDispatch, SecSMIFlashSMIHandler, &SwContext, &Handle);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) break;
+ //If any errors,unregister any registered SwSMI by this driver.
+ //If error, and driver is unloaded, then a serious problem would exist.
+ }
+#endif
+Done:
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: SecSMIFlashDriverEntryPoint
+//
+// Description: Secure SMI Flash driver init
+//
+// Input:
+//
+// Output:
+//
+// Returns:
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS SecSMIFlashDriverEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ InitAmiLib(ImageHandle, SystemTable);
+ return InitSmmHandler(ImageHandle, SystemTable, InSmmFunction, NULL);
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.cif b/Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.cif
new file mode 100644
index 0000000..5a62525
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.cif
@@ -0,0 +1,16 @@
+<component>
+ name = "Secure SMIFlash"
+ category = ModulePart
+ LocalRoot = "CORE\EM\SecurityPkg\SecSMIFlash\"
+ RefName = "SecSMIFlash"
+[files]
+"SecSMIFlash.sdl"
+"SecSMIFlash.mak"
+"SecSMIFlash.dxs"
+"SecSMIFlash.c"
+"VerifyFwCapsule.c"
+[parts]
+"SecSMIFlashProtocols"
+[dependOn]
+"SMIFlash"
+<endComponent>
diff --git a/Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.dxs b/Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.dxs
new file mode 100644
index 0000000..f28ae6d
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.dxs
@@ -0,0 +1,67 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SecureFlashPkg/SecureSmiFlash/SecSMIFlash.dxs 4 3/18/14 3:12p Alexp $
+//
+// $Revision: 4 $
+//
+// $Date: 3/18/14 3:12p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureFlashPkg/SecureSmiFlash/SecSMIFlash.dxs $
+//
+// 4 3/18/14 3:12p Alexp
+// update year to 2014 in ftr & hdr
+//
+// 3 8/10/12 11:42a Alexp
+// Removed dependency on Flash Update protocol
+//
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: SMIFlash_dxs
+//
+// Description:
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include <Protocol/SmiFlash.h>
+#include <Protocol/SmmBase.h>
+#include <Protocol/SmmSwDispatch.h>
+#include <Protocol/AmiDigitalSignature.h>
+
+DEPENDENCY_START
+ EFI_SMI_FLASH_GUID AND
+ EFI_SMM_BASE_PROTOCOL_GUID AND
+ EFI_SMM_SW_DISPATCH_PROTOCOL_GUID AND
+ AMI_SMM_DIGITAL_SIGNATURE_PROTOCOL_GUID
+DEPENDENCY_END
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.mak b/Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.mak
new file mode 100644
index 0000000..25aae09
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.mak
@@ -0,0 +1,108 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2014, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#************************************************************************//
+# $Header: /Alaska/SOURCE/Modules/SecureFlashPkg/SecureSmiFlash/SecSMIFlash.mak 14 3/18/14 3:12p Alexp $
+#
+# $Revision: 14 $
+#
+# $Date: 3/18/14 3:12p $
+#************************************************************************//
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/SecureFlashPkg/SecureSmiFlash/SecSMIFlash.mak $
+#
+# 14 3/18/14 3:12p Alexp
+# update year to 2014 in ftr & hdr
+#
+# 13 11/21/12 10:40a Alexp
+# do not link CryptoLib with SecSmiFlash.
+#
+# 12 8/10/12 11:48a Alexp
+# Removed build rules of now obsolete SecSmiFlashHooks
+#
+# 11 5/18/12 5:03p Alexp
+# 1. Link Crypto Library with VerifyFwCap in Recovery boot flow.Use Hash
+# functions only
+# 2. Pass SEC_FLASH_GUID_DEFINES containing unique FwCap Ffs Guid and
+# Section guids
+#
+# 10 12/01/11 5:30p Alexp
+# restore build rules. When needed, PRESERVE_LIB eLink can be reused
+#
+# 9 12/01/11 3:37p Alexp
+# Add Build target for SecSmiFlashHooks library. New lib is linked to
+# SmiFlash and (or) OFBD SecFlash via PRESERVE_LIB eLink list
+#
+# 7 11/30/11 8:13p Alexp
+# left optional link rules for future usage with Ofbd module
+#
+# 5 9/20/11 2:20p Alexp
+# removed linkage of SecFlashHooks with ReFlash.
+#
+# 4 8/18/11 4:47p Alexp
+# 1. Add Depex rule to launch SecSmiFlash after AimDigitalSig protocol is
+# available
+# 2. Link SecSMIFlashHooks to ReFlash driver. Needed to preserve
+# SecureVars on Recovery style reFlash
+#
+# 3 8/11/11 5:32p Alexp
+# updated header
+#
+# 2 8/05/11 3:28p Alexp
+# add SMM_COMPILE flag to SecSMIFlashHook compile rules
+#
+#************************************************************************//
+
+all : SecSMIFlash
+
+SecSMIFlash : $(BUILD_DIR)\SecSMIFlash.mak SecSMIFlashBin
+
+$(BUILD_DIR)\SecSMIFlash.mak : $(SEC_SMI_FLASH_DIR)\SecSMIFlash.cif $(SEC_SMI_FLASH_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(SEC_SMI_FLASH_DIR)\SecSMIFlash.cif $(CIF2MAK_DEFAULTS)
+
+BUILD_SecSMIFlash_DIR = $(BUILD_DIR)\$(SEC_SMI_FLASH_DIR)
+
+SecSMIFlash_INCLUDES= \
+ /I $(SEC_SMI_FLASH_DIR)\
+ /I$(CORE_DIR)
+
+SecSMIFlash_OBJECTS = \
+ $(BUILD_SecSMIFlash_DIR)\SecSMIFlash.obj \
+ $(BUILD_SecSMIFlash_DIR)\VerifyFwCapsule.obj
+
+SecSMIFlashBin : $(AMIDXELIB) $(AMICSPLib)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\SecSMIFlash.mak all\
+ GUID=3BF4AF16-AB7C-4b43-898D-AB26AC5DDC6C\
+ ENTRY_POINT=SecSMIFlashDriverEntryPoint\
+ OBJECTS="$(SecSMIFlash_OBJECTS)" \
+ "CFLAGS=$(CFLAGS) $(SEC_FLASH_GUID_DEFINES)" \
+ TYPE=RT_DRIVER "EXT_HEADERS=$(BUILD_DIR)\token.h"\
+ DEPEX1=$(SEC_SMI_FLASH_DIR)\SecSMIFlash.DXS DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX \
+ COMPRESS=1
+
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2014, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
diff --git a/Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.sdl b/Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.sdl
new file mode 100644
index 0000000..f0ad04a
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecSMIFlash/SecSMIFlash.sdl
@@ -0,0 +1,74 @@
+TOKEN
+ Name = "SecSMIFlash_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable Secured SMIFlash support in Project"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "INSTALL_SECURE_FLASH_SW_SMI_HNDL"
+ Value = "0"
+ Help = "Install SecFlash SW SMI callbacks. Not needed if OFBD Secure Flash is present"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "NEW_BIOS_MEM_ALLOC"
+ Value = "1"
+ Help = "Memory buffer location for new BIOS image.\0-SMM TSEG, 1-ACPI NVS, 2-allocated by AFU"
+ Range = "0-1-2"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "CSLIB_WARM_RESET_SUPPORTED"
+ Value = "0"
+ Help = "1 - Chipset provides SBLib_ResetSystem(EfiResetWarm).\0 - Simulate Warm Reset via S3 & RTC resume."
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "SwSmi_LoadFwImage"
+ Value = "0x1d"
+ Help = "SW SMI value for Load FW image to SMM RAM"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "SwSmi_GetFlashPolicy"
+ Value = "0x1e"
+ Help = "SW SMI value for Get Fl Upd Policy"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "SwSmi_SetFlashMethod"
+ Value = "0x1f"
+ Help = "SW SMI value for Set Fl Upd Method"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+PATH
+ Name = "SEC_SMI_FLASH_DIR"
+End
+
+MODULE
+ Help = "Includes SecSMIFlash.mak to Project"
+ File = "SecSMIFlash.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\SecSMIFlash.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
diff --git a/Core/EM/SecurityPkg/SecSMIFlash/VerifyFwCapsule.c b/Core/EM/SecurityPkg/SecSMIFlash/VerifyFwCapsule.c
new file mode 100644
index 0000000..b078df2
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecSMIFlash/VerifyFwCapsule.c
@@ -0,0 +1,790 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SecureFlashPkg/SecureSmiFlash/VerifyFwCapsule.c 30 7/03/14 10:15a Alexp $
+//
+// $Revision: 30 $
+//
+// $Date: 7/03/14 10:15a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureFlashPkg/SecureSmiFlash/VerifyFwCapsule.c $
+//
+// 30 7/03/14 10:15a Alexp
+// EIP176297: Fix bug in condition expresison inside For loops.
+//
+// 29 5/20/14 5:22p Alexp
+// Replace a var name gRomFileSize to a more appropriate gFwCapMaxSize
+//
+// 27 3/20/14 12:31p Alexp
+// 1. Don't re-read FwKey. Use gpPubKeyHndl
+// 2. CapsuleValidate: sanity check: FwCapHdr RomImageOffset checked
+// against max size
+// (FWCAPSULE_IMAGE_SIZE-FLASH_SIZE)
+// 3. CapsuleValidate: add parameter check pFWCapsuleHdr != NULL
+//
+// 26 8/22/13 11:34a Alexp
+// VerifyFwCertRsa2048Sha256() - Break a loop after RootCert Verify if key
+// match is found. Old code would cycle through all certs.
+//
+// 25 8/12/13 4:31p Alexp
+// add check for end of Certificate block marker
+//
+// 24 7/11/13 3:41p Alexp
+// Removed check for FWCAPSULE_MAX_HDR_SIZE. Replaced it with fixed 0x8000
+// value
+//
+// 23 6/27/13 9:43a Alexp
+// fixed range check in ROM_MAP table processing.
+//
+// 22 6/21/13 11:00a Alexp
+// HashFwRomMapImage(): add check for address overflow in UIN32 build mode
+//
+// 21 6/12/13 3:51p Alexp
+// 1. CapsuleValidate() made external function in SecSmiFlash API
+// EIP#125800 : Privilege escalation into SMM via Secure SMI Flash SMM
+// driver via GetFlUpdPolicy and SetFlUpdMethod - BugID 305294
+// add IsAddressInSmram() checks inside exposed API functions
+// 2. VerifyFwCertRsa2048Sha256() - parse multiple chained RootKey
+// certificate structures in FwCert header
+//
+// 20 12/17/12 2:51p Alexp
+// fix cppcheck style check finds
+//
+// 19 11/21/12 10:44a Alexp
+// EIP#105015: Implemented handling of Pkcs7# Certificate in Aptio Fw
+// Capsule update packages
+// Replace direct calls to Hash() infrom CryptoLib with calls to Crypto
+// API. Saves ROM space
+//
+//
+// 18 11/20/12 3:30p Alexp
+// EIP[104046]: Findings from Security review on Aptio4 Image verification
+// Includes the fix for item #10: hardening of RomMap parsing oin
+// FwCapsule update
+//
+// 17 11/13/12 3:23p Alexp
+// 1. EIP#106359 : Secure Flash Cross function fail.
+// Move FwCapSectionGuid define outside of #if branch
+// 2. Calculate offset to RomLayout table within FwCapsHdr instead of
+// using hardwired location. Pkcs#7
+// cert will differ in size and offset may change
+// 3. Remove dependency on FWSIG_SIGNHDR flag. Use Capsule flags instead.
+//
+// 16 9/18/12 6:59p Alexp
+// Bug: Recovery update was broken for FwCapsule with embedded signature
+// and FwSig_hdr token 0.
+// Fix: FindCapHdrFFS() change Ffs Hdr size testing
+//
+// 15 9/06/12 7:28p Alexp
+// Add new IGNORE_RUNTIME_UPDATE_IMAGE_REVISION_CHECK flag
+// When set, FW Capsule Validate logic will skip image Revision check only
+// for Runtime updates
+//
+// 14 7/26/12 3:26p Alexp
+// replaced #if FWSIG_PADDING == 0 with #if FWSIG_SIGNHDR == 1.
+// Flag in the FwCap Hdr to switch between PKCS1_5 and PSS padding is
+// available only if #if FWSIG_SIGNHDR == 1
+//
+// 13 5/21/12 4:55p Alexp
+// keep a pointer to FwCaps Hdr withing Capsule image. Streamlines
+// creation of Capsule Mailbox.
+//
+// 12 5/18/12 5:14p Alexp
+// 1. Add support for Embedded FwSignature file
+// 2. EIP:89687 Replace Hash PPI calls with calls to Crypto lib
+// functions.
+// Allows to support RomMap tables in FwCaps Hdr with unlimited
+// number of
+// entries
+// 3. VerifyFwVersion.
+// a) Moved the call after Rom image signature is verified.;
+// b) search $FID struct only in signed FVs with PEI or DXE
+// attributes
+//
+// 11 4/25/12 2:11p Alexp
+// Platform FW Key is compared with either Signing or if no match - with
+// RootKey certificates
+//
+// 9 3/09/12 11:16a Alexp
+// VerifyFwImage-> fixed logic to process RomMap entries.
+// Number of signed elements in RomMap may not exceed max_num_elem
+// constant.
+// Overall number of elements in th RomMap may not exceed max_num_elem x 2
+//
+// 8 2/29/12 4:13p Alexp
+// Update format of Capsule signing:
+// 1. Entire Cap Hdr and FW_Cert Hdr are included in SigCert Signature
+// calculation. Improves Cap image security
+// 2. RootKey signs only SignKey buffer and not entire Sign Certificate.
+// No need for resigning of RootCert each time SignCert is being created
+//
+// 7 2/13/12 1:57p Alexp
+// GetFidData: Use 1 byte alligned pointer in searching "Section Guid".
+// Fixes the issue with RomMap entries that are not 4 byte alligned
+//
+// 6 12/29/11 4:00p Alexp
+// VerifyProjectId().
+// Calculate size of ProjectId string based on SDL Token PROJECT_TAG
+//
+// 5 11/30/11 8:04p Alexp
+// FW Revision searched inside FID structure. Simplified the search
+// throughout FW block by 4byte aligned $FID signature only
+//
+// 4 10/17/11 11:26a Alexp
+// Fix misspelled FidSignature name
+//
+// 3 9/29/11 3:27p Alexp
+// Bug fix. EIP#71244: No Rollback support
+//
+// 2 8/05/11 3:29p Alexp
+// add SDL condition to IGNORE_IMAGE_ROLLBACK. Disabled by default
+//
+// 4 5/16/11 5:54p Alexp
+// Use 5 characters for Project Tag comparison (old was 4)
+//
+// 3 5/10/11 5:09p Alexp
+// Hash guids are defined globally
+//
+// 2 4/13/11 7:15p Alexp
+// included first draft of VersionControl code
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: VerifyFwCapsule.c
+//
+// Description: Verify Aptio FW capsule integrity and performs other security checks
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <AmiDxeLib.h>
+#include <Protocol\SmiFlash.h>
+#include <Protocol\SecSmiFlash.h>
+#include <Ppi\FwVersion.h>
+#include <RomLayout.h>
+#include <Ffs.h>
+#include "AmiCertificate.h"
+
+//----------------------------------------------------------------------------
+// Function Externs
+extern AMI_DIGITAL_SIGNATURE_PROTOCOL *gAmiSig;
+extern UINTN gFwCapMaxSize; // add 4k for capsule's header
+extern EFI_GUID gFWCapsuleGuid;
+extern EFI_GUID gPRKeyGuid;
+extern EFI_GUID gFwCapFfsGuid;
+extern EFI_SHA256_HASH *gHashTbl;
+extern CRYPT_HANDLE gpPubKeyHndl;
+extern UINT8 gHashDB[SHA256_DIGEST_SIZE];
+
+BOOLEAN IsAddressInSmram (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+);
+//----------------------------------------------------------------------------
+// Local prototypes
+EFI_STATUS CapsuleValidate (
+ IN OUT UINT8 **pFwCapsule,
+ IN OUT APTIO_FW_CAPSULE_HEADER **pFWCapsuleHdr
+);
+
+typedef struct {
+ EFI_FFS_FILE_HEADER FfsHdr;
+ EFI_COMMON_SECTION_HEADER SecHdr;
+ EFI_GUID SectionGuid;
+ UINT8 FwCapHdr[0];
+} AMI_FFS_COMMON_SECTION_HEADER;
+
+//----------------------------------------------------------------------------
+// Local Variables
+
+static EFI_GUID FwCapSectionGuid = AMI_FW_CAPSULE_SECTION_GUID;
+
+//----------------------------------------------------------------------------
+#if IGNORE_RUNTIME_UPDATE_IMAGE_REVISION_CHECK == 0
+//----------------------------------------------------------------------------
+typedef struct _FID_SECTION {
+ EFI_GUID Guid;
+ FW_VERSION FwVersion;
+} FID_SECTION;
+
+static EFI_GUID FidSectionGuid = \
+ { 0x2EBE0275, 0x6458, 0x4AF9, 0x91, 0xed, 0xD3, 0xF4, 0xED, 0xB1, 0x00, 0xAA };
+
+const UINT8 *FidSignature = "$FID";
+//----------------------------------------------------------------------------
+// Function Definitions
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: VerifyProjectId
+//
+// Description:
+//
+// Input:
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN
+VerifyProjectId (
+ IN FW_VERSION *FwVersionData
+)
+{
+ char *strProjectId = CONVERT_TO_STRING(PROJECT_TAG);
+ UINTN Size = sizeof(CONVERT_TO_STRING(PROJECT_TAG));
+/*
+CHAR8 BiosTag[9]; //BIOS Tag
+EFI_GUID FirmwareGuid; //Firmware GUID
+CHAR8 CoreMajorVersion[3];
+CHAR8 CoreMinorVersion[3];
+CHAR8 ProjectMajorVersion[3];
+CHAR8 ProjectMinorVersion[3];
+*/
+// Project ID, Major, Minor rev
+ TRACE((-1, "OrgBiosTag=%s,NewBiosTag=%s\nPrjMajVer=%02X, NewMajVer=%s\nPrjMinorVer=%02X, NewMinorVer=%s\n",
+ FwVersionData->BiosTag, strProjectId,
+ PROJECT_MAJOR_VERSION, FwVersionData->ProjectMajorVersion,
+ PROJECT_MINOR_VERSION, FwVersionData->ProjectMinorVersion
+ ));
+
+ if (Size==0 || MemCmp (FwVersionData->BiosTag, strProjectId, Size-1)) return FALSE;
+#if IGNORE_IMAGE_ROLLBACK == 0
+ if(Atoi(FwVersionData->ProjectMajorVersion) < PROJECT_MAJOR_VERSION) return FALSE;
+ if(Atoi(FwVersionData->ProjectMinorVersion) < PROJECT_MINOR_VERSION) return FALSE;
+#endif
+
+ return TRUE;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetFidData
+//
+// Description: Function to read FFS FID data structure from the given data buffer
+//
+// Input: OUT FW_VERSION **Fid - pointer to output buffer
+// IN VOID *pFV - pointer to data buffer to read from
+
+//
+// Output: EFI_SUCCESS if FID data is retrieved
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN GetFidData(
+ IN VOID *pFV,
+ IN UINT32 Size,
+ OUT FW_VERSION **FwVersionData
+)
+{
+// UINT32 Signature;
+ UINT8 *SearchPointer;
+ FID_SECTION *Section;
+
+// Simplified search by $FID signature only.
+// SearchPointer = (UINT32 *)((UINT8 *)pFV + sizeof(EFI_GUID));
+// Signature = FidSectionGuid.Data1;
+ SearchPointer = (UINT8 *)pFV;
+
+ do {
+// if(*SearchPointer == Signature) {
+ Section = (FID_SECTION *)SearchPointer;
+ if(!guidcmp(&FidSectionGuid, &(Section->Guid)) &&
+ (*((UINT32*)(&Section->FwVersion.FirmwareID[0])) == *(UINT32*)FidSignature)){
+ *FwVersionData = &Section->FwVersion;
+ return TRUE;
+ }
+// }
+ } while( SearchPointer++ < (UINT8*)((UINT32)pFV+Size));
+
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: VerifyFwRevision
+//
+// Description: Verify Fw revision compatibility
+// NewVer > OldVer, newProjectTAGid = oldProjectTAGid
+//
+// Input:
+// IN OUT UINT8 *pCapsule
+// Output:
+// EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+VerifyFwRevision (
+ IN APTIO_FW_CAPSULE_HEADER *FWCapsuleHdr,
+ IN UINT8 *RomData
+)
+{
+ ROM_AREA *Area;
+ EFI_PHYSICAL_ADDRESS FvAddress;
+ FW_VERSION *FwVersionData;
+
+ Area = (ROM_AREA *)(UINTN)((UINT32)FWCapsuleHdr+FWCapsuleHdr->RomLayoutOffset);
+
+ for (Area; Area->Size != 0; Area++) {
+ if (!(Area->Attributes & ROM_AREA_FV_SIGNED))
+ continue;
+ // $FID can be in FV with either PEI or DXE
+ if (!(Area->Attributes & (ROM_AREA_FV_PEI+ROM_AREA_FV_DXE)))
+ continue;
+
+ FvAddress = (EFI_PHYSICAL_ADDRESS)RomData + (Area->Offset);
+ if (GetFidData((UINT8*)FvAddress, Area->Size, &FwVersionData)) {
+ if(VerifyProjectId(FwVersionData))
+ return EFI_SUCCESS;
+ break;
+ }
+ }
+// At least one FW block must be signed OR no $FID structure found in the new FW image
+ return EFI_SECURITY_VIOLATION;
+}
+
+#endif // #if IGNORE_RUNTIME_UPDATE_IMAGE_REVISION_CHECK == 0
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindCapHdrFFS
+//
+// Description: Function to read FW Cap Sig data from Ffs
+//
+// Input: OUT UINT8 **pFwCapHdr - pointer to output buffer
+// IN VOID *pCapsule - pointer to data buffer to read from
+//
+// Output: EFI_SUCCESS if Capsule Hdr with Signature is retrieved
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FindCapHdrFFS(
+ IN VOID *pCapsule,
+ OUT UINT8 **pFfsData
+)
+{
+ UINT32 Signature;
+ UINT32 *SearchPointer;
+ AMI_FFS_COMMON_SECTION_HEADER *FileSection;
+ APTIO_FW_CAPSULE_HEADER *pFwCapHdr;
+
+ SearchPointer = (UINT32 *)((UINT8 *)pCapsule - sizeof(AMI_FFS_COMMON_SECTION_HEADER) + FLASH_SIZE);
+ Signature = gFwCapFfsGuid.Data1;
+ do {
+ if(*SearchPointer == Signature) {
+ FileSection = (AMI_FFS_COMMON_SECTION_HEADER *)SearchPointer;
+ if(!guidcmp(&gFwCapFfsGuid, &(FileSection->FfsHdr.Name))
+ && !guidcmp(&FwCapSectionGuid, &(FileSection->SectionGuid))
+ ){
+ pFwCapHdr = (APTIO_FW_CAPSULE_HEADER*)(FileSection->FwCapHdr);
+ // just a sanity check - Cap Size must match the Section size
+ if(((*(UINT32 *)FileSection->FfsHdr.Size) & 0xffffff) >=
+ pFwCapHdr->CapHdr.HeaderSize + sizeof(AMI_FFS_COMMON_SECTION_HEADER) &&
+ !guidcmp((EFI_GUID*)&pFwCapHdr->CapHdr.CapsuleGuid, &gFWCapsuleGuid)
+ ){
+ *pFfsData = (UINT8*)pFwCapHdr;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ } while(SearchPointer-- != pCapsule);
+
+ return EFI_NOT_FOUND;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HashFwRomMapImage
+//
+// Description: The Rom image hash is calculated based on info from the Rom Area map
+//
+// Input:
+// Payload - pointer to a FW Image
+// FwCapsuleHdr - pointer to a FW Capsule Hdr
+// RomSize - Size of Rom Image
+//
+// Output: EFI_SUCCESS - capsule processed successfully
+// EFI_DEVICE_ERROR - capsule processing failed
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HashFwRomMapImage (
+ IN APTIO_FW_CAPSULE_HEADER *FWCapsuleHdr,
+ IN UINT8 *Payload,
+ IN UINTN RomSize,
+ OUT UINT8 *gHashDB
+){
+ EFI_STATUS Status = EFI_SUCCESS;
+ ROM_AREA *RomAreaTbl;
+ UINTN *Addr;
+ UINTN *Len;
+ UINTN i, RomMap_size, max_num_elem, num_elem, max_hash_elem;
+
+ RomAreaTbl = (ROM_AREA *)(UINTN)((UINT32)FWCapsuleHdr+FWCapsuleHdr->RomLayoutOffset);
+
+ RomMap_size = FWCapsuleHdr->RomImageOffset-FWCapsuleHdr->RomLayoutOffset;
+ max_num_elem = RomMap_size/sizeof(ROM_AREA);
+// assume max size of RomMap array = RomMap_size/sizeof(ROM_AREA);
+// or better yet ...calculate exact number
+ num_elem = 0;
+ for (i=0; i < max_num_elem && RomAreaTbl[i].Size != 0; i++ )
+ {
+ if (RomAreaTbl[i].Attributes & ROM_AREA_FV_SIGNED)
+ num_elem++;
+ }
+ max_num_elem = i;
+ max_hash_elem = num_elem+2; // add 2 extra entries
+ Addr = (UINTN*)gHashTbl;
+ Len = (UINTN*)((UINT8*)gHashTbl + max_hash_elem*sizeof(UINTN));
+
+ num_elem = 0;
+ for (i=0; i < max_num_elem && num_elem < max_hash_elem && RomAreaTbl[i].Size != 0; i++)
+ {
+ if (!(RomAreaTbl[i].Attributes & ROM_AREA_FV_SIGNED))
+ continue;
+ // sanity check for buffer overruns
+ if(RomAreaTbl[i].Offset > RomSize ||
+ (UINT64)RomAreaTbl[i].Offset + RomAreaTbl[i].Size > RomSize)
+ return EFI_SECURITY_VIOLATION;
+ // RomArea only holds offsets within a payload
+ Addr[num_elem] = (UINTN)((UINTN)Payload + RomAreaTbl[i].Offset);
+ Len[num_elem] = RomAreaTbl[i].Size;
+//TRACE((-1, "\n Num %d: Offs = %X (%X), len %X\n", num_elem, /*Addr[num_elem]*/RomAreaTbl[i].Offset, (UINT32)*(UINT32*)Addr[num_elem], Len[num_elem]));
+
+ num_elem++;
+
+ }
+ if(num_elem >= max_hash_elem) return EFI_SECURITY_VIOLATION;
+//
+// Hash of Capsule Hdr + FW Certificate Hdr
+//
+ if(FWCapsuleHdr->CapHdr.Flags & CAPSULE_FLAGS_CAPHDR_IN_SIGNCERT) {
+ Addr[num_elem] = (UINTN) FWCapsuleHdr;
+ Len[num_elem] = (UINTN)&FWCapsuleHdr->FWCert.SignCert.CertData - (UINTN)FWCapsuleHdr;
+//TRACE((-1, "\n Num %d: Offs = %X (%X), len %X\n", num_elem, Addr[num_elem], (UINT32)*(UINT32*)Addr[num_elem], Len[num_elem]));
+ num_elem++;
+ if(num_elem >= max_hash_elem) return EFI_SECURITY_VIOLATION;
+ }
+//
+// Hash of the ROM_MAP table
+//
+ Addr[num_elem] = (UINTN)RomAreaTbl;
+ Len[num_elem] = (i+1)*sizeof(ROM_AREA);
+//TRACE((-1, "\n Num %d: Offs = %X (%X), len %X\n", num_elem, Addr[num_elem], (UINT32)*(UINT32*)Addr[num_elem], Len[num_elem]));
+ num_elem++;
+
+ Status = gAmiSig->Hash(gAmiSig, &gEfiHashAlgorithmSha256Guid,
+ num_elem, (const UINT8**)Addr, (const UINTN*)Len, gHashDB );
+
+//TRACE((-1, "\nHash the FW Image %r\nNumElems = %d\n", Status, num_elem));
+
+//for (i=0; i<16; i++)
+// TRACE((-1,"%02X ", (gHashDB[i]) ));
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: VerifyFwCertPkcs7
+//
+// Description: This code verifies FW Capsule is genuine,
+// and performs following checks on the image:
+// 1. Signing certificate is signed with trusted Root Platform key
+// 2. Integrity check. Image Signature verification
+//
+// Input:
+// Payload - pointer to a FW Image
+// FwCapsuleHdr - pointer to a FW Capsule Hdr
+// RomSize - Size of Rom Image
+//
+// Output: EFI_SUCCESS - capsule processed successfully
+// EFI_DEVICE_ERROR - capsule processing failed
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS VerifyFwCertPkcs7 (
+ IN APTIO_FW_CAPSULE_HEADER *FWCapsuleHdr,
+ IN UINT8 *Payload,
+ IN UINTN RomSize
+){
+ EFI_STATUS Status;
+ UINT8 *Pkcs7Cert, *pDigest;
+ UINTN Pkcs7Cert_len, DigestLen;
+ UINT32 Flags=0;
+
+// TRACE((-1, "Verify Fw Pkcs7 Cert\n"));
+//
+// 1. Verify Platform Key algo matches x509 cert
+//
+ if(guidcmp(&gpPubKeyHndl.AlgGuid, &gEfiCertX509Guid))
+ return EFI_UNSUPPORTED;
+
+// 2. Verify Signing Cert Signature
+//
+// 2.1 The Rom image hash is calculated based on info from the Rom Area map
+//
+ Status = HashFwRomMapImage(FWCapsuleHdr, Payload, RomSize, gHashDB);
+ if (EFI_ERROR(Status)) return Status;
+
+// 2.2 Verify Fw Certificate
+ pDigest = &gHashDB[0];
+ DigestLen = SHA256_DIGEST_SIZE;
+ Pkcs7Cert = (UINT8*)&FWCapsuleHdr->FWCert.SignCert.CertData;
+ Pkcs7Cert_len = FWCapsuleHdr->FWCert.SignCert.Hdr.Hdr.dwLength-sizeof(WIN_CERTIFICATE_UEFI_GUID_1);
+ Status = gAmiSig->Pkcs7Verify( gAmiSig,
+ Pkcs7Cert, Pkcs7Cert_len, // Pkcs7Cert
+ gpPubKeyHndl.Blob, gpPubKeyHndl.BlobSize, // TrustCert
+ &pDigest, &DigestLen, // In/OutData
+ Pkcs7CertValidate,
+ RELEASE // Flags, mutex
+ );
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: VerifyFwCertRsa2048Sha256
+//
+// Description: This code verifies FW Capsule is genuine,
+// and performs following checks on the image:
+// 1. Signing certificate is signed with trusted Root Platform key
+// 2. Integrity check. Image Signature verification
+//
+// Input:
+// Payload - pointer to a FW Image
+// FwCapsuleHdr - pointer to a FW Capsule Hdr
+// RomSize - Size of Rom Image
+//
+// Output: EFI_SUCCESS - capsule processed successfully
+// EFI_DEVICE_ERROR - capsule processing failed
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS VerifyFwCertRsa2048Sha256 (
+ IN APTIO_FW_CAPSULE_HEADER *FWCapsuleHdr,
+ IN UINT8 *Payload,
+ IN UINTN RomSize
+){
+ EFI_STATUS Status;
+ CRYPT_HANDLE HashHndl;
+ CRYPT_HANDLE PubKeyHndl;
+ UINT8 *pSig;
+ UINT32 Flags;
+ UINT8 *Addr;
+ UINTN Size;
+ EFI_CERT_BLOCK_RSA_2048_SHA256* pRootCert;
+
+// Version 010 and later supporting extended flags
+// if(FWCapsuleHdr->CapHdr.Flags & CAPSULE_FLAGS_CAPHDR_IN_SIGNCERT)
+ if(FWCapsuleHdr->CapHdr.HeaderSize == FWCapsuleHdr->RomImageOffset)
+ {
+ if(FWCapsuleHdr->CapHdr.Flags & CAPSULE_FLAGS_RSA_PSS_PADDING_SCHEME)
+ Flags = EFI_CRYPT_RSASSA_PSS;
+ else
+ Flags = EFI_CRYPT_RSASSA_PKCS1V15;
+ }
+ else
+ Flags = EFI_CRYPT_RSASSA_PSS;
+
+ HashHndl.AlgGuid = gEfiHashAlgorithmSha256Guid;
+ HashHndl.BlobSize = SHA256_DIGEST_SIZE;
+ HashHndl.Blob = gHashDB;
+
+ PubKeyHndl.AlgGuid = gEfiCertRsa2048Guid;
+ PubKeyHndl.BlobSize = DEFAULT_RSA_KEY_MODULUS_LEN;
+//
+// 1. Compare Capsule's Sign Cert key with Platform Root Key
+//
+ PubKeyHndl.Blob = (UINT8*)FWCapsuleHdr->FWCert.SignCert.CertData.PublicKey;
+ Status = gAmiSig->VerifyKey(gAmiSig, &gPRKeyGuid, &PubKeyHndl);
+ // Skip the RootCert key checking if SignCert Key and PR Key are matching
+//TRACE((-1, "Compare SignCert Key == FW Key(%X) : %r\n", (UINT32)*PubKeyHndl.Blob, Status));
+ if(EFI_ERROR(Status)) {
+//
+// 1.1 Compare Platform Root with Capsule's Key from a Root Key store
+//
+ for (pRootCert = &FWCapsuleHdr->FWCert.RootCert;
+ (UINT8*)pRootCert <
+ (UINT8*)&FWCapsuleHdr->FWCert+FWCapsuleHdr->FWCert.SignCert.Hdr.Hdr.dwLength &&
+ pRootCert->PublicKey[0]!=0;
+ pRootCert++)
+ {
+ PubKeyHndl.Blob = pRootCert->PublicKey;
+ Status = gAmiSig->VerifyKey(gAmiSig, &gPRKeyGuid, &PubKeyHndl);
+//TRACE((-1, "Compare RootCert Key == FW Key(%X) : %r\n", (UINT32)*PubKeyHndl.Blob, Status));
+ if (EFI_ERROR(Status)) continue;
+//
+// 2. Verify RootCert.Signature
+//
+// 2.1 Compute FWCert.SignCert.PublicKey Hash
+ if(FWCapsuleHdr->CapHdr.Flags & CAPSULE_FLAGS_SIGNKEY_IN_ROOTCERT)
+ {
+ Addr = (UINT8*)&FWCapsuleHdr->FWCert.SignCert.CertData.PublicKey;
+ Size = DEFAULT_RSA_KEY_MODULUS_LEN;
+ } else
+// 2.2 Compute FWCert.SignCert Hash
+ {
+ Addr = (UINT8*)&FWCapsuleHdr->FWCert.SignCert;
+ Size = sizeof(AMI_CERTIFICATE_RSA2048_SHA256);
+ }
+
+ Status = gAmiSig->Hash(gAmiSig, &gEfiHashAlgorithmSha256Guid, 1,&Addr,(const UINTN*)&Size, gHashDB);
+ if (EFI_ERROR(Status)) break;
+
+ pSig = (void*)pRootCert->Signature;
+ Status = gAmiSig->Pkcs1Verify(gAmiSig, &PubKeyHndl, &HashHndl, pSig, DEFAULT_RSA_SIG_LEN, Flags);
+//TRACE((-1, "Verify Root Cert : %r\n", Status));
+ break;
+ }
+ }
+ if (EFI_ERROR(Status)) return EFI_SECURITY_VIOLATION;
+// 3. Verify Signing Cert Signature
+//
+// 3.1 The Rom image hash is calculated based on info from the Rom Area map
+//
+ Status = HashFwRomMapImage(FWCapsuleHdr, Payload, RomSize, gHashDB);
+ if (EFI_ERROR(Status)) return Status;
+
+ pSig = (void*)FWCapsuleHdr->FWCert.SignCert.CertData.Signature;
+ PubKeyHndl.Blob = (UINT8*)FWCapsuleHdr->FWCert.SignCert.CertData.PublicKey;
+ Status = gAmiSig->Pkcs1Verify(gAmiSig, &PubKeyHndl, &HashHndl, pSig, DEFAULT_RSA_SIG_LEN, Flags);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CapsuleValidate
+//
+// Description: This code verifies FW Capsule is genuine,
+// and performs following checks on the image:
+// 1. Re-Play protection. Verifies that new FW image version is newer then the current one
+// 2. Signing certificate is signed with trusted Root Platform key
+// 3. Integrity check. Image Signature verification
+//
+// Input:
+// IN VOID *pFwCapsule - pointer to a FW Image
+// OUT UINT8 *pFwCapsuleHdr - return a pointer to a FW Capsule Hdr(optional if parameter is not NULL)
+//
+// Output: EFI_SUCCESS - capsule processed successfully
+// EFI_SECURITY_VIOLATION - capsule processing failed
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CapsuleValidate (
+ IN OUT UINT8 **pFwCapsule,
+ IN OUT APTIO_FW_CAPSULE_HEADER **pFWCapsuleHdr
+){
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ APTIO_FW_CAPSULE_HEADER *FWCapsuleHdr;
+ UINTN RomSize;
+ UINT8 *Payload;
+
+ FWCapsuleHdr = (APTIO_FW_CAPSULE_HEADER*)*pFwCapsule;
+ Payload = (UINT8*)*pFwCapsule;
+ RomSize = FLASH_SIZE;
+
+/*
+ - CapsuleValidate
+ - Look up Capsule GUID
+ - Found -
+ update pFwCapsule ptr to beginning of BIOS ROM data
+ continue with Image Verify
+ - Not found at offs 0 - assume Cap Hdr in FFS
+ Call GetSigFFS
+ locate FFS by Hole GUID, Sec GUID
+ if found, update FWCapsuleHdr,
+ continue with Image Verify
+*/
+// proper FW Capsule presence check
+
+// verify Capsule Mailbox points to FW_CAPSULE hdr
+ if(!guidcmp((EFI_GUID*)&FWCapsuleHdr->CapHdr.CapsuleGuid, &gFWCapsuleGuid))
+ {
+// Update pFwCapsule to point to beginning of Bios ROM
+ Payload = (UINT8*)((UINT32)FWCapsuleHdr + FWCapsuleHdr->RomImageOffset);
+ RomSize = (FWCapsuleHdr->CapHdr.CapsuleImageSize - FWCapsuleHdr->RomImageOffset);
+ *pFwCapsule = Payload;
+ }
+ else
+ {
+//TRACE((-1, "Looking for embedded Signature...\n"));
+ if(EFI_ERROR(FindCapHdrFFS(Payload, (UINT8**)&FWCapsuleHdr)))
+ return EFI_SECURITY_VIOLATION;
+ }
+TRACE((-1, "Found Fw Capsule GUID %g\n\r", &(FWCapsuleHdr->CapHdr.CapsuleGuid)));
+
+// update return argument with a ptr to FwCapHdr
+ if(pFWCapsuleHdr)
+ *pFWCapsuleHdr = FWCapsuleHdr;
+
+// Aptio FW Capsule only supporting WIN_CERT_TYPE_EFI_GUID
+ if(FWCapsuleHdr->FWCert.SignCert.Hdr.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID)
+ return EFI_SECURITY_VIOLATION;
+
+// sanity check for buffer overruns
+ if((FWCapsuleHdr->CapHdr.CapsuleImageSize > gFwCapMaxSize) ||
+ (FWCapsuleHdr->RomImageOffset > (FWCAPSULE_IMAGE_SIZE-FLASH_SIZE)) || // 16k is a MAX possible FwCap Hdr size
+ (FWCapsuleHdr->CapHdr.HeaderSize > FWCapsuleHdr->RomImageOffset) ||
+ (FWCapsuleHdr->RomLayoutOffset > FWCapsuleHdr->RomImageOffset) ||
+ (FWCapsuleHdr->FWCert.SignCert.Hdr.Hdr.dwLength + offsetof(APTIO_FW_CAPSULE_HEADER, FWCert) >
+ FWCapsuleHdr->RomLayoutOffset )
+ )
+ return EFI_SECURITY_VIOLATION;
+
+ if(!IsAddressInSmram((EFI_PHYSICAL_ADDRESS)gpPubKeyHndl.Blob, gpPubKeyHndl.BlobSize) )
+ return EFI_SECURITY_VIOLATION;
+ TRACE((TRACE_ALWAYS,"gpKey (%x, %x bytes)\n",gpPubKeyHndl.Blob,gpPubKeyHndl.BlobSize));
+// Begin Authentication
+ if(!guidcmp((EFI_GUID*)&FWCapsuleHdr->FWCert.SignCert.Hdr.CertType, &gEfiCertTypePkcs7Guid))
+ Status = VerifyFwCertPkcs7(FWCapsuleHdr, Payload, RomSize);
+ else
+ Status = VerifyFwCertRsa2048Sha256(FWCapsuleHdr, Payload, RomSize);
+ TRACE((-1, "Signature validate %r\n", Status));
+ if (EFI_ERROR(Status)) return Status;
+//
+// Local PEI $FID is linked with CspLib. extern FW_VERSION FwVersionData;
+// Find $FID in new Fw FVs. Any found should do for us. Use RomMap from Capsule's Hdr
+// compare local BB and Main $Fid BIOS Major/Minor revs with New one.
+#if IGNORE_RUNTIME_UPDATE_IMAGE_REVISION_CHECK == 0
+ Status = VerifyFwRevision(FWCapsuleHdr, Payload);
+//TRACE((-1, "FW Revision test %r\n", Status));
+#endif
+
+//TRACE((-1, "Capsule Verify %r\n", Status));
+
+ return Status;
+}
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************