summaryrefslogtreecommitdiff
path: root/Core/EM/SecurityPkg
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/SecurityPkg
downloadzprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'Core/EM/SecurityPkg')
-rw-r--r--Core/EM/SecurityPkg/AuthenticatedVariable/Auth2Variable.c869
-rw-r--r--Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.c1729
-rw-r--r--Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.cif12
-rw-r--r--Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.h351
-rw-r--r--Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.mak89
-rw-r--r--Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.sdl44
-rw-r--r--Core/EM/SecurityPkg/ImageVerificationLib/DxeImageVerificationLib.c2431
-rw-r--r--Core/EM/SecurityPkg/ImageVerificationLib/DxeImageVerificationLib.h175
-rw-r--r--Core/EM/SecurityPkg/ImageVerificationLib/EfiImage.h702
-rw-r--r--Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.cif12
-rw-r--r--Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.mak92
-rw-r--r--Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.sdl109
-rw-r--r--Core/EM/SecurityPkg/SecFlashUpd/EfiCapsuleRecovery.c325
-rw-r--r--Core/EM/SecurityPkg/SecFlashUpd/EfiCapsuleRecovery.dxs89
-rw-r--r--Core/EM/SecurityPkg/SecFlashUpd/IsSecRecovery.c390
-rw-r--r--Core/EM/SecurityPkg/SecFlashUpd/SecFlashUpd.cif17
-rw-r--r--Core/EM/SecurityPkg/SecFlashUpd/SecFlashUpd.mak176
-rw-r--r--Core/EM/SecurityPkg/SecFlashUpd/SecFlashUpd.sdl152
-rw-r--r--Core/EM/SecurityPkg/SecFlashUpd/SecFlashUpdDxe.c276
-rw-r--r--Core/EM/SecurityPkg/SecFlashUpd/SecFlashUpdDxe.dxs58
-rw-r--r--Core/EM/SecurityPkg/SecFlashUpd/VerifyFwCapsule.c974
-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
-rw-r--r--Core/EM/SecurityPkg/SecureBootMod.c2503
-rw-r--r--Core/EM/SecurityPkg/SecureBootMod.chmbin0 -> 2097632 bytes
-rw-r--r--Core/EM/SecurityPkg/SecureBootMod.cif21
-rw-r--r--Core/EM/SecurityPkg/SecureBootMod.dxs51
-rw-r--r--Core/EM/SecurityPkg/SecureBootMod.h116
-rw-r--r--Core/EM/SecurityPkg/SecureBootMod.mak153
-rw-r--r--Core/EM/SecurityPkg/SecureBootMod.sd685
-rw-r--r--Core/EM/SecurityPkg/SecureBootMod.sdl277
-rw-r--r--Core/EM/SecurityPkg/SecureBootMod.unibin0 -> 22308 bytes
-rw-r--r--Core/EM/SecurityPkg/SecureMod.chmbin0 -> 1872070 bytes
-rw-r--r--Core/EM/SecurityPkg/SecureMod.cif17
-rw-r--r--Core/EM/SecurityPkg/SecureMod.mak458
-rw-r--r--Core/EM/SecurityPkg/SecureMod.sdl315
40 files changed, 16533 insertions, 0 deletions
diff --git a/Core/EM/SecurityPkg/AuthenticatedVariable/Auth2Variable.c b/Core/EM/SecurityPkg/AuthenticatedVariable/Auth2Variable.c
new file mode 100644
index 0000000..e979531
--- /dev/null
+++ b/Core/EM/SecurityPkg/AuthenticatedVariable/Auth2Variable.c
@@ -0,0 +1,869 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SecureBoot_WIN8/AuthenticatedVariable_efi/Auth2Variable.c 30 3/09/15 4:31p Alexp $
+//
+// $Revision: 30 $
+//
+// $Date: 3/09/15 4:31p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureBoot_WIN8/AuthenticatedVariable_efi/Auth2Variable.c $
+//
+// 30 3/09/15 4:31p Alexp
+// Compliancy with UEFI spec:
+// EFI_VARIABLE_AUTHENTICATION_2.TimeStamp -
+// during Append operations the TimeStamp value may be set to '0'
+//
+// 29 10/08/14 3:16p Alexp
+// Introduced global mCustomMode flag passing the status from
+// PhysicalUserPresent()
+//
+// 28 8/15/13 11:27a Alexp
+// Link AmyCryptoLib. Replaced locally defined mkLongTime() with generic
+// AmiCryptoLib defined os_mktime()
+//
+// 27 2/08/13 5:15p Alexp
+// Optimized the code flow fro Auth2 Variables.
+//
+// 26 12/07/12 3:48p Alexp
+// - Replaced TRACE macro with AVAR_TRACE. Stop debug traces in Virtual
+// address mode
+// - VerifyVariable2() Fix final check for IsPk and run
+// ValidateSignatureList()
+//
+// 25 12/04/12 6:56p Alexp
+// VerifyVariable2()
+// IsPk -> skip ValidateSignatureList if *DataSize =0
+//
+// 24 11/29/12 3:08p Alexp
+// ValidateSelfSigned(): keep *x509_SignCert ptr to non-0 for
+// Pkcs7CertValidateGetSignerKeyHash operation
+// Will trigger an error in old CryptoDxe.c Pkcs7Verify()
+//
+// 22 11/16/12 7:11p Alexp
+// Fixed ValidateSignatureList() return status for Zero Data or Size
+//
+// 21 11/16/12 5:09p Alexp
+// EIP:104961 UEFI 2.3.1 SCTc test failed in Generic\EfiCompliant case.
+// Fix for SelfSigned variables.
+//
+// 19 9/17/12 4:50p Alexp
+// add Time Stamp traces
+//
+// 18 9/06/12 5:14p Alexp
+// ConstructDataParameter() Fix debug messages.
+//
+// 17 9/04/12 3:35p Alexp
+// EIP#99648: SCT will fail when enable Secure Boot in setup menu.
+// Fix: Use globally defined buffer to pass calculated Key Hash for
+// SelfSigned Variables
+//
+// 15 8/22/12 6:19p Alexp
+// ProcessVarWithPk2()
+// Properly implemented the case for PK variable carrying RSA2048 Key.
+// Requires CryptoPkg Label 009 or later.
+//
+// 12 4/26/12 7:29p Alexp
+// fix debug trace messages
+//
+// 11 4/16/12 5:28p Alexp
+// Add debug traces in ConstructDataParameter to display serialization
+// data
+//
+// 10 11/30/11 7:58p Alexp
+// According to UEFI 2.3.1 Sec 7.2.1 : "db" vars can be validated either
+// by KEK key or by PK key.
+// The fix adds the check for PK if none of KEKs can validate new "db"
+//
+// 9 8/19/11 5:06p Alexp
+//
+// 8 8/18/11 4:54p Alexp
+// restored use of global variable mPlatformMode instead of a field in
+// AuthVarMaibox
+//
+// 7 8/16/11 7:18p Alexp
+// added Mailbox variable AuthVarMAilbox to syncronize local state between
+// DXE and SMM AuthVariable services
+//
+// 6 7/18/11 10:17a Alexp
+// made gEfiGlobalVariableGuid static to prevent linker issues
+//
+// 5 6/27/11 6:16p Alexp
+// code optimization: moved ValidateSignatureList () call in the main
+// VerifyVariable1(2) function.
+//
+// 4 6/24/11 7:04p Alexp
+// fixed ValidateSignatureList () logic. Added Certificate RSA2048 to
+// supported Signatures
+//
+// 3 6/24/11 3:23p Alexp
+// test PK, KEK, db(x) for valid Signatuer List header with
+// ValidateSignatureList()
+// run test only if other tests passed
+//
+// 2 6/23/11 6:19p Alexp
+// Added ValidateSigList() function
+//
+// 1 6/13/11 5:25p Alexp
+//
+// 13 6/13/11 4:29p Alexp
+//
+// 12 6/10/11 6:24p Alexp
+// Update SelfSigned variable: Pkcs7CertValidateGetSignerKeyHash
+//
+// 11 6/09/11 5:51p Alexp
+// add new parameter to ValidateSelfSigned - Operation.
+// test for self-signed variables: hash CA certificate instead of Signer
+// certificate.
+//
+// 10 6/03/11 10:36a Alexp
+// Add alternative cert verify logic in ProcessVarWithPk2 (). Keep it
+// commented for now
+//
+// 9 6/02/11 5:53p Alexp
+// add new function to ValidateSelfSigned certificates
+// add processing for Time BAsed self signed variables
+// succesfully Verified Msft Win8 PK-KEK test keys
+//
+// 8 5/31/11 3:11p Alexp
+// Use UpdatePlatformMode() to update SetupMode variable
+//
+// 7 5/25/11 8:34p Alexp
+// draft fix for TimeBased auth variables. More work w Msft needed
+//
+// 6 5/19/11 4:59p Alexp
+// Major code revamp to be able to handle of handling Secure vars in Setup
+// Mode
+// TBD: TimeBased certificates from Msft fail to process. Not compiled as
+// Authenticode format
+//
+// 5 5/17/11 12:48p Alexp
+// fix WDK level4 compiler warnings
+//
+// 4 5/13/11 3:43p Alexp
+// add dependency on Core rev.
+//
+// 3 5/11/11 7:20p Alexp
+// VarData init for FindVariable
+//
+// 2 5/10/11 5:07p Alexp
+// removed local Hash Guid defines
+// intermediate check in befor implementing Auth2 var verify logic
+//
+//**********************************************************************
+
+#include "NVRAM.h"
+#include <AmiDxeLib.h>
+#include <AmiCspLib.h>
+#include <Protocol/AmiDigitalSignature.h>
+
+#include "AuthVariable.h"
+#include <cryptlib.h>
+
+///
+/// Global database array for scratch
+///
+extern BOOLEAN AVarRuntime;
+extern UINT8 mCustomMode;
+extern UINT8 mPlatformMode;
+extern UINT8 PublicKeyHashArray[HASH_SHA256_LEN];
+
+extern AMI_DIGITAL_SIGNATURE_PROTOCOL *mDigitalSigProtocol;
+static EFI_GUID gEfiGlobalVariableGuid = EFI_GLOBAL_VARIABLE;
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ProcessVarWithPk2
+//
+// Description: Process variable with platform key for verification.
+// Called for PK or KEK Variables
+//
+//
+// Input:
+// Pkcs7Cert Pointer to Pkcs#7 cert.
+// Pkcs7Cert_len Size of Pkcs7 cert
+// pDigest Digest of serialized data block
+// Digest_len size of the digest (20 or 32 bytes)
+// Output:
+// Status
+// EFI_SUCCESS Variable passed validation successfully.
+// EFI_INVALID_PARAMETER Invalid parameter.
+// EFI_SECURITY_VIOLATION The variable does NOT pass the validation.
+// check carried out by the firmware.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ProcessVarWithPk2 (
+ IN UINT8 *Pkcs7Cert,
+ IN UINTN Pkcs7Cert_len,
+ IN UINT8 *pDigest,
+ IN UINTN Digest_len
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIGNATURE_LIST *OldPkList;
+ EFI_SIGNATURE_DATA *OldPkData;
+ UINT32 VarAttr;
+ UINT8 *VarData;
+ UINTN VarDataSize=0;
+ UINT8 *x509_TrustCert, *TrustCert;
+ UINTN x509_TrustCert_len, TrustCert_len;
+ UINT8 Pkcs7Operation;
+
+ //
+ // Get platform key from variable.
+ //
+ Status = FindVariable (
+ EFI_PLATFORM_KEY_NAME,
+ &gEfiGlobalVariableGuid,
+ &VarAttr,
+ &VarDataSize,
+ &VarData
+ );
+// PK should have been set when we were in SETUP_MODE. This condition is INVALID.
+// ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status) || VarData==NULL || !VarDataSize)
+ return EFI_SECURITY_VIOLATION;
+
+ OldPkList = (EFI_SIGNATURE_LIST *) VarData;
+ OldPkData = (EFI_SIGNATURE_DATA *) ((UINT8 *) OldPkList + sizeof (EFI_SIGNATURE_LIST) + OldPkList->SignatureHeaderSize);
+
+// Verify the PK SignatureType GUID
+
+ if (!guidcmp ((EFI_GUID*) &(OldPkList->SignatureType), &gEfiCertRsa2048Guid))
+ {
+ //Process x509 cert and load Raw Key for Root cert comparison
+ Pkcs7Operation = Pkcs7CertValidateGetSignerKey;
+ x509_TrustCert = NULL;
+ x509_TrustCert_len = 0;
+ }
+ else if(!guidcmp ((EFI_GUID*) &(OldPkList->SignatureType), &gEfiCertX509Guid))
+ {
+ Pkcs7Operation = Pkcs7CertValidateGetSignerCert;
+ x509_TrustCert = (UINT8*)OldPkData->SignatureData;
+ x509_TrustCert_len = (UINTN)OldPkList->SignatureSize-sizeof(EFI_GUID);
+ } else
+ //
+ // Unsupported Sig Type, return EFI_SECURITY_VIOLATION.
+ //
+ return EFI_SECURITY_VIOLATION;
+
+ TrustCert = (UINT8*)OldPkData->SignatureData;
+ TrustCert_len = (UINTN)OldPkList->SignatureSize-sizeof(EFI_GUID);
+
+/*
+// Validate Self-Signed
+//
+ x509_TrustCert = &pDigest; // Init with addr to global var
+ //&PublicKeyHashArray[0];
+ x509_TrustCert_len = Digest_len;
+ Status = mDigitalSigProtocol->Pkcs7Verify (
+ mDigitalSigProtocol,
+ Pkcs7Cert, Pkcs7Cert_len, // Pkcs7Cert
+ NULL, 0, // use Internal Cert
+ &x509_TrustCert, &x509_TrustCert_len, // Input->Digest, Output->DER Ptr to Signing Cert
+ Pkcs7Operation,
+ RESET
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = ( TrustCert_len == x509_TrustCert_len &&
+ !(MemCmp(TrustCert, x509_TrustCert, x509_TrustCert_len))) ?
+ EFI_SUCCESS:EFI_SECURITY_VIOLATION;
+ }
+*/
+ Status = mDigitalSigProtocol->Pkcs7Verify (
+ mDigitalSigProtocol,
+ Pkcs7Cert, Pkcs7Cert_len, // Pkcs7Cert
+ x509_TrustCert, x509_TrustCert_len, // TrustCert
+ &pDigest, &Digest_len, // In/OutData
+ Pkcs7Operation,
+ RELEASE // Flags, mutex
+ );
+ if (!EFI_ERROR (Status)) {
+
+ Status = ( TrustCert_len == Digest_len &&
+ !(MemCmp(TrustCert, pDigest, Digest_len))) ?
+ EFI_SUCCESS:EFI_SECURITY_VIOLATION;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ProcessVarWithKek2
+//
+// Description: Process variable with key exchange key for verification.
+// Called for DB or DBx variables
+//
+//
+// Input:
+// Pkcs7Cert Pointer to Pkcs#7 cert.
+// Pkcs7Cert_len Size of Pkcs7 cert
+// pDigest Digest of serialized data block
+// Digest_len size of the digest (20 or 32 bytes)
+//
+// Output:
+// Status
+// EFI_SUCCESS Variable passed validation successfully.
+// EFI_INVALID_PARAMETER Invalid parameter.
+// EFI_SECURITY_VIOLATION The variable does NOT pass the validation.
+// check carried out by the firmware.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ProcessVarWithKek2 (
+ IN UINT8 *Pkcs7Cert,
+ IN UINTN Pkcs7Cert_len,
+ IN UINT8 *pDigest,
+ IN UINTN Digest_len
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIGNATURE_LIST *KekList;
+ EFI_SIGNATURE_DATA *KekItem;
+ UINT32 KekCount;
+ BOOLEAN IsFound;
+ UINT32 Index;
+ UINT32 VarAttr;
+ UINT8 *VarData;
+ UINTN VarDataSize=0;
+
+ //
+ // Get KEK database from variable.
+ //
+ Status = FindVariable (
+ EFI_KEY_EXCHANGE_KEY_NAME,
+ &gEfiGlobalVariableGuid,
+ &VarAttr,
+ &VarDataSize,
+ &VarData
+ );
+ if (EFI_ERROR (Status) || VarData==NULL || !VarDataSize)
+ return EFI_SECURITY_VIOLATION;
+
+ KekList = (EFI_SIGNATURE_LIST *) VarData;
+
+ //
+ // Enumerate all Kek items in this list to verify the variable certificate data.
+ // If anyone is authenticated successfully, it means the variable is correct!
+ //
+ IsFound = FALSE;
+ //
+ // scan thru multiple Sig Lists if exist. Add 1 more loop....
+ //
+ while (!IsFound && (VarDataSize > 0) && (VarDataSize >= KekList->SignatureListSize)) {
+ if (!guidcmp ((EFI_GUID*) &(KekList->SignatureType), &gEfiCertX509Guid))
+ {
+ KekCount = (KekList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - KekList->SignatureHeaderSize) / KekList->SignatureSize;
+ KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekList + sizeof (EFI_SIGNATURE_LIST) + KekList->SignatureHeaderSize);
+ for (Index = 0; Index < KekCount; Index++) {
+ // find x509 cert and compare against one from Kek
+ Status = mDigitalSigProtocol->Pkcs7Verify (
+ mDigitalSigProtocol,
+ Pkcs7Cert, Pkcs7Cert_len, // Pkcs7Cert
+ KekItem->SignatureData, // TrustCert Cert
+ KekList->SignatureSize,
+ &pDigest, &Digest_len, // In/OutData
+ Pkcs7CertValidate,
+ RELEASE
+ );
+ if (!EFI_ERROR(Status)) {
+ IsFound = TRUE;
+ break;
+ }
+ KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekItem + KekList->SignatureSize);
+ }
+ }// else
+ // Auth2 Vars must be signed with x509 Certs
+// if (!guidcmp ((EFI_GUID*) &(KekList->SignatureType), &gEfiCertRsa2048Guid))
+// return EFI_SECURITY_VIOLATION;
+ VarDataSize -= KekList->SignatureListSize;
+ KekList = (EFI_SIGNATURE_LIST *) ((UINT8 *) KekList + KekList->SignatureListSize);
+ }
+
+ if (!IsFound)
+ return EFI_SECURITY_VIOLATION;
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ValidateSelfSigned
+//
+// Description: Extract Signer certificate and verify Pkcs#7 SignedData signature.
+// Called for Private Authenticated variables
+//
+//
+// Input:
+// Pkcs7Cert Pointer to Pkcs#7 cert.
+// Pkcs7Cert_len Size of Pkcs7 cert
+// pDigest Digest of serialized data block
+// Digest_len size of the digest (20 or 32 bytes)
+// Operation type of Pkcs operation:Pkcs7CertValidateGetSignerCert...
+//
+// Output: EFI_SUCCESS SignedData passed validation successfully.
+// EFI_INVALID_PARAMETER Invalid parameter.
+// EFI_SECURITY_VIOLATION The data does NOT pass the validation.
+// check carried out by the firmware.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ValidateSelfSigned (
+ IN UINT8 *Pkcs7Cert,
+ IN UINTN Pkcs7Cert_len,
+ IN OUT UINT8 **pDigest,
+ IN OUT UINTN *Digest_len,
+ IN UINT8 Operation
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *x509_SignCert;
+ UINTN x509_SignCert_len=0;
+
+ //
+ // Extract x509 Signing Cert and validate self-signed data
+ //
+ x509_SignCert=(UINT8*)&x509_SignCert_len; // non-zero ptr
+ Status = mDigitalSigProtocol->Pkcs7Verify (
+ mDigitalSigProtocol,
+ Pkcs7Cert, Pkcs7Cert_len,
+ NULL, 0, // RootCert
+ &x509_SignCert, &x509_SignCert_len,
+ Pkcs7GetSignerCert,
+ KEEP
+ );
+ //
+ // Authenticate using internal Signer Cert, Extract Cert or Key Hash
+ //
+ if (!EFI_ERROR (Status))
+ {
+ Status = mDigitalSigProtocol->Pkcs7Verify (
+ mDigitalSigProtocol,
+ Pkcs7Cert, Pkcs7Cert_len, // Pkcs7Cert
+ x509_SignCert, x509_SignCert_len, // RootCert
+ pDigest, Digest_len, // Input->Digest, Output->DER Ptr to Signing Cert
+ Operation,
+ RELEASE
+ );
+
+// Status = mDigitalSigProtocol->Hash(mDigitalSigProtocol, &gEfiHashAlgorithmSha256Guid, 1 &x509_SignCert, (const UINTN*)&x509_SignCert_len, pDigest);
+// *Digest_len = HASH_SHA256_LEN;
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConstructDataParameter
+//
+// Description:
+// Generates the Hash (SHA256) out of serialized data block
+// Hash(VariableName, VendorGuid, Attributes, TimeStamp, Data)
+//
+// Input:
+// CHAR16 *VariableName Name of Variable to be found.
+// EFI_GUID *VendorGuid Variable vendor GUID.
+// IN UINT32 Attributes - Attributes of the Var
+// VOID *Data - pointer to data block within AutVar Data
+// UINTN DataSize - size of data block
+//
+// Output: EFI_STATUS
+// UINT8 Digest - Hash of the serialized data block
+// UINTN Digest_len - size of data block
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ConstructDataParameter (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN VOID *Data,
+ IN UINTN DataSize,
+ OUT UINT8 *pDigest,
+ OUT UINTN *Digest_len,
+ IN UINT8 Mutex
+)
+{
+ EFI_STATUS Status;
+
+ EFI_GUID *HashAlgorithm;
+ UINT8 *Addr[5];
+ UINTN Len[5];
+ EFI_VARIABLE_AUTHENTICATION_2 *CertData;
+ UINTN CertHdrSize, Pkcs7Cert_len;
+ UINT8 *Pkcs7Cert;
+ UINT8 HashType=SHA1;
+ UINT8 *pHash=&HashType;
+
+#ifdef EFI_DEBUG
+ UINTN j, i;
+#endif
+
+ CertData = (EFI_VARIABLE_AUTHENTICATION_2 *)Data;
+ CertHdrSize = AUTHINFO_2_SIZE(Data);
+
+// !!!sha256 is the only digest algorithm supported.
+// temp w/a: determine the digest algorithm from contentInfo hdr
+//
+ // quick cheat. CertBlock->CerData is a begining of Pkcs7 Cert
+ Pkcs7Cert = (UINT8*)&(CertData->AuthInfo.CertData);
+ Pkcs7Cert_len = CertHdrSize - ((UINTN)Pkcs7Cert - (UINTN)Data);
+
+ Status = mDigitalSigProtocol->Pkcs7Verify (
+ mDigitalSigProtocol,
+ Pkcs7Cert,
+ Pkcs7Cert_len,
+ NULL,
+ 0,
+ &pHash, // returns DER Ptr to Sign Cert
+ &Len[0],
+ Pkcs7GetDigestAlgorithm,
+ Mutex
+ );
+ if (EFI_ERROR(Status))
+ return Status;
+
+ switch(*pHash) {
+ case SHA1:
+ *Digest_len = HASH_SHA1_LEN;
+ HashAlgorithm = &gEfiHashAlgorithmSha1Guid;
+ break;
+ case SHA256:
+ *Digest_len = HASH_SHA256_LEN;
+ HashAlgorithm = &gEfiHashAlgorithmSha256Guid;
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ break;
+ }
+ //
+ // Hash data payload with SHA.
+ //
+ Addr[0] = (UINT8*)VariableName;
+ Len[0] = StrSize16(VariableName);
+ Addr[1] = (UINT8*)VendorGuid;
+ Len[1] = sizeof(EFI_GUID);
+ Addr[2] = (UINT8*)&Attributes;
+ Len[2] = sizeof(UINT32);
+ Addr[3] = (UINT8*)&(CertData->TimeStamp);
+ Len[3] = sizeof(EFI_TIME);
+ Addr[4] = (UINT8*) Data + (CertHdrSize) ;
+ Len[4] = DataSize - (CertHdrSize);
+// zero out unused Time fields:
+/* CertData->TimeStamp.Pad1 = 0;
+ CertData->TimeStamp.Pad2 = 0;
+ CertData->TimeStamp.Nanosecond = 0;
+ CertData->TimeStamp.TimeZone = 0;
+ CertData->TimeStamp.Daylight = 0;*/
+#ifdef EFI_DEBUG
+AVAR_TRACE((TRACE_ALWAYS,"Hash Serialization"));
+ for (j=0; j<5; j++) {
+ AVAR_TRACE((TRACE_ALWAYS,"\nArg%d, Len=0x%x\n0000: ", j, Len[j]));
+ for (i=0; i<Len[j]; i++)
+ {
+ AVAR_TRACE((TRACE_ALWAYS,"%02X ", *(UINT8*)(Addr[j]+i) ));
+ if(Len[j]>16 && i>=15){
+ AVAR_TRACE((TRACE_ALWAYS,"\n....\n%04X: ",Len[j]-16));
+ for (i=Len[j]-16; i<Len[j]; i++)
+ AVAR_TRACE((TRACE_ALWAYS,"%02X ", *(UINT8*)(Addr[j]+i) ));
+ }
+ }
+ }
+#endif
+ Status = mDigitalSigProtocol->Hash(mDigitalSigProtocol, HashAlgorithm, 5, Addr, Len, pDigest);
+#ifdef EFI_DEBUG
+AVAR_TRACE((TRACE_ALWAYS,"\nOutput Digest\n"));
+ for (i=0; i<16; i++)
+ AVAR_TRACE((TRACE_ALWAYS,"%02X ", (pDigest[i]) ));
+AVAR_TRACE((TRACE_ALWAYS,"...\n"));
+#endif
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: VerifyVariable2
+//
+// Description:
+// Verify data payload with AuthInfo in EFI_VARIABLE_AUTHENTICATION_2 type.
+// Follow the steps in UEFI2.3.1. This function is called every time variable with
+// EFI_VARIABLE_AUTHENTICATED_TIME_BASED_ACCESS attribute is
+// created, updated or deleted. This function does all necessary
+// authetication checks and based on the results returns Status.
+// Also it updates the ExtFlags.KeyHash with the hash the Signer's
+// certificate from Variable's AuthInfo Hdr
+//
+// Input:
+// CHAR16 *VariableName Name of Variable to be found.
+// EFI_GUID *VendorGuid Variable vendor GUID.
+// IN UINT32 Attributes - Attributes of the Var
+// VOID **Data - pointer to data block within AutVar Data
+// UINTN *DataSize - size of data block
+// VOID *OldData - pointer to Existing in NVRAM data block
+// UINTN OldDataSize - size of data block
+// UINT64 ExtFlags.MonotonicCount - value of MC or TIME stamp
+// UINT8 ExtFlags.KeyHash[32] - pointer to memory, allocated by caller,
+// where Hash of Signer's certificate will be returned.
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS VerifyVariable2 (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN VOID **Data,
+ IN UINTN *DataSize,
+ IN VOID *OldData,
+ IN UINTN OldDataSize,
+ IN OUT EXT_SEC_FLAGS *ExtFlags
+){
+ EFI_STATUS Status;
+ VOID *RealData;
+ EFI_VARIABLE_AUTHENTICATION_2 *CertData;
+ UINTN CertHdrSize, Pkcs7Cert_len, i;
+ UINT8 *Pkcs7Cert;
+ INT32 TimeStamp, NonZeroTime;
+ UINT8 *PubKeyHash;
+ UINTN PubKeyHashLen;
+ UINT8 AuthVarType;
+
+/*
+ common algo for all Auth2 Vars
+
+1. Verify that the correct AuthInfo.CertType (EFI_CERT_TYPE_PKCS7_GUID) has been
+used and that the AuthInfo.CertData value parses correctly as a PKCS #7 SignedData
+value
+
+2. Verify the signature by:
+-extracting the EFI_VARIABLE_AUTHENTICATION_2 descriptor from the Data buffer;
+-using the descriptor contents and other parameters to
+- construct the input to the digest algorithm;
+-computing the digest;
+ digest = hash (VariableName, VendorGuid, Attributes, TimeStamp, DataNew_variable_content).
+ and
+-comparing the digest with the result of applying the signer's public key to the signature
+!!!!Signer must have at least one Cert!!!!
+
+3. Verify that the signer's certificate chains to a certificate in the Key Exchange Key database (or
+the Platform Key)
+!!!!
+!!!! branch off to handle special Vars for PK or KEK-> Use PK Cert to verify Signer's key
+!!!! all other vars including DB and DBx should be looking for Cert chains in KEK db!!!!
+!!!!
+
+4. Unless the EFI_VARIABLE_APPEND_WRITE attribute is set, verify that the TimeStamp value
+is later than the current timestamp value associated with the variable.
+
+5. For variables with GUID EFI_IMAGE_SECURITY_DATABASE_GUID (i.e. where the data buffer is formatted
+ as EFI_SIGNATURE_LIST), the driver shall not perform an append of EFI_SIGNATURE_DATA values that
+ are already part of the existing variable value
+*/
+// must have Auth attribute to go deeper
+ if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)==0)
+ return EFI_INVALID_PARAMETER;
+
+ RealData = *Data;
+
+ CertData = (EFI_VARIABLE_AUTHENTICATION_2 *) *Data;
+ CertHdrSize = AUTHINFO_2_SIZE(CertData);//(CertData->AuthInfo.Hdr.Hdr.dwLength + sizeof(EFI_TIME));
+
+ if(*DataSize < CertHdrSize)
+ return EFI_SECURITY_VIOLATION;
+
+ // CertBlock->CerData is a begining of Pkcs7 Cert
+ Pkcs7Cert = (UINT8*)&(CertData->AuthInfo.CertData);
+ Pkcs7Cert_len = CertHdrSize - ((UINTN)Pkcs7Cert - (UINTN)*Data);
+
+ //
+ // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.
+ // Cert type should be EFI_CERT_TYPE_PKCS7_GUID.
+ //
+ if ((CertData->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) ||
+ guidcmp ((EFI_GUID*) &(CertData->AuthInfo.CertType), &gEfiCertTypePkcs7Guid)
+ ) {
+ //
+ // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
+ //
+ return EFI_SECURITY_VIOLATION;
+ }
+
+ //
+ // Time check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
+ //
+ TimeStamp = 0;
+ if(os_mktime( CertData->TimeStamp.Year, CertData->TimeStamp.Month,
+ CertData->TimeStamp.Day, CertData->TimeStamp.Hour,
+ CertData->TimeStamp.Minute, CertData->TimeStamp.Second, &TimeStamp ))
+ {
+ NonZeroTime = 0;
+ for(i=0;i < sizeof(EFI_TIME); i++)
+ NonZeroTime+=(INT32)((UINT8*)CertData)[i];
+
+ if(NonZeroTime || ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0)) {
+ AVAR_TRACE((TRACE_ALWAYS,"Invalid Time Stamp\n"));
+ return EFI_SECURITY_VIOLATION;
+ }
+ }
+ AVAR_TRACE((TRACE_ALWAYS,"Update Time Stamp\nOld=%x\nNew=%x\n", ExtFlags->Mc, TimeStamp));
+ if( (Attributes & EFI_VARIABLE_APPEND_WRITE) == EFI_VARIABLE_APPEND_WRITE) {
+ // AppendWrite: Only update Timestamp if New one is greater then current
+ if(OldData && (INT32)ExtFlags->Mc > TimeStamp)
+ TimeStamp = (INT32)ExtFlags->Mc;
+ } else {
+ //Unless the EFI_VARIABLE_APPEND_WRITE attribute is set, verify that the TimeStamp value
+ //is later than the current timestamp value associated with the variable.
+ // and reserved TimeStamp fields must be set to 0
+ if( CertData->TimeStamp.Pad1 ||
+ CertData->TimeStamp.Pad2 ||
+ CertData->TimeStamp.Nanosecond ||
+ CertData->TimeStamp.TimeZone ||
+ CertData->TimeStamp.Daylight ||
+ (OldData && (INT32)ExtFlags->Mc >= TimeStamp)
+ ) {
+ AVAR_TRACE((TRACE_ALWAYS,"Failed\n"));
+ return EFI_SECURITY_VIOLATION;
+ }
+ }
+ ExtFlags->Mc = TimeStamp;
+ AVAR_TRACE((TRACE_ALWAYS,"Upd=%x\n", ExtFlags->Mc));
+ //
+ // Process PK, KEK, seperately.
+ //
+ if (IsDbVar(VendorGuid))
+ AuthVarType = IsDbVarType;
+ else
+ if (IsPkVar(VariableName, VendorGuid))
+ AuthVarType = IsPkVarType;
+ else
+ if (IsKekVar(VariableName, VendorGuid))
+ AuthVarType = IsKekVarType;
+ else
+ AuthVarType = IsPrivateVarType;
+
+ if(AuthVarType != IsPrivateVarType) {
+
+ //
+ // PK, KEK and db/dbx should set EFI_VARIABLE_NON_VOLATILE attribute
+ // authenticated variable.
+ //
+ if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (mPlatformMode == SETUP_MODE || mCustomMode == 1 ) {
+ Status = EFI_SUCCESS;
+ goto Exit_SetupMode;
+ }
+ }
+
+ PubKeyHash = &PublicKeyHashArray[0];
+ Status = ConstructDataParameter (
+ VariableName, VendorGuid, Attributes,
+ *Data, *DataSize,
+ PublicKeyHashArray, &PubKeyHashLen,
+ LOCK // first time Pkcs7 cert process.
+ );
+ if (EFI_ERROR(Status))
+ return EFI_SECURITY_VIOLATION;
+
+//
+// Process UEFI Private TimeBased Authenticated Variables
+//
+ if (AuthVarType == IsPrivateVarType){
+ /*
+ Extract x509 Signing Cert(hash) and validate self signed data
+ Updating Cert hash Existing Variable
+ */
+ Status = ValidateSelfSigned (
+ Pkcs7Cert, Pkcs7Cert_len, // Pkcs7Cert
+ &PubKeyHash, &PubKeyHashLen, // Input->Digest, Output->DER Ptr to Signing Cert
+ Pkcs7CertValidateGetSignerKeyHash
+ );
+ if (!EFI_ERROR(Status)) {
+ // Updating Existing Variable
+ if (OldData && MemCmp(&ExtFlags->KeyHash[0], PubKeyHash, PubKeyHashLen)){
+ AVAR_TRACE((TRACE_ALWAYS,"Private Var Key Compare FAILED!\n"));
+ return EFI_SECURITY_VIOLATION;
+ }
+ // Setting Hash for self signed variables
+ MemCpy(&ExtFlags->KeyHash[0], PubKeyHash, PubKeyHashLen);
+
+ *DataSize = *DataSize - CertHdrSize;
+ *Data = (UINT8*)RealData + CertHdrSize;
+ }
+ } else {
+//
+// Process UEFI TimeBased PK, KEK and db(x) variables
+//
+ if (AuthVarType == IsDbVarType) {
+ Status = ProcessVarWithKek2 (Pkcs7Cert, Pkcs7Cert_len, PubKeyHash, PubKeyHashLen);
+ // verify process db(x) with one of KEK keys or if not found within KEK - with PK
+ AVAR_TRACE((TRACE_ALWAYS,"kek for db check %r\n", Status));
+ if (Status == EFI_SECURITY_VIOLATION) {
+ Status = ProcessVarWithPk2 (Pkcs7Cert, Pkcs7Cert_len, PubKeyHash, PubKeyHashLen);
+ AVAR_TRACE((TRACE_ALWAYS,"PK for db check %r\n", Status));
+ }
+ //
+ // Process PK, KEK separately.
+ //
+ } else
+ if (AuthVarType == IsPkVarType || AuthVarType == IsKekVarType)
+ Status = ProcessVarWithPk2 (Pkcs7Cert, Pkcs7Cert_len, PubKeyHash, PubKeyHashLen);
+
+ if (EFI_ERROR(Status))
+ return EFI_SECURITY_VIOLATION;
+
+Exit_SetupMode:
+
+ *DataSize = *DataSize - CertHdrSize;
+ *Data = (UINT8*)RealData + CertHdrSize;
+
+ // Validate Signature List integrity
+ if(*DataSize && EFI_ERROR(ValidateSignatureList (*Data, *DataSize)))
+ return EFI_SECURITY_VIOLATION;
+ //
+ // If delete PK in user mode -> change to setup mode.
+ // If enroll PK in setup mode -> change to user mode.
+ //
+ if(AuthVarType == IsPkVarType) {
+ if (*DataSize == 0)
+ UpdatePlatformMode (SETUP_MODE);
+ else
+ UpdatePlatformMode (USER_MODE);
+ }
+ }
+
+ return Status;
+}
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.c b/Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.c
new file mode 100644
index 0000000..a8489f9
--- /dev/null
+++ b/Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.c
@@ -0,0 +1,1729 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SecureBoot_WIN8/AuthenticatedVariable_efi/AuthVariable.c 90 3/09/15 4:28p Alexp $
+//
+// $Revision: 90 $
+//
+// $Date: 3/09/15 4:28p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureBoot_WIN8/AuthenticatedVariable_efi/AuthVariable.c $
+//
+// 90 3/09/15 4:28p Alexp
+// Update year 2015 in the file header
+//
+// 88 10/08/14 3:16p Alexp
+// Introduced global mCustomMode flag passing the status from
+// PhysicalUserPresent()
+//
+// 87 10/17/13 12:58p Alexp
+//
+// 85 6/25/13 1:52p Alexp
+// GetmSecureBootSupport() Init SecureBootVar structure with SDL defaults.
+//
+// 84 5/17/13 4:37p Alexp
+// EIP:122063 CSM related: failure to boot UEFI if DefaultKeyProvision is
+// set without system reset
+// change: SecureBoot variable is set once during AuthVar Init()
+//
+// 83 4/15/13 11:07a Alexp
+// Restore the code to install "SignatureSupport" variable.
+// It was mistakenly removed due to a discussin at USWG that
+// the Var should have been deprectated.
+//
+// 82 3/06/13 6:52p Alexp
+// AuthVariableServiceInitSMM()
+// verify if gAmiSmmDigitalSignatureProtocol already installed before
+// installing a callback on protocol
+//
+// 79 2/20/13 6:31p Alexp
+// EIP[115120]:Secureboot Firmware does not verify duplication before
+// Appending to the variable.
+// Fix: Update FindInSignatureDb() to process combination of SigData and
+// SigLists
+//
+// 77 2/08/13 5:14p Alexp
+// removed unused arguments from ProcessVarWithPk & ProcessVarWithKek
+//
+// 76 12/18/12 10:58a Alexp
+// code fixes according to "cppcheck" style & performance suggestions
+//
+// 73 12/11/12 6:31p Alexp
+// - Replaced TRACE macro with AVAR_TRACE. Stop debug traces in Virtual
+// address mode
+// - VerifyVariable() Fix final check for IsPk and run
+// ValidateSignatureList()
+//
+// 71 12/06/12 7:36p Alexp
+// EIP#98995, EIP#102807 : WHCK tests fail
+// -removed AuthVarLock logic,
+// -use PhysicalUserPresent() hook
+// to unlock Secure Variables for write/erase
+//
+// 70 12/04/12 6:54p Alexp
+// EIP#98995, EIP#102807 : Secure Boot WHCK tests fail
+// temp fix in PhysicalUserPresent()->return NOT_DETECTED if var not found
+//
+// 69 11/26/12 10:46a Alexp
+// replaced hardwired Var name L"SecureBootSetup" to generic Var define
+//
+// 68 11/21/12 3:33p Alexp
+// Fix for Win8 SecureBoot logo requirement: restore Secure Boot state
+// across flash updates.
+// Move all secure boot Setup settings to a separate varstore variable
+// in order to preserve settings across re-flash
+//
+// 66 11/16/12 7:11p Alexp
+// Fixed ValidateSignatureList() return status for Zero Data or Size
+//
+// 65 11/09/12 4:30p Alexp
+// EIP:104961 UEFI 2.3.1 SCTc test failed in Generic\EfiCompliant case.
+// Fix for SelfSigned variables.
+//
+// 64 11/01/12 5:45p Alexp
+// bug fix: ValidateSignatureList () returned Success
+// even if no sig detected if file size = 0( line 1015)
+//
+// 63 10/22/12 10:32a Alexp
+// fixed SetupMode overwrite while updating RO vars:SetupMode and
+// SecureBoot.
+//
+// 62 10/19/12 5:07p Alexp
+// Implemented R/O Variables support via fixed and OEM defined (eLink)
+// lists. Secure Boot RO Variable logic includes Vendor GUID check
+// Reserved Secure Boot RO variables are gEfiGlobalVariableGuid.
+//
+// 58 9/25/12 11:20a Alexp
+// Add New feature:
+// include facility to link external Physical User Presence
+// detect hooks via eLink:PhysicalUserPresenceDetect
+//
+// 55 9/14/12 3:40p Alexp
+// 1. removed unused code for setting Pk/Kek/db vars
+// 2. optimized mAuthVarLock logic
+//
+// 54 9/12/12 12:16p Alexp
+// removed dependency on mSecureBootMode. AuthVar is locked always at
+// ReadyTo boot
+//
+// 53 8/29/12 5:02p Alexp
+// SetVariable(): return status matched to UEFI Spec: if both
+// Authenticated Attributes are set returns INVALID_PARAMETER (old
+// UNSUPPORTED)
+//
+// 52 8/27/12 6:55p Alexp
+// GetmSecureBootSupport():
+// Add input parameter SetupMode to disable
+// Setup Flag:SecureBootSupport when platform in Setup Mode
+// Logic enabled by DEFAULT_SECURE_BOOT_ENABLE = 0
+//
+// 50 8/23/12 5:36p Alexp
+// UEFI ECR change.
+// Don't install SignatureSupport Variable. It's obsolete in UEFI 2.3.1+
+//
+// 49 8/22/12 9:23a Alexp
+// difined CUSTOM_BOOT_MODE = 2 to match value in Setup Variable
+//
+// 47 7/27/12 4:36p Alexp
+// Changed Auth Var rules override policy: no need for Admin var checking
+// Further enhancement will introduce physical user presence detection
+//
+// 45 7/25/12 6:37p Alexp
+// enhance ValidateSignatureList() checking. SigList.Size field must be of
+// valid size.
+//
+// 44 5/17/12 4:21p Alexp
+// Fix for SCT 5/12 test for Auth Variables. SCT ignores rules for
+// reserved Secure Boot variables always be formatted as Authenticated
+// Variable with proper attributes.
+//
+// 42 4/30/12 10:53a Alexp
+// EIP88439: irrespective of SetupMode, only properly formatted
+// Authenticated Variable can be erased
+//
+// 40 4/10/12 6:53p Alexp
+// comment clean up
+//
+// 36 3/14/12 1:02p Alexp
+// AuthServiceVirtualFixup: fixup addresses within AmiSigAPI
+//
+// 35 3/13/12 2:36p Alexp
+// Add check for System in Admin mode while allowing Var Security override
+//
+// 33 3/09/12 3:37p Alexp
+// -add logic to process new Secure Boot mode-Custom
+// -just a temp change - will be reviewed in later releases
+//
+// 13 3/09/12 3:35p Alexp
+// -add logic to process new Secure Boot mode-Custom
+// -just a temp change - will be reviewed in later releases
+//
+// 32 2/27/12 6:48p Alexp
+//
+// 31 2/15/12 11:00a Alexp
+// added traces for Signature List validation.
+//
+// 30 2/03/12 9:56a Alexp
+// EIP#82122. WHCK "Secure Boot Manual Logo Test" fails
+// Fixed Append logic to process multiple sig data instances in a single
+// Signature List block
+// New logic will remove dupplicated certs and update new SigList header.
+//
+// 29 12/29/11 6:52p Alexp
+// Updated logic for handling cases with mAuthVarLock = FALSE.
+//
+// 28 12/16/11 4:44p Alexp
+// Add build time switch USER_MODE_POLICY_OVERRIDE
+// AuthVariable logic will allow override/erase Secure Variables without
+// enforcing Authentication rules until receiving EFI ReadyToBoot event.
+//
+// 26 11/30/11 7:58p Alexp
+// According to UEFI 2.3.1 Sec 7.2.1 : "db" vars can be validated either
+// by KEK key or by PK key.
+// The fix adds the check for PK if none of KEKs can validate new "db"
+//
+// 25 11/08/11 3:03p Alexp
+// 1. ValidateSignatureList: add check for invalid parameter Data== NULL
+// 2. VerifyVariable: ignore check for AuthAttribute match if in Setup
+// Mode
+// 3. VerifyVariable: Always set TimeBased Attributes for reserved Sec
+// variables
+//
+// 24 11/02/11 10:53a Alexp
+// 1. EIP#71452. Due to a bug in FindVariable() in NVRAMDXE.C SecureBootSetup
+// Variable cannot be located at first boot.
+// Changed GetmSecureBootSupport() to use
+// DxeGetVariable instead of FindVariable
+// 2. Made temp fixes to pass SCT 2.3.1 TW UEFI Plugfest build.
+// a. MC Based Variable. Length of the CertHdr reported wrongly
+// 22b vs 230 bytes
+// b. MC based Variable. CertType GUID is reported wrongly
+// c. Allow to set reserved Sec Variables KEK, db(x) without Auth
+// attributes in Setup Mode
+//
+// 22 8/24/11 8:45a Alexp
+// added Mailbox variable AuthVarMailbox to inform SMM AuthVariable code
+// of ReadyToBoot event. Needed to prevent erase of Signed Variables in
+// runtime
+//
+//
+// 19 8/22/11 11:11a Alexp
+// UpdatePlatformMode() - moved mPlatformMode=Mode at the end
+// VerifyVar - move back door code inside AuthAttribute branch
+//
+// 17 8/18/11 5:59p Alexp
+// renamed SecureBootMode to more appropriate SecureBootSupport
+// renamed BeforeBoot to AuthVarLock.
+// Keep unlocked in DXE phase and locked while in SMM
+//
+// 16 8/18/11 4:57p Alexp
+// 1. Removed use of Mailbox varaible to communicate state to SMM copy of
+// AuthVar service
+// 2. Removed Callback event to erase Secure Variables.
+// 3. Optimized logic to exchange local data between DXE and SMM copies of
+// AuthVar
+// 4. Add provision to erase of Auth Variables before
+// BdsConnect(ReadyToBoot) lock event
+//
+// 15 8/16/11 7:18p Alexp
+// added Mailbox variable AuthVarMAilbox to syncronize local state between
+// DXE and SMM AuthVariable services
+//
+// 14 8/12/11 1:49p Alexp
+// comment out getplatfmode() in VerifyVariable call. Not needed as we do
+// not want to change the SetupMode in runtime
+//
+// 13 8/05/11 3:13p Alexp
+// VerifyVariable->Set current time as TimeStamp for Signed Variables (PK,
+// KEK..) if they are set in User mode
+//
+// 12 8/04/11 7:15p Alexp
+// 1. UpdatePlatformMode. Moved Get SecureBootSetup to Init function.
+// 2. Fix detection of IsPk() in VerifyVariable for SetupMode control flow
+//
+// 11 7/18/11 10:09a Alexp
+// 1. Made gEfiGlobalVariableGuid static. Fixes link issues in older Aptio
+// cores
+// 2. Update Append verify with added check for the new data to be in
+// SignatureList format
+//
+// 10 6/30/11 4:02p Alexp
+// added Callback event on Setup Mode change request form Security Setup
+// Page.
+//
+// 9 6/27/11 6:16p Alexp
+// code optimization: moved ValidateSignatureList () call in the main
+// VerifyVariable1(2) function.
+//
+// 8 6/24/11 7:03p Alexp
+// fixed ValidateSignatureList () logic. Added Certificate RSA2048 to
+// supported Signatures
+//
+// 7 6/24/11 3:22p Alexp
+// test PK, KEK, db(x) for valid Signatuer List header with
+// ValidateSignatureList()
+//
+// 6 6/24/11 2:24p Alexp
+// 1. Call Auth Variable init in smm callback. need to initialize global
+// variables for SetupMode and SecureBoot
+// 2. Enable SignatureList header validation for PK-KEK-db payload
+//
+// 5 6/23/11 6:19p Alexp
+// Added ValidateSigList() function
+//
+// 4 6/23/11 10:05a Alexp
+// add dependency on ImageAuthentication token for SecureBoot Variable
+// installation
+//
+// 3 6/22/11 5:42p Alexp
+// ignore Authenticated Variable rules while in non SecureBoot mode
+//
+// 2 6/15/11 3:01p Alexp
+// Add checks for variables with zero parameters: Attributes, Data, Size
+//
+// 1 6/13/11 5:25p Alexp
+//
+// 18 6/13/11 4:28p Alexp
+// rearranged calls to VerifyVariable1 & 2 from main VerifyVariable()
+//
+// 17 6/09/11 5:49p Alexp
+// add AuthServiceVirtualFixup
+//
+// 16 6/06/11 6:01p Alexp
+// UpdatePlatformMode: update both SetupMode and SecureBoot at once
+//
+// 15 6/03/11 4:12p Alexp
+// bug fix: when changing SetupMode check for PK file attribute to have
+// Auth flag
+// set TimeBased attrib for non-signed generic Secured variables (Win8
+// w/a)
+//
+//
+// 13 6/02/11 5:50p Alexp
+// fix a bug with self signed key hash compare
+//
+// 12 6/02/11 1:06p Alexp
+// fix failed case with Append db logic if certificate already existed
+//
+// 11 6/01/11 1:06p Alexp
+// removed GetSecureVars hook. Use UpdatePlatformMode() instead
+// cleaned Append logic
+//
+// 9 5/25/11 8:34p Alexp
+// draft fix for TimeBased auth variables. More work w Msft needed
+//
+// 8 5/19/11 4:59p Alexp
+// Major code revamp to be able to handle of handling Secure vars in Setup
+// Mode
+// TBD: TimeBased certificates from Msft fail to process. Not compiled as
+// Authenticode format
+//
+// 7 5/17/11 12:48p Alexp
+// fix WDK level4 compiler warnings
+//
+// 6 5/13/11 3:43p Alexp
+// add dependency on Core rev.
+//
+// 5 5/12/11 5:53p Alexp
+// fix tobuld for Aptio core 4.6.4. and older.
+//
+// 4 5/11/11 7:20p Alexp
+// VarData init for FindVariable
+//
+// 3 5/10/11 5:07p Alexp
+// removed local Hash Guid defines
+//
+// 2 5/10/11 3:56p Alexp
+// move FindVariable to NVRAMDXE.c
+//
+// 1 5/09/11 10:00a Alexp
+//
+// 9 5/05/11 12:10p Alexp
+// make it as eModule, replace TRACE call to TRACE macro. Only dump TRACEs
+// in Debug mode
+//
+// 8 3/31/11 6:27p Alexp
+// removed asserts on missing DB, KEK
+//
+//**********************************************************************
+
+#include "NVRAM.h"
+#include <AmiDxeLib.h>
+#include <AmiCspLib.h>
+#include <Setup.h>
+#include <SecureBootMod.h>
+
+#include <Protocol/AmiDigitalSignature.h>
+
+#include "AuthVariable.h"
+
+//
+// Global defines and variables
+//
+
+BOOLEAN AVarRuntime = FALSE;
+
+#define BDS_CONNECT_DRIVERS_PROTOCOL_GUID \
+{0x3aa83745, 0x9454, 0x4f7a, 0xa7, 0xc0, 0x90, 0xdb, 0xd0, 0x2f, 0xab, 0x8e}
+static EFI_GUID gBdsConnectDriversProtocolGuid = BDS_CONNECT_DRIVERS_PROTOCOL_GUID;
+static EFI_GUID gEfiGlobalVariableGuid = EFI_GLOBAL_VARIABLE;
+static EFI_GUID mSignatureSupport[SIGSUPPORT_NUM] = {SIGSUPPORT_LIST};
+static EFI_GUID gSecureSetupGuid = SECURITY_FORM_SET_GUID;
+static EFI_GUID gSystemAccessGuid = SYSTEM_ACCESS_GUID;
+static SECURE_BOOT_SETUP_VAR mSecureBootSetup;
+
+UINT8 PublicKeyHashArray[HASH_SHA256_LEN];
+UINT8 mPlatformMode = SETUP_MODE;
+UINT8 mSetupMode = USER_MODE;
+UINT8 mCustomMode = 0;
+static UINT8 mSecureBootSupport = NONSECURE_BOOT;
+
+AMI_DIGITAL_SIGNATURE_PROTOCOL *mDigitalSigProtocol = NULL;
+
+static CHAR16* ReservedReadOnlyVarNameList[] = {
+ EFI_SETUP_MODE_NAME,
+ EFI_SECURE_BOOT_NAME,
+ EFI_SIGNATURE_SUPPORT_NAME,
+ EFI_IMAGE_SECURITY_DATABASE_DEFAULT,
+ EFI_IMAGE_SECURITY_DATABASE1_DEFAULT,
+ EFI_PLATFORM_KEY_NAME_DEFAULT,
+ EFI_KEY_EXCHANGE_KEY_NAME_DEFAULT,
+ NULL
+};
+static CHAR16* OemReadOnlyVariableList[] = {OEM_READONLY_VAR_LIST NULL};
+
+#if USER_MODE_POLICY_OVERRIDE == 1
+
+typedef BOOLEAN (HOOK_PHYSICAL_USER_PRESENCE_DETECT)(
+ VOID
+);
+
+extern HOOK_PHYSICAL_USER_PRESENCE_DETECT PHYSICAL_USER_PRESENCE_DETECT_LIST EndOfPhysicalUserPresentHook;
+
+HOOK_PHYSICAL_USER_PRESENCE_DETECT* PhysicalUserPresentHookList[]=
+ {PHYSICAL_USER_PRESENCE_DETECT_LIST NULL};
+
+BOOLEAN PhysicalUserPresent( VOID )
+{
+ UINTN i;
+ BOOLEAN Result = FALSE;
+ for(i=0; PhysicalUserPresentHookList[i] && (Result == FALSE); i++)
+ Result = PhysicalUserPresentHookList[i]();
+ return Result;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AuthVarAdminUserPresent
+//
+// Description: Default implementation for Physical User Presense detection.
+// Detects if Admin User signed in by checking "SystemAccess" Variable
+//
+// Input: NONE
+//
+// Output: BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN AuthVarAdminUserPresent ( VOID )
+{
+ SYSTEM_ACCESS SystemAccess = {SYSTEM_PASSWORD_USER};
+ UINTN Size = sizeof(SYSTEM_ACCESS);
+ UINT32 Attributes = 0;
+ EFI_STATUS Status;
+ // TBD. Replace Admin User mode with true Physical user presence detection
+ Status = DxeGetVariable(L"SystemAccess", &gSystemAccessGuid, &Attributes, &Size, &SystemAccess);
+ if (!EFI_ERROR(Status)
+ && !(Attributes & EFI_VARIABLE_NON_VOLATILE)
+ && SystemAccess.Access==SYSTEM_PASSWORD_ADMIN)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AuthServiceVirtualFixup
+//
+// Description: This function will be invoked to convert
+// runtime pointers to virtual address
+//
+// Input: none
+//
+// Output: VOID
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID AuthServiceVirtualFixup()
+{
+
+ static BOOLEAN bSigProtoVirtual = FALSE;
+ VOID **p;
+ UINT8 i;
+
+ //if mDigitalSigProtocol is NULL, nothing to fix up
+ if (!mDigitalSigProtocol) return;
+
+ // This function gets called from Nvramdxe.c, do nothing when
+ // the function is called second time.
+ if (bSigProtoVirtual == TRUE) return;
+ else bSigProtoVirtual = TRUE;
+//AVAR_TRACE((-1,"AuthVarService mDigitalSig Virtual addr Fixup\n"));
+ //Fixup mDigitalSigProtocol member functions
+ for(i=0,p = (VOID**)mDigitalSigProtocol; p < (VOID**)(mDigitalSigProtocol + 1); i++,p++)
+// {
+//AVAR_TRACE((-1,"mSigAPI[%d] before Virtual MemFixup = %lx (%lx), ", i, p));
+ pRS->ConvertPointer(0, p);
+//AVAR_TRACE((-1,"After = %lx\n", p));
+// }
+ pRS->ConvertPointer(0,&mDigitalSigProtocol);
+ AVarRuntime = TRUE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InitSmmAuthServiceCallback
+//
+// Description: This function initialize mDigitalSigProtocol in SMM
+//
+//
+// Input: IN EFI_EVENT Event - Event that was triggered
+// IN VOID *Context - data pointer to information that is defined
+// when the event is registered
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS InitSmmAuthServiceCallback (IN EFI_EVENT Event, IN VOID *Context)
+{
+ return pBS->LocateProtocol(
+ &gAmiSmmDigitalSignatureProtocolGuid, NULL, &mDigitalSigProtocol
+ );
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InitSmmAuthService
+//
+// Description: This function calls InitSmmAuthServiceCallback to initialaze
+// DigitalSigProtocol in SMM by trying to Locate
+// DigitalSigProtocol. If Protocol is not installed yet
+// RegisterProtocolCallback will be called.
+//
+//
+// Input: None
+//
+// Output: VOID
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID AuthVariableServiceInitSMM ()
+{
+ EFI_STATUS Status;
+ EFI_EVENT SmmHashEvent;
+ VOID *pSmm;
+
+ // temp w/a: don't print debug traces from SMM
+ AVarRuntime = TRUE;
+ //
+ // Authenticated variable initialize.
+ //
+ // Check PK database's existence to determine the value.
+ // Then create "SetupMode" with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
+ //
+ // Update mPlatformMode
+ GetPlatformMode();
+
+ // Update mSecureBootSupport global variable
+ GetmSecureBootSupport(mPlatformMode);
+
+ Status = InitSmmAuthServiceCallback (NULL, NULL);
+ if (EFI_ERROR(Status))
+ RegisterProtocolCallback(
+ &gAmiSmmDigitalSignatureProtocolGuid,
+ InitSmmAuthServiceCallback,
+ NULL,
+ &SmmHashEvent,
+ &pSmm
+ );
+}
+
+//------------------------------------------------------------------------------
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InitAuthServiceCallback
+//
+// Description: This function initialize mDigitalSigProtocol not in SMM
+//
+//
+// Input: IN EFI_EVENT Event - Event that was triggered
+// IN VOID *Context - data pointer to information that is defined
+// when the event is registered
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS InitAuthServiceCallback (IN EFI_EVENT Event, IN VOID *Context)
+{
+ return pBS->LocateProtocol(
+ &gAmiDigitalSignatureProtocolGuid, NULL, &mDigitalSigProtocol
+ );
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AuthVariableServiceInit
+//
+// Description: This function calls InitAuthServiceCallback to initialaze
+// DigitalSigProtocol not in SMM by trying to Locate
+// DigitalSigProtocol. If Protocol is not installed yet
+// RegisterProtocolCallback will be called.
+//
+//
+// Input: None
+//
+// Output: VOID
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID AuthVariableServiceInit ()
+{
+ EFI_EVENT Event;
+ VOID *p;
+ UINT8 Data;
+
+ //
+ // Create "SignatureSupport" with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
+ //
+ DxeSetVariable(EFI_SIGNATURE_SUPPORT_NAME,&gEfiGlobalVariableGuid,
+ EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ SIGSUPPORT_NUM * sizeof(EFI_GUID), &mSignatureSupport
+ );
+ //
+ // Check presence of PK database to determine the value.
+ // Then create "SetupMode" with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
+ // Update mPlatformMode
+ GetPlatformMode();
+
+ // Update mSecureBootSupport global variable
+ GetmSecureBootSupport(mPlatformMode);
+
+ // Set SecureBoot, both conditions must be met
+ Data = (mPlatformMode==USER_MODE && mSecureBootSupport==SECURE_BOOT)?1:0;
+ DxeSetVariable(EFI_SECURE_BOOT_NAME,&gEfiGlobalVariableGuid,
+ EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof(UINT8), &Data);
+
+ // Create "SetupMode" variable with RO access
+ UpdatePlatformMode(mPlatformMode);
+
+ if (EFI_ERROR(InitAuthServiceCallback (NULL, NULL)))
+ RegisterProtocolCallback(
+ &gAmiDigitalSignatureProtocolGuid,
+ InitAuthServiceCallback,
+ NULL,
+ &Event,
+ &p
+ );
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StrSize16
+//
+// Description:
+// This function returns UNICODE string size in bytes
+//
+// Input:
+// CHAR16 *String - Pointer to string
+//
+// Output:
+// UINT32 - Size of string in bytes excluding the nul-terminator
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT32 StrSize16(CHAR16 *String)
+{
+ UINT32 Size = 0;//2;
+ while(*String++)
+ Size += 2;
+ return Size;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StrCmp16
+//
+// Description:
+// This function compares two UNICODE strings
+//
+// Input:
+// IN CHAR16 *Dest - Pointer to destination string
+// IN CHAR16 *Src - Pointer to source string
+//
+// Output:
+// INTN - Zero if strings are equal, non-zero otherwise
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+INTN StrCmp16(CHAR16 *Dest, CHAR16 *Src)
+{
+ return MemCmp(Dest, Src, StrSize16(Src));
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsPkVar
+//
+// Description:
+// This function compares two UNICODE strings
+//
+// Input:
+// CHAR16 - Pointer to UNICODE Variable Name
+// EFI_GUID - Pointer to Variable GUID
+//
+// Output:
+// BOOLEAN - TRUE if strings are equal
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN IsPkVar(
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid
+)
+{
+ return ((guidcmp(VendorGuid, &gEfiGlobalVariableGuid) == 0) &&
+ (StrCmp16 ((CHAR16 *)VariableName, (CHAR16 *)EFI_PLATFORM_KEY_NAME) == 0));
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsKekVar
+//
+// Description:
+// This function compares two UNICODE strings
+//
+// Input:
+// CHAR16 - Pointer to UNICODE Variable Name
+// EFI_GUID - Pointer to Variable GUID
+//
+// Output:
+// BOOLEAN - TRUE if strings are equal
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN IsKekVar(
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid
+)
+{
+ return ((guidcmp(VendorGuid, &gEfiGlobalVariableGuid) == 0) &&
+ (StrCmp16 ((CHAR16 *)VariableName, (CHAR16 *)EFI_KEY_EXCHANGE_KEY_NAME) == 0));
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsReservedVariableName
+//
+// Description:
+// Check if Variable name matches one from Predefined Read-Only Variable Name list
+//
+// Input:
+// CHAR16 - Pointer to UNICODE Variable Name
+// EFI_GUID *VendorGuid - Variable GUID
+//
+// Output:
+// BOOLEAN
+// TRUE if Variable name found in the Predefined Read-Only Variable Name lists
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+IsReservedVariableName(
+ CHAR16 *VariableName,
+ EFI_GUID *VendorGuid
+)
+{
+ UINT8 Index;
+ Index = 0;
+
+ while(ReservedReadOnlyVarNameList[Index] != NULL)
+ {
+ if(StrCmp16 (VariableName, ReservedReadOnlyVarNameList[Index]) == 0)
+ {
+// Reserved Secure Boot RO variables are gEfiGlobalVariableGuid.
+ return (guidcmp(VendorGuid, &gEfiGlobalVariableGuid) == 0);
+ }
+ Index++;
+ }
+ Index = 0;
+ while(OemReadOnlyVariableList[Index] != NULL)
+ {
+ if(StrCmp16 (VariableName, OemReadOnlyVariableList[Index]) == 0)
+ return TRUE;
+ Index++;
+ }
+
+ return FALSE;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsDbVar
+//
+// Description:
+// This function compares two UNICODE strings
+//
+// Input:
+// IN CHAR16 *Dest - Pointer to destination string
+// IN CHAR16 *Src - Pointer to source string
+//
+// Output:
+// INTN - Zero if strings are equal, non-zero otherwise
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN IsDbVar(
+ IN EFI_GUID *VendorGuid
+)
+{
+ return (!guidcmp (VendorGuid, &gEfiImageSecurityDatabaseGuid));
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetPlatformMode
+//
+// Description:
+// Initializes for authenticated varibale service.
+//
+// Input:
+// UINT8 *PlatformMode
+//
+// Output: EFI_STATUS Function successfully executed.
+// UINT8 *PlatformMode
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+GetPlatformMode (
+ VOID
+)
+{
+ EFI_STATUS Status;
+ UINT32 VarAttr;
+ UINTN VarDataSize;
+ VOID *Data;
+
+ mPlatformMode = USER_MODE;
+
+ //
+ // Check PK database's existence to determine the value.
+ //
+ VarDataSize = 0;
+ Status = FindVariable (
+ EFI_PLATFORM_KEY_NAME,
+ &gEfiGlobalVariableGuid,
+ &VarAttr,
+ &VarDataSize,
+ &Data
+ );
+ if (Status != EFI_SUCCESS || Data == NULL || VarDataSize == 0 ||
+ !(VarAttr & UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES)
+ ) {
+ mPlatformMode = SETUP_MODE;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetmSecureBootSupport
+//
+// Description:
+// Initializes for authenticated varibale service.
+//
+// Input:
+// SetupMode Disable SecureBoot control if Platform runs in SetupMode (no PK)
+//
+// Output: EFI_STATUS Function successfully executed.
+// EFI_OUT_OF_RESOURCES Fail to allocate enough memory resources.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+GetmSecureBootSupport (
+ UINT8 SetupMode
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+//#if defined(ImageVerification_SUPPORT) && ImageVerification_SUPPORT==1
+ UINTN DataSize=0;
+ //
+ // Get Setup variable, check SecureBoot and set the EFI Var
+ //
+ Status = DxeGetVariable(
+ AMI_SECURE_BOOT_SETUP_VAR,
+ &gSecureSetupGuid,
+ NULL,
+ &DataSize,
+ &mSecureBootSetup
+ );
+ if(Status == EFI_BUFFER_TOO_SMALL)
+ Status = DxeGetVariable(
+ AMI_SECURE_BOOT_SETUP_VAR,
+ &gSecureSetupGuid,
+ NULL,
+ &DataSize,
+ &mSecureBootSetup
+ );
+ ASSERT_EFI_ERROR (Status);
+ mSecureBootSupport = (mSecureBootSetup.SecureBootSupport);
+// Disable SecureBoot Setup Option if system is in Setup mode
+#if DEFAULT_SECURE_BOOT_ENABLE == 0
+ if(mSecureBootSupport == 1 &&
+ (SetupMode == SETUP_MODE && mSecureBootSetup.DefaultKeyProvision == 0)
+ )
+ {
+ mSecureBootSupport = NONSECURE_BOOT;
+ }
+#endif
+//#else
+// mSecureBootSupport = NONSECURE_BOOT;
+//#endif
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UpdatePlatformMode
+//
+// Description: Update mPlatformMode & "SetupMode" Efi var
+//
+// Input: Mode SETUP_MODE or USER_MODE.
+//
+// Output: none
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+UpdatePlatformMode(
+ IN UINT8 Mode
+)
+{
+AVAR_TRACE((TRACE_ALWAYS,"Update Setup Mode\nCurrent=%x, New=%x\n", mPlatformMode, Mode));
+ //
+ // update global mPlatformMode var
+ //
+ mPlatformMode = Mode;
+ //
+ // Set "SetupMode" variable.
+ //
+ // Setting of mSetupMode=SETUP_MODE will un-lock access to runtime R/O vars
+ mSetupMode = SETUP_MODE;
+
+ DxeSetVariable(EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof(UINT8), &mPlatformMode);
+
+// Re-lock access to runtime protected vars
+ mSetupMode = USER_MODE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ValidateSignatureList
+//
+// Description:
+// Validate the data payload begins with valid Signature List header
+// and based on the results returns Status.
+//
+// Input:
+// IN VOID *Data - pointer to the Var data
+// IN UINTN DataSize - size of Var data
+//
+// Output: EFI_STATUS
+// UINTN RealDataSize - only the size of the combined length of Signature Lists
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ValidateSignatureList (
+ IN VOID *Data,
+ IN UINTN DataSize
+)
+{
+ EFI_STATUS Status;
+ EFI_SIGNATURE_LIST *SigList;
+ UINTN Index;
+
+ Status = EFI_SECURITY_VIOLATION;
+
+ if(Data == NULL || DataSize == 0)
+ return Status; // Sig not found
+
+ SigList = (EFI_SIGNATURE_LIST *)Data;
+
+// loop till end of DataSize for all available SigLists
+
+// Verify signature is one from SigDatabase list mSignatureSupport / sizeof(EFI_GUID)
+// SigData begins with SigOwner GUID
+// SignatureHdrSize = 0 for known Sig Types
+
+ while ((DataSize > 0) && (DataSize >= SigList->SignatureListSize)) {
+
+ for (Index = 0; Index < SIGSUPPORT_NUM; Index++) {
+ if (!guidcmp ((EFI_GUID*) &(SigList->SignatureType), &mSignatureSupport[Index]))
+ break;
+ }
+AVAR_TRACE((TRACE_ALWAYS,"SigList.Type-"));
+ if(Index >= SIGSUPPORT_NUM)
+ return EFI_SECURITY_VIOLATION; // Sig not found
+
+AVAR_TRACE((TRACE_ALWAYS,"OK\nSigList.Size-"));
+ if(SigList->SignatureListSize < 0x4c || // Min size for SHA2 Hash Certificate sig list
+ SigList->SignatureListSize > NVRAM_SIZE)
+ return EFI_SECURITY_VIOLATION;
+
+AVAR_TRACE((TRACE_ALWAYS,"OK\nSigList.HdrSize-"));
+ if(SigList->SignatureHeaderSize != 0)
+ return EFI_SECURITY_VIOLATION; // Sig not found
+AVAR_TRACE((TRACE_ALWAYS,"OK\n"));
+ DataSize -= SigList->SignatureListSize;
+ SigList = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + SigList->SignatureListSize);
+
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ProcessVarWithPk
+//
+// Description: Process variable with platform key for verification.
+//
+//
+// Input:
+// VariableName Name of Variable to be found.
+// VendorGuid Variable vendor GUID.
+// Data Data pointer.
+// DataSize Size of Data found. If size is less than the
+// data, this value contains the required size.
+// Variable The variable information which is used to
+// keep track of variable usage.
+// Attributes Attribute value of the variable
+// IsPk Indicate whether it is to process pk.
+//
+// Output: EFI_SUCCESS Variable passed validation successfully.
+// EFI_INVALID_PARAMETER Invalid parameter.
+// EFI_SECURITY_VIOLATION The variable does NOT pass the validation.
+// check carried out by the firmware.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ProcessVarWithPk (
+ IN VOID *Data,
+ IN UINTN DataSize,
+ IN UINT32 Attributes,
+ IN BOOLEAN IsPk
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_SIGNATURE_LIST *OldPkList;
+ EFI_SIGNATURE_DATA *OldPkData;
+ UINT32 VarAttr;
+ UINT8 *VarData;
+ UINTN VarDataSize=0;
+
+ if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
+ //
+ // PK and KEK should set EFI_VARIABLE_NON_VOLATILE attribute.
+ //
+//AVAR_TRACE((TRACE_ALWAYS,"PK NOT_VOLITILE\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mPlatformMode == SETUP_MODE || mCustomMode == 1)
+ return Status;
+ //
+ // Get platform key from variable.
+ //
+ Status = FindVariable (
+ EFI_PLATFORM_KEY_NAME,
+ &gEfiGlobalVariableGuid,
+ &VarAttr,
+ &VarDataSize,
+ &VarData
+ );
+// PK should have been set when we were in SETUP_MODE. This condition is INVALID.
+ if (EFI_ERROR (Status) || VarData==NULL || !VarDataSize)
+ return EFI_SECURITY_VIOLATION;
+
+ OldPkList = (EFI_SIGNATURE_LIST *) VarData;
+ OldPkData = (EFI_SIGNATURE_DATA *) ((UINT8 *) OldPkList + sizeof (EFI_SIGNATURE_LIST) + OldPkList->SignatureHeaderSize);
+
+// Authenticate
+ Status = VerifyDataPayload (Data, DataSize, OldPkData->SignatureData);
+//AVAR_TRACE((TRACE_ALWAYS,"PK VerifyPayload %r\n",Status));
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ProcessVarWithKek
+//
+// Description: Process variable with key exchange key for verification.
+//
+//
+// Input:
+// Data Data pointer.
+// DataSize Size of Data found. If size is less than the
+// data, this value contains the required size.
+// Variable The variable information which is used to
+// keep track of variable usage.
+// Attributes Attribute value of the variable
+//
+// Output: EFI_SUCCESS Variable passed validation successfully.
+// EFI_INVALID_PARAMETER Invalid parameter.
+// EFI_SECURITY_VIOLATION The variable does NOT pass the validation.
+// check carried out by the firmware.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ProcessVarWithKek (
+ IN VOID *Data,
+ IN UINTN DataSize,
+ IN UINT32 Attributes
+ )
+{
+// so far can be DB or DBx variables
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_SIGNATURE_LIST *KekList;
+ EFI_SIGNATURE_DATA *KekItem;
+ UINT32 KekCount;
+ EFI_VARIABLE_AUTHENTICATION *CertData;
+ EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock;
+// BOOLEAN IsFound;
+ UINT32 Index;
+ UINT32 VarAttr;
+ UINT8 *VarData;
+ UINTN VarDataSize = 0;
+
+ if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
+ //
+ // PK and KEK should set EFI_VARIABLE_NON_VOLATILE attribute.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+//
+// If in setup mode, no authentication needed.
+//
+ if (mPlatformMode == SETUP_MODE || mCustomMode == 1)
+ return Status;
+
+ CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;
+ CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *)&(CertData->AuthInfo.CertData);
+ //
+ // Get Key database from KEK variable.
+ //
+ Status = FindVariable (
+ EFI_KEY_EXCHANGE_KEY_NAME,
+ &gEfiGlobalVariableGuid,
+ &VarAttr,
+ &VarDataSize,
+ &VarData
+ );
+
+ KekList = (EFI_SIGNATURE_LIST *) VarData;
+ if (EFI_ERROR(Status) || guidcmp ((EFI_GUID*) &(KekList->SignatureType), &gEfiCertRsa2048Guid))
+ return EFI_SECURITY_VIOLATION;
+ //
+ // Enumerate all Kek items in this list to verify the variable certificate data.
+ // If anyone is authenticated successfully, it means the variable is correct!
+ //
+// IsFound = FALSE;
+//
+// scan thru multiple Sig Lists if exist. Add 1 more loop....
+// actually, KEK would have one list since KEK owner may club all Kek keys together before signing with PK
+// do {
+ KekCount = (KekList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - KekList->SignatureHeaderSize) / KekList->SignatureSize;
+ KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekList + sizeof (EFI_SIGNATURE_LIST) + KekList->SignatureHeaderSize);
+ for (Index = 0; Index < KekCount; Index++) {
+ if (MemCmp (KekItem->SignatureData, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {
+// IsFound = TRUE;
+ break;
+ }
+ KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekItem + KekList->SignatureSize);
+ }
+// KekList = (EFI_SIGNATURE_LIST *) ((UINT8 *) KekList + KekList->SignatureListSize);
+// } while (!IsFound || (UINT8*)KekList < (VarData+VarDataSize));
+// if (!IsFound) {
+ if (Index >= KekCount) {
+ return EFI_SECURITY_VIOLATION;
+ }
+// Authenticate
+ Status = VerifyDataPayload (Data, DataSize, CertBlock->PublicKey);
+//AVAR_TRACE((TRACE_ALWAYS,"KEK VerifyPayload %r\n",Status));
+
+ return Status;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: VerifyDataPayload
+//
+// Description:
+// Verify data payload with AuthInfo in EFI_CERT_TYPE_RSA2048_SHA256 type.
+// Follow the steps in UEFI2.2. This function does signature
+// authetication and based on the results returns Status.
+//
+// Input:
+// IN VOID *Data - pointer to the Var data
+// IN UINTN DataSize - size of Var data
+// UINT8 *PubKey - PublicKey used for Sig verification.
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS VerifyDataPayload (
+ IN VOID *Data,
+ IN UINTN DataSize,
+ IN UINT8 *PubKey
+)
+{
+ EFI_STATUS Status;
+ EFI_VARIABLE_AUTHENTICATION *CertData;
+ EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock;
+ UINT8 Digest[HASH_SHA256_LEN];
+ UINT8 *Addr[2];
+ UINTN Len[2];
+ UINTN CertHdrSize;
+
+ CRYPT_HANDLE PublicKey;
+ CRYPT_HANDLE HashToVerify;
+
+ CertData = (EFI_VARIABLE_AUTHENTICATION *)Data;
+// CertHdrSize = AUTHINFO_SIZE(Data);
+// SCT 2.3.1. TW UEFI Plugfest BUG with listing of a Cert Size in Cert->AuthInfo.Hdr.dwLength
+ CertHdrSize = 0x230;
+
+ CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256*)&(CertData->AuthInfo.CertData);
+
+ //
+ // Hash data payload with SHA256.
+ //
+ Addr[0] = (UINT8*) Data + (CertHdrSize) ;
+ Len[0] = DataSize - (CertHdrSize);
+ Addr[1] = (UINT8*)&(CertData->MonotonicCount);
+ Len[1] = sizeof(UINT64);
+ Status = mDigitalSigProtocol->Hash(mDigitalSigProtocol,
+ &gEfiHashAlgorithmSha256Guid,
+ 2, Addr, Len, (UINT8*)&Digest[0]);
+ if (EFI_ERROR(Status))
+ return Status;
+
+ PublicKey.AlgGuid = gEfiCertRsa2048Guid;
+ PublicKey.BlobSize = EFI_CERT_TYPE_RSA2048_SIZE;
+ PublicKey.Blob = PubKey;//(UINT8*)&(CertData->AuthInfo.CertData.PublicKey);
+
+ HashToVerify.AlgGuid = gEfiHashAlgorithmSha256Guid;
+ HashToVerify.BlobSize = SHA256_DIGEST_SIZE;
+ HashToVerify.Blob = &Digest[0];
+
+ Status = mDigitalSigProtocol->Pkcs1Verify(
+ mDigitalSigProtocol,
+ &PublicKey,
+ &HashToVerify,
+ (UINT8*)&(CertBlock->Signature),
+ EFI_CERT_TYPE_RSA2048_SHA256_SIZE, EFI_CRYPT_RSASSA_PKCS1V15/*EFI_CRYPT_RSASSA_PSS*/);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindInSignatureDb
+//
+// Description:
+// For variables with GUID EFI_IMAGE_SECURITY_DATABASE_GUID
+// (i.e. where the data buffer is formatted as EFI_SIGNATURE_LIST),
+// the driver shall not perform an append of EFI_SIGNATURE_DATA values
+// that are already part of the existing variable value (Note: This situation
+// is not considered an error, and shall in itself not cause a status code other
+// than EFI_SUCCESS to be returned or the timestamp associated with the variable not
+// to be updated).
+//
+// Input:
+// EFI_GUID *VendorGuid Variable vendor GUID.
+// IN UINT32 Attributes - Attributes of the Var
+// VOID *Data - pointer to data block within AutVar Data
+// UINTN *DataSize - ptr to size of data block
+// VOID *SigDb - current SigDb
+// UINTN SigDbSize
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FindInSignatureDb (
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN VOID *Data,
+ IN OUT UINTN *DataSize,
+ IN VOID *SigDb,
+ IN UINTN SigDbSize
+){
+ EFI_SIGNATURE_LIST *SigList;
+ EFI_SIGNATURE_LIST *SigListNew;
+ EFI_SIGNATURE_DATA *SigItem;
+ EFI_SIGNATURE_DATA *SigItemNew;
+ UINT32 SigCount;
+ UINT32 Index;
+ UINT32 SigCountNew;
+ UINT32 IndexNew;
+
+ UINTN SigNewSize;
+ BOOLEAN bSigMatch;
+ // Is Append & SigDB
+ if ( (SigDb && SigDbSize) &&
+ ((Data != SigDb) && (Attributes & EFI_VARIABLE_APPEND_WRITE)) &&
+ // Validate Signature List integrity
+ !EFI_ERROR(ValidateSignatureList (Data, *DataSize))
+ ) {
+ SigList = (EFI_SIGNATURE_LIST *)SigDb;
+ SigListNew = (EFI_SIGNATURE_LIST *)Data;
+AVAR_TRACE((TRACE_ALWAYS,"FindInDB(x)\nDataSize In %d (0x%X)\n",*DataSize,*DataSize));
+ //
+ // Enumerate all Sig items in this list to verify the variable certificate data.
+ //
+ //
+ // scan through multiple Sig Lists in DB exist.
+ while ((SigDbSize > 0) && (SigDbSize >= SigList->SignatureListSize)) {
+ SigCount = (SigList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - SigList->SignatureHeaderSize) / SigList->SignatureSize;
+ SigItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigList + sizeof (EFI_SIGNATURE_LIST) + SigList->SignatureHeaderSize);
+//AVAR_TRACE((TRACE_ALWAYS,"Org SigList Count: %d, SigSize %X\n", SigCount, SigList->SignatureSize));
+ // scan through multiple Sig Lists in NewSigList.
+ for (Index = 1; Index <= SigCount; Index++) {
+////AVAR_TRACE((TRACE_ALWAYS,"OrgCert %d, Data %X\n",Index, *(UINT32*)SigItem->SignatureData));
+ SigListNew = (EFI_SIGNATURE_LIST *)Data;
+ SigNewSize = *DataSize;
+ while ((SigNewSize > 0) && (SigNewSize >= SigListNew->SignatureListSize)) {
+ bSigMatch = FALSE;
+ SigItemNew = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigListNew + sizeof (EFI_SIGNATURE_LIST) + SigListNew->SignatureHeaderSize);
+ SigCountNew = (SigListNew->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - SigListNew->SignatureHeaderSize) / SigListNew->SignatureSize;
+ if (!guidcmp ((EFI_GUID*) &(SigList->SignatureType), (EFI_GUID*)&(SigListNew->SignatureType)) &&
+ SigList->SignatureSize == SigListNew->SignatureSize) {
+//AVAR_TRACE((TRACE_ALWAYS,"New SigDb Size %X\nNew SigList Count: %d, SigSize %X\n", SigNewSize, SigNewCount, SigNewList->SignatureSize));
+ // loop through all instances of NewSigList->SigData.
+ for (IndexNew = 1; IndexNew <= SigCountNew; IndexNew++) {
+////AVAR_TRACE((TRACE_ALWAYS,"NewCert %d, Data %X\n",IndexNew, *(UINT32*)SigNewItem->SignatureData));
+ if (MemCmp (SigItem->SignatureData, SigItemNew->SignatureData, SigList->SignatureSize-sizeof(EFI_GUID)) == 0) {
+//AVAR_TRACE((TRACE_ALWAYS,"---> match found!!!\n"));
+//AVAR_TRACE((TRACE_ALWAYS,"OrgCert %4d, Data %X\n",Index, *(UINT32*)SigItem->SignatureData));
+//AVAR_TRACE((TRACE_ALWAYS,"NewCert %4d, Data %X\n",IndexNew, *(UINT32*)SigNewItem->SignatureData));
+ if(SigCountNew == 1) {
+ // only 1 SigData per SigList - discard this SigList
+ bSigMatch = TRUE;
+//AVAR_TRACE((TRACE_ALWAYS,"Before: DataSize=%x\nAfter : DataSize=%x\n", *DataSize, *DataSize-SigNewList->SignatureListSize));
+ // 1. Decrease *Datasize by SigNewList->SignatureSize
+ SigNewSize -= SigListNew->SignatureListSize;
+ *DataSize -= SigListNew->SignatureListSize;
+ // 2. replace this SigData block with data following it
+ MemCpy (SigListNew, (void*)((UINTN)SigListNew+SigListNew->SignatureListSize), SigNewSize);
+ // 3. Skip to next SigListNew
+ break;
+ } else {
+ // more then 1 - discard this SigData
+ // 1. replace this SigData block with data following it
+ MemCpy (SigItemNew, (void*)((UINTN)SigItemNew+SigListNew->SignatureSize), ((UINTN)Data+*DataSize)-((UINTN)SigItemNew+SigListNew->SignatureSize));
+ // 2. Decrease SigNewList->SignatureListSize by SigNewList->SignatureSize
+ SigListNew->SignatureListSize-=SigListNew->SignatureSize;
+ *DataSize-=SigListNew->SignatureSize;
+//AVAR_TRACE((TRACE_ALWAYS,"Upd SignatureListSize=%x, DataSize=%x\n",SigNewList->SignatureListSize, *DataSize));
+ // 3. If this is last SigData element
+ if((SigListNew->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - SigListNew->SignatureHeaderSize)==0)
+ {
+//AVAR_TRACE((TRACE_ALWAYS,"SigList is Empty!\n"));
+ break;
+ }
+ // 4. Skip incrementing of SigNewItem
+ continue;
+ }
+ } // if cmp
+ SigItemNew = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigItemNew + SigListNew->SignatureSize);
+ } // for SigNewItem
+ } // if guid
+ // Skip incrementing of SigNewList if bSigListMatch is found - we already on next siglist
+ if(!bSigMatch) {
+ SigNewSize -= SigListNew->SignatureListSize;
+ SigListNew = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigListNew + SigListNew->SignatureListSize);
+ }
+ } // while SigNewList
+ SigItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigItem + SigList->SignatureSize);
+ } // for SigItem
+ SigDbSize -= SigList->SignatureListSize;
+ SigList = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + SigList->SignatureListSize);
+ } // while SigList
+
+AVAR_TRACE((TRACE_ALWAYS,"DataSize Out: %d (0x%X)\n",*DataSize, *DataSize));
+ if(*DataSize==0)
+ return EFI_ALREADY_STARTED;
+
+AVAR_TRACE((TRACE_ALWAYS,"APPEND OK!\n"));
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: VerifyVariable1
+//
+// Description:
+// Verify data payload with AuthInfo in EFI_CERT_TYPE_RSA2048_SHA256 type.
+// Follow the steps in UEFI2.2.
+// This function is called every time variable with
+// EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute is
+// created, updated or deleted. This function does all necessary
+// authetication checks and based on the results returns Status.
+// Also it returns the Mc Hash of PublicKey from Variable's AuthInfo Hdr
+//
+// Input:
+// CHAR16 *VariableName Name of Variable to be found.
+// EFI_GUID *VendorGuid Variable vendor GUID.
+// IN UINT32 Attributes - Attributes of the Var
+// VOID **Data - pointer to data block within AutVar Data
+// UINTN *DataSize - size of data block
+// VOID *OldData - pointer to Existing in NVRAM data block
+// UINTN OldDataSize - size of data block
+// UINT64 ExtFlags.MonotonicCount - value of MC or TIME stamp
+// UINT8 ExtFlags.KeyHash[32] - pointer to memory, allocated by caller,
+// where Hash of Public Key will be returned.
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS VerifyVariable1 (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN VOID **Data,
+ IN UINTN *DataSize,
+ IN VOID *OldData,
+ IN UINTN OldDataSize,
+ IN OUT EXT_SEC_FLAGS *ExtFlags
+){
+ EFI_STATUS Status;
+
+ VOID *RealData;
+ EFI_VARIABLE_AUTHENTICATION *CertData;
+ EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock;
+ UINT8 *PubKey, *PubKeyHash;
+ UINTN CertHdrSize;
+ UINTN Size;
+ BOOLEAN IsSigListVar;
+ BOOLEAN IsPk;
+
+ RealData = *Data;
+ Status = EFI_SUCCESS;
+ IsSigListVar = TRUE;
+ IsPk = FALSE;
+
+// must have Auth attribute to go deeper
+ if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0)
+ return EFI_INVALID_PARAMETER;
+
+ if(*DataSize < sizeof(EFI_VARIABLE_AUTHENTICATION))
+ return EFI_SECURITY_VIOLATION;
+
+// specific for EFI_VARIABLE_AUTHENTICATION mode variables
+//--->>>
+ CertData = (EFI_VARIABLE_AUTHENTICATION *) *Data;
+ CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256*)&(CertData->AuthInfo.CertData);
+// SCT 2.3.1 TW Plugfest BUG with listing of a Cert Size in Cert->AuthInfo.Hdr.dwLength
+// 0x22b vs 0x230
+// CertHdrSize = AUTHINFO_SIZE(CertData);//(CertData->AuthInfo.Hdr.Hdr.dwLength + sizeof(CertData->MonotonicCount));
+ AVAR_TRACE((TRACE_ALWAYS,"VerifyVariable CertHdr Size 0x%x (expected(0x230)\n",AUTHINFO_SIZE(CertData)));
+
+ CertHdrSize = 0x230;
+
+ //
+ // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.
+ // Cert type should be EFI_CERT_TYPE_RSA2048_SHA256.
+ //
+ if ((CertData->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) ||
+ guidcmp ((EFI_GUID*) &(CertData->AuthInfo.CertType), &gEfiCertTypeRsa2048Sha256Guid)
+ ) {
+ //
+ // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
+ //
+ AVAR_TRACE((TRACE_ALWAYS,"VerifyVariable AuthHdr GUID test Fails\nWinCert_Type\nExpected %x\nReceived %x\nGUID\nExpected %g\nReceived %g\n",WIN_CERT_TYPE_EFI_GUID, CertData->AuthInfo.Hdr.wCertificateType, gEfiCertTypeRsa2048Sha256Guid, &(CertData->AuthInfo.CertType)));
+// SCT 2.3.1 TW Plugfest uses wrong GUID
+ return EFI_SECURITY_VIOLATION;
+ }
+
+ if(*DataSize < CertHdrSize)
+ {
+AVAR_TRACE((TRACE_ALWAYS,"VerifyVariable DataSize test fails: DataSize(%x) < AuthHdrSize (%x)\n", *DataSize, CertHdrSize));
+ return EFI_SECURITY_VIOLATION;
+ }
+ //
+ // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
+ //
+AVAR_TRACE((TRACE_ALWAYS,"Check MC:\nOld=%x\nNew=%x\n",ExtFlags->Mc, CertData->MonotonicCount));
+ if (((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) &&
+ (OldData && ExtFlags->Mc >= CertData->MonotonicCount)
+ ) {
+ AVAR_TRACE((TRACE_ALWAYS,"Failed\n"));
+ return EFI_SECURITY_VIOLATION;
+ }
+AVAR_TRACE((TRACE_ALWAYS,"Pass\n"));
+
+// AppendWrite: Only update Timestamp if New one is greater then current
+ if( (Attributes & EFI_VARIABLE_APPEND_WRITE) &&
+ (OldData && ExtFlags->Mc > CertData->MonotonicCount)
+ );
+ else
+ ExtFlags->Mc = CertData->MonotonicCount;
+ //
+ // Process PK, KEK, Sig db separately.
+ //
+ if (IsPkVar(VariableName, VendorGuid)){
+ IsPk = TRUE;
+ Status = ProcessVarWithPk (*Data, *DataSize, Attributes, TRUE);
+ } else if (IsKekVar(VariableName, VendorGuid)) {
+ Status = ProcessVarWithPk (*Data, *DataSize, Attributes, FALSE);
+ } else if (IsDbVar(VendorGuid)) {
+ Status = ProcessVarWithKek (*Data, *DataSize, Attributes);
+ // verify process db(x) with one of KEK keys or if not found within KEK - with PK
+ if (Status == EFI_SECURITY_VIOLATION)
+ Status = ProcessVarWithPk (*Data, *DataSize, Attributes, FALSE);
+ } else {
+ IsSigListVar = FALSE;
+ PubKey = &(CertBlock->PublicKey[0]);
+ PubKeyHash = &PublicKeyHashArray[0];
+ // Verify SelfSigned variable is signed with a valid Key
+ Status = VerifyDataPayload (*Data, *DataSize, PubKey);
+ if (!EFI_ERROR(Status)) {
+
+ Size = RSA2048_PUB_KEY_LEN;
+ Status = mDigitalSigProtocol->Hash(mDigitalSigProtocol,
+ &gEfiHashAlgorithmSha256Guid,
+ 1, &PubKey, (const UINTN*)&Size, PubKeyHash);
+
+ if (OldData && MemCmp(&ExtFlags->KeyHash[0], PubKeyHash, HASH_SHA256_LEN)){
+//AVAR_TRACE((TRACE_ALWAYS,"Self Signed MC Var Key Compare FAILED!\n"));
+ return EFI_SECURITY_VIOLATION;
+ }
+ // Setting key Hash for self signed variables
+ MemCpy(&ExtFlags->KeyHash[0], PubKeyHash, HASH_SHA256_LEN);
+ }
+ }
+ if (EFI_ERROR(Status))
+ return EFI_SECURITY_VIOLATION;
+
+ *DataSize = *DataSize - CertHdrSize;
+ *Data = (UINT8*)RealData + CertHdrSize;
+
+ if(IsSigListVar == TRUE) {
+
+ // Validate Signature List integrity
+ if(*DataSize && EFI_ERROR(ValidateSignatureList (*Data, *DataSize)))
+ return EFI_SECURITY_VIOLATION;
+ //
+ // If delete PK in user mode -> change to setup mode.
+ // If enroll PK in setup mode -> change to user mode.
+ //
+ if(IsPk) {
+ if (*DataSize == 0)
+ UpdatePlatformMode (SETUP_MODE);
+ else
+ UpdatePlatformMode (USER_MODE);
+ }
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: VerifyVariable
+//
+// Description:
+// This function is called every time variable with
+// EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS and
+// EFI_VARIABLE_AUTHENTICATED_TIME_BASED_ACCESS attributes
+// created, updated or deleted. This function does all necessary
+// authetication checks and based on the results returns Status.
+// Also it returns the Mc Hash of PublicKey from Variable's AuthInfo Hdr
+//
+// Input:
+// CHAR16 *VariableName Name of Variable to be found.
+// EFI_GUID *VendorGuid Variable vendor GUID.
+// IN UINT32 Attributes - Attributes of the Var
+// VOID **Data - pointer to data block within AutVar Data
+// UINTN *DataSize - size of data block
+// VOID *OldData - pointer to Existing in NVRAM data block
+// UINTN OldDataSize - size of data block
+// UINT64 ExtFlags.MonotonicCount - value of MC or TIME stamp
+// UINT8 ExtFlags.KeyHash[32] - pointer to memory, allocated by caller,
+// where Hash of Public Key will be returned.
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS VerifyVariable (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 *Attributes,
+ IN VOID **Data,
+ IN UINTN *DataSize,
+ IN VOID *OldData,
+ IN UINTN OldDataSize,
+ IN OUT EXT_SEC_FLAGS *ExtSecFlags
+){
+ EFI_STATUS Status;
+ UINT32 AuthAttributes;
+ UINT64 OldMC;
+
+ Status = EFI_SUCCESS;
+ mCustomMode = 0;
+
+//AVAR_TRACE((TRACE_ALWAYS,"Var Name: %S, Attr=%X, Data=%X, Size=%d\n", VariableName, *Attributes, *Data, *DataSize));
+
+ // bypass Var R/O check when updating
+ // SetupMode and SecureBoot variables after changing of a PK
+ if(mSetupMode == SETUP_MODE) {
+// Faking presense of NV attribute for SetupMode in order to meet UEFI requirement
+// to display SetupMode state even in runtime (after exit boot services)
+// AuthAttributes = *Attributes & (~EFI_VARIABLE_NON_VOLATILE);
+// *Attributes = AuthAttributes;
+// *Attributes &= (UINT32)(~EFI_VARIABLE_NON_VOLATILE);
+ // Re-lock access to runtime protected vars
+ mSetupMode = USER_MODE;
+ return Status;//EFI_SUCCESS;
+ }
+
+ // existing reserved variables are RO!!!
+ if(OldData && OldDataSize && IsReservedVariableName(VariableName, VendorGuid))
+ return EFI_WRITE_PROTECTED;
+
+ AuthAttributes = ExtSecFlags->AuthFlags & UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES;
+
+ while ((*Attributes & UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES)
+ // Old Variable with no attributes can be erased after proper AuthHeader validation
+ // EIP88439: irrespective of SetupMode, only properly formatted Auth Variable can be erased
+ || (AuthAttributes)
+ ){
+ // get mPlatformMode
+ GetPlatformMode ();
+
+ // check if both attributes are set
+ if ((*Attributes & UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES) ==
+ UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES
+ )
+ { Status = EFI_INVALID_PARAMETER; break;}
+
+#if USER_MODE_POLICY_OVERRIDE == 1
+ // ignore Variable Authentication rules while in Physical User Presence
+ mCustomMode = PhysicalUserPresent();
+ AVAR_TRACE((TRACE_ALWAYS,"Physical User %s\n",
+ (mCustomMode?"detected - suppress Variable Authentication":"not detected")));
+ if (mCustomMode) {
+ if(*DataSize==0 || *Data==NULL) {
+ if(IsPkVar(VariableName, VendorGuid))
+ UpdatePlatformMode(SETUP_MODE);
+
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+#endif
+// Old - nonAuth, New - nonAuth - exit with EFI_SUCCESS
+// Old - nonAuth, New - Auth - Continue with new Auth attr
+// Old - Auth, New - nonAuth - if *Attribs=0 - Erase in progress if in SetupMode
+// else EFI_SECURITY_VIOLATION
+// Old - Auth, New - Auth - Continue if AuthAttr matching
+// else EFI_SECURITY_VIOLATION
+// OldVar AuthAttributes mismatch
+ if( AuthAttributes && *Attributes &&
+ !(AuthAttributes & (*Attributes & UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES))
+ )
+ // Attribute mismatch
+ { Status = EFI_SECURITY_VIOLATION; break;}
+
+ // else in process of erasing or Setting AuthVar
+
+ AuthAttributes |= *Attributes;
+ OldMC = ExtSecFlags->Mc;
+
+ if(*DataSize==0 || *Data==NULL)
+ { Status = EFI_SECURITY_VIOLATION; break;}
+
+ if(!mDigitalSigProtocol)
+ { Status = EFI_UNSUPPORTED; break;}
+
+//AVAR_TRACE((TRACE_ALWAYS,"Verify AuthVar: %S, Attr=%X, Data=%X, Size=%d\n", VariableName, *Attributes, *Data, *DataSize));
+ if (AuthAttributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
+ Status = VerifyVariable2(VariableName, VendorGuid, AuthAttributes, Data, DataSize, OldData, OldDataSize, ExtSecFlags);
+ else
+ Status = VerifyVariable1(VariableName, VendorGuid, AuthAttributes, Data, DataSize, OldData, OldDataSize, ExtSecFlags);
+//AVAR_TRACE((TRACE_ALWAYS, "Exit - %r, Data - %X, Size %d, Attributes %x\n",Status, *Data, *DataSize, *Attributes));
+ if (EFI_ERROR(Status))
+ break;
+
+ // Find out if New Var is a Signature Db and the Sig already present in current Sig DB Variable
+ // bail out SetVar if present - nothing to change
+ Status = FindInSignatureDb(VendorGuid, *Attributes, *Data, DataSize, OldData, OldDataSize);
+ if (EFI_ERROR(Status)) {
+ // Only update the Timestamp if new Sig found in OldSig list
+ if(OldMC != ExtSecFlags->Mc)
+ {
+ *DataSize = 0;
+ Status = EFI_SUCCESS;
+
+ }
+ // else Variable not changed, abort the SetVar
+ }
+
+ break;
+ } // end while loop
+
+ return Status; // variable not changed
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.cif b/Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.cif
new file mode 100644
index 0000000..4bc04f6
--- /dev/null
+++ b/Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.cif
@@ -0,0 +1,12 @@
+<component>
+ name = "NVRAM. Authenticated Variables"
+ category = ModulePart
+ LocalRoot = "Core\EM\SecurityPkg\AuthenticatedVariable\"
+ RefName = "AuthVariable"
+[files]
+"AuthVariable.sdl"
+"AuthVariable.mak"
+"AuthVariable.c"
+"Auth2Variable.c"
+"AuthVariable.h"
+<endComponent>
diff --git a/Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.h b/Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.h
new file mode 100644
index 0000000..38a4cfa
--- /dev/null
+++ b/Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.h
@@ -0,0 +1,351 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SecureBoot_WIN8/AuthenticatedVariable_efi/AuthVariable.h 17 3/09/15 4:27p Alexp $
+//
+// $Revision: 17 $
+//
+// $Date: 3/09/15 4:27p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureBoot_WIN8/AuthenticatedVariable_efi/AuthVariable.h $
+//
+// 17 3/09/15 4:27p Alexp
+// Update year 2015 in the file header
+//
+// 16 2/08/13 5:15p Alexp
+// Optimized the code flow fro Auth2 Variables.
+//
+// 15 12/07/12 3:45p Alexp
+// define AVAR_TRACE macro
+//
+// 14 11/19/12 4:41p Alexp
+// Fix for Win8 SecureBoot logo requirement: restore Secure Boot state
+// across flash updates.
+// Move all secure boot Setup settings to a separate varstore variable.
+// Preserve var across re-flash
+//
+// 13 10/16/12 3:45p Alexp
+// Implemented R/O Variables support via fixed and OEM defined (eLink)
+// lists
+//
+// 12 8/27/12 10:42a Alexp
+// GetmSecureBootSupport():
+// Add input parameter SetupMode to control state of
+// Setup Flag:SecureBootSupport
+//
+// 11 2/27/12 6:52p Alexp
+// removed AuthenticatedVariableServiceInitialize()
+//
+// 10 2/03/12 9:56a Alexp
+// EIP#82122. WHCK "Secure Boot Manual Logo Test" fails
+// Fixed Append logic to process multiple sig data instances in a single
+// Signature List block
+// New logic will remove dupplicated certs and update new SigList header.
+//
+// 9 8/18/11 5:59p Alexp
+// renamed func SecureBootSupport()
+//
+// 8 8/18/11 4:53p Alexp
+// removed AuthVar mailbox
+//
+// 7 8/16/11 7:18p Alexp
+// added Mailbox variable AuthVarMAilbox to syncronize local state between
+// DXE and SMM AuthVariable services
+//
+// 6 8/05/11 3:12p Alexp
+// add mkime prototyte define
+//
+// 5 8/04/11 7:12p Alexp
+//
+// 4 6/30/11 4:02p Alexp
+// added Callback event on Setup Mode change request form Security Setup
+// Page.
+//
+// 3 6/24/11 7:04p Alexp
+// fixed ValidateSignatureList () logic. Added Certificate RSA2048 to
+// supported Signatures
+//
+// 2 6/23/11 6:19p Alexp
+// Added ValidateSigList() function
+//
+// 5 6/09/11 5:49p Alexp
+// add new parameter to ValidateSelfSigned - Operation.
+//
+// 4 6/02/11 5:52p Alexp
+// add ValidateSelfSigned certificates func definition
+//
+// 2 5/19/11 4:59p Alexp
+// Major code revamp to be able to handle of handling Secure vars in Setup
+// Mode
+// TBD: TimeBased certificates from Msft fail to process. Not compiled as
+// Authenticode format
+//
+// 4 3/31/11 6:28p Alexp
+// Add SHA256 to supported SignatureList
+//
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: AuthVariable.h Implement authentication services for the authenticated variable
+// service in UEFI2.2+
+//
+// Description:
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#ifndef _AUTHVARIABLE_H_
+#define _AUTHVARIABLE_H_
+
+#include <Efi.h>
+// All are EDKII defined headers
+#include "WinCertificate.h"
+#include "ImageAuthentication.h"
+#include <Protocol/Hash.h>
+
+#define HASH_SHA256_LEN sizeof(EFI_SHA256_HASH) // 32
+#define HASH_SHA1_LEN sizeof(EFI_SHA1_HASH)
+#define RSA2048_PUB_KEY_LEN DEFAULT_RSA_KEY_MODULUS_LEN // 256
+#define EFI_CERT_TYPE_RSA2048_SHA256_SIZE RSA2048_PUB_KEY_LEN
+#define EFI_CERT_TYPE_RSA2048_SIZE RSA2048_PUB_KEY_LEN
+
+//
+// EFI_VARIABLE_AUTHENTICATION descriptor
+//
+// A authentication authentication method descriptor template
+// AuthInfo is a WIN_CERTIFICATE using the wCertificateType
+// WIN_CERTIFICATE_UEFI_GUID and the CertType
+// EFI_CERT_TYPE_RSA2048_SHA256.
+//
+#ifndef EFI_VARIABLE_AUTHENTICATION
+typedef struct {
+ UINT64 MonotonicCount;
+ WIN_CERTIFICATE_UEFI_GUID AuthInfo;
+} EFI_VARIABLE_AUTHENTICATION;
+#endif
+
+//
+// EFI_VARIABLE_AUTHENTICATION_2 descriptor
+//
+// A time-based authentication method descriptor template
+//
+#ifndef EFI_VARIABLE_AUTHENTICATION_2
+typedef struct {
+ EFI_TIME TimeStamp;
+ WIN_CERTIFICATE_UEFI_GUID AuthInfo;
+} EFI_VARIABLE_AUTHENTICATION_2;
+#endif
+
+///
+/// Size of AuthInfo prior to the data payload
+///
+#define AUTHINFO_SIZE(Cert) (((UINTN)(((EFI_VARIABLE_AUTHENTICATION *) Cert)->AuthInfo.Hdr.dwLength)) + sizeof(UINT64))
+#define AUTHINFO_2_SIZE(Cert) (((UINTN)(((EFI_VARIABLE_AUTHENTICATION_2 *) Cert)->AuthInfo.Hdr.dwLength)) + sizeof(EFI_TIME))
+
+#ifdef EFI_DEBUG
+#define AVAR_TRACE(Arguments) { if (!AVarRuntime) TRACE(Arguments); }
+#else
+#define AVAR_TRACE(Arguments)
+#endif
+
+
+typedef enum {
+ IsPkVarType = 0,
+ IsKekVarType,
+ IsDbVarType,
+ IsPrivateVarType
+} AUTHVAR_TYPE;
+
+VOID AuthVariableServiceInitSMM (VOID );
+VOID AuthVariableServiceInit ( VOID );
+
+EFI_STATUS VerifyVariable (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 *Attributes,
+ IN VOID **Data,
+ IN UINTN *DataSize,
+ IN VOID *OldData,
+ IN UINTN OldDataSize,
+ IN OUT EXT_SEC_FLAGS *ExtFlags
+ );
+
+EFI_STATUS FindInSignatureDb (
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN VOID *Data,
+ IN UINTN *DataSize,
+ IN VOID *SigDB,
+ IN UINTN SigDBSize
+ );
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Variable Auth Hdr EFI_VARIABLE_AUTHENTICATION
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+EFI_STATUS VerifyVariable1 (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN VOID **Data,
+ IN UINTN *DataSize,
+ IN VOID *OldData,
+ IN UINTN OldDataSize,
+ IN OUT EXT_SEC_FLAGS *ExtFlags
+ );
+
+EFI_STATUS VerifyDataPayload (
+ IN VOID *Data,
+ IN UINTN DataSize,
+ IN UINT8 *PubKey
+ );
+
+EFI_STATUS ProcessVarWithPk (
+ IN VOID *Data,
+ IN UINTN DataSize,
+ IN UINT32 Attributes,
+ IN BOOLEAN IsPk
+ );
+
+EFI_STATUS ProcessVarWithKek (
+ IN VOID *Data,
+ IN UINTN DataSize,
+ IN UINT32 Attributes
+ );
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Variable Auth Hdr EFI_VARIABLE_AUTHENTICATION_2
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+EFI_STATUS VerifyVariable2 (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN VOID **Data,
+ IN UINTN *DataSize,
+ IN VOID *OldData,
+ IN UINTN OldDataSize,
+ IN OUT EXT_SEC_FLAGS *ExtFlags
+ );
+
+EFI_STATUS ValidateSelfSigned (
+ IN UINT8 *Pkcs7Cert,
+ IN UINTN Pkcs7Cert_len,
+ IN OUT UINT8 **pDigest,
+ IN OUT UINTN *Digest_len,
+ IN UINT8 Operation
+ );
+
+EFI_STATUS ConstructDataParameter (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN VOID *Data,
+ IN UINTN DataSize,
+ OUT UINT8 *pDigest,
+ OUT UINTN *Digest_len,
+ IN UINT8 Mutex
+ );
+
+EFI_STATUS ProcessVarWithPk2 (
+ IN UINT8 *Pkcs7Cert,
+ IN UINTN Pkcs7Cert_len,
+ IN UINT8 *pDigest,
+ IN UINTN Digest_len
+ );
+
+EFI_STATUS ProcessVarWithKek2 (
+ IN UINT8 *Pkcs7Cert,
+ IN UINTN Pkcs7Cert_len,
+ IN UINT8 *pDigest,
+ IN UINTN Digest_len
+ );
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Misc auxilary functions
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+INTN StrCmp16(CHAR16 *Dest, CHAR16 *Src);
+UINT32 StrSize16(CHAR16 *String);
+
+BOOLEAN IsPkVar(
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid
+ );
+
+BOOLEAN IsKekVar(
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid
+ );
+
+BOOLEAN IsDbVar(
+ IN EFI_GUID *VendorGuid
+ );
+
+EFI_STATUS GetPlatformMode (
+ VOID
+ );
+
+EFI_STATUS GetmSecureBootSupport (
+ UINT8
+ );
+
+VOID UpdatePlatformMode (
+ IN UINT8 Mode
+ );
+
+EFI_STATUS ValidateSignatureList (
+ IN VOID *Data,
+ IN UINTN DataSize
+);
+
+UINT64 mkLongTime (
+ EFI_TIME *TimeStamp
+);
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// NVRAM module defined auxilary functions
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+EFI_STATUS FindVariable(
+ IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid,
+ OUT UINT32 *Attributes OPTIONAL,
+ IN OUT UINTN *DataSize, OUT VOID **Data
+ );
+
+EFI_STATUS DxeSetVariable(
+ IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data
+);
+EFI_STATUS DxeGetVariable(
+ IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid,
+ OUT UINT32 *Attributes OPTIONAL,
+ IN OUT UINTN *DataSize, OUT VOID *Data
+);
+
+#endif // _AUTHVARIABLE_H_
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.mak b/Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.mak
new file mode 100644
index 0000000..5633611
--- /dev/null
+++ b/Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.mak
@@ -0,0 +1,89 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2012, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#*************************************************************************
+# $Header: /Alaska/SOURCE/Modules/SecureBoot_WIN8/AuthenticatedVariable_efi/AuthVariable.mak 6 8/15/13 11:26a Alexp $
+#
+# $Revision: 6 $
+#
+# $Date: 8/15/13 11:26a $
+#*************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/SecureBoot_WIN8/AuthenticatedVariable_efi/AuthVariable.mak $
+#
+# 6 8/15/13 11:26a Alexp
+# Link AmyCryptoLib
+#
+# 5 11/19/12 4:41p Alexp
+# Fix for Win8 SecureBoot logo requirement: restore Secure Boot state
+# across flash updates.
+# Move all secure boot Setup settings to a separate varstore variable.
+# Preserve var across re-flash
+#
+# 4 10/16/12 3:45p Alexp
+# Implemented R/O Variables support via fixed and OEM defined (eLink)
+# lists
+#
+# 3 9/19/12 4:29p Alexp
+# New feature: add facility to link external Physical User Presence
+# detect hooks via eLink:PhysicalUserPresenceDetect
+#
+# 2 6/30/11 4:02p Alexp
+# added Callback event on Setup Mode change request form Security Setup
+# Page.
+#
+# 1 6/13/11 5:25p Alexp
+#
+# 2 5/11/11 1:03p Alexp
+# filled in file header text
+#*************************************************************************
+#<AMI_FHDR_START>
+#
+# Name: AuthVariable.mak
+#
+# Description:
+# Link Authenticated Variable extension to NVRAM driver
+#
+#<AMI_FHDR_END>
+#*************************************************************************
+NvramDxeBin : $(BUILD_DIR)\$(NVRAM_DIR)\AUTHVARIABLE.obj $(BUILD_DIR)\$(NVRAM_DIR)\AUTH2VARIABLE.obj $(CRYPTOLIB)
+
+AuthVariable_INCLUDES= \
+ /I $(AuthVariable_DIR) \
+ /I $(SecureBoot_DIR) \
+ /I $(NVRAM_DIR)
+
+AuthVariable_LISTS= \
+ /D PHYSICAL_USER_PRESENCE_DETECT_LIST=$(PhysicalUserPresenceDetect) \
+ /D OEM_READONLY_VAR_LIST=$(OemReadOnlyVariableList)
+
+$(BUILD_DIR)\$(NVRAM_DIR)\AUTHVARIABLE.obj $(BUILD_DIR)\$(NVRAM_DIR)\AUTH2VARIABLE.obj: \
+ $(AuthVariable_DIR)\AUTHVARIABLE.c $(AuthVariable_DIR)\AUTH2VARIABLE.c
+ if not exist $(*D) mkdir $(*D)
+ $(CC) $(CFLAGS) $(AuthVariable_LISTS) $(AuthVariable_INCLUDES) /Fo$@ $(AuthVariable_DIR)\$(*B).c
+
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2012, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
diff --git a/Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.sdl b/Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.sdl
new file mode 100644
index 0000000..e90eddc
--- /dev/null
+++ b/Core/EM/SecurityPkg/AuthenticatedVariable/AuthVariable.sdl
@@ -0,0 +1,44 @@
+TOKEN
+ Name = "AuthVariable_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable AuthVariable support in Project"
+ TokenType = Boolean
+ TargetH = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "USER_MODE_POLICY_OVERRIDE"
+ Value = "1"
+ Help = "Ignore Variable Authentication rules until AuthVarLock(ready to boot) event\A back door for Administrative Users to modify Secure Variables from Key Management Setup Page"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+PATH
+ Name = "AuthVariable_DIR"
+ Help = "Path to AuthVariable Module in Project"
+End
+
+MODULE
+ Help = "Includes AuthVariable.mak to Project"
+ File = "AuthVariable.mak"
+End
+
+
+ELINK
+ Name = "PhysicalUserPresenceDetect"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "AuthVarAdminUserPresent,"
+ InvokeOrder = AfterParent
+ Parent = PhysicalUserPresenceDetect
+End
+
+ELINK
+ Name = "OemReadOnlyVariableList"
+ InvokeOrder = ReplaceParent
+End
diff --git a/Core/EM/SecurityPkg/ImageVerificationLib/DxeImageVerificationLib.c b/Core/EM/SecurityPkg/ImageVerificationLib/DxeImageVerificationLib.c
new file mode 100644
index 0000000..7593b20
--- /dev/null
+++ b/Core/EM/SecurityPkg/ImageVerificationLib/DxeImageVerificationLib.c
@@ -0,0 +1,2431 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SecureBoot_WIN8/ImageVerification_efi/DxeImageVerificationLib.c 79 6/22/15 6:26p Alexp $
+//
+// $Revision: 79 $
+//
+// $Date: 6/22/15 6:26p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureBoot_WIN8/ImageVerification_efi/DxeImageVerificationLib.c $
+//
+// 79 6/22/15 6:26p Alexp
+// EIP219415
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] UEFI PXE can launch unsigned images when
+// SecureBoot is enabled.
+// [RootCause] Image from PXE server gets cloned device path
+// from its parent network controller with PciIo protocol
+// and embedded PCI ROM attributes
+// [Solution] Add checking for unique path for embedded
+// Pci OpROMs to prevent non-OpROM images
+//
+// 77 5/14/15 9:49a Alexp
+// DxeImageVerificationHandler()
+// Modify certificate offset calculation to match EDKII version
+//
+// 76 3/09/15 4:24p Alexp
+// EIP192504: Prevent Built In EFI Shell boot option from being created in
+// BDS when Secure Boot is enabled
+// [Resolution]: Leave old logic to allow launching embedded shell
+// based on the token:LOAD_UNSIGNED_EMBEDDED_SHELL
+// enabled by default only in Debug mode
+// EIP197749: Need to authenticate images loaded from external FV
+// [Resolution] Add logic inside GetImageType() to detect images loaded
+// from external FV
+//
+// 75 5/29/14 8:52a Alexp
+// minor debug trace message change;
+//
+// 74 8/15/13 11:29a Alexp
+// EIP#118850: Implement support for Certificate Revocation Storage
+// reduction and Timestamp Support.
+// Link AmyCryptoLib to make use of os_mktime()
+//
+// 73 7/26/13 3:40p Alexp
+// 1. EIP118850: Integrate ECR1009 chnages for TimeStamp dbt processing
+// 2. Image policy settings are checked against the build time defaults.
+// Prevents un-authorized change to NVRAM policy settings
+// to lower security policy.
+//
+// 72 6/26/13 10:48a Alexp
+// EIP[125931]: Security review. Fix after follow up review.
+// UINT32 integer wrapping still occurs due to incorrect placement
+// of delimiting parentheses
+//
+// 70 6/25/13 7:21p Alexp
+// EIP:127292 Item#2. Add dependency on ENABLE_IMAGE_EXEC_POLICY_OVERRIDE
+// EIP:127292 Item#3 Only For deprecated Security protocol:
+// DxeImageVerificationHandler Returns Error if FileRead() is
+// unsuccessful
+//
+// 67 6/21/13 10:41a Alexp
+// EIP[125931]: Security review: HashPeImage does not validate certificate
+// table offset and size
+//
+// 66 5/21/13 4:05p Alexp
+// EIP:124444 Secure boot improvement for LoadImage call with NULL
+// DevicePath
+// EIP:122339 GetImageType() detect if PciOpROM image is loaded from
+// internal FV by
+// checking the corresponding PCI I/O instance for the embedded
+// attribute.
+//
+// 63 3/25/13 3:41p Alexp
+// 1. EIP:118243 add support for multi-signed PE Images
+// 2. Removed append image certificates to db from User Query dialog.
+//
+// 56 3/11/13 5:07p Alexp
+// IsSignatureFoundInDatabase(): fix method to calculate CertCount.
+// AddImageExeInfo(): code cleanup for cases when *Name is NULL
+// DxeImageVerificationHandler(): Optimized code to determine if PE image
+// is signed
+//
+// 55 3/09/13 4:31p Alexp
+// EIP114998: wrong cert size passed in PCR[7] calculation
+//
+// 54 12/19/12 10:28a Alexp
+// EIP[104046]: Hardened code per #2,3,4,5,6,7 of security review findings
+//
+//
+// 53 12/17/12 3:10p Alexp
+// code fixes according to "cppcheck" style & performance suggestions
+//
+// 52 12/06/12 7:31p Alexp
+// Update ImageAuthorization()
+//
+// 51 11/26/12 10:46a Alexp
+// replaced hardwired Var name L"SecureBootSetup" to generic Var define
+//
+// 50 11/19/12 4:42p Alexp
+// Fix for Win8 SecureBoot logo requirement: restore Secure Boot state
+// across flash updates.
+// Move all secure boot Setup settings to a separate varsore variable.
+// Preserve var across re-flash
+//
+// 49 11/09/12 4:32p Alexp
+// IsPkcsSignedDataVerifiedBySignatureList()
+// Fix CertData size - excude EFI_GUID size
+//
+// 48 10/17/12 3:03p Alexp
+// EIP[104046]: Findings from Security review on Aptio4 Image verification
+// Includes the fix for item #4:
+// HashPeImage returns TRUE even in error case
+//
+// 47 10/16/12 3:53p Alexp
+// EIP[104046]: Findings from Security review on Aptio4 Image verification
+// Includes the fix for item #7 from the list attached to the EIP
+//
+// 46 9/25/12 11:22a Alexp
+// removed ImageVerify simulation when system in SetupMode.
+//
+// 45 9/24/12 12:26p Alexp
+// fix code branch for WIN_CERT_TYPE_EFI_GUID certificates
+//
+// 44 9/19/12 4:07p Alexp
+// fix code branch to set action EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED
+//
+// 43 9/14/12 3:42p Alexp
+// Hardwire LoadFromFv to AlwaysEnable irrespective of SetupData
+//
+// 42 9/13/12 11:38a Alexp
+// Fix Bug in HashPeiImage.
+// Last step 16 in hashing of optional data structures after the
+// Certificate entry was missing
+//
+// 41 9/07/12 9:37a Alexp
+// 1. Set all global variables Static
+// 2. IsPkcsSignedDataVerifiedBySignatureList(). Compiler optimization for
+// "IsVerified = VerifyWinCertificateForPkcsSignedData(
+// &(PkcsCertData->Hdr));"
+// may not link the main code.
+// 3. Run Verify code when platform is in SetupMode and SecureBoot set to
+// Custom
+//
+// 39 9/05/12 5:42p Alexp
+// GetImageType() :
+// Change Device Path search criteria to match EDKII example:
+// check FV path first and then Block I/O
+//
+// 38 8/29/12 11:16a Alexp
+// Add definition for EFI_MAX_ADDRESS if it's not defined elsewhere in
+// included header files
+//
+// 37 8/28/12 4:21p Alexp
+// Restore dependencies on SecureBootMode->Custom Setup option
+//
+// 35 8/15/12 4:16p Alexp
+// IsPkcsSignedDataVerifiedBySignatureList()
+// Fix bug prev version in processing multiple Certs from PE Hdr.
+//
+// 34 7/26/12 3:54p Alexp
+// Query User -> Append Certificate only available in Setup Mode.
+//
+// 33 7/25/12 6:45p Alexp
+// 1. Update ImageVerification logic to the latest EDK2 patch (13469)
+// Add support for multiple Signatures within PE/COFF table
+// Additional Header validation checks
+// 2. Add code flow when SecureBoot set to Custom mode.
+// Image Verification is performed but failing images are allowed to
+// run
+// Use this mode to append image certificates to DB in User Query mode.
+//
+// 32 6/11/12 3:15p Alexp
+// use modified WIN_CERTIFICATE_UEFI_GUID_1 struc in
+// AppendEfiImageSecurityDatabaseVariableEx()
+// moded struc is shorter by 4 bytes
+//
+// 30 5/18/12 9:21a Alexp
+// Fine tune User Query messages. Only display the messages if Admin user
+// has signed in
+//
+// 29 5/01/12 4:43p Alexp
+// PCR[7] - mTrustSigDbOffs contains offset to SigData struct within SigDb
+//
+// 28 4/27/12 3:57p Alexp
+// Fix Certificate type in AppendEfiImageSecurityDatabaseVariableEx()
+//
+// 27 4/23/12 5:19p Alexp
+// EIP:80874 Made changes to support PCR[7] measurments for Secure Boot
+// state in TCG
+// Install "Efi Boot Image Certificate" info strusture on Efi System
+// Table.
+//
+// 26 4/20/12 5:14p Alexp
+// Add new function to install the handle on Efi System Table with the
+// location
+// within DB variable of the Trusted Certificate that was used to verify
+// signature of Efi OS BootLoader image.
+//
+// 25 4/10/12 6:52p Alexp
+// Update VerifyCertPkcsSignedData() to support extended search in
+// Forbidded db for any leaf certificate, not only Root CA
+//
+// 23 4/03/12 7:35p Alexp
+// Move ReadImage() under legacy SecureFileAuthentication()
+//
+// 22 4/02/12 4:24p Alexp
+// Installs EFI_SECURITY2_ARCH_PROTOCOL.
+// Input arguments include File Path and pointer to a File buffer in
+// memory.
+//
+// 20 3/20/12 10:51a Alexp
+// 1. fix in AppendEfiImageSecurityDatabaseVariableEx()
+// 2. removed unused global vars
+//
+// 18 3/16/12 10:29a Alexp
+// [EIP85500] Build problem with (INT)4.6.5.1_SECUREBOOT_WIN8_11
+// move "extern EFI_GUID BdsConnectDriversProtocolGuid " outside of #ifdef
+// scope
+//
+// 17 3/13/12 2:41p Alexp
+// Add check for Admin signed credentials while allowing User Querry
+// policy
+//
+// 16 3/12/12 3:01p Alexp
+// 1. Deffer image verification till BdsConnectDriversProtocol event.
+// Speeds up the boot time.
+// 2. Enforce default (hardwired by SDL token) image veriication policy
+// for image device path if SecureBootMode is set to Standard.
+//
+// 15 3/09/12 3:39p Alexp
+// 1. Fixed Image authentication by Hash certificate in "db"
+// 2. Add User interructive controls to append image certificate to Sig
+// "db" (test implementation, will change in later releases)
+//
+// 14 2/27/12 6:47p Alexp
+// Reduce time spent in the DxeImageVerificationHandler function during
+// non-Secure Boot mode. Original code caused additional 0.5 sec to boot
+// time.
+// Note: internal SecureBoot mode flag once registered during
+// initializaton - will not change until restart.
+//
+// 13 1/04/12 3:27p Alexp
+// Fixed possible security risk:
+// GetImageType(). Block I/O Device Path check made higher priority then
+// of FV device path.
+//
+// 12 12/29/11 6:49p Alexp
+// GetImageType() - Fix for Image Device Path resolution
+// Added SubType = MEDIA_FV_FILEPATH_DP to search options for
+// MEDIA_DEVICE_PATH.
+// It appears SmmDriverDispatcher sets this device path for files loaded
+// by SmmDispatcher.
+//
+// 11 12/23/11 8:59a Alexp
+// Bug fix:
+// EIP:78978:Secure boot will hang at CP 0x72
+// ConOut & ConIn are not available until later in BDS phase, earlier
+// calls to display User Prompt may hang the system
+//
+// 10 12/07/11 7:23p Alexp
+// Bug fix:
+// EIP:77088 SecureBoot: Image can be loaded if click "No" when query
+// user after image verification failed
+// ImageAuthorization() -> Return EFI_ACCESS_DENIED of User Override
+// option
+//
+// 9 8/22/11 11:14a Alexp
+// optimizations to GetImageType()
+//
+// 6 7/18/11 4:12p Alexp
+// EIP:65085. LoadImage Error status is different When Secure Boot is ON
+// EIP:65194: No way to control the Secure Boot module to not interact
+// with the USER without changing the code
+//
+// 4 6/23/11 9:27a Alexp
+// moved mDigitalSig Protocol check up before API may be called
+//
+// 3 6/22/11 5:45p Alexp
+// draft change: add Sha256 as valid cert for "db" databases
+//
+// 2 6/13/11 7:21p Alexp
+// fix Hash calculation for Sha256 Certs in Forbidden database dbx
+//
+// 10 5/17/11 5:36p Alexp
+// update conOut messages
+//
+// 9 5/17/11 12:50p Alexp
+// replace AmiPostManager with pST->ConOut
+// use pBS instead of gBS
+//
+// 6 5/13/11 4:02p Alexp
+// 1. add dependency on Core rev. 4.6.5+ to buld for older Aptio cores
+// 2. Ignore Querry User policy for internal FV files
+//
+//**********************************************************************
+/*++
+ This file contains an 'Intel Peripheral Driver' and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+--*/
+/** @file
+
+ Implement image verification services for secure boot
+ service in UEFI2.2.
+
+ Caution: This file requires additional review when modified.
+ This library will have external input - PE/COFF image.
+ This external input must be validated carefully to avoid security issue like
+ buffer overflow, integer overflow.
+
+ DxeImageVerificationLibImageRead() function will make sure the PE/COFF image content
+ read is within the image buffer.
+
+ DxeImageVerificationHandler(), HashPeImageByType(), HashPeImage() function will accept
+ untrusted PE/COFF image and validate its data structure within this image buffer before use.
+
+Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
+
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+**/
+
+#pragma warning (disable : 4090)
+
+#include <Token.h>
+#include <Protocol/Security.h>
+#include "DxeImageVerificationLib.h"
+#include "EfiImage.h"
+#include <AmiDxeLib.h>
+#include<Guid/PeiPeCoffLoader.h>
+#include <Protocol/AmiDigitalSignature.h>
+#include <AmiCertificate.h>
+#include <Setup.h>
+#include <SecureBootMod.h>
+#include <Protocol/PciIo.h> //EIP 122339
+#include <cryptlib.h>
+
+extern EFI_GUID BdsConnectDriversProtocolGuid;
+
+// 4.6.5.4
+#if defined(CORE_COMBINED_VERSION) && CORE_COMBINED_VERSION >=0x4028e
+#include <Protocol/Security2.h>
+#endif
+
+// 4.6.5.1
+#if defined(CORE_COMBINED_VERSION) && CORE_COMBINED_VERSION >=0x4028b
+#include <EdkIICommon.h>
+#else
+#include <Tiano.h>
+
+//********tmp declaration from EdkIICommon.h
+#define MEDIA_RELATIVE_OFFSET_RANGE_DP 0x08
+
+extern VOID ZeroMem (
+ OUT VOID *Buffer,
+ IN UINTN Size
+);
+VOID* CopyMem (
+ OUT VOID *DestinationBuffer,
+ IN VOID *SourceBuffer,
+ IN UINTN Length
+);
+#endif
+EFI_STATUS
+EFIAPI
+PeCoffLoaderGetImageInfo (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ );
+
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextOut.h>
+
+#define AMI_MEDIA_DEVICE_PATH_GUID \
+ { 0x5023b95c, 0xdb26, 0x429b, 0xa6, 0x48, 0xbd, 0x47, 0x66, 0x4c, 0x80, 0x12 }
+
+#define STANDARD_SECURE_BOOT 0
+#define CUSTOM_SECURE_BOOT 1
+
+static EFI_GUID AmiMediaDevicePathGuid = AMI_MEDIA_DEVICE_PATH_GUID;
+static EFI_GUID gSecureSetupGuid = SECURITY_FORM_SET_GUID;
+static EFI_GUID gEfiGlobalVariableGuid = EFI_GLOBAL_VARIABLE;
+
+static AMI_DIGITAL_SIGNATURE_PROTOCOL *mDigitalSigProtocol = NULL;
+//
+// Caution: This is used by a function which may receive untrusted input.
+// These global variables hold PE/COFF image data, and they should be validated before use.
+//
+EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;
+static UINT8 *mImageBase = NULL;
+static UINTN mImageSize;
+static EFI_GUID *mCertType;
+static UINT32 mPeCoffHeaderOffset;
+static UINT8 mImageDigest[MAX_DIGEST_SIZE];
+static UINTN mImageDigestSize;
+static SECURE_BOOT_SETUP_VAR mSecureBootSetup;
+static UINT8 mSecureBootEnable = 0;
+static UINTN mFvHandlesCount = 0;
+static EFI_HANDLE *mFvHandles = NULL;
+static BOOLEAN gImageLoadingAfterBDS = FALSE;
+
+//
+// Notify string for authorization UI.
+//
+CHAR16 mNotifyString1[MAX_NOTIFY_STRING_LEN] = L"\r\nImage verification failed!\r\n";
+CHAR16 mNotifyString2[MAX_NOTIFY_STRING_LEN] = L"\r\nLaunch this image anyway? (Y/N)";
+CHAR16 mNotifyString3[MAX_NOTIFY_STRING_LEN] = L"Image Certificate not found in Authorized database(db)!";
+CHAR16 mNotifyString4[MAX_NOTIFY_STRING_LEN] = L"Image Certificate is found in Forbidden database(dbx)!";
+CHAR16 mNotifyString5[MAX_NOTIFY_STRING_LEN] = L"Image is unsigned or Certificate is invalid!";
+
+//6683D10C-CF6E-4914-B5B4-AB8ED7370ED7
+EFI_GUID gBootImageCertTblGuid = AMI_VALID_BOOT_IMAGE_CERT_TBL_GUID;
+static UINT32 mTrustSigDbOffs = 0;
+static UINT32 mTrustSigDbSize = 0;
+
+//---------------------------------------
+// NEW TIME STAMP definitions ECR#1009
+//---------------------------------------
+extern EFI_GUID gEfiCertX509Sha256Guid;
+extern EFI_GUID gEfiCertX509Sha384Guid;
+extern EFI_GUID gEfiCertX509Sha512Guid;
+static INT32 mTimeOfSigningLong;
+typedef enum {
+ CertUndefined,
+ CertSha256,
+ CertX509,
+ CertX509Sha256,
+ CertX509Sha384,
+ CertX509Sha512,
+} nCertType;
+//---------------------------------------
+// NEW TIME STAMP definitions ECR#1009
+//---------------------------------------
+
+//************TEMP UTILITY FUNCTIONS. Use EDKII common wrapper lib instead****************
+#if defined(CORE_COMBINED_VERSION) && CORE_COMBINED_VERSION >=0x4028b
+#else
+UINTN StrSize (
+ IN CHAR16 *String)
+{
+ UINTN Size;
+
+ for (Size = 2; *String != L'\0'; String++, Size += 2);
+
+ return Size;
+}
+#endif
+
+VOID* GetEfiGlobalVariableEx (
+ IN CHAR16 *Name,
+ IN OUT UINTN *VarSize
+ )
+{
+ EFI_STATUS Status;
+ VOID *Var=NULL;
+
+ Status = GetEfiVariable(Name, &gEfiGlobalVariableGuid, NULL, VarSize, &Var);
+ return (EFI_ERROR(Status)) ? NULL : Var;
+}
+
+VOID* GetEfiImageSecurityDatabaseVariableEx (
+ IN CHAR16 *Name,
+ IN OUT UINTN *VarSize
+ )
+{
+ EFI_STATUS Status;
+ VOID *Var = NULL;
+
+ Status = GetEfiVariable(Name, &gEfiImageSecurityDatabaseGuid, NULL, VarSize, &Var);
+ return (EFI_ERROR(Status)) ? NULL : Var;
+}
+
+/**
+ Reads contents of a PE/COFF image in memory buffer.
+
+ Caution: This function may receive untrusted input.
+ PE/COFF image is external input, so this function will make sure the PE/COFF image content
+ read is within the image buffer.
+
+ @param FileHandle Pointer to the file handle to read the PE/COFF image.
+ @param FileOffset Offset into the PE/COFF image to begin the read operation.
+ @param ReadSize On input, the size in bytes of the requested read operation.
+ On output, the number of bytes actually read.
+ @param Buffer Output buffer that contains the data read from the PE/COFF image.
+
+ @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
+**/
+EFI_STATUS
+EFIAPI
+DxeImageVerificationLibImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ )
+{
+
+ if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((EFI_MAX_ADDRESS - FileOffset) < *ReadSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((UINT64)FileOffset + *ReadSize) > mImageSize) {
+// *ReadSize = (UINT32)(mImageSize - FileOffset);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FileOffset >= mImageSize) {
+// *ReadSize = 0;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Get the image type.
+
+ @param[in] File This is a pointer to the device path of the file that is
+ being dispatched.
+
+ @return UINT32 Image Type
+
+**/
+UINT32
+GetImageType (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DeviceHandle;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ UINT8 nDevicePathSubType;
+ //EIP 122339 Start
+ EFI_PCI_IO_PROTOCOL *PciIoInterface = NULL;
+ UINT64 AttributesResult;
+ //EIP 122339 Stop
+ UINTN Index;
+ BOOLEAN IsFv = FALSE;
+
+ // Unknown device path: image security policy is applied to the image with the least trusted origin.
+ if (File == NULL) {
+ return IMAGE_UNKNOWN;
+ }
+
+ //
+ // Check if File is just a Firmware Volume.
+ //
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
+ while (!IsDevicePathEndType(TempDevicePath)){
+ nDevicePathSubType = DevicePathSubType (TempDevicePath);
+ TRACE((TRACE_ALWAYS,"Device PathType %x, SubType %x\n", DevicePathType(TempDevicePath), nDevicePathSubType ));
+ //
+ // EFI Specification extension on Media Device Path. MEDIA_FW_VOL_FILEPATH_DEVICE_PATH is adopted by UEFI later and added in UEFI2.10.
+ // In EdkCompatibility Package, we only support MEDIA_FW_VOL_FILEPATH_DEVICE_PATH that complies with EFI 1.10 and UEFI 2.10.
+ //
+ if( (DevicePathType(TempDevicePath) == MEDIA_DEVICE_PATH && nDevicePathSubType == MEDIA_FV_FILEPATH_DP) ||
+ (DevicePathType(TempDevicePath) == HARDWARE_DEVICE_PATH && nDevicePathSubType == HW_MEMMAP_DP)
+ ){
+ IsFv = TRUE;
+ } else {
+ IsFv = FALSE;
+ break;
+ }
+ TempDevicePath = NextDevicePathNode(TempDevicePath);
+ }
+
+ //
+ // Check to see if a File or a FV is from internal Firmware Volume.
+ //
+ if(IsFv) {
+
+ DeviceHandle = NULL;
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
+ Status = pBS->LocateDevicePath (
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ &gEfiFirmwareVolumeProtocolGuid,
+#else
+ &gEfiFirmwareVolume2ProtocolGuid,
+#endif
+ &TempDevicePath,
+ &DeviceHandle
+ );
+
+ if (!EFI_ERROR (Status)) {
+ if(!gImageLoadingAfterBDS)
+ return IMAGE_FROM_FV;
+
+ Status = pBS->OpenProtocol (
+ DeviceHandle,
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ &gEfiFirmwareVolumeProtocolGuid,
+#else
+ &gEfiFirmwareVolume2ProtocolGuid,
+#endif
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ for(Index=0;Index < mFvHandlesCount;Index++){
+ TRACE((TRACE_ALWAYS,"FV%02d. DeviceHandle %X=%X\n", Index, DeviceHandle, mFvHandles[Index] ));
+ if(DeviceHandle == mFvHandles[Index] )
+ return IMAGE_FROM_FV;
+ }
+ }
+ }
+ return IMAGE_UNKNOWN;
+ }
+ //
+ // Next check to see if File is from a Block I/O device
+ // Must be a Block I/O device since we reached here after Int FV path check
+ //
+ DeviceHandle = NULL;
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
+ Status = pBS->LocateDevicePath (
+ &gEfiBlockIoProtocolGuid,
+ &TempDevicePath,
+ &DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ BlockIo = NULL;
+ Status = pBS->OpenProtocol (
+ DeviceHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status) && BlockIo != NULL) {
+ if (BlockIo->Media != NULL) {
+ if (BlockIo->Media->RemovableMedia) {
+ //
+ // Block I/O is present and specifies the media is removable
+ //
+ return IMAGE_FROM_REMOVABLE_MEDIA;
+ } else {
+ //
+ // Block I/O is present and specifies the media is not removable
+ //
+ return IMAGE_FROM_FIXED_MEDIA;
+ }
+ }
+ }
+ }
+ //
+ // File is not in a Firmware Volume or on a Block I/O device, so check to see if
+ // the device path supports the Simple File System Protocol.
+ //
+ DeviceHandle = NULL;
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
+ Status = pBS->LocateDevicePath (
+ &gEfiSimpleFileSystemProtocolGuid,
+ &TempDevicePath,
+ &DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Simple File System is present without Block I/O, so assume media is fixed.
+ //
+ return IMAGE_FROM_FIXED_MEDIA;
+ }
+
+ //
+ // File is not from an FV, Block I/O or Simple File System, so the only options
+ // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
+ //
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
+ while (!IsDevicePathEndType (TempDevicePath)) {
+ nDevicePathSubType = DevicePathSubType (TempDevicePath);
+ switch (DevicePathType (TempDevicePath)) {
+ //EIP 219415 Start
+ //Embedded OpROM
+ case HARDWARE_DEVICE_PATH:
+
+ if(nDevicePathSubType == HW_MEMMAP_DP) {
+ //EIP 122339 Start: Return IMAGE_FROM_FV if the EFI_PCI_IO_PROTOCOL installed
+ //on the same handle as the Device Path has the attribute EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
+ DeviceHandle = NULL;
+ //
+ // Check if an instance of the EFI_PCI_IO_PROTOCOL is installed on the same handle
+ // as the Device Path. If an instance is found WorkAroundDevHandle contains the
+ // handle for the Device Path and EFI_PCI_IO_PROTOCOL instance.
+ //
+ Status = pBS->LocateDevicePath(
+ &gEfiPciIoProtocolGuid,
+ &File,
+ &DeviceHandle
+ );
+ if(EFI_ERROR(Status)) break;
+
+ Status = pBS->HandleProtocol(
+ DeviceHandle,
+ &gEfiPciIoProtocolGuid,
+ &PciIoInterface
+ );
+
+ if(EFI_ERROR(Status)) break;
+
+ //
+ // Using the EFI_PCI_IO_PROTOCOL get the value of the PCI controller's
+ // Embedded Rom attribute (EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)
+ //
+ Status = PciIoInterface->Attributes(
+ PciIoInterface,
+ EfiPciIoAttributeOperationGet,
+ 0, //this parameter is ignored during Get operation
+ &AttributesResult
+ );
+ if(EFI_ERROR(Status)) break;
+ //
+ // Check if the PCI controller's EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM is set
+ //
+ if(AttributesResult & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)
+ return IMAGE_FROM_FV;
+ //EIP 122339 Stop
+ }
+ break;
+ //EIP 219415 end
+ case MEDIA_DEVICE_PATH:
+
+ if (nDevicePathSubType == MEDIA_RELATIVE_OFFSET_RANGE_DP) {
+ return IMAGE_FROM_OPTION_ROM;
+ }
+#if LOAD_UNSIGNED_EMBEDDED_SHELL == 1
+ // Case for embedded FV application such as Shell(check GUID. BootOptions.h)
+ if (nDevicePathSubType == MEDIA_VENDOR_DP &&
+ !guidcmp(&((VENDOR_DEVICE_PATH*)TempDevicePath)->Guid, &AmiMediaDevicePathGuid)) {
+ return IMAGE_FROM_FV;
+ }
+#endif
+ break;
+
+ case MESSAGING_DEVICE_PATH:
+
+ if (nDevicePathSubType == MSG_MAC_ADDR_DP) {
+ return IMAGE_FROM_REMOVABLE_MEDIA;
+ }
+ break;
+ }
+ TempDevicePath = NextDevicePathNode (TempDevicePath);
+ }
+
+ return IMAGE_UNKNOWN;
+}
+
+/**
+ Caculate hash of Pe/Coff image based on the authenticode image hashing in
+ PE/COFF Specification 8.0 Appendix A
+
+ Caution: This function may receive untrusted input.
+ PE/COFF image is external input, so this function will validate its data structure
+ within this image buffer before use.
+
+ @param[in] HashAlg Hash algorithm type.
+
+ @retval TRUE Successfully hash image.
+ @retval FALSE Fail in hash image.
+
+**/
+BOOLEAN
+HashPeImage (
+ IN UINT32 HashAlg
+ )
+{
+ EFI_STATUS EfiStatus;
+ BOOLEAN Status;
+ UINT16 Magic;
+ EFI_IMAGE_SECTION_HEADER *Section;
+ UINT8 *HashBase;
+ UINTN HashSize;
+ UINTN SumOfBytesHashed;
+ EFI_IMAGE_SECTION_HEADER *SectionHeader;
+ UINTN Index;
+ UINTN Pos;
+
+ const UINT8 *addr[MAX_ELEM_NUM]; // tbd. test if 20 elements is enough
+ UINTN num_elem, len[MAX_ELEM_NUM];
+ EFI_GUID *EfiHashAlgorithmGuid;
+
+ UINT32 CertSize;
+ UINT32 NumberOfRvaAndSizes;
+
+ SectionHeader = NULL;
+ Status = FALSE;
+ EfiStatus = EFI_SECURITY_VIOLATION;
+ num_elem = 0;
+ //
+ // Initialize context of hash.
+ //
+ ZeroMem (mImageDigest, MAX_DIGEST_SIZE);
+ if (HashAlg == HASHALG_SHA1) {
+ mImageDigestSize = SHA1_DIGEST_SIZE;
+ EfiHashAlgorithmGuid = &gEfiHashAlgorithmSha1Guid;
+ mCertType = &gEfiCertSha1Guid;
+ } else if (HashAlg == HASHALG_SHA256) {
+ mImageDigestSize = SHA256_DIGEST_SIZE;
+ EfiHashAlgorithmGuid = &gEfiHashAlgorithmSha256Guid;
+ mCertType = &gEfiCertSha256Guid;
+ } else {
+ return FALSE;
+ }
+
+ // 1. Load the image header into memory.
+
+ //
+ // Measuring PE/COFF Image Header;
+ // But CheckSum field and SECURITY data directory (certificate) are excluded
+ //
+ if (mNtHeader.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
+ // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
+ // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
+ // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
+ //
+ Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+ } else {
+ //
+ // Get the magic value from the PE/COFF Optional Header
+ //
+ Magic = mNtHeader.Pe32->OptionalHeader.Magic;
+ }
+
+ //
+ // 3. Calculate the distance from the base of the image header to the image checksum address.
+ // 4. Hash the image header from its base to beginning of the image checksum.
+ //
+ HashBase = mImageBase;
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use PE32 offset.
+ //
+ HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);
+ NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;
+ } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ //
+ // Use PE32+ offset.
+ //
+ HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);
+ NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
+ } else {
+ //
+ // Invalid header magic number.
+ //
+ TRACE((TRACE_ALWAYS,"Invalid header magic number.\n"));
+ goto Done;
+ }
+
+ if (HashSize != 0)
+ {
+ addr[num_elem] = HashBase;
+ len[num_elem++] = HashSize;
+ } else {
+//TRACE((TRACE_ALWAYS,"Hash1.%x\n", HashSize));
+ goto Done;}
+ //
+ // 5. Skip over the image checksum (it occupies a single ULONG).
+ //
+ if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
+ //
+ // 6. Since there is no Cert Directory in optional header, hash everything
+ // from the end of the checksum to the end of image header.
+ //
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use PE32 offset.
+ //
+ HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
+ HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);
+ } else {
+ //
+ // Use PE32+ offset.
+ //
+ HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
+ HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);
+ }
+
+ if (HashSize != 0)
+ {
+ addr[num_elem] = HashBase;
+ len[num_elem++] = HashSize;
+ } else {
+//TRACE((TRACE_ALWAYS,"Hash2.%x\n", HashSize));
+ goto Done;}
+ } else {
+ //
+ // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
+ //
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use PE32 offset.
+ //
+ HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
+ HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
+ } else {
+ //
+ // Use PE32+ offset.
+ //
+ HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
+ HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
+ }
+ if (HashSize != 0)
+ {
+ addr[num_elem] = HashBase;
+ len[num_elem++] = HashSize;
+ } else {
+//TRACE((TRACE_ALWAYS,"Hash3.%x\n", HashSize));
+ goto Done;}
+
+ //
+ // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
+ // 9. Hash everything from the end of the Cert Directory to the end of image header.
+ //
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use PE32 offset
+ //
+ HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
+ HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);
+ } else {
+ //
+ // Use PE32+ offset.
+ //
+ HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
+ HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);
+ }
+ if (HashSize != 0)
+ {
+ addr[num_elem] = HashBase;
+ len[num_elem++] = HashSize;
+ } else {
+//TRACE((TRACE_ALWAYS,"Hash4.%x\n", HashSize));
+ goto Done;}
+ }
+
+ //
+ // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
+ //
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use PE32 offset.
+ //
+ SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;
+ } else {
+ //
+ // Use PE32+ offset
+ //
+ SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;
+ }
+
+
+ Section = (EFI_IMAGE_SECTION_HEADER *) (
+ mImageBase +
+ mPeCoffHeaderOffset +
+ sizeof (UINT32) +
+ sizeof (EFI_IMAGE_FILE_HEADER) +
+ mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader
+ );
+ //
+ // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
+ // structures in the image. The 'NumberOfSections' field of the image
+ // header indicates how big the table should be. Do not include any
+ // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
+ //
+// TRACE((TRACE_ALWAYS,"Num Sections = %x\n", mNtHeader.Pe32->FileHeader.NumberOfSections));
+
+// Security review [305408]: HashPeImage does not validate NumberOfSections field
+ Pos = sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections;
+ if(Pos > mImageSize)
+ goto Done;
+
+ EfiStatus = pBS->AllocatePool(EfiBootServicesData, Pos, &SectionHeader);
+ if (SectionHeader == NULL || EFI_ERROR(EfiStatus)) {
+//TRACE((TRACE_ALWAYS,"Hash4.\n"));
+ goto Done;
+
+ }
+ MemSet(SectionHeader, Pos, 0);
+ //
+ // 12. Using the 'PointerToRawData' in the referenced section headers as
+ // a key, arrange the elements in the table in ascending order. In other
+ // words, sort the section headers according to the disk-file offset of
+ // the section.
+ //
+ for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
+ Pos = Index;
+
+ // Security review EIP[104046]:6. HashPeImage does not validate NumberOfSections field
+ if(((UINT64)Section + sizeof (EFI_IMAGE_SECTION_HEADER))> ((UINT64)mImageBase+mImageSize) )
+ goto Done;
+
+ while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
+ CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
+ Pos--;
+ }
+ CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
+ Section += 1;
+ }
+
+ //
+ // 13. Walk through the sorted table, bring the corresponding section
+ // into memory, and hash the entire section (using the 'SizeOfRawData'
+ // field in the section header to determine the amount of data to hash).
+ // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
+ // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
+ //
+ for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
+ Section = &SectionHeader[Index];
+ if (Section->SizeOfRawData == 0) {
+ continue;
+ }
+
+//TRACE((TRACE_ALWAYS,"Section->PointerToRawData = %x\nSection->SizeOfRawData = %x\nSumOfBytesHashed = %x\n",Section->PointerToRawData, Section->SizeOfRawData, SumOfBytesHashed+Section->SizeOfRawData));
+ // Security review EIP[104046]: 5.HashPeImage does not validate PointerToRawData and SizeOfRawData fields
+ if( ((UINT64)Section->PointerToRawData + Section->SizeOfRawData) > mImageSize )
+ goto Done;
+
+ HashBase = mImageBase + Section->PointerToRawData;
+ HashSize = (UINTN) Section->SizeOfRawData;
+
+ addr[num_elem] = HashBase;
+ len[num_elem++] = HashSize;
+ if(num_elem >= MAX_ELEM_NUM)
+// goto Done;
+ {
+TRACE((TRACE_ALWAYS,"MAX_ELEM_NUM.1 = %d\n", num_elem));
+ goto Done;}
+ // Security review EIP[125931]: HashPeImage does not validate certificate table offset and size
+ if (((UINT64)SumOfBytesHashed+HashSize) > mImageSize)
+ goto Done;
+
+ SumOfBytesHashed += HashSize;
+ }
+
+ //
+ // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
+ // data in the file that needs to be added to the hash. This data begins
+ // at file offset SUM_OF_BYTES_HASHED and its length is:
+ // FileSize - (CertDirectory->Size)
+ //
+//dbg
+//TRACE((TRACE_ALWAYS,"mImageSize > SumOfBytesHashed.\n%x > %x\n", mImageSize, SumOfBytesHashed));
+//dbg
+ if (mImageSize > SumOfBytesHashed) {
+
+ HashBase = mImageBase + SumOfBytesHashed;
+
+ if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
+ CertSize = 0;
+ } else {
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use PE32 offset.
+ //
+ CertSize = mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
+ } else {
+ //
+ // Use PE32+ offset.
+ //
+ CertSize = mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
+ }
+ }
+
+ if (mImageSize > ((UINT64)CertSize + SumOfBytesHashed)) {
+ HashSize = (UINTN) (mImageSize - CertSize - SumOfBytesHashed);
+
+//TRACE((TRACE_ALWAYS,"\nData beyond nSumOfBytesHashed\nBase = %x, Size = %x\n",SumOfBytesHashed, HashSize));
+
+ addr[num_elem] = HashBase;
+ len[num_elem++] = HashSize;
+ if(num_elem >= MAX_ELEM_NUM)
+// goto Done;
+ {
+TRACE((TRACE_ALWAYS,"MAX_ELEM_NUM.2=%d\n", num_elem));
+ goto Done;}
+
+ } else if (mImageSize < ((UINT64)CertSize + SumOfBytesHashed)) {
+TRACE((TRACE_ALWAYS,"mImageSize < CertSize + SumOfBytesHashed.\n%d < %d\n", mImageSize, CertSize + SumOfBytesHashed));
+ goto Done;
+ }
+ else
+ HashSize = 0;
+ // ??? HashBase += CertSize;
+//TRACE((TRACE_ALWAYS,"\nData beyond CertDir\nBase = %x, Size = %x\n",SumOfBytesHashed+HashSize+CertSize, mImageSize-(SumOfBytesHashed+HashSize+CertSize)));
+ }
+ EfiStatus = mDigitalSigProtocol->Hash(
+ mDigitalSigProtocol,
+ EfiHashAlgorithmGuid, num_elem, addr, len, (UINT8*)&mImageDigest);
+
+TRACE((TRACE_ALWAYS,"Found HashElements %d\nImageHash: [%2X],[%2X],..\n", num_elem, mImageDigest[0], mImageDigest[1]));
+
+ if(!EFI_ERROR(EfiStatus))
+ Status = TRUE;
+
+Done:
+
+ if (SectionHeader != NULL) {
+ pBS->FreePool (SectionHeader);
+ }
+ // Security review EIP[104046]: 4.HashPeImage returns TRUE even in error case
+ // Status = FALSE unless updated to TRUE in the final Hash step before "Done" label
+ return Status;
+}
+
+/**
+ Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
+ Pe/Coff image based on the authenticode image hashing in PE/COFF Specification
+ 8.0 Appendix A
+
+ Caution: This function may receive untrusted input.
+ PE/COFF image is external input, so this function will validate its data structure
+ within this image buffer before use.
+
+ @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.
+ @param[in] AuthDataSize Size of the Authenticode Signature in bytes.
+
+ @retval EFI_UNSUPPORTED Hash algorithm is not supported.
+ @retval EFI_SUCCESS Hash successfully.
+
+**/
+EFI_STATUS
+HashPeImageByType (
+ IN UINT8 *AuthData,
+ IN UINTN AuthDataSize
+ )
+{
+ EFI_STATUS Status;
+ UINT8 DigestAlgo;
+ UINT8 *pDigestAlgo;
+ UINTN Size;
+
+// get Digest Algorithm
+ Size = 0;
+ pDigestAlgo = (UINT8*)&DigestAlgo;
+ Status = mDigitalSigProtocol->Pkcs7Verify (
+ mDigitalSigProtocol,
+ AuthData,
+ AuthDataSize,
+ NULL,
+ 0,
+ &pDigestAlgo, // returns DER Ptr to Sign Cert
+ &Size,
+ Pkcs7GetDigestAlgorithm,
+ LOCK
+ );
+ if (EFI_ERROR(Status))
+ return Status;
+
+ switch(DigestAlgo) {
+ case SHA1:
+ if (!HashPeImage (HASHALG_SHA1)) {
+ Status = EFI_SECURITY_VIOLATION;
+ }
+ break;
+ case SHA256:
+ if (!HashPeImage (HASHALG_SHA256)) {
+ Status = EFI_SECURITY_VIOLATION;
+ }
+ break;
+ default:
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ Returns the size of a given image execution info table in bytes.
+
+ This function returns the size, in bytes, of the image execution info table specified by
+ ImageExeInfoTable. If ImageExeInfoTable is NULL, then 0 is returned.
+
+ @param ImageExeInfoTable A pointer to a image execution info table structure.
+
+ @retval 0 If ImageExeInfoTable is NULL.
+ @retval Others The size of a image execution info table in bytes.
+
+**/
+UINTN
+GetImageExeInfoTableSize (
+ EFI_IMAGE_EXECUTION_INFO_TABLE *ImageExeInfoTable
+ )
+{
+ UINTN Index;
+ EFI_IMAGE_EXECUTION_INFO *ImageExeInfoItem;
+ UINTN TotalSize;
+
+ if (ImageExeInfoTable == NULL) {
+ return 0;
+ }
+
+ ImageExeInfoItem = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) ImageExeInfoTable + sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE));
+ TotalSize = sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE);
+ for (Index = 0; Index < ImageExeInfoTable->NumberOfImages; Index++) {
+ TotalSize += ImageExeInfoItem->InfoSize;
+ ImageExeInfoItem = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) ImageExeInfoItem + ImageExeInfoItem->InfoSize);
+ }
+
+ return TotalSize;
+}
+
+/**
+ Create an Image Execution Information Table entry and add it to system configuration table.
+
+ @param[in] Action Describes the action taken by the firmware regarding this image.
+ @param[in] Name Input a null-terminated, user-friendly name.
+ @param[in] DevicePath Input device path pointer.
+ @param[in] Signature Input signature info in EFI_SIGNATURE_LIST data structure.
+ @param[in] SignatureSize Size of signature.
+
+**/
+VOID
+AddImageExeInfo (
+ IN EFI_IMAGE_EXECUTION_ACTION Action,
+ IN CHAR16 *Name OPTIONAL,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_SIGNATURE_LIST *Signature OPTIONAL,
+ IN UINTN SignatureSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_IMAGE_EXECUTION_INFO_TABLE *ImageExeInfoTable;
+ EFI_IMAGE_EXECUTION_INFO_TABLE *NewImageExeInfoTable;
+ EFI_IMAGE_EXECUTION_INFO *ImageExeInfoEntry;
+ UINTN ImageExeInfoTableSize;
+ UINTN NewImageExeInfoEntrySize;
+ UINTN NameStringLen;
+ UINTN DevicePathSize;
+
+ NewImageExeInfoTable = NULL;
+ ImageExeInfoEntry = NULL;
+ NameStringLen = sizeof (CHAR16);
+
+ if (DevicePath == NULL) {
+ return ;
+ }
+
+ if (Name != NULL) {
+ NameStringLen = StrSize (Name);
+ }
+
+ ImageExeInfoTable = GetEfiConfigurationTable(pST, &gEfiImageSecurityDatabaseGuid);
+ if (ImageExeInfoTable != NULL) {
+ //
+ // The table has been found!
+ // We must enlarge the table to accmodate the new exe info entry.
+ //
+ ImageExeInfoTableSize = GetImageExeInfoTableSize (ImageExeInfoTable);
+ } else {
+ //
+ // Not Found!
+ // We should create a new table to append to the configuration table.
+ //
+ ImageExeInfoTableSize = sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE);
+ }
+
+ DevicePathSize = DPLength(DevicePath);
+ NewImageExeInfoEntrySize = sizeof (EFI_IMAGE_EXECUTION_INFO) + NameStringLen + DevicePathSize + SignatureSize;
+
+ Status = pBS->AllocatePool(EfiRuntimeServicesData, ImageExeInfoTableSize + NewImageExeInfoEntrySize, &NewImageExeInfoTable);
+ if(EFI_ERROR(Status)) return;
+
+ if (ImageExeInfoTable != NULL) {
+ CopyMem (NewImageExeInfoTable, ImageExeInfoTable, ImageExeInfoTableSize);
+ } else {
+ NewImageExeInfoTable->NumberOfImages = 0;
+ }
+ NewImageExeInfoTable->NumberOfImages++;
+ ImageExeInfoEntry = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) NewImageExeInfoTable + ImageExeInfoTableSize);
+ //
+ // Update new item's infomation.
+ //
+ ImageExeInfoEntry->Action = Action;
+ ImageExeInfoEntry->InfoSize = (UINT32) NewImageExeInfoEntrySize;
+
+ if (Name != NULL) {
+ CopyMem ((UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32), Name, NameStringLen);
+ } else {
+ ZeroMem ((UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32), NameStringLen);
+ }
+ CopyMem (
+ (UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32) + NameStringLen,
+ DevicePath,
+ DevicePathSize
+ );
+ if (Signature != NULL) {
+ CopyMem (
+ (UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32) + NameStringLen + DevicePathSize,
+ Signature,
+ SignatureSize
+ );
+ }
+ //
+ // Update/replace the image execution table.
+ //
+ Status = pBS->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID *) NewImageExeInfoTable);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Free Old table data!
+ //
+ if (ImageExeInfoTable != NULL) {
+ pBS->FreePool (ImageExeInfoTable);
+ }
+}
+
+/**
+ Create a Boot Image Certificate table entry and add it to system configuration table.
+
+ @param[in] Name Input a null-terminated, user-friendly name.
+ @param[in] DevicePath Input device path pointer.
+ @param[in] Signature Input signature info in EFI_SIGNATURE_LIST data structure.
+ @param[in] SignatureSize Size of signature.
+
+**/
+VOID
+AddBootImageCertInfo (
+ IN CHAR16 *Name OPTIONAL,
+ IN UINT32 SignatureOffs,
+ IN UINT32 SignatureSize
+ )
+{
+ EFI_STATUS Status;
+ AMI_VALID_CERT_IN_SIG_DB *BootImageCertInfoTable;
+ UINTN BootImageCertInfoTableSize;
+
+ if(SignatureOffs == 0 || SignatureSize == 0)
+ return;
+
+ BootImageCertInfoTable = GetEfiConfigurationTable(pST, &gBootImageCertTblGuid);
+ if (BootImageCertInfoTable == NULL) {
+ //
+ // Not Found!
+ // We should create a new table.
+ //
+ BootImageCertInfoTableSize = sizeof (AMI_VALID_CERT_IN_SIG_DB);
+ Status = pBS->AllocatePool(EfiRuntimeServicesData, BootImageCertInfoTableSize, &BootImageCertInfoTable);
+ if(EFI_ERROR(Status)) return;
+ //
+ // Update/replace the image execution table.
+ //
+ Status = pBS->InstallConfigurationTable (&gBootImageCertTblGuid, (VOID *) BootImageCertInfoTable);
+ ASSERT_EFI_ERROR (Status);
+ TRACE((TRACE_ALWAYS,"Install BootImageCert Table ...%r\n", Status));
+ if (EFI_ERROR (Status)) return;
+ }
+ //
+ // Update Table's infomation.
+ //
+ BootImageCertInfoTable->SigOffset = SignatureOffs;
+ BootImageCertInfoTable->SigLength = SignatureSize;
+
+TRACE((TRACE_ALWAYS,"BootImage Cert in db\nOffset=%X\nLength=%X\n", BootImageCertInfoTable->SigOffset, BootImageCertInfoTable->SigLength));
+}
+
+/**
+ Discover if the UEFI image is authorized by user's policy setting.
+
+ @param[in] Policy Specify platform's policy setting.
+ @param[in] Action Image Validation status.
+
+ @retval EFI_ACCESS_DENIED Image is not allowed to run.
+ @retval EFI_SECURITY_VIOLATION Image is deferred.
+ @retval EFI_SUCCESS Image is authorized to run.
+
+**/
+EFI_STATUS
+ImageAuthorization (
+ IN UINT32 Policy,
+ IN UINT32 Action
+ )
+{
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Key = {0,0};
+ UINTN Index;
+ BOOLEAN bQuery;
+
+ Status = EFI_ACCESS_DENIED;
+
+ switch (Policy) {
+
+ case QUERY_USER_ON_SECURITY_VIOLATION:
+ // Conditions to allow overwrite of Execution Policy:
+ // 1. Output Console available
+ if((pST->ConIn != NULL && pST->ConOut != NULL))
+ {
+ pST->ConOut->OutputString(pST->ConOut, mNotifyString1);
+ bQuery = TRUE;
+ switch(Action) {
+ case EFI_IMAGE_EXECUTION_AUTH_SIG_NOT_FOUND: // not found in db
+ pST->ConOut->OutputString(pST->ConOut, mNotifyString3);
+ break;
+ case EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND: // found in dbx
+ pST->ConOut->OutputString(pST->ConOut, mNotifyString4);
+ break;
+ case EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED:
+ case EFI_IMAGE_EXECUTION_AUTH_UNTESTED:
+ pST->ConOut->OutputString(pST->ConOut, mNotifyString5);
+ break;
+ default:
+ bQuery = FALSE;
+ break;
+ }
+ if(!bQuery) break;
+ //Wait for key
+ pST->ConOut->OutputString(pST->ConOut, mNotifyString2);
+Repeat:
+ pBS->WaitForEvent( 1, &pST->ConIn->WaitForKey, &Index );
+ Status = pST->ConIn->ReadKeyStroke( pST->ConIn, &Key );
+ if (!EFI_ERROR (Status)) {
+ if ((Key.UnicodeChar == L'y') || (Key.UnicodeChar == L'Y')) { //yes
+ Status = EFI_SUCCESS;
+ } else if ((Key.UnicodeChar == L'n') || (Key.UnicodeChar == L'N')) { //no
+ Status = EFI_ACCESS_DENIED;
+ } else {
+ goto Repeat;
+ }
+ }
+ pST->ConOut->OutputString(pST->ConOut, L"\r\n");
+ }
+ break;
+
+ case DEFER_EXECUTE_ON_SECURITY_VIOLATION:
+ Status = EFI_SECURITY_VIOLATION;
+ break;
+
+ // case DENY_EXECUTE_ON_SECURITY_VIOLATION:
+ default:
+ Status = EFI_ACCESS_DENIED;
+ break;
+ }
+
+TRACE((TRACE_ALWAYS,"Image Authorization policy...%r\n", Status));
+
+ return Status;
+}
+
+/**
+ Advanced check in Signature Database
+ Check whether signature is located in target database
+
+ @param[in] Signature Pointer to signature that is searched for.
+ @param[in] SignatureSize Size of Signature.
+ @param[in] SignatureType Type of the Certificate, Guid
+
+ @return TRUE - found in IsSigForbidden
+ @return FALSE
+
+**/
+BOOLEAN
+IsSignatureFoundInDatabase (
+ IN CHAR16 *Name,
+ EFI_GUID *SignatureType,
+ IN UINT8 *Signature,
+ IN UINTN SignatureSize
+ )
+{
+ EFI_SIGNATURE_LIST *CertList;
+ EFI_SIGNATURE_DATA *Cert;
+ UINT8 *Data;
+ UINTN DataSize;
+ UINTN Index;
+ UINTN CertCount;
+ BOOLEAN IsSigFound;
+
+ //
+ // Read signature database variable.
+ //
+ IsSigFound = FALSE;
+
+ //
+ // Get Signature Database variable.
+ //
+
+ Data = GetEfiImageSecurityDatabaseVariableEx (Name, &DataSize);
+
+ if (Data != NULL) {
+// not an error if no "dbx" defined
+ //
+ // Enumerate all signature data in SigDB to check if executable's signature exists.
+ //
+ CertList = (EFI_SIGNATURE_LIST *) Data;
+ while (!IsSigFound && (DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
+ if (!guidcmp(&CertList->SignatureType, SignatureType)) { // Cert types do match
+ CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
+ if (CertList->SignatureSize == (sizeof(EFI_SIGNATURE_DATA) - 1 + SignatureSize)) {
+ for (Index = 0; Index < CertCount; Index++) {
+ if (MemCmp(Cert->SignatureData, Signature, SignatureSize) == 0) {
+ //
+ // Find the signature in database.
+ //
+ IsSigFound = TRUE;
+ break;
+ }
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
+ }
+ }
+ } // next CertList
+ DataSize -= CertList->SignatureListSize;
+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+ }
+ pBS->FreePool (Data);
+ }
+
+ return IsSigFound;
+}
+
+
+/**
+ Verify PKCS#7 SignedData using certificate found in Variable which formatted
+ as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.
+
+ @param VariableName Name of Variable to search for Certificate.
+
+ @retval TRUE Image pass verification.
+ @retval FALSE Image fail verification.
+
+**/
+BOOLEAN
+IsPkcsSignedDataVerifiedBySignatureList (
+ IN UINT8 *AuthData,
+ IN UINTN AuthDataSize,
+ IN CHAR16 *VariableName,
+ IN UINT8 Operation
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIGNATURE_LIST *CertList;
+ EFI_SIGNATURE_DATA *Cert;
+ UINT32 CertCount;
+ UINT32 Index;
+ UINT8 *Data;
+ UINTN DataSize;
+ UINT8 *RootCert;
+ UINTN RootCertSize;
+ UINT8 *SigCert;
+ UINTN SigCertSize;
+ BOOLEAN IsVerified;
+ EFI_TIME *TimeStamp;
+ INT32 TimeOfRevocationLong;
+ UINT8 ValidCertType;
+ BOOLEAN bVerifyTimeStampStatus;
+ BOOLEAN bProcessVerifyTimeStampStatus;
+
+ CertList = NULL;
+ Cert = NULL;
+ RootCert = NULL;
+ RootCertSize = 0;
+ IsVerified = FALSE;
+ ValidCertType = CertUndefined;
+ bVerifyTimeStampStatus= FALSE;
+ bProcessVerifyTimeStampStatus = FALSE;
+
+ mTimeOfSigningLong = 0;
+ TimeOfRevocationLong = 0;
+ // Verify the certificate's header
+ //
+ // Find certificate in store and verify authenticode struct.
+ //
+ Data = GetEfiImageSecurityDatabaseVariableEx (VariableName, &DataSize);
+
+ if (!Data)
+ return IsVerified;
+
+TRACE((TRACE_ALWAYS,"\nLook for a match in '%S'===>\n\n", VariableName));
+
+ CertList = (EFI_SIGNATURE_LIST *)Data;
+
+ //
+ // TO DO Optimization.
+ // 1. Find Root CA Cert Ptr or Signer Cert if Root is not found
+ // 2. loop thru Trust Cert list and compare each one against Root CA cert(verify SignCert signature with Trust Cert)
+ // 3. If found, break the 'while' loop and Pkcs7Verify with Trust Cert
+ //
+ //
+ // Find Cert Enrolled in database to verify the signature in pkcs7 signed data.
+ //
+ // here should be a loop thru Cert list till CertCount
+ while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
+
+ if(!guidcmp(&CertList->SignatureType, &gEfiCertX509Guid))
+ ValidCertType = CertX509;
+ else
+ if(!guidcmp(&CertList->SignatureType, mCertType))
+ ValidCertType = CertSha256;
+ else
+ if(!guidcmp(&CertList->SignatureType, &gEfiCertX509Sha256Guid))
+ ValidCertType = CertX509Sha256;
+ else
+ if(!guidcmp(&CertList->SignatureType, &gEfiCertX509Sha384Guid))
+ ValidCertType = CertX509Sha384;
+ else
+ if(!guidcmp(&CertList->SignatureType, &gEfiCertX509Sha512Guid))
+ ValidCertType = CertX509Sha512;
+
+ if (ValidCertType)
+ {
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
+ CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
+ RootCertSize = CertList->SignatureSize-sizeof(EFI_GUID); // sig data structure starts with SigOwner Guid
+TRACE((TRACE_ALWAYS,"Signature Type %g\nRootCertSize = %X\n",CertList->SignatureType, RootCertSize));
+
+ for (Index = 0; Index < CertCount; Index++) {
+ //
+ // Iterate each Signature Data Node within this CertList for verify.
+ //
+ RootCert = Cert->SignatureData;
+ switch(ValidCertType) {
+// is Sha256/Sha1
+ case CertSha256:
+ if(RootCertSize == mImageDigestSize &&
+ MemCmp(RootCert, mImageDigest, mImageDigestSize) == 0) {
+TRACE((TRACE_ALWAYS,"Hash Cert match found...\n"));
+ //
+ // Found the signature in database.
+ //
+ IsVerified = TRUE;
+ }
+ break;
+// x509, x509_ShaXXX
+/*
+Revocation is true:
+- return success && Time = 0
+- return success && Time != 0 && VerifyTimeStampStatus
+- success
+if success but mVerifyTimeStampStatus = ACCESS_DENIED = return FAIL
+timestamp non-0 Year > 0
+*/
+ case CertX509Sha256:
+ case CertX509Sha384:
+ case CertX509Sha512:
+ switch(ValidCertType) {
+ case CertX509Sha256:
+ TimeStamp = &((EFI_CERT_X509_SHA256*)RootCert)->TimeOfRevocation;
+ break;
+ case CertX509Sha384:
+ TimeStamp = &((EFI_CERT_X509_SHA384*)RootCert)->TimeOfRevocation;
+ break;
+ case CertX509Sha512:
+ TimeStamp = &((EFI_CERT_X509_SHA512*)RootCert)->TimeOfRevocation;
+ break;
+ }
+ // Check the timestamp cert validity the valid certificate in allowed database (dbt).
+ if(!bProcessVerifyTimeStampStatus) {
+ bVerifyTimeStampStatus = IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE2, Pkcs7TimeStampCertValidateGet);
+ bProcessVerifyTimeStampStatus = TRUE;
+ }
+ if(os_mktime(TimeStamp->Year, TimeStamp->Month, TimeStamp->Day, TimeStamp->Hour, TimeStamp->Minute, TimeStamp->Second,&TimeOfRevocationLong))
+ TimeOfRevocationLong = 0;
+TRACE((TRACE_ALWAYS,"\nTimeStamp cert validate %s\nTimeOfSigning %X\nTimeOfRevocation %X\n", (!bVerifyTimeStampStatus?"FAIL":"PASS"), mTimeOfSigningLong, TimeOfRevocationLong));
+ if(TimeOfRevocationLong) {
+ if(!bVerifyTimeStampStatus) {
+ IsVerified = TRUE; // found in dbx -> image is revoked!
+ break;
+ }
+ // keep looking for cert with sign time passed revocation
+ if(mTimeOfSigningLong < TimeOfRevocationLong)
+ break;
+ }
+ case CertX509:
+TRACE((TRACE_ALWAYS,"proceed with Pkcs7Verify...\n"));
+ //
+ //
+ // Verify Authenticode struct for image's current certificate.
+ //
+ // using protocol
+ SigCert = mImageDigest;
+ SigCertSize = mImageDigestSize;
+ Status = mDigitalSigProtocol->Pkcs7Verify (
+ mDigitalSigProtocol,
+ AuthData,
+ AuthDataSize,
+ RootCert,
+ RootCertSize,
+ // mDigest, DigestLen
+ &SigCert,
+ &SigCertSize,
+ Operation, // Operation; Pkcs7CertValidate OR Pkcs7CertGetMatchInCertChain
+ KEEP // Flags
+ );
+TRACE((TRACE_ALWAYS,"====> %r\n", Status));
+ if (!EFI_ERROR(Status)) {
+ IsVerified = TRUE; // found matching certificate in the image
+ switch(Operation) {
+ case Pkcs7TimeStampCertValidateGet:
+ mTimeOfSigningLong = (INT32)SigCertSize;
+ break;
+ case Pkcs7CertValidate:
+ // only x509 certs frm db are measured in PCR[7]
+ mTrustSigDbOffs = (UINT32)(UINT8*)(((UINT8*)Cert-Data));
+ mTrustSigDbSize = CertList->SignatureSize;
+ break;
+ }
+ }
+ break;
+ default :
+ goto Exit;
+ } // switch
+ if (IsVerified)
+ {
+ goto Exit;
+ }
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
+ } // end for
+ } // end If
+
+ DataSize -= CertList->SignatureListSize;
+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+ } // end while
+Exit:
+ pBS->FreePool (Data);
+TRACE((TRACE_ALWAYS,"\n<===%s cert match in '%S'\n",(IsVerified?"Got":"No"), VariableName));
+ return IsVerified;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DxeImageVerificationHandler
+//
+// Description: Handle for Security Architectural Protocol
+// Provide verification service for signed images, which include both signature validation
+// and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and
+// MSFT Authenticode type signatures are supported.
+//
+// In this implementation, only verify external executables when in USER MODE.
+// Executables from FV is bypass, so pass in AuthenticationStatus is ignored.
+//
+// The image verification policy is:
+// If the image is signed,
+// At least one valid signature or at least one hash value of the image must match a record
+// in the security database "db", and no valid signature nor any hash value of the image may
+// be reflected in the security database "dbx".
+// Otherwise, the image is not signed,
+// The SHA256 hash value of the image must match a record in the security database "db", and
+// not be reflected in the security data base "dbx".
+//
+// Caution: This function may receive untrusted input.
+// PE/COFF image is external input, so this function will validate its data structure
+// within this image buffer before use.
+//
+// Input:
+// File This is a pointer to the device path of the file that is
+// being dispatched. This will optionally be used for logging.
+// FileBuffer File buffer matches the input file device path.
+// FileSize Size of File buffer matches the input file device path.
+//
+// Output: EFI_STATUS
+//
+// EFI_SUCCESS The file specified by File did authenticate, and the
+// platform policy dictates that the DXE Core may use File.
+// EFI_INVALID_PARAMETER File is NULL.
+// EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
+// the platform policy dictates that File should be placed
+// in the untrusted state. A file may be promoted from
+// the untrusted to the trusted state at a future time
+// with a call to the Trust() DXE Service.
+// EFI_ACCESS_DENIED The file specified by File did not authenticate, and
+// the platform policy dictates that File should not be
+// used for any purpose.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+DxeImageVerificationHandler (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File,
+ IN VOID *FileBuffer,
+ IN UINTN FileSize,
+ IN BOOLEAN BootPolicy
+ )
+
+{
+ EFI_STATUS Status;
+ UINT16 Magic;
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ EFI_STATUS VerifyStatus;
+ EFI_SIGNATURE_LIST *SignatureList;
+ UINTN SignatureListSize;
+ EFI_SIGNATURE_DATA *Signature;
+ EFI_IMAGE_EXECUTION_ACTION Action;
+ WIN_CERTIFICATE *WinCertificate;
+ UINT32 Policy;
+ BOOLEAN bFileRead;
+
+ EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ UINT32 NumberOfRvaAndSizes;
+
+ WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
+ WIN_CERTIFICATE_UEFI_GUID *WinCertUefiGuid;
+ UINT8 *AuthData;
+ UINTN AuthDataSize;
+ EFI_IMAGE_DATA_DIRECTORY *SecDataDir;
+ UINT32 OffSet;
+
+
+ SignatureList = NULL;
+ SignatureListSize = 0;
+ WinCertificate = NULL;
+ SecDataDir = NULL;
+ PkcsCertData = NULL;
+ Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
+ VerifyStatus = EFI_ACCESS_DENIED;
+ Status = EFI_ACCESS_DENIED;
+ bFileRead = FALSE;
+
+ mImageDigestSize = 0;
+ mCertType = NULL;
+ //
+ // Check the image type and get policy setting.
+ //
+ switch (GetImageType (File)) {
+
+ case IMAGE_FROM_FV:
+ Policy = ALWAYS_EXECUTE;
+ break;
+
+ case IMAGE_FROM_OPTION_ROM:
+ Policy = mSecureBootSetup.Load_from_OROM;
+ break;
+
+ case IMAGE_FROM_REMOVABLE_MEDIA:
+ Policy = mSecureBootSetup.Load_from_REMOVABLE_MEDIA;
+ break;
+
+ case IMAGE_FROM_FIXED_MEDIA:
+ Policy = mSecureBootSetup.Load_from_FIXED_MEDIA;
+ break;
+
+ default:
+TRACE((TRACE_ALWAYS,"Unknown Image Path\n"));
+ Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION;
+ break;
+ }
+
+ //
+ // If policy is always/never execute, return directly.
+ //
+ if (Policy == ALWAYS_EXECUTE) {
+ return EFI_SUCCESS;
+ } else
+ if (Policy == NEVER_EXECUTE) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (FileBuffer == NULL) {
+ //
+ // Read the PE/COFF file.
+ //
+ TRACE((TRACE_ALWAYS,"FileAuthentication\nFileType = %x, SubType = %x\n", File->Type, File->SubType));
+ Status = ReadImage(FALSE, File, &FileBuffer, &FileSize, NULL, NULL, NULL);
+ TRACE((TRACE_ALWAYS,"File read(1)...%r\n", Status));
+ if(EFI_ERROR(Status)) {
+ Status = ReadImage(TRUE, File, &FileBuffer, &FileSize, NULL, NULL, NULL);
+ TRACE((TRACE_ALWAYS,"File read(2)...%r\n", Status));
+ if(EFI_ERROR(Status))
+ return EFI_ACCESS_DENIED;
+ }
+
+ bFileRead = TRUE;
+ }
+ //
+ // Read the Dos header.
+ //
+ ASSERT (FileBuffer != NULL);
+ if (FileBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ mImageBase = (UINT8 *) FileBuffer;
+ mImageSize = FileSize;
+
+ ZeroMem (&ImageContext, sizeof (ImageContext));
+ ImageContext.Handle = (VOID *) FileBuffer;
+ ImageContext.ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) DxeImageVerificationLibImageRead;
+
+ //
+ // Get information about the image being loaded
+ //
+ if (EFI_ERROR (PeCoffLoaderGetImageInfo (NULL, &ImageContext)) ||
+ ( mImageSize< sizeof(EFI_IMAGE_DOS_HEADER)) ) {
+ //
+ // The information can't be gotten from the invalid PeImage
+ //
+ TRACE((TRACE_ALWAYS,"PeCoffLoaderGetImageInfo Error\n"));
+ goto Done;
+ }
+
+ DosHdr = (EFI_IMAGE_DOS_HEADER *) mImageBase;
+ if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+ //
+ // DOS image header is present,
+ // so read the PE header after the DOS image header.
+ //
+ mPeCoffHeaderOffset = DosHdr->e_lfanew;
+ } else {
+ mPeCoffHeaderOffset = 0;
+ }
+ // Security review EIP[104046]: 3.HashPeImage does not validate minimum image size
+ // Validate mPeCoffHeaderOffset is within the Image size range
+ if(((UINT64)mPeCoffHeaderOffset+sizeof(EFI_IMAGE_NT_HEADERS32)) > mImageSize) {
+ TRACE((TRACE_ALWAYS,"EFI_IMAGE_NT_SIGNATURE Error\n"));
+ goto Done;
+ }
+
+ //
+ // Check PE/COFF image.
+ //
+ mNtHeader.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) (mImageBase + mPeCoffHeaderOffset);
+ if (mNtHeader.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
+ //
+ // It is not a valid Pe/Coff file.
+ //
+ TRACE((TRACE_ALWAYS,"EFI_IMAGE_NT_SIGNATURE Error\n"));
+ goto Done;
+ }
+
+ if (mNtHeader.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
+ // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
+ // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
+ // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
+ //
+ Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+ } else {
+ //
+ // Get the magic value from the PE/COFF Optional Header
+ //
+ Magic = mNtHeader.Pe32->OptionalHeader.Magic;
+ }
+
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use PE32 offset.
+ //
+ NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;
+ if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
+ SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
+ }
+ } else {
+ //
+ // Use PE32+ offset.
+ //
+ NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
+ if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
+ SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
+ }
+ }
+
+ TRACE((TRACE_ALWAYS,"mImageSize %x\n", mImageSize));
+
+ //
+ // Start Image Validation.
+ //
+ if (SecDataDir && SecDataDir->Size) {
+ //
+ // Image is possibly signed
+ //
+ TRACE((TRACE_ALWAYS,"SecDataDir->VirtualAddress %x\nSecDataDir->Size = %x\nIMAGE is Signed\n",
+ SecDataDir->VirtualAddress, SecDataDir->Size));
+ // Security review EIP[104046]: 2.Multiple integer underflows calculating size of certificate data in PE file
+ if(((UINT64)SecDataDir->VirtualAddress+SecDataDir->Size) > mImageSize)
+ goto Done;
+
+ //
+ // Verify the signature of the image, multiple signatures are allowed as per PE/COFF Section 4.7
+ // "Attribute Certificate Table".
+ // The first certificate starts at offset (SecDataDir->VirtualAddress) from the start of the file.
+ //
+ Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;
+ for (OffSet = SecDataDir->VirtualAddress;
+ OffSet < (SecDataDir->VirtualAddress + SecDataDir->Size);
+// OffSet += WinCertificate->dwLength, OffSet += ALIGN_SIZE (OffSet)) {
+ OffSet +=(WinCertificate->dwLength + ALIGN_SIZE (WinCertificate->dwLength))) {
+
+ WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);
+ TRACE((TRACE_ALWAYS,"\nOffSet = %x, WinCertificate->dwLength %x\n\n", OffSet, WinCertificate->dwLength));
+ if ((SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <= sizeof (WIN_CERTIFICATE) ||
+ (SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) < WinCertificate->dwLength) {
+ break;
+ }
+ //
+ // Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported.
+ //
+ //
+ // Verify signature of executables.
+ //
+
+ if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
+ //
+ // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the
+ // Authenticode specification.
+ //
+ PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) WinCertificate;
+ if (PkcsCertData->Hdr.dwLength <= sizeof (PkcsCertData->Hdr)) {
+ break;
+ }
+ AuthData = PkcsCertData->CertData;
+ AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr);
+
+ } else if (WinCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
+ //
+ // The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is described in UEFI Spec.
+ //
+ WinCertUefiGuid = (WIN_CERTIFICATE_UEFI_GUID *) WinCertificate;
+ if (WinCertUefiGuid->Hdr.dwLength <= OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)) {
+ break;
+ }
+ if (guidcmp (&WinCertUefiGuid->CertType, &gEfiCertTypePkcs7Guid)) {
+ continue;
+ }
+ AuthData = WinCertUefiGuid->CertData;
+ AuthDataSize = WinCertUefiGuid->Hdr.dwLength - OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);
+
+ } else {
+ if (WinCertificate->dwLength < sizeof (WIN_CERTIFICATE)) {
+ break;
+ }
+ continue;
+ }
+ //
+ // Verify Pkcs signed data type.
+ //
+ // At least 1 Cert from Pe Image should be in DB
+ // None of Certs should be found in DBX
+ //
+ // get Digest Algorithm, set mCertType
+ // lock mutex, preserve Pkcs7 context
+ Status = HashPeImageByType (AuthData, AuthDataSize);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Check the digital signature against the revoked certificate in forbidden database (dbx).
+ //
+ if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE1, Pkcs7CertGetMatchInCertChain)) {
+
+ Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;
+ VerifyStatus = EFI_ACCESS_DENIED;
+ break;
+ }
+ //
+ // Check the digital signature against the valid certificate in allowed database (db).
+ //
+ if (EFI_ERROR (VerifyStatus)) {
+ if(IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE, Pkcs7CertValidate)) {
+
+ VerifyStatus = EFI_SUCCESS;
+ }
+ }
+ // clear context
+ Status = mDigitalSigProtocol->Pkcs7Verify (
+ mDigitalSigProtocol,
+ AuthData, AuthDataSize,
+ NULL, 0,
+ NULL, NULL,
+ Pkcs7Arg0, // Dummy op
+ RESET // Flags
+ );
+
+ } // end multi-sig for
+
+// if (OffSet != (SecDataDir->VirtualAddress + SecDataDir->Size + ALIGN_SIZE(SecDataDir->Size))) {
+ if(Action != EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND) {
+ if (OffSet != (SecDataDir->VirtualAddress + SecDataDir->Size)) {
+ TRACE((TRACE_ALWAYS,"Offset outside of CertDir boundary %X != %x\n", OffSet, SecDataDir->VirtualAddress + SecDataDir->Size));
+ //
+ // The Size in Certificate Table or the attribute certificate table is corrupted.
+ //
+ VerifyStatus = EFI_ACCESS_DENIED;
+ } else
+ Action = EFI_IMAGE_EXECUTION_AUTH_SIG_NOT_FOUND;
+ }
+
+ } // end Signed cert branch
+
+ // Image not Signed or
+ // Image is Signed, its Cert verified in db but not found in DBX
+ if(mCertType != &gEfiCertSha256Guid &&
+ Action != EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND) {
+
+ //
+ // This image is not signed or signed but found only in db or failed previous checks.
+ // Expected:
+ // The SHA256 hash value of the image must match a record in the security database "db",
+ // and not be reflected in the security data base "dbx".
+ //
+ TRACE((TRACE_ALWAYS,"IMAGE not Signed\n\tor signed with non-Sha256, Try Sha256 Hash Cert...\n"));
+
+ if(!HashPeImage (HASHALG_SHA256)) // init Hash type and calculate PE hash if not done already
+ goto Done;
+
+ if(IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, &gEfiCertSha256Guid, mImageDigest, mImageDigestSize)) {
+ //
+ // Image Hash in forbidden database (DBX)
+ //
+ VerifyStatus = EFI_ACCESS_DENIED;
+ Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;
+ } else
+ // no - try in allowed db if not there already
+ if(EFI_ERROR (VerifyStatus) &&
+ IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, &gEfiCertSha256Guid, mImageDigest, mImageDigestSize)) {
+ //
+ // Image Hash is in allowed database (DB).
+ //
+ VerifyStatus = EFI_SUCCESS;
+ }
+ }
+ //
+ // Signature database check after verification.
+ //
+ if(!EFI_ERROR (VerifyStatus) ) {
+ //
+ // Executable signature is found in authorized signature database.
+ //
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_ACCESS_DENIED;
+
+ if(Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND) {
+ //
+ // Executable signature is found in forbidden signature database.
+ //
+ TRACE((TRACE_ALWAYS,"Certificate IS FOUND in Forbidden database!\n"));
+ } else
+ //
+ // Verification failure.
+ //
+ if(Action == EFI_IMAGE_EXECUTION_AUTH_SIG_NOT_FOUND) {
+ //
+ // Executable signature cannot be found in authorized signature database.
+ // Use platform policy to determine the action.
+ //
+ TRACE((TRACE_ALWAYS,"Certificate NOT FOUND in authorized database!\n"));
+ }
+ else
+ TRACE((TRACE_ALWAYS,"Image Certificate is Invalid!\n"));
+
+ TRACE((TRACE_ALWAYS,"%r Record added to Image Execution Table\n", Status));
+
+ if(!mCertType || !mImageDigestSize ) {
+ goto Done;
+ }
+ SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize;
+
+ // Security review EIP[104046]:7. Unchecked AllocatePool may result in NULL pointer dereference
+ if (!EFI_ERROR(pBS->AllocatePool(EfiBootServicesData, SignatureListSize, &SignatureList)))
+ {
+ MemSet(SignatureList, SignatureListSize, 0);
+ SignatureList->SignatureHeaderSize = 0;
+ SignatureList->SignatureListSize = (UINT32) SignatureListSize;
+ SignatureList->SignatureSize = (UINT32) mImageDigestSize;
+ CopyMem (&SignatureList->SignatureType, mCertType, sizeof (EFI_GUID));
+ Signature = (EFI_SIGNATURE_DATA *) ((UINT8 *) SignatureList + sizeof (EFI_SIGNATURE_LIST));
+ CopyMem (Signature->SignatureData, mImageDigest, mImageDigestSize);
+ }
+ if (SignatureList != NULL) {
+ pBS->FreePool (SignatureList);
+ }
+ }
+Done:
+ if (Status != EFI_SUCCESS) {
+ //
+ // Policy decides to defer or reject the image; add its information in image executable information table.
+ //
+ AddImageExeInfo (Action, NULL, File, SignatureList, SignatureListSize);
+ // Treat unsecured images according to Image Authorization policy
+ Status = ImageAuthorization (Policy, Action);
+ }
+ if(bFileRead)
+ pBS->FreePool (FileBuffer);
+
+TRACE((TRACE_ALWAYS,"Image Verification ...%r\n", Status));
+ return Status;
+}
+
+//===================== Security Architectural Protocol ======================
+#ifndef EFI_SECURITY2_ARCH_PROTOCOL_GUID
+#define EFI_SECURITY2_ARCH_PROTOCOL_GUID \
+ { 0x94ab2f58, 0x1438, 0x4ef1, 0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0xe, 0x68 }
+
+typedef struct _EFI_SECURITY2_ARCH_PROTOCOL EFI_SECURITY2_ARCH_PROTOCOL;
+
+typedef EFI_STATUS (EFIAPI *EFI_SECURITY2_FILE_AUTHENTICATION) (
+ IN CONST EFI_SECURITY2_ARCH_PROTOCOL *This,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File,
+ IN VOID *FileBuffer,
+ IN UINTN FileSize,
+ IN BOOLEAN BootPolicy
+);
+
+struct _EFI_SECURITY2_ARCH_PROTOCOL {
+ EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication;
+};
+
+static EFI_GUID gEfiSecurity2ArchProtocolGuid = EFI_SECURITY2_ARCH_PROTOCOL_GUID;
+#endif
+
+EFI_STATUS SecureFileAuthentication2(
+ IN CONST EFI_SECURITY2_ARCH_PROTOCOL *This,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File,
+ IN VOID *FileBuffer,
+ IN UINTN FileSize,
+ IN BOOLEAN BootPolicy
+ )
+{
+ EFI_STATUS Status;
+
+ TRACE((TRACE_ALWAYS,"...............Call Security2 Arch proto.. File=%x, FileBuffer=%x, FileSize=%d\n",File,FileBuffer,FileSize ));
+
+ //
+ // skip verification if platform is NOT in SECURE BOOT MODE
+ //
+ if(mSecureBootEnable == 0)
+ return EFI_SUCCESS;
+
+ //
+ // Protocol should have been installed by AmiDigitalSig Driver once it's dispatched
+ //
+ if( mDigitalSigProtocol == NULL )
+ return EFI_ACCESS_DENIED;
+
+ Status = DxeImageVerificationHandler(File, FileBuffer, FileSize, BootPolicy);
+ // Install Tbl only on the Boot Loader launch
+ if (!EFI_ERROR (Status)/* && BootPolicy*/) {
+ AddBootImageCertInfo(NULL, mTrustSigDbOffs, mTrustSigDbSize);
+ mTrustSigDbOffs = 0;
+ mTrustSigDbSize = 0;
+ }
+ TRACE((TRACE_ALWAYS,"...............return status %r\n",Status));
+ return Status;
+}
+
+EFI_STATUS SecureFileAuthentication(
+ IN EFI_SECURITY_ARCH_PROTOCOL *This,
+ IN UINT32 AuthenticationStatus,
+ IN EFI_DEVICE_PATH_PROTOCOL *File
+ )
+{
+ BOOLEAN BootPolicy;
+ VOID *FileBuffer;
+ UINTN FileSize;
+
+ BootPolicy = TRUE;
+ FileBuffer = NULL;
+ FileSize = 0;
+
+ TRACE((TRACE_ALWAYS,".........Call Security Arch proto.. File=%x\n",File));
+
+ if (File == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ //Security Protocol w/a: BootPolicy == 1 if File->Type == 4 Media Dev Path
+// if(File->Type == 4) // Media Dev Path
+// BootPolicy=TRUE;
+
+ return SecureFileAuthentication2(NULL, File, FileBuffer, FileSize, BootPolicy);
+}
+
+EFI_SECURITY2_ARCH_PROTOCOL mSecurity2 = {SecureFileAuthentication2};
+EFI_SECURITY_ARCH_PROTOCOL mSecurity = {SecureFileAuthentication};
+
+//----------------------------------------------------------------------------
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InitDigitalProtocolCallback
+//
+// Description: This function initialize mDigitalSigProtocol ptr
+//
+//
+// Input: IN EFI_EVENT Event - Event that was triggered
+// IN VOID *Context - data pointer to information that is defined
+// when the event is registered
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS InitDigitalProtocolCallback(IN EFI_EVENT Event, IN VOID *Context)
+{
+ EFI_STATUS Status;
+ UINTN DataSize;
+ UINT8 *pSecureBootEnable=NULL;
+ //
+ // Look up for image authorization policy in "SetupData" variable
+ //
+#if (defined(ENABLE_IMAGE_EXEC_POLICY_OVERRIDE) && ENABLE_IMAGE_EXEC_POLICY_OVERRIDE == 1)
+ DataSize = sizeof(mSecureBootSetup);
+ Status = pRS->GetVariable (AMI_SECURE_BOOT_SETUP_VAR,&gSecureSetupGuid,NULL,&DataSize,&mSecureBootSetup);
+ if(EFI_ERROR(Status) ||
+ // Standard boot mode policy->apply defaults
+ mSecureBootSetup.SecureBootMode == STANDARD_SECURE_BOOT ||
+ // Policy check against fixed settings
+ mSecureBootSetup.Load_from_OROM < LOAD_FROM_OROM ||
+ mSecureBootSetup.Load_from_REMOVABLE_MEDIA < LOAD_FROM_REMOVABLE_MEDIA ||
+ mSecureBootSetup.Load_from_FIXED_MEDIA < LOAD_FROM_FIXED_MEDIA
+ )
+#endif
+ {
+ mSecureBootSetup.Load_from_OROM = LOAD_FROM_OROM;
+ mSecureBootSetup.Load_from_REMOVABLE_MEDIA = LOAD_FROM_REMOVABLE_MEDIA;
+ mSecureBootSetup.Load_from_FIXED_MEDIA = LOAD_FROM_FIXED_MEDIA;
+ }
+ //
+ // SecureBoot variable to be installed along with NVRAM driver
+ //
+ pSecureBootEnable = GetEfiGlobalVariableEx (EFI_SECURE_BOOT_NAME, &DataSize);
+ if(pSecureBootEnable && DataSize==1)
+ mSecureBootEnable = *pSecureBootEnable;
+ //
+ // will skip verification if platform is NOT in SECURE BOOT MODE
+ //
+ if(mSecureBootEnable == 0)
+ return EFI_SUCCESS;
+
+ Status = pBS->LocateHandleBuffer (
+ ByProtocol,
+ #if (PI_SPECIFICATION_VERSION < 0x00010000)
+ &gEfiFirmwareVolumeProtocolGuid,
+ #else
+ &gEfiFirmwareVolume2ProtocolGuid,
+ #endif
+ NULL,
+ &mFvHandlesCount,
+ &mFvHandles
+ );
+ if(!EFI_ERROR(Status)){
+ gImageLoadingAfterBDS = TRUE;
+ }
+
+ return pBS->LocateProtocol( &gAmiDigitalSignatureProtocolGuid, NULL, &mDigitalSigProtocol );
+}
+
+extern BOOLEAN const InstallDummySecurityProtocol;
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InstallSecurityArchProtocol
+//
+// Description: This function installs the EFI_SECURITY_ARCH_PROTOCOL.
+// It is called at DxeCoreInitialize.
+//
+// Input:
+// EFI_HANDLE ImageHandle Image handle.
+// EFI_SYSTEM_TABLE *SystemTable Pointer to the EFI system table.
+//
+// Output:
+// EFI_SUCCESS : Security Architecture protocols are successfully installed.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID InstallSecurityArchProtocol(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_HANDLE Handle = NULL;
+ EFI_EVENT Event;
+ VOID *p;
+
+ if (InstallDummySecurityProtocol)
+ return;
+
+ // Enable Security verification at beginning of BDS connect controller phase,
+ // We assume all drivers before the event were launched from internal FV
+ // !!! This bds event is only available since core 4.6.3.5.
+ RegisterProtocolCallback(
+ &BdsConnectDriversProtocolGuid,
+ InitDigitalProtocolCallback,
+ NULL,
+ &Event,
+ &p
+ );
+ // Security2 Arch protocol must be installed before Security Arch protocol
+ pBS->InstallMultipleProtocolInterfaces(
+ &Handle,
+ &gEfiSecurity2ArchProtocolGuid, &mSecurity2,
+ &gEfiSecurityArchProtocolGuid, &mSecurity,
+ NULL
+ );
+}
+
+#pragma warning (default : 4090)
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/SecurityPkg/ImageVerificationLib/DxeImageVerificationLib.h b/Core/EM/SecurityPkg/ImageVerificationLib/DxeImageVerificationLib.h
new file mode 100644
index 0000000..1a3ddd5
--- /dev/null
+++ b/Core/EM/SecurityPkg/ImageVerificationLib/DxeImageVerificationLib.h
@@ -0,0 +1,175 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SecureBoot_WIN8/ImageVerification_efi/DxeImageVerificationLib.h 3 3/15/13 4:59p Alexp $
+//
+// $Revision: 3 $
+//
+// $Date: 3/15/13 4:59p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureBoot_WIN8/ImageVerification_efi/DxeImageVerificationLib.h $
+//
+// 3 3/15/13 4:59p Alexp
+// EIP:118243 add support for multi-signed PE Images
+//
+// 2 4/20/12 5:14p Alexp
+// Add new function to install the handle on Efi System Table with the
+// location
+// within DB variable of the Trusted Certificate that was used to verify
+// signature of Efi OS BootLoader image.
+//
+// 1 6/13/11 5:25p Alexp
+//
+// 2 5/10/11 5:05p Alexp
+// add header & footer
+//
+//
+//
+//**********************************************************************
+//
+// This file contains an 'Intel Peripheral Driver' and is
+// licensed for Intel CPUs and chipsets under the terms of your
+// license agreement with Intel or your vendor. This file may
+// be modified by the user, subject to additional terms of the
+// license agreement
+//
+/** @file
+
+ The internal header file includes the common header files, defines
+ internal structure and functions used by ImageVerificationLib.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved. <BR>
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+**/
+
+#ifndef __IMAGEVERIFICATIONLIB_H__
+#define __IMAGEVERIFICATIONLIB_H__
+
+
+#include <Protocol/FirmwareVolume.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/SimpleFileSystem.h>
+
+#include "WinCertificate.h"
+#include <ImageAuthentication.h>
+#include <Protocol/Hash.h>
+
+#define EFI_CERT_TYPE_RSA2048_SHA256_SIZE 256
+#define EFI_CERT_TYPE_RSA2048_SIZE 256
+#define EFI_CERT_TYPE_SHA256_SIZE 32
+#define MAX_NOTIFY_STRING_LEN 64
+
+//
+// Image type definitions
+//
+#define IMAGE_UNKNOWN 0x00000000
+#define IMAGE_FROM_FV 0x00000001
+#define IMAGE_FROM_OPTION_ROM 0x00000002
+#define IMAGE_FROM_REMOVABLE_MEDIA 0x00000003
+#define IMAGE_FROM_FIXED_MEDIA 0x00000004
+
+//
+// Authorization policy bit definition
+//
+#define ALWAYS_EXECUTE 0x00000000
+#define NEVER_EXECUTE 0x00000001
+#define ALLOW_EXECUTE_ON_SECURITY_VIOLATION 0x00000002
+#define DEFER_EXECUTE_ON_SECURITY_VIOLATION 0x00000003
+#define DENY_EXECUTE_ON_SECURITY_VIOLATION 0x00000004
+#define QUERY_USER_ON_SECURITY_VIOLATION 0x00000005
+
+//
+// Support hash types
+//
+#define HASHALG_SHA1 0x00000001
+#define HASHALG_SHA256 0x00000002
+
+#define MAX_ELEM_NUM 28 // TBD. ~20 max number of PE hdr elements to be hashed in one pass
+///
+/// SHA-1 digest size in bytes.
+///
+#define SHA1_DIGEST_SIZE 20
+///
+/// SHA-256 digest size in bytes
+///
+#define SHA256_DIGEST_SIZE 32
+
+//
+// Set max digest size as SHA256 Output (32 bytes) by far
+//
+#define MAX_DIGEST_SIZE SHA256_DIGEST_SIZE
+
+#define ALIGNMENT_SIZE 8
+#define ALIGN_SIZE(a) (((a) % ALIGNMENT_SIZE) ? ALIGNMENT_SIZE - ((a) % ALIGNMENT_SIZE) : 0)
+
+#ifndef OFFSET_OF
+#define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field))
+#endif
+
+//defined for every CPU architecture
+// Maximum legal IA-32 address
+#ifndef EFI_MAX_ADDRESS
+#define EFI_MAX_ADDRESS 0xFFFFFFFF
+#endif
+
+//
+//
+// PKCS7 Certificate definition
+//
+typedef struct _WIN_CERTIFICATE_EFI_PKCS {
+ WIN_CERTIFICATE Hdr;
+ UINT8 CertData[1];
+} WIN_CERTIFICATE_EFI_PKCS;
+
+//
+// Definitions for Efi System table entry to store the location within DB variable
+// of the Trusted Certificate that was used to verify Efi OS BootLoader image
+//
+//6683D10C-CF6E-4914-B5B4-AB8ED7370ED7
+#define AMI_VALID_BOOT_IMAGE_CERT_TBL_GUID \
+ { 0x6683D10C, 0xCF6E, 0x4914, 0xB5, 0xB4, 0xAB, 0x8E, 0xD7, 0x37, 0x0E, 0xD7 }
+//
+//
+// Data Table definition
+//
+typedef struct _AMI_VALID_CERT_IN_SIG_DB {
+ UINT32 SigOffset;
+ UINT32 SigLength;
+} AMI_VALID_CERT_IN_SIG_DB;
+
+#endif
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/SecurityPkg/ImageVerificationLib/EfiImage.h b/Core/EM/SecurityPkg/ImageVerificationLib/EfiImage.h
new file mode 100644
index 0000000..f50b0e5
--- /dev/null
+++ b/Core/EM/SecurityPkg/ImageVerificationLib/EfiImage.h
@@ -0,0 +1,702 @@
+/*++
+
+Copyright (c) 2004 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EfiImage.h
+
+Abstract:
+
+ EFI image format for PE32+. Please note some data structures are different
+ for IA-32 and Itanium-based images, look for UINTN and the #ifdef EFI_IA64
+
+ BugBug: Fix text - doc as defined in MSFT EFI specification
+
+--*/
+
+#ifndef _EFI_IMAGE_H_
+#define _EFI_IMAGE_H_
+
+//
+// PE32+ Subsystem type for EFI images
+//
+#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION 10
+#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
+#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
+
+//
+// BugBug: Need to get a real answer for this problem. This is not in the
+// PE specification.
+//
+// A SAL runtime driver does not get fixed up when a transition to
+// virtual mode is made. In all other cases it should be treated
+// like a EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER image
+//
+#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13
+
+//
+// PE32+ Machine type for EFI images
+//
+#define EFI_IMAGE_MACHINE_IA32 0x014c
+#define EFI_IMAGE_MACHINE_IA64 0x0200
+#define EFI_IMAGE_MACHINE_X64 0x8664
+#define EFI_IMAGE_MACHINE_ARMTHUMB_MIXED 0x01c2
+
+//
+// #define EFI_IMAGE_MACHINE_FCODE 0xfc0d
+//
+#define EFI_IMAGE_MACHINE_EBC 0x0EBC
+
+#define EFI_IMAGE_DOS_SIGNATURE 0x5A4D // MZ
+#define EFI_IMAGE_OS2_SIGNATURE 0x454E // NE
+#define EFI_IMAGE_OS2_SIGNATURE_LE 0x454C // LE
+#define EFI_IMAGE_NT_SIGNATURE 0x00004550 // PE00
+#define EFI_IMAGE_EDOS_SIGNATURE 0x44454550 // PEED
+//
+// PE images can start with an optional DOS header, so if an image is run
+// under DOS it can print an error message.
+//
+typedef struct {
+ UINT16 e_magic; // Magic number
+ UINT16 e_cblp; // Bytes on last page of file
+ UINT16 e_cp; // Pages in file
+ UINT16 e_crlc; // Relocations
+ UINT16 e_cparhdr; // Size of header in paragraphs
+ UINT16 e_minalloc; // Minimum extra paragraphs needed
+ UINT16 e_maxalloc; // Maximum extra paragraphs needed
+ UINT16 e_ss; // Initial (relative) SS value
+ UINT16 e_sp; // Initial SP value
+ UINT16 e_csum; // Checksum
+ UINT16 e_ip; // Initial IP value
+ UINT16 e_cs; // Initial (relative) CS value
+ UINT16 e_lfarlc; // File address of relocation table
+ UINT16 e_ovno; // Overlay number
+ UINT16 e_res[4]; // Reserved words
+ UINT16 e_oemid; // OEM identifier (for e_oeminfo)
+ UINT16 e_oeminfo; // OEM information; e_oemid specific
+ UINT16 e_res2[10]; // Reserved words
+ UINT32 e_lfanew; // File address of new exe header
+} EFI_IMAGE_DOS_HEADER;
+
+//
+// File header format.
+//
+typedef struct {
+ UINT16 Machine;
+ UINT16 NumberOfSections;
+ UINT32 TimeDateStamp;
+ UINT32 PointerToSymbolTable;
+ UINT32 NumberOfSymbols;
+ UINT16 SizeOfOptionalHeader;
+ UINT16 Characteristics;
+} EFI_IMAGE_FILE_HEADER;
+
+#define EFI_IMAGE_SIZEOF_FILE_HEADER 20
+
+#define EFI_IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file.
+#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references).
+#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file.
+#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file.
+#define EFI_IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed.
+#define EFI_IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine.
+#define EFI_IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file
+#define EFI_IMAGE_FILE_SYSTEM 0x1000 // System File.
+#define EFI_IMAGE_FILE_DLL 0x2000 // File is a DLL.
+#define EFI_IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed.
+#define EFI_IMAGE_FILE_MACHINE_UNKNOWN 0
+#define EFI_IMAGE_FILE_MACHINE_I386 0x14c // Intel 386.
+#define EFI_IMAGE_FILE_MACHINE_R3000 0x162 // MIPS* little-endian, 0540 big-endian
+#define EFI_IMAGE_FILE_MACHINE_R4000 0x166 // MIPS* little-endian
+#define EFI_IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP*
+#define EFI_IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM* PowerPC Little-Endian
+#define EFI_IMAGE_FILE_MACHINE_TAHOE 0x7cc // Intel EM machine
+//
+// * Other names and brands may be claimed as the property of others.
+//
+//
+// Directory format.
+//
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 Size;
+} EFI_IMAGE_DATA_DIRECTORY;
+
+#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16
+
+typedef struct {
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ UINT32 BaseOfData;
+ UINT32 BaseOfBss;
+ UINT32 GprMask;
+ UINT32 CprMask[4];
+ UINT32 GpValue;
+} EFI_IMAGE_ROM_OPTIONAL_HEADER;
+
+#define EFI_IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107
+#define EFI_IMAGE_SIZEOF_ROM_OPTIONAL_HEADER sizeof (EFI_IMAGE_ROM_OPTIONAL_HEADER)
+
+typedef struct {
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_ROM_OPTIONAL_HEADER OptionalHeader;
+} EFI_IMAGE_ROM_HEADERS;
+
+//
+// ATTENTION!!! EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64
+// are for use ONLY by tools. All proper EFI code MUST use
+// EFI_IMAGE_OPTIONAL_HEADER ONLY!!!
+//
+#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
+
+typedef struct {
+ //
+ // Standard fields.
+ //
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ UINT32 BaseOfData;
+ //
+ // NT additional fields.
+ //
+ UINT32 ImageBase;
+ UINT32 SectionAlignment;
+ UINT32 FileAlignment;
+ UINT16 MajorOperatingSystemVersion;
+ UINT16 MinorOperatingSystemVersion;
+ UINT16 MajorImageVersion;
+ UINT16 MinorImageVersion;
+ UINT16 MajorSubsystemVersion;
+ UINT16 MinorSubsystemVersion;
+ UINT32 Win32VersionValue;
+ UINT32 SizeOfImage;
+ UINT32 SizeOfHeaders;
+ UINT32 CheckSum;
+ UINT16 Subsystem;
+ UINT16 DllCharacteristics;
+ UINT32 SizeOfStackReserve;
+ UINT32 SizeOfStackCommit;
+ UINT32 SizeOfHeapReserve;
+ UINT32 SizeOfHeapCommit;
+ UINT32 LoaderFlags;
+ UINT32 NumberOfRvaAndSizes;
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
+} EFI_IMAGE_OPTIONAL_HEADER32;
+
+//
+// ATTENTION!!! EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64
+// are for use ONLY by tools. All proper EFI code MUST use
+// EFI_IMAGE_OPTIONAL_HEADER ONLY!!!
+//
+#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
+
+typedef struct {
+ //
+ // Standard fields.
+ //
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ //
+ // NT additional fields.
+ //
+ UINT64 ImageBase;
+ UINT32 SectionAlignment;
+ UINT32 FileAlignment;
+ UINT16 MajorOperatingSystemVersion;
+ UINT16 MinorOperatingSystemVersion;
+ UINT16 MajorImageVersion;
+ UINT16 MinorImageVersion;
+ UINT16 MajorSubsystemVersion;
+ UINT16 MinorSubsystemVersion;
+ UINT32 Win32VersionValue;
+ UINT32 SizeOfImage;
+ UINT32 SizeOfHeaders;
+ UINT32 CheckSum;
+ UINT16 Subsystem;
+ UINT16 DllCharacteristics;
+ UINT64 SizeOfStackReserve;
+ UINT64 SizeOfStackCommit;
+ UINT64 SizeOfHeapReserve;
+ UINT64 SizeOfHeapCommit;
+ UINT32 LoaderFlags;
+ UINT32 NumberOfRvaAndSizes;
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
+} EFI_IMAGE_OPTIONAL_HEADER64;
+
+//
+// ATTENTION!!! EFI_IMAGE_NT_HEADERS32 and EFI_IMAGE_HEADERS64 are for use ONLY
+// by tools. All proper EFI code MUST use EFI_IMAGE_NT_HEADERS ONLY!!!
+//
+typedef struct {
+ UINT32 Signature;
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader;
+} EFI_IMAGE_NT_HEADERS32;
+
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32)
+
+typedef struct {
+ UINT32 Signature;
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader;
+} EFI_IMAGE_NT_HEADERS64;
+
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64)
+
+//
+// Include processor specific definition of EFI_IMAGE_OPTIONAL_HEADER so the
+// type name EFI_IMAGE_OPTIONAL_HEADER is appropriate to the build. Same for
+// EFI_IMAGE_NT_HEADERS. These definitions MUST be used by ALL EFI code.
+//
+#if !defined(EFI64) && !defined(EFIx64)
+//IA32
+#define EFI_IMAGE_MACHINE_TYPE (EFI_IMAGE_MACHINE_IA32)
+
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_IA32) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_X64)
+
+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
+typedef EFI_IMAGE_OPTIONAL_HEADER32 EFI_IMAGE_OPTIONAL_HEADER;
+typedef EFI_IMAGE_NT_HEADERS32 EFI_IMAGE_NT_HEADERS;
+#elif defined(EFI64)
+//IPF
+#define EFI_IMAGE_MACHINE_TYPE (EFI_IMAGE_MACHINE_IA64)
+
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_IA64) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE)
+
+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
+typedef EFI_IMAGE_OPTIONAL_HEADER64 EFI_IMAGE_OPTIONAL_HEADER;
+typedef EFI_IMAGE_NT_HEADERS64 EFI_IMAGE_NT_HEADERS;
+#elif defined(EFIx64)
+//x64
+#define EFI_IMAGE_MACHINE_TYPE (EFI_IMAGE_MACHINE_X64)
+
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_X64) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_IA32)
+
+//
+// Assume we can use IPF values
+//
+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
+typedef EFI_IMAGE_OPTIONAL_HEADER64 EFI_IMAGE_OPTIONAL_HEADER;
+typedef EFI_IMAGE_NT_HEADERS64 EFI_IMAGE_NT_HEADERS;
+#endif
+
+#define EFI_IMAGE_FIRST_SECTION(ntheader) \
+ ( \
+ (EFI_IMAGE_SECTION_HEADER *) \
+ ( \
+ (UINT32) ntheader + \
+ FIELD_OFFSET (EFI_IMAGE_NT_HEADERS, OptionalHeader) + \
+ ((EFI_IMAGE_NT_HEADERS *) (ntheader))->FileHeader.SizeOfOptionalHeader \
+ ) \
+ )
+
+//
+// Subsystem Values
+//
+#define EFI_IMAGE_SUBSYSTEM_UNKNOWN 0
+#define EFI_IMAGE_SUBSYSTEM_NATIVE 1
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3.
+#define EFI_IMAGE_SUBSYSTEM_OS2_CUI 5
+#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI 7
+
+//
+// Directory Entries
+//
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT 0
+#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT 1
+#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE 2
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
+#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY 4
+#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5
+#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG 6
+#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
+#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
+#define EFI_IMAGE_DIRECTORY_ENTRY_TLS 9
+#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
+
+//
+// Section header format.
+//
+#define EFI_IMAGE_SIZEOF_SHORT_NAME 8
+
+typedef struct {
+ UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME];
+ union {
+ UINT32 PhysicalAddress;
+ UINT32 VirtualSize;
+ } Misc;
+ UINT32 VirtualAddress;
+ UINT32 SizeOfRawData;
+ UINT32 PointerToRawData;
+ UINT32 PointerToRelocations;
+ UINT32 PointerToLinenumbers;
+ UINT16 NumberOfRelocations;
+ UINT16 NumberOfLinenumbers;
+ UINT32 Characteristics;
+} EFI_IMAGE_SECTION_HEADER;
+
+#define EFI_IMAGE_SIZEOF_SECTION_HEADER 40
+
+#define EFI_IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved.
+#define EFI_IMAGE_SCN_CNT_CODE 0x00000020
+#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
+#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
+
+#define EFI_IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved.
+#define EFI_IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information.
+#define EFI_IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image.
+#define EFI_IMAGE_SCN_LNK_COMDAT 0x00001000
+
+#define EFI_IMAGE_SCN_ALIGN_1BYTES 0x00100000
+#define EFI_IMAGE_SCN_ALIGN_2BYTES 0x00200000
+#define EFI_IMAGE_SCN_ALIGN_4BYTES 0x00300000
+#define EFI_IMAGE_SCN_ALIGN_8BYTES 0x00400000
+#define EFI_IMAGE_SCN_ALIGN_16BYTES 0x00500000
+#define EFI_IMAGE_SCN_ALIGN_32BYTES 0x00600000
+#define EFI_IMAGE_SCN_ALIGN_64BYTES 0x00700000
+
+#define EFI_IMAGE_SCN_MEM_DISCARDABLE 0x02000000
+#define EFI_IMAGE_SCN_MEM_NOT_CACHED 0x04000000
+#define EFI_IMAGE_SCN_MEM_NOT_PAGED 0x08000000
+#define EFI_IMAGE_SCN_MEM_SHARED 0x10000000
+#define EFI_IMAGE_SCN_MEM_EXECUTE 0x20000000
+#define EFI_IMAGE_SCN_MEM_READ 0x40000000
+#define EFI_IMAGE_SCN_MEM_WRITE 0x80000000
+
+//
+// Symbol format.
+//
+#define EFI_IMAGE_SIZEOF_SYMBOL 18
+
+//
+// Section values.
+//
+// Symbols have a section number of the section in which they are
+// defined. Otherwise, section numbers have the following meanings:
+//
+#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0 // Symbol is undefined or is common.
+#define EFI_IMAGE_SYM_ABSOLUTE (UINT16) -1 // Symbol is an absolute value.
+#define EFI_IMAGE_SYM_DEBUG (UINT16) -2 // Symbol is a special debug item.
+//
+// Type (fundamental) values.
+//
+#define EFI_IMAGE_SYM_TYPE_NULL 0 // no type.
+#define EFI_IMAGE_SYM_TYPE_VOID 1 //
+#define EFI_IMAGE_SYM_TYPE_CHAR 2 // type character.
+#define EFI_IMAGE_SYM_TYPE_SHORT 3 // type short integer.
+#define EFI_IMAGE_SYM_TYPE_INT 4
+#define EFI_IMAGE_SYM_TYPE_LONG 5
+#define EFI_IMAGE_SYM_TYPE_FLOAT 6
+#define EFI_IMAGE_SYM_TYPE_DOUBLE 7
+#define EFI_IMAGE_SYM_TYPE_STRUCT 8
+#define EFI_IMAGE_SYM_TYPE_UNION 9
+#define EFI_IMAGE_SYM_TYPE_ENUM 10 // enumeration.
+#define EFI_IMAGE_SYM_TYPE_MOE 11 // member of enumeration.
+#define EFI_IMAGE_SYM_TYPE_BYTE 12
+#define EFI_IMAGE_SYM_TYPE_WORD 13
+#define EFI_IMAGE_SYM_TYPE_UINT 14
+#define EFI_IMAGE_SYM_TYPE_DWORD 15
+
+//
+// Type (derived) values.
+//
+#define EFI_IMAGE_SYM_DTYPE_NULL 0 // no derived type.
+#define EFI_IMAGE_SYM_DTYPE_POINTER 1
+#define EFI_IMAGE_SYM_DTYPE_FUNCTION 2
+#define EFI_IMAGE_SYM_DTYPE_ARRAY 3
+
+//
+// Storage classes.
+//
+#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION (UINT8) -1
+#define EFI_IMAGE_SYM_CLASS_NULL 0
+#define EFI_IMAGE_SYM_CLASS_AUTOMATIC 1
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL 2
+#define EFI_IMAGE_SYM_CLASS_STATIC 3
+#define EFI_IMAGE_SYM_CLASS_REGISTER 4
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF 5
+#define EFI_IMAGE_SYM_CLASS_LABEL 6
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL 7
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8
+#define EFI_IMAGE_SYM_CLASS_ARGUMENT 9
+#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG 10
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION 11
+#define EFI_IMAGE_SYM_CLASS_UNION_TAG 12
+#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION 13
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC 14
+#define EFI_IMAGE_SYM_CLASS_ENUM_TAG 15
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16
+#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM 17
+#define EFI_IMAGE_SYM_CLASS_BIT_FIELD 18
+#define EFI_IMAGE_SYM_CLASS_BLOCK 100
+#define EFI_IMAGE_SYM_CLASS_FUNCTION 101
+#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT 102
+#define EFI_IMAGE_SYM_CLASS_FILE 103
+#define EFI_IMAGE_SYM_CLASS_SECTION 104
+#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL 105
+
+//
+// type packing constants
+//
+#define EFI_IMAGE_N_BTMASK 017
+#define EFI_IMAGE_N_TMASK 060
+#define EFI_IMAGE_N_TMASK1 0300
+#define EFI_IMAGE_N_TMASK2 0360
+#define EFI_IMAGE_N_BTSHFT 4
+#define EFI_IMAGE_N_TSHIFT 2
+
+//
+// Communal selection types.
+//
+#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES 1
+#define EFI_IMAGE_COMDAT_SELECT_ANY 2
+#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE 3
+#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH 4
+#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE 5
+
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3
+
+//
+// Relocation format.
+//
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 SymbolTableIndex;
+ UINT16 Type;
+} EFI_IMAGE_RELOCATION;
+
+#define EFI_IMAGE_SIZEOF_RELOCATION 10
+
+//
+// I386 relocation types.
+//
+#define EFI_IMAGE_REL_I386_ABSOLUTE 0 // Reference is absolute, no relocation is necessary
+#define EFI_IMAGE_REL_I386_DIR16 01 // Direct 16-bit reference to the symbols virtual address
+#define EFI_IMAGE_REL_I386_REL16 02 // PC-relative 16-bit reference to the symbols virtual address
+#define EFI_IMAGE_REL_I386_DIR32 06 // Direct 32-bit reference to the symbols virtual address
+#define EFI_IMAGE_REL_I386_DIR32NB 07 // Direct 32-bit reference to the symbols virtual address, base not included
+#define EFI_IMAGE_REL_I386_SEG12 011 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address
+#define EFI_IMAGE_REL_I386_SECTION 012
+#define EFI_IMAGE_REL_I386_SECREL 013
+#define EFI_IMAGE_REL_I386_REL32 024 // PC-relative 32-bit reference to the symbols virtual address
+//
+// Based relocation format.
+//
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 SizeOfBlock;
+} EFI_IMAGE_BASE_RELOCATION;
+
+#define EFI_IMAGE_SIZEOF_BASE_RELOCATION 8
+
+//
+// Based relocation types.
+//
+#define EFI_IMAGE_REL_BASED_ABSOLUTE 0
+#define EFI_IMAGE_REL_BASED_HIGH 1
+#define EFI_IMAGE_REL_BASED_LOW 2
+#define EFI_IMAGE_REL_BASED_HIGHLOW 3
+#define EFI_IMAGE_REL_BASED_HIGHADJ 4
+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5
+#define EFI_IMAGE_REL_BASED_IA64_IMM64 9
+#define EFI_IMAGE_REL_BASED_DIR64 10
+
+//
+// Line number format.
+//
+typedef struct {
+ union {
+ UINT32 SymbolTableIndex; // Symbol table index of function name if Linenumber is 0.
+ UINT32 VirtualAddress; // Virtual address of line number.
+ } Type;
+ UINT16 Linenumber; // Line number.
+} EFI_IMAGE_LINENUMBER;
+
+#define EFI_IMAGE_SIZEOF_LINENUMBER 6
+
+//
+// Archive format.
+//
+#define EFI_IMAGE_ARCHIVE_START_SIZE 8
+#define EFI_IMAGE_ARCHIVE_START "!<arch>\n"
+#define EFI_IMAGE_ARCHIVE_END "`\n"
+#define EFI_IMAGE_ARCHIVE_PAD "\n"
+#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER "/ "
+#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER "// "
+
+typedef struct {
+ UINT8 Name[16]; // File member name - `/' terminated.
+ UINT8 Date[12]; // File member date - decimal.
+ UINT8 UserID[6]; // File member user id - decimal.
+ UINT8 GroupID[6]; // File member group id - decimal.
+ UINT8 Mode[8]; // File member mode - octal.
+ UINT8 Size[10]; // File member size - decimal.
+ UINT8 EndHeader[2]; // String to end header.
+} EFI_IMAGE_ARCHIVE_MEMBER_HEADER;
+
+#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60
+
+//
+// DLL support.
+//
+//
+// Export Format
+//
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT32 Name;
+ UINT32 Base;
+ UINT32 NumberOfFunctions;
+ UINT32 NumberOfNames;
+ UINT32 AddressOfFunctions;
+ UINT32 AddressOfNames;
+ UINT32 AddressOfNameOrdinals;
+} EFI_IMAGE_EXPORT_DIRECTORY;
+
+//
+// Import Format
+//
+typedef struct {
+ UINT16 Hint;
+ UINT8 Name[1];
+} EFI_IMAGE_IMPORT_BY_NAME;
+
+typedef struct {
+ union {
+ UINT32 Function;
+ UINT32 Ordinal;
+ EFI_IMAGE_IMPORT_BY_NAME *AddressOfData;
+ } u1;
+} EFI_IMAGE_THUNK_DATA;
+
+#define EFI_IMAGE_ORDINAL_FLAG 0x80000000
+#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0)
+#define EFI_IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
+
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT32 ForwarderChain;
+ UINT32 Name;
+ EFI_IMAGE_THUNK_DATA *FirstThunk;
+} EFI_IMAGE_IMPORT_DESCRIPTOR;
+
+//
+// Debug Format
+//
+#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2
+
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT32 Type;
+ UINT32 SizeOfData;
+ UINT32 RVA;
+ UINT32 FileOffset;
+} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY;
+
+#define CODEVIEW_SIGNATURE_NB10 0x3031424E // "NB10"
+typedef struct {
+ UINT32 Signature; // "NB10"
+ UINT32 Unknown;
+ UINT32 Unknown2;
+ UINT32 Unknown3;
+ //
+ // Filename of .PDB goes here
+ //
+} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY;
+
+#define CODEVIEW_SIGNATURE_RSDS 0x53445352 // "RSDS"
+typedef struct {
+ UINT32 Signature; // "RSDS"
+ UINT32 Unknown;
+ UINT32 Unknown2;
+ UINT32 Unknown3;
+ UINT32 Unknown4;
+ UINT32 Unknown5;
+ //
+ // Filename of .PDB goes here
+ //
+} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY;
+
+//
+// Header format for TE images
+//
+typedef struct {
+ UINT16 Signature; // signature for TE format = "VZ"
+ UINT16 Machine; // from the original file header
+ UINT8 NumberOfSections; // from the original file header
+ UINT8 Subsystem; // from original optional header
+ UINT16 StrippedSize; // how many bytes we removed from the header
+ UINT32 AddressOfEntryPoint; // offset to entry point -- from original optional header
+ UINT32 BaseOfCode; // from original image -- required for ITP debug
+ UINT64 ImageBase; // from original file header
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]; // only base relocation and debug directory
+} EFI_TE_IMAGE_HEADER;
+
+#define EFI_TE_IMAGE_HEADER_SIGNATURE 0x5A56 // "VZ"
+//
+// Data directory indexes in our TE image header
+//
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1
+
+//
+// Union of PE32, PE32+, and TE headers
+//
+typedef union {
+ EFI_IMAGE_NT_HEADERS32 Pe32;
+ EFI_IMAGE_NT_HEADERS64 Pe32Plus;
+ EFI_TE_IMAGE_HEADER Te;
+} EFI_IMAGE_OPTIONAL_HEADER_UNION;
+
+typedef union {
+ EFI_IMAGE_NT_HEADERS32 *Pe32;
+ EFI_IMAGE_NT_HEADERS64 *Pe32Plus;
+ EFI_TE_IMAGE_HEADER *Te;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *Union;
+} EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION;
+
+#endif
diff --git a/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.cif b/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.cif
new file mode 100644
index 0000000..ff5909a
--- /dev/null
+++ b/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.cif
@@ -0,0 +1,12 @@
+<component>
+ name = "Image Verification Library"
+ category = ModulePart
+ LocalRoot = "Core\EM\SecurityPkg\ImageVerificationLib"
+ RefName = "ImageVerificationLib"
+[files]
+"ImageVerificationLib.sdl"
+"ImageVerificationLib.mak"
+"DxeImageVerificationLib.c"
+"DxeImageVerificationLib.h"
+"EfiImage.h"
+<endComponent>
diff --git a/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.mak b/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.mak
new file mode 100644
index 0000000..bb6b02b
--- /dev/null
+++ b/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.mak
@@ -0,0 +1,92 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2008, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#*************************************************************************
+# $Header: /Alaska/SOURCE/Modules/SecureBoot_WIN8/ImageVerification_efi/ImageVerificationLib.mak 5 8/15/13 11:28a Alexp $
+#
+# $Revision: 5 $
+#
+# $Date: 8/15/13 11:28a $
+#*************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/SecureBoot_WIN8/ImageVerification_efi/ImageVerificationLib.mak $
+#
+# 5 8/15/13 11:28a Alexp
+#
+# 4 11/19/12 4:42p Alexp
+# Fix for Win8 SecureBoot logo requirement: restore Secure Boot state
+# across flash updates.
+# Move all secure boot Setup settings to a separate varsore variable.
+# Preserve var across re-flash
+#
+# 3 6/30/11 4:01p Alexp
+# moved Setup Page defines to parent SecureBoot module
+#
+# 2 6/15/11 3:06p Alexp
+# removed commented instructions
+#
+# 1 6/13/11 5:25p Alexp
+#
+# 5 5/17/11 5:35p Alexp
+#
+#
+# 3 5/11/11 1:03p Alexp
+# update file hdr
+#
+# 2 5/10/11 12:35p Alexp
+#
+# 1 5/09/11 10:04a Alexp
+#
+# 3 5/04/11 7:15p Alexp
+# add Setup controls on Secure page
+#
+# 2 4/11/11 12:58p Alexp
+# remove Crypto lib linkage
+#
+# 1 3/12/11 11:31a Alexp
+#
+# 1 3/10/11 5:00p Alexp
+#
+# 1 3/03/11 6:35p Alexp
+#
+#*************************************************************************
+#<AMI_FHDR_START>
+#
+# Name: ImageVerificationLib.mak
+#
+# Description: installs Security Architecture Protocol
+#
+#
+#<AMI_FHDR_END>
+#*************************************************************************
+CORE_DXE_LIBBin : $(IMAGEVERIFY_LIB)
+
+$(IMAGEVERIFY_LIB) : $(BUILD_DIR)\ImageVerificationLib.mak ImageVerificationLibBin
+
+$(BUILD_DIR)\ImageVerificationLib.mak : $(ImageVerificationLib_DIR)\ImageVerificationLib.cif $(BUILD_RULES)
+ $(CIF2MAK) $(ImageVerificationLib_DIR)\ImageVerificationLib.cif $(CIF2MAK_DEFAULTS)
+
+ImageVerificationLib_INCLUDES= \
+ /I $(ImageVerificationLib_DIR) \
+ /I $(SecureBoot_DIR) \
+ /I $(CORE_DIR)
+
+ImageVerificationLibBin : $(CRYPTOLIB)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\ImageVerificationLib.mak all\
+ NAME=ImageVerificationLib\
+ MAKEFILE=$(BUILD_DIR)\ImageVerificationLib.mak\
+ "MY_INCLUDES= $(ImageVerificationLib_INCLUDES)" \
+ TYPE=LIBRARY
diff --git a/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.sdl b/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.sdl
new file mode 100644
index 0000000..73e98c0
--- /dev/null
+++ b/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.sdl
@@ -0,0 +1,109 @@
+TOKEN
+ Name = "ImageVerification_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable Crypto library support in Project"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "ENABLE_IMAGE_EXEC_POLICY_OVERRIDE"
+ Value = "0"
+ Help = "Enable user override of Image Execution policy"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "ENABLE_IMAGE_EXEC_POLICY_OVERRIDE"
+ Value = "1"
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "DEBUG_MODE" "=" "1"
+End
+
+TOKEN
+ Name = "LOAD_FROM_FV"
+ Value = "0"
+ Help = "Load image from Internal FV. Possible options:\0-ALWAYS_EXECUTE; 1-NEVER_EXECUTE; 2-ALLOW_EXECUTE_ON_SECURITY_VIOLATION;\3-DEFER_EXECUTE_ON_SECURITY_VIOLATION; 4-DENY_EXECUTE_ON_SECURITY_VIOLATION; 5-QUERY_USER_ON_SECURITY_VIOLATION"
+ TokenType = Integer
+ TargetH = Yes
+ Lock = Yes
+ Range = "Supported options: 0"
+End
+
+TOKEN
+ Name = "LOAD_FROM_OROM"
+ Value = "4"
+ Help = "Load image from Option ROM"
+ TokenType = Integer
+ TargetH = Yes
+ Range = "Supported options: 3,4,5"
+End
+
+TOKEN
+ Name = "LOAD_FROM_REMOVABLE_MEDIA"
+ Value = "4"
+ Help = "Load image from Removable Media"
+ TokenType = Integer
+ TargetH = Yes
+ Range = "Supported options: 3,4,5"
+End
+
+TOKEN
+ Name = "LOAD_FROM_FIXED_MEDIA"
+ Value = "4"
+ Help = "Load image from Fixed Media"
+ TokenType = Integer
+ TargetH = Yes
+ Range = "Supported options: 3,4,5"
+End
+
+TOKEN
+ Name = "INSTALL_DUMMY_SECURITY_PROTOCOL"
+ Value = "0"
+ Help = "When this token is 'on', the Core publishes dummy instance of the security protocol.\The security protocol is one of the architectural protocols and as such must be available.\The default value is 'on'. \Set to 'off' if project includes driver that publishes the security protocol.\"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "LOAD_UNSIGNED_EMBEDDED_SHELL"
+ Value = "0"
+ Help = "Load Shell from Internal FV"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "LOAD_UNSIGNED_EMBEDDED_SHELL"
+ Value = "1"
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "DEBUG_MODE" "=" "1"
+End
+
+TOKEN
+ Name = "IMAGEVERIFY_LIB"
+ Value = "$$(LIB_BUILD_DIR)\ImageVerificationLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "ImageVerificationLib_DIR"
+ Help = "Path to Crypto library Module in Project"
+End
+
+MODULE
+ Help = "Includes ImageVerificationLib.mak to Project"
+ File = "ImageVerificationLib.mak"
+End
+
+ELINK
+ Name = "InstallSecurityArchProtocol,"
+ Parent = "DxeCoreInitialize"
+ InvokeOrder = AfterParent
+End
diff --git a/Core/EM/SecurityPkg/SecFlashUpd/EfiCapsuleRecovery.c b/Core/EM/SecurityPkg/SecFlashUpd/EfiCapsuleRecovery.c
new file mode 100644
index 0000000..a82e2c7
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecFlashUpd/EfiCapsuleRecovery.c
@@ -0,0 +1,325 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (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/FlashUpdate/EfiCapsuleRecovery.c 13 3/18/14 3:02p Alexp $
+//
+// $Revision: 13 $
+//
+// $Date: 3/18/14 3:02p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureFlashPkg/FlashUpdate/EfiCapsuleRecovery.c $
+//
+// 13 3/18/14 3:02p Alexp
+// year '2014' in file hdr & ftr
+//
+// 12 2/27/13 6:31p Alexp
+// don't assume the Capsule hob starts with FWCapsule header.
+// helps to hadle Windows Update Capsule with Ami.rom as payload
+//
+// 11 12/17/12 2:40p Alexp
+// optimized LoadRecoveryCapsule()
+//
+// 10 8/28/12 4:19p Alexp
+// change return NULL to return 0 for EFI_PHYSICAL_ADDRESS types
+//
+// 8 4/19/12 2:43p Alexp
+// EIP:87678: Woking image during Recovery and Capsule Secure Flash Update
+// Deffer Publishing of FV DXE to DxeIpl. Launch DXE from original FV on
+// Flash updates while in Recovery use DXE form new image
+//
+// 7 2/14/12 3:24p Alexp
+// Replace VOID (32bit) with EFI_PHYSICAL_ADDRESS(64bit) pointer for an
+// address of a Recovery Hob data.
+//
+// 6 12/08/11 12:22p Alexp
+// Re-define EFI_HOB_TYPE_CV type as EFI_HOB_TYPE_UEFI_CAPSULE
+// for forward compatibility with PI 1.2 Hob.h definitions
+//
+// 5 11/17/11 10:01a Alexp
+// 1. Replace local Capsule pointer with global one.
+// 2. Locate FW CApsule includes search in 2 potential Capsule Hob types
+// - EFI_HOB_TYPE_GUID_EXTENSION
+// - EFI_HOB_TYPE_CV
+//
+// 4 10/11/11 12:23p Alexp
+// re-arrange Function defines and global defines
+//
+// 3 9/20/11 2:26p Alexp
+// do not change BootMode from FlUpdate to Recovery if FwCapsule update is
+// pending
+//
+// 2 7/20/11 7:16p Alexp
+// remove dependency on Capsule module
+//
+// 1 7/01/11 4:39p Alexp
+//
+// 3 4/29/11 10:28a Alexp
+// Capsule Recovery to be invoked sepparately from generic Recovery PPI
+//
+//
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------
+//
+// Name: EFICapsuleRecovery.c - PEI driver
+//
+// Description: Implements EFI_PEI_RECOVERY_BLOCK_IO_PPI for Capsule HOB.
+// Capsule Recovery to be invoked separately from generic Recovery PPI
+//----------------------------------------------------------------------
+//<AMI_FHDR_END>
+#include <Token.h>
+#include <PPI/RecoveryModule.h>
+
+#include <AmiPeiLib.h>
+#include <AmiHobs.h>
+#include <Hob.h>
+#include "AmiCertificate.h"
+#include <FlashUpd.h>
+
+// Definitions
+
+EFI_GUID gFWCapsuleGuid = APTIO_FW_CAPSULE_GUID;
+EFI_GUID guidRecoveryModule = EFI_PEI_RECOVERY_MODULE_PPI_GUID;
+
+#ifndef EFI_HOB_TYPE_CV
+#define EFI_HOB_TYPE_CV EFI_HOB_TYPE_UEFI_CAPSULE
+typedef EFI_HOB_UEFI_CAPSULE EFI_HOB_CAPSULE_VOLUME;
+#endif // PI BACKWARD_COMPATIBLE_MODE
+
+EFI_PHYSICAL_ADDRESS gCapsuleAddress = 0;
+UINT64 gCapsuleLength = 0;
+//----------------------------------------------------------------------------
+// Function Prototypes
+//----------------------------------------------------------------------------
+EFI_STATUS ReportFV2Dxe(
+ IN VOID* RecoveryCapsule OPTIONAL,
+ IN EFI_PEI_SERVICES **PeiServices
+);
+
+EFI_STATUS VerifyFwImage(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT VOID **pCapsule,
+ IN OUT UINT32 *pCapsuleSize,
+ IN OUT UINT32 *FailedVTask
+);
+
+//----------------------------------------------------------------------------
+// Function Definitions
+//----------------------------------------------------------------------------
+EFI_STATUS LoadRecoveryCapsule(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN struct _EFI_PEI_RECOVERY_MODULE_PPI *This
+);
+
+BOOLEAN IsFlashUpdateS3Capsule (
+ EFI_PEI_SERVICES **PeiServices,
+ EFI_BOOT_MODE *BootMode
+);
+//----------------------------------------------------------------------------
+// PPI to be installed
+//----------------------------------------------------------------------------
+static EFI_PEI_RECOVERY_MODULE_PPI RecoveryModule =
+{
+ LoadRecoveryCapsule
+};
+
+//----------------------------------------------------------------------------
+// Notify list that are installed
+//----------------------------------------------------------------------------
+static EFI_PEI_PPI_DESCRIPTOR RecoveryPpiList[] =
+{
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &guidRecoveryModule, &RecoveryModule
+ }
+};
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: FindFWCapsuleHOB
+//
+// Description: Locates Aptio FW Capsule in Capsule Hob
+//
+// Input: EFI_PEI_SERVICES **PeiServices
+// Output: EFI_PHYSICAL_ADDRESS pointer to FW CApsule
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+FindFWCapsuleHOB
+(
+ IN EFI_PEI_SERVICES **PeiServices
+){
+ EFI_HOB_GUID_TYPE *pHob;
+ EFI_HOB_CAPSULE_VOLUME *pHob1;
+ EFI_PHYSICAL_ADDRESS CapsuleAddress;
+ UINT64 CapsuleLength;
+ EFI_CAPSULE_HEADER *FWCapsuleVolume;
+
+ (*PeiServices)->GetHobList(PeiServices, &pHob);
+ pHob1 = (EFI_HOB_CAPSULE_VOLUME*)pHob;
+// 1. attempt to locate Capsule by GUID guidAmiCapsuleHob
+ while (!EFI_ERROR(FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION, &pHob)))
+ {
+ if((pHob->Header.HobType == EFI_HOB_TYPE_GUID_EXTENSION)&&
+ !(guidcmp(&((AMI_CAPSULE_HOB*)pHob)->CapsuleGuid, &gFWCapsuleGuid)))
+ {
+ PEI_TRACE((-1, PeiServices, "FW Capsule found in GUIDed Capsule Hob\n"));
+ gCapsuleLength = ((AMI_CAPSULE_HOB*)pHob)->CapsuleLength;
+ gCapsuleAddress = (EFI_PHYSICAL_ADDRESS)(((AMI_CAPSULE_HOB*)pHob)->CapsuleData);
+ return EFI_SUCCESS;
+ }
+ }
+// 2. attempt to locate capsule volume hob
+ while (!EFI_ERROR(FindNextHobByType(EFI_HOB_TYPE_CV, &pHob1)))
+ {
+ // if capsule volume hob is found, determine the capsule's location
+ CapsuleAddress = pHob1->BaseAddress;
+ CapsuleLength = pHob1->Length;
+ FWCapsuleVolume = (EFI_CAPSULE_HEADER*) CapsuleAddress;
+ if(CapsuleLength != 0 && FWCapsuleVolume->CapsuleImageSize <= CapsuleLength &&
+ !(guidcmp(&(FWCapsuleVolume->CapsuleGuid), &gFWCapsuleGuid)))
+ {
+ PEI_TRACE((-1, PeiServices, "FW Capsule found in Capsule Volume Hob\n"));
+ gCapsuleLength = CapsuleLength;
+ gCapsuleAddress = CapsuleAddress;
+ return EFI_SUCCESS;
+ }
+ }
+
+ PEI_TRACE((-1,PeiServices, "FW capsule HOB not found\n"));
+ return EFI_NOT_FOUND;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: LoadRecoveryCapsule
+//
+// Description: LoadRecoveryCapsule function of EFI_PEI_RECOVERY_MODULE_PPI
+// ppi. RecoveryDeviceOrder is a list of guids; each guid
+// represents a type of recovery device. We go through
+// this list and call FindRecoveryDevice for each type of
+// device.
+// -This function should not be confused with LoadRecoveryCapsule
+// function of the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI ppi.
+// -Called by DxeIpl.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS LoadRecoveryCapsule(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN struct _EFI_PEI_RECOVERY_MODULE_PPI *This
+)
+{
+ EFI_STATUS Status;
+ static EFI_GUID RecoveryHobGuid = AMI_RECOVERY_IMAGE_HOB_GUID;
+ RECOVERY_IMAGE_HOB *pRecoveryHob;
+ UINTN Size;
+ EFI_PHYSICAL_ADDRESS CapsuleAddress;
+
+ PEI_PROGRESS_CODE(PeiServices,PEI_RECOVERY_STARTED);
+
+ PEI_TRACE((TRACE_DXEIPL, PeiServices, "Loading Recovery Image..."));
+
+// Locate Capsule Hob
+ if(!gCapsuleAddress || !gCapsuleLength) return EFI_NOT_FOUND;
+
+ //create HOB that describes location of the Recovery image
+ Status = (*PeiServices)->CreateHob(
+ PeiServices, EFI_HOB_TYPE_GUID_EXTENSION,
+ sizeof(RECOVERY_IMAGE_HOB), &pRecoveryHob
+ );
+ pRecoveryHob->Header.Name = RecoveryHobGuid;
+ pRecoveryHob->Address = 0;
+
+// Size = (UINTN)((APTIO_FW_CAPSULE_HEADER*)gFwCapsule)->CapHdr.CapsuleImageSize;
+ Size = (UINTN)gCapsuleLength;
+ CapsuleAddress = (EFI_PHYSICAL_ADDRESS)gCapsuleAddress;
+ Status = VerifyFwImage(PeiServices, (VOID**)&CapsuleAddress, (UINT32*)&Size,(UINT32*)&pRecoveryHob->FailedStage );
+ pRecoveryHob->Status = (UINT8)Status;
+ pRecoveryHob->Address = CapsuleAddress;
+ if (EFI_ERROR(Status)) {
+ PEI_ERROR_CODE(PeiServices, PEI_RECOVERY_INVALID_CAPSULE, EFI_ERROR_MAJOR | Status);
+ }
+// < 4.6.5.4
+#if defined(CORE_COMBINED_VERSION) && CORE_COMBINED_VERSION < 0x4028e
+ else{
+ // DxeIpl from 4.6.5.4. will publish Dxe FV
+ Status = ReportFV2Dxe((VOID *)CapsuleAddress, PeiServices);
+ }
+#endif
+
+ if (EFI_ERROR(Status)) {
+ PEI_ERROR_CODE(PeiServices, PEI_RECOVERY_NO_CAPSULE, EFI_ERROR_MAJOR);
+ }
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: EFICapsuleRecoveryPeimEntry
+//
+// Description: Entry point. Installs EFI_PEI_RECOVERY_MODULE_PPI ppi
+// (which has function LoadRecoveryCapsule).
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+EFICapsuleRecoveryPeimEntry (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+)
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+
+// Change the Boot Mode to Recovery from S3_RESUME/BOOT_ON_FLASH_UPDATE
+ Status = (*PeiServices)->GetBootMode(PeiServices, &BootMode);
+ PEI_TRACE((-1, PeiServices, "FW Capsule Recovery Module, BootMode 0x%x\n", BootMode));
+ if(BootMode == BOOT_ON_S3_RESUME || BootMode == BOOT_ON_FLASH_UPDATE)
+ {
+// Locate Capsule Hob
+ Status = FindFWCapsuleHOB(PeiServices);
+ if (EFI_ERROR(Status) || !gCapsuleAddress || !gCapsuleLength) {
+// Capsule not found:
+// Change the Boot Mode to BOOT_WITH_FULL_CONFIGURATION from BOOT_ON_FLASH_UPDATE
+ BootMode = BOOT_WITH_FULL_CONFIGURATION;
+ Status = (*PeiServices)->SetBootMode(PeiServices, BootMode);
+ } else {
+ Status = (*PeiServices)->InstallPpi(PeiServices,RecoveryPpiList);
+ ASSERT_PEI_ERROR (PeiServices, Status);
+ }
+ PEI_TRACE((-1, PeiServices, "\tchange mode to 0x%x\n",BootMode));
+ }
+
+ return Status;
+}
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014 American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/SecurityPkg/SecFlashUpd/EfiCapsuleRecovery.dxs b/Core/EM/SecurityPkg/SecFlashUpd/EfiCapsuleRecovery.dxs
new file mode 100644
index 0000000..85dc91e
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecFlashUpd/EfiCapsuleRecovery.dxs
@@ -0,0 +1,89 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (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/FlashUpdate/EfiCapsuleRecovery.dxs 6 3/18/14 3:01p Alexp $
+//
+// $Revision: 6 $
+//
+// $Date: 3/18/14 3:01p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureFlashPkg/FlashUpdate/EfiCapsuleRecovery.dxs $
+//
+// 6 3/18/14 3:01p Alexp
+// set 2014 in file hdr & ftr
+//
+// 5 5/31/12 1:18p Alexp
+// EIP74625:New Capsule PPI required by latest Intel's MRC code
+// New PPI GUID;
+// Capsule_2_0 Mailbox does not need extra Cap Hdr
+// EIP90678: MonotonicCounter variable guid changed
+// Use gAmiGlobalVariableGuid
+//
+// 4 11/21/11 5:49p Alexp
+// include optional GUID dependenccy on Intel Misc Framework
+// PEI_CAPSULE_PPI_GUID
+//
+// 3 11/17/11 10:02a Alexp
+// include dependency on AMI_DIGITAL_SIG PPI
+//
+// 2 7/20/11 7:16p Alexp
+// remove dependency on Capsule module
+//
+// 1 7/01/11 4:39p Alexp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Recovery.dxs
+//
+// Description: Dependancy expression for the component
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#include <PPI/LoadFile.h>
+#include <PPI/CryptoPPI.h>
+#include <FlashUpd.h>
+// AMI Capsule PPI (deprecated)
+#define EFI_PEI_CAPSULE_PPI_GUID \
+ { 0x066785b1, 0xedb8, 0x46dc, 0x84, 0x2f, 0x57, 0x44, 0x04, 0xb8, 0x69, 0x2f }
+// Intel Misc Framework PEI_CAPSULE_PPI_GUID
+#define PEI_CAPSULE_PPI_GUID \
+ { 0x3acf33ee, 0xd892, 0x40f4, 0xa2, 0xfc, 0x38, 0x54, 0xd2, 0xe1, 0x32, 0x3d }
+DEPENDENCY_START
+EFI_PEI_FV_FILE_LOADER_GUID
+AND
+EFI_PEI_PERMANENT_MEMORY_INSTALLED_PPI
+AND
+EFI_PEI_BOOT_IN_FLASH_UPDATE_MODE_PEIM_PPI
+AND
+(EFI_PEI_CAPSULE_PPI_GUID OR PEI_CAPSULE_PPI_GUID)
+AND
+AMI_DIGITAL_SIGNATURE_PPI_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/SecFlashUpd/IsSecRecovery.c b/Core/EM/SecurityPkg/SecFlashUpd/IsSecRecovery.c
new file mode 100644
index 0000000..112f655
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecFlashUpd/IsSecRecovery.c
@@ -0,0 +1,390 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (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/FlashUpdate/IsSecRecovery.c 18 10/29/14 5:11p Alexp $
+//
+// $Revision: 18 $
+//
+// $Date: 10/29/14 5:11p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureFlashPkg/FlashUpdate/IsSecRecovery.c $
+//
+// 18 10/29/14 5:11p Alexp
+// GetFlashUpdateVar() - set default value of CounterHi= -1
+// for cases when MC variable is available only in pre-boot.
+//
+// 15 3/18/14 3:02p Alexp
+// year '2014' in file hdr & ftr
+//
+// 14 8/12/13 4:36p Alexp
+// fix ChangeBootModeAfterEndofMrc() to change BootMode and install PPI if
+// CApsule Upd is pending
+//
+// 13 4/01/13 9:37a Alexp
+// exclude capsule recovery code if FWCAPSULE_RECOVERY_SUPPORT is 0
+//
+// 12 2/27/13 6:43p Alexp
+// GetFlashUpdateVar() to check for AMI Capsule Variable
+// if Ami FwCapsule is pending and update boot mode to
+// BOOT_ON_FLASH_UPDATE
+//
+// 11 7/09/12 5:30p Alexp
+// IsFlashUpdateS3Capsule
+// Install Capsule Recovery Event whether by checking FlashUpd variable
+// or if BOOT_ON_FLASH_UPDATE. It may've already been set by Capsule PEI
+//
+//
+// 9 6/01/12 10:44a Alexp
+// EIP74625:New Capsule PPI required by latest Intel's MRC code
+// New PPI GUID;
+// Capsule_2_0 Mailbox does not need extra Cap Hdr
+// EIP90678: MonotonicCounter variable guid changed
+// Use AMI_GLOBAL_VARIABLE_GUID
+//
+// 7 12/08/11 4:51p Alexp
+// Change method of calling IsSecRecovery init routine.
+// Replaced IsSecRecovery PEI with function call IsFlashUpdateRecovery
+// from PeiCoreInitialize
+//
+// 6 11/10/11 7:10p Alexp
+// minor optimizations
+//
+// 5 11/03/11 6:41p Alexp
+// Add provision to build file as .FFS with new function to install
+// callback on gAmiPeiAfterMrcGuid event
+// Update BootMode to BOOT_ON_FLASH_UPDATE if Capsule update is detected
+//
+// 4 10/17/11 11:33a Alexp
+// Replace old method to detect FlashUpd with single IsFlashUpdate() hook
+// to be called from SbPei.c ->GetBootMode
+//
+// 3 10/11/11 12:23p Alexp
+// removed comments
+//
+// 2 7/20/11 7:16p Alexp
+// remove dependency on Capsule module
+//
+// 1 7/01/11 4:39p Alexp
+//
+//
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------
+//
+// Name: IsSecRecovery.c - PEI recovery services
+//
+// Description: File contains hook to determine if BootMode needs to follow
+// recovery path due to pending Flash Update
+//
+//----------------------------------------------------------------------
+//<AMI_FHDR_END>
+// Module specific Includes
+#include "Efi.h"
+#include "Pei.h"
+#include "token.h"
+#include <AmiPeiLib.h>
+#include <Hob.h>
+#include <Ppi\ReadOnlyVariable.h>
+#include <FlashUpd.h>
+#if FWCAPSULE_RECOVERY_SUPPORT == 1
+#include "AmiCertificate.h"
+#include <Capsule.h>
+
+// Definitions
+static EFI_GUID gFWCapsuleGuid = APTIO_FW_CAPSULE_GUID;
+static EFI_GUID gEfiCapsuleVendorGuid = EFI_CAPSULE_AMI_GUID;
+#endif
+static EFI_GUID gFlashUpdBootModeGuid = EFI_PEI_BOOT_IN_FLASH_UPDATE_MODE_PEIM_PPI;
+// PPI that are installed
+static EFI_PEI_PPI_DESCRIPTOR mFlashUpdateModePpi[] =
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gFlashUpdBootModeGuid,
+ NULL
+};
+
+static EFI_GUID gPeiReadOnlyVariablePpiGuid = EFI_PEI_READ_ONLY_VARIABLE_PPI_GUID;
+static EFI_GUID gFlashUpdGuid = FLASH_UPDATE_GUID;
+// must be defined in AmiLib.h (Core 4.6.5.4 +)
+#if defined(AMI_GLOBAL_VARIABLE_GUID)
+static EFI_GUID guidVar = AMI_GLOBAL_VARIABLE_GUID;
+#else
+static EFI_GUID guidVar = EFI_GLOBAL_VARIABLE;
+#endif
+
+#if FWCAPSULE_RECOVERY_SUPPORT == 1
+///////////////////////////////////////////////////////
+// {64C96700-6B4C-480C-A3E1-B8BDE8F602B2}
+#define AMI_PEI_AFTER_MRC_GUID \
+ {0x64c96700, 0x6b4c, 0x480c, 0xa3, 0xe1, 0xb8, 0xbd, 0xe8, 0xf6, 0x2, 0xb2}
+
+static EFI_GUID gAmiPeiAfterMrcGuid = AMI_PEI_AFTER_MRC_GUID;
+
+EFI_STATUS ChangeBootModeAfterEndofMrc (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *InvokePpi
+);
+
+static EFI_PEI_NOTIFY_DESCRIPTOR EndOfMrcNotifyList[] = {
+ { EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | \
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, \
+ &gAmiPeiAfterMrcGuid, ChangeBootModeAfterEndofMrc },
+};
+#endif
+//--------------------------------------------------------------------------
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetFlashUpdateVar
+//
+// Description:
+// This function checks if recovery flow is needed due to pending Flash Update
+//
+// Input:
+// PeiServices Pointer to the PEI services table
+//
+// Output:
+// TRUE - recovery is requested
+// FALSE - recovery is not requested
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN
+GetFlashUpdateVar (
+ EFI_PEI_SERVICES **PeiServices,
+ AMI_FLASH_UPDATE_BLOCK *FlashUpdDesc,
+ UINT32 *CounterHi
+){
+ EFI_STATUS Status;
+ UINTN Size;
+ EFI_PEI_READ_ONLY_VARIABLE_PPI *ReadOnlyVariable;
+#if FWCAPSULE_RECOVERY_SUPPORT == 1
+ EFI_PHYSICAL_ADDRESS IoData;
+ EFI_CAPSULE_HEADER *CapsuleHeader;
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *pCapsuleMailboxPtr;
+#endif
+// Check FlashOp variable for Recovery Flash operation
+// Detect if we are in Flash Update mode and set some recovery global variables
+// Read "FlashOp" Variable to update global RecoveryFileName, Size
+ Status = (*PeiServices)->LocatePpi( PeiServices,
+ &gPeiReadOnlyVariablePpiGuid,
+ 0,
+ NULL,
+ &ReadOnlyVariable );
+ if(EFI_ERROR(Status))
+ return FALSE;
+
+ Size = sizeof(AMI_FLASH_UPDATE_BLOCK);
+ Status = ReadOnlyVariable->GetVariable( PeiServices,
+ FLASH_UPDATE_VAR,
+ &gFlashUpdGuid,
+ NULL,
+ &Size,
+ FlashUpdDesc );
+ if (!EFI_ERROR(Status))
+ {
+ Size = sizeof(UINT32);
+ Status = ReadOnlyVariable->GetVariable(PeiServices,
+ L"MonotonicCounter",
+ &guidVar,
+ NULL,
+ &Size,
+ CounterHi);
+ if (EFI_ERROR(Status) || FlashUpdDesc->MonotonicCounter == 0xffffffff)
+ *CounterHi = 0xffffffff;
+
+ return TRUE;
+#if FWCAPSULE_RECOVERY_SUPPORT == 1
+ } else {
+ Size=sizeof(EFI_PHYSICAL_ADDRESS);
+ Status = ReadOnlyVariable->GetVariable( PeiServices,
+ CAPSULE_UPDATE_VAR, &gEfiCapsuleVendorGuid,
+ NULL,
+ &Size,
+ &IoData );
+ if (!EFI_ERROR(Status))
+ {
+ // verify the FW capsule is in memory. May first check if pCapsuleMailboxPtr == IoData
+ pCapsuleMailboxPtr = (EFI_CAPSULE_BLOCK_DESCRIPTOR*)IoData;
+ CapsuleHeader = (EFI_CAPSULE_HEADER*)pCapsuleMailboxPtr[0].DataBlock;
+ //
+ // Compare GUID with APTIO_FW_CAPSULE_GUID
+ //
+ if (guidcmp (&CapsuleHeader->CapsuleGuid, &gFWCapsuleGuid)==0) {
+ FlashUpdDesc->FlashOpType = FlCapsule;
+ return TRUE;
+ }
+ }
+#endif
+ }
+
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsFlashUpdate
+//
+// Description:
+// This function returns proper BootMode if Flash Update mode is pending
+//
+// Input:
+// **PeiServices - Pointer to the PEI services table
+// *BootMode - Pointer to a BootMode variable
+//
+// Output:
+// BOOLEAN
+// TRUE - recovery is requested
+// FALSE - recovery is not requested
+// BootMode - updated BootMode value if TRUE
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN
+IsFlashUpdate(
+ EFI_PEI_SERVICES **PeiServices,
+ EFI_BOOT_MODE *BootMode
+){
+ UINT32 CounterHi = 0;
+ AMI_FLASH_UPDATE_BLOCK FlashUpdDesc;
+
+ FlashUpdDesc.MonotonicCounter = 0;
+ FlashUpdDesc.FlashOpType = FlDisabled;
+
+//SetMode should have set FlashUpd var even if no MC var detected.
+// MC check should fail Recovery
+ if(/**BootMode != BOOT_IN_RECOVERY_MODE && */
+ GetFlashUpdateVar(PeiServices, &FlashUpdDesc, &CounterHi) &&
+ CounterHi==(UINT32)FlashUpdDesc.MonotonicCounter)
+ {
+ if(FlashUpdDesc.FlashOpType == FlRecovery)
+ {
+ *BootMode = BOOT_IN_RECOVERY_MODE;
+ return TRUE;
+ }
+ if(FlashUpdDesc.FlashOpType == FlCapsule/* && *BootMode == BOOT_ON_S3_RESUME*/)
+ {
+ *BootMode = BOOT_ON_FLASH_UPDATE;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsFlashUpdateRecovery
+//
+// Description:
+// This function checks if recovery flow is needed due to pending Flash Update
+//
+// Input:
+// PeiServices Pointer to the PEI services table
+//
+// Output:
+// TRUE - recovery is requested
+// FALSE - recovery is not requested
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN
+IsFlashUpdateRecovery (
+ EFI_PEI_SERVICES **PeiServices
+){
+ EFI_BOOT_MODE BootMode;
+ if(IsFlashUpdate(PeiServices, &BootMode) && BootMode == BOOT_IN_RECOVERY_MODE)
+ return TRUE;
+ return FALSE;
+}
+
+#if FWCAPSULE_RECOVERY_SUPPORT == 1
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: ChangeBootModeAfterEndofMrc
+//
+// Description: Change BootMode to BOOT_ON_FLASH_UPDATE if Capsule update is pending
+//
+// Input: PeiServices - Pointer to the PEI services table
+// NotifyDescriptor - Pointer to the descriptor for the
+// notification event.
+// InvokePpi - Pointer to the PPI that was installed
+//
+// Output: EFI_STATUS
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ChangeBootModeAfterEndofMrc (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *InvokePpi )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+
+ Status = (*PeiServices)->GetBootMode( PeiServices, &BootMode );
+// if (!EFI_ERROR(Status) && (BootMode != BOOT_IN_RECOVERY_MODE))
+// BOOT_ON_FLASH_UPDATE may already be set by Capsule PEI
+ if(!EFI_ERROR(Status) && (BootMode == BOOT_ON_S3_RESUME || BootMode == BOOT_ON_FLASH_UPDATE))
+ {
+ // Change the Boot Mode to Recovery from S3_RESUME/BOOT_ON_FLASH_UPDATE
+ if (IsFlashUpdate(PeiServices, &BootMode) && BootMode == BOOT_ON_FLASH_UPDATE)
+ (*PeiServices)->SetBootMode(PeiServices, BootMode);
+ }
+ //install Flash Update Boot Mode PPI
+ if(BootMode == BOOT_ON_FLASH_UPDATE)
+ (*PeiServices)->InstallPpi( PeiServices, mFlashUpdateModePpi);
+
+ return EFI_SUCCESS;
+}
+#endif
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: IsFlashUpdateCapsuleInit
+//
+// Description: Installs callback to ChangeBootModeAfterEndofMrc
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+IsFlashUpdateCapsuleInit (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+)
+{
+#if FWCAPSULE_RECOVERY_SUPPORT == 1
+ return (*PeiServices)->NotifyPpi( PeiServices, EndOfMrcNotifyList);
+#else
+ return EFI_SUCCESS;
+#endif
+
+}
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (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/SecFlashUpd/SecFlashUpd.cif b/Core/EM/SecurityPkg/SecFlashUpd/SecFlashUpd.cif
new file mode 100644
index 0000000..aecb88d
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecFlashUpd/SecFlashUpd.cif
@@ -0,0 +1,17 @@
+<component>
+ name = "Secure Flash Update"
+ category = ModulePart
+ LocalRoot = "Core\EM\SecurityPkg\SecFlashUpd\"
+ RefName = "SecFlashUpd"
+[files]
+"SecFlashUpd.sdl"
+"SecFlashUpd.mak"
+"VerifyFwCapsule.c"
+"IsSecRecovery.c"
+"EfiCapsuleRecovery.c"
+"EfiCapsuleRecovery.dxs"
+"SecFlashUpdDxe.c"
+"SecFlashUpdDxe.dxs"
+[parts]
+"FlashUpdInc"
+<endComponent>
diff --git a/Core/EM/SecurityPkg/SecFlashUpd/SecFlashUpd.mak b/Core/EM/SecurityPkg/SecFlashUpd/SecFlashUpd.mak
new file mode 100644
index 0000000..f44a380
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecFlashUpd/SecFlashUpd.mak
@@ -0,0 +1,176 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (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/FlashUpdate/SecFlashUpd.mak 17 9/30/14 3:34p Alexp $
+#
+# $Revision: 17 $
+#
+# $Date: 9/30/14 3:34p $
+#*************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/SecureFlashPkg/FlashUpdate/SecFlashUpd.mak $
+#
+# 17 9/30/14 3:34p Alexp
+# EIP185686:Build error with Recovery_SUPPORT = 0
+#
+# 16 3/18/14 3:02p Alexp
+# year '2014' in file hdr & ftr
+#
+# 15 4/19/13 4:48p Alexp
+# add external define
+#
+# 14 11/21/12 10:36a Alexp
+# don not link cryptolib
+#
+# 13 10/31/12 10:09a Alexp
+# EIP#100418: Make SecureFlashPkg build independent
+# from Core's ReFlash driver Support
+#
+# 12 9/06/12 6:15p Alexp
+# EIP#100418: Make SecureFlashPkg build independant from ReFlash-Support
+#
+# 11 7/13/12 12:11p Alexp
+# Replace custom _EFI_CAPSULE_BLOCK_DESCRIPTOR_ with
+# generic EFI_CAPSULE_BLOCK_DESCRIPTOR
+#
+# 10 5/18/12 4:22p 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
+#
+# 9 12/08/11 4:51p Alexp
+# Change method of calling IsSecRecovery init routine ->
+# ->Replaced IsSecRecovery PEI with function call IsFlashUpdateRecovery
+# from PeiCoreInitialize
+#
+# 8 11/10/11 4:36p Alexp
+# Add build rules to generate SecFlashDxe driver
+#
+# 7 11/03/11 6:38p Alexp
+# create build rules for IsSecRecovery.ffs PEI module
+#
+# 6 10/17/11 11:33a Alexp
+# Replace old method to detect FlashUpd with single IsFlashUpdate() hook
+# to be called from SbPei.c ->GetBootMode
+#
+# 5 8/22/11 5:22p Alexp
+# removed build rules for SecFlash Setup pages
+#
+# 4 8/18/11 4:45p Alexp
+# removed unused build target:SecFlashUpdDxeBin
+#
+# 3 8/05/11 3:18p Alexp
+# removed Flash Policy driver, files, Protocol; Flash Policy is hardwired
+# via SDL
+#
+# 2 7/20/11 7:16p Alexp
+# remove dependency on Capsule module
+#
+# 1 7/01/11 4:39p Alexp
+#
+#
+#*************************************************************************
+#<AMI_FHDR_START>
+#
+# Name: SecFlashUpd.mak
+#
+# Description:
+#
+#
+#<AMI_FHDR_END>
+#*************************************************************************
+SecureModule: SecureFlashUpdate
+
+SecureFlashUpdate : $(BUILD_DIR)\SecFlashUpd.mak SecFlashUpdDxeBin \
+!IF $(Recovery_SUPPORT) == 1
+FwCapsuleRecoveryPPIBin
+!ENDIF
+
+$(BUILD_DIR)\SecFlashUpd.mak : $(SecFlashUpd_DIR)\SecFlashUpd.cif $(SecFlashUpd_DIR)\SecFlashUpd.mak $(BUILD_RULES)
+ $(CIF2MAK) $(SecFlashUpd_DIR)\SecFlashUpd.cif $(CIF2MAK_DEFAULTS)
+
+BUILD_SecFlashUpd_DIR = $(BUILD_DIR)\$(SecFlashUpd_DIR)
+
+!IFDEF ReFlash_SUPPORT
+SecFlashUpd_DEFINES= \
+ /D ReFlash_SUPPORT=$(ReFlash_SUPPORT)
+!ENDIF
+
+SecFlashUpd_INCLUDES= \
+ /I $(SecFlashUpd_DIR)\
+ $(SEC_FLASH_GUID_DEFINES)\
+!IFDEF ReFlash_DIR
+ /I $(ReFlash_DIR)\
+!ENDIF
+ /I$(CORE_DIR)
+
+AMI_CSP_LIB_INCLUDE_FILES = "Include\FlashUpd.h" + \
+$(AMI_CSP_LIB_INCLUDE_FILES)
+
+AMI_CSP_LIB_OBJS = $(AMI_CSP_LIB_OBJS) \
+$(BUILD_DIR)\IsSecRecovery.obj
+#-----------------------------------------------------------------------
+# Auxilary library files compilation
+#-----------------------------------------------------------------------
+RecoveryBin FwCapsuleRecoveryPPIBin : $(BUILD_DIR)\VerifyFwCapsule.obj $(CRYPTOLIBPEI)
+
+{$(SecFlashUpd_DIR)}.c{$(BUILD_DIR)}.obj::
+ $(CC) $(CFLAGS) $(SEC_FLASH_GUID_DEFINES) /I $(SecFlashUpd_DIR) /Fo$(BUILD_DIR)\ $<
+
+SecFlashUpdDxeBin : $(AMIDXELIB)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\SecFlashUpd.mak all\
+ NAME=SecFlashUpdDxe\
+ MAKEFILE=$(BUILD_DIR)\SecFlashUpd.mak \
+ GUID=A0EF80E3-F9AB-4CBA-98FD-704620F4048D \
+ ENTRY_POINT=SecFlashUpdDxe_Init\
+ DEPEX1=$(SecFlashUpd_DIR)\SecFlashUpdDxe.DXS DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX\
+ "MY_INCLUDES=$(SecFlashUpd_INCLUDES) "\
+ "CFLAGS=$(CFLAGS) $(SecFlashUpd_DEFINES)" \
+ OBJECTS="$(BUILD_SecFlashUpd_DIR)\SecFlashUpdDxe.obj" \
+ TYPE=RT_DRIVER COMPRESS=1
+
+!IF $(CORE_COMBINED_VERSION) < 0x4028e
+FwCapsuleRecoveryPPIBin : $(AMIPEILIB) $(BUILD_DIR)\$(BOARD_DIR)\ReportFV2.obj
+!ELSE
+FwCapsuleRecoveryPPIBin : $(AMIPEILIB)
+!ENDIF
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\SecFlashUpd.mak all\
+ NAME=FwCapsuleRecoveryPPI\
+ MAKEFILE=$(BUILD_DIR)\SecFlashUpd.mak \
+ GUID=83FA5AED-5171-4949-BDC9-0CBC9E123663 \
+ ENTRY_POINT=EFICapsuleRecoveryPeimEntry \
+# "MY_INCLUDES=$(SecFlashUpd_INCLUDES) /I $(Recovery_DIR)"\
+ "MY_INCLUDES=$(SecFlashUpd_INCLUDES)"\
+ OBJECTS="$(BUILD_SecFlashUpd_DIR)\EfiCapsuleRecovery.obj" \
+ DEPEX1=$(SecFlashUpd_DIR)\EfiCapsuleRecovery.DXS DEPEX1_TYPE=EFI_SECTION_PEI_DEPEX \
+ TYPE=PEIM 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/SecFlashUpd/SecFlashUpd.sdl b/Core/EM/SecurityPkg/SecFlashUpd/SecFlashUpd.sdl
new file mode 100644
index 0000000..a21f769
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecFlashUpd/SecFlashUpd.sdl
@@ -0,0 +1,152 @@
+TOKEN
+ Name = "SecFlashUpd_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable Secured FlashUpdate support in Project"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "FlashUpdatePolicy"
+ Value = "7"
+ Help = "Flash update policy bitmap\0-Disabled, \bit0-Cold Reboot(recovery),bit1-Warm Reboot(capsule),bit2-Runtime,\bits 3..31-Reserved"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "BBUpdatePolicy"
+ Value = "7"
+ Help = "Select Boot Block (CRTM) Flash update policy."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "IGNORE_IMAGE_ROLLBACK"
+ Value = "0"
+ Help = "1-FW Capsule Validate logic will skip image Revision check"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "IGNORE_RUNTIME_UPDATE_IMAGE_REVISION_CHECK"
+ Value = "0"
+ Help = "When set, FW Capsule Validate logic will skip image Revision check during Runtime updates"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "IGNORE_RUNTIME_UPDATE_IMAGE_REVISION_CHECK"
+ Value = "1"
+ Help = "Force Ignore_runtime. if master Ignore_image_rollback is set"
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "IGNORE_IMAGE_ROLLBACK" "=" "1"
+End
+
+TOKEN
+ Name = "RUNTIME_SECURE_UPDATE_FLOW"
+ Value = "1"
+ Help = "Force security checks during runtime SMM flash update process"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "FWCAPSULE_RECOVERY_SUPPORT"
+ Value = "0"
+ Help = "Enable APTIO FW Capsule recovery PPI"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "FWCAPSULE_RECOVERY_SUPPORT"
+ Value = "1"
+ Help = "Don't modify this value!"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+ Token = "Recovery_SUPPORT" "=" "1"
+ Token = "CAPSULE_SUPPORT" "=" "1"
+ Token = "WARM_BOOT_SUPPORT" "=" "1"
+ Token = "UEFI_2_0_CAPSULE" "=" "1"
+End
+
+TOKEN
+ Name = "FWCAPSULE_RECOVERY_SUPPORT"
+ Value = "1"
+ Help = "Don't modify this value!"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+ Token = "Recovery_SUPPORT" "=" "1"
+ Token = "CAPSULE2_0_SUPPORT" "=" "1"
+ Token = "SUPPORT_UPDATE_CAPSULE_RESET" "=" "1"
+End
+
+TOKEN
+ Name = "FWCAPSULE_2_0_SUPPORT"
+ Value = "1"
+ Help = "Older Aptio Capsule formats expected extra Cap Hdr in Mailbox"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+ Token = "CAPSULE2_0_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "FLASH_LOCK_EVENT_NOTIFY"
+ Value = "1"
+ Help = "1:Issue Flash Ready to Lock Event"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+PATH
+ Name = "SecFlashUpd_DIR"
+ Help = "Path to FlashUpdate Module in Project"
+End
+
+MODULE
+ File = "SecFlashUpd.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\FwCapsuleRecoveryPPI.ffs"
+ Parent = "FV_BB"
+ Token = "FWCAPSULE_RECOVERY_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "IsFlashUpdateRecovery,"
+ Parent = "IsRecovery"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "IsFlashUpdateCapsuleInit,"
+ Parent = "PeiCoreInitialize"
+ Token = "FWCAPSULE_RECOVERY_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "FwCapsuleInfo"
+ Parent = "AmiGetRecoveryFileInfo"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\SecFlashUpdDxe.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
diff --git a/Core/EM/SecurityPkg/SecFlashUpd/SecFlashUpdDxe.c b/Core/EM/SecurityPkg/SecFlashUpd/SecFlashUpdDxe.c
new file mode 100644
index 0000000..8ce7d3f
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecFlashUpd/SecFlashUpdDxe.c
@@ -0,0 +1,276 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (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/FlashUpdate/SecFlashUpdDxe.c 10 3/18/14 3:01p Alexp $
+//
+// $Revision: 10 $
+//
+// $Date: 3/18/14 3:01p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureFlashPkg/FlashUpdate/SecFlashUpdDxe.c $
+//
+// 10 3/18/14 3:01p Alexp
+// set 2014 in file hdr & ftr
+//
+// 9 5/09/13 10:37a Alexp
+// EIP#123379 : Disabling FLASH_LOCK_EVENT_NOTIFY causes build error
+//
+// 8 10/31/12 1:36p Alexp
+// removed #ifdef for CAPSULE_SUPPORTbefore checks for capsule variable.
+//
+// 7 9/06/12 6:15p Alexp
+// EIP#100418: Make SecureFlashPkg build independant from ReFlash-Support
+//
+// 6 1/06/12 10:37a Alexp
+// Streamlined the code for Setup.AutoFlash variable update if FlashUpdate
+// is pending
+//
+// 4 11/17/11 10:02a Alexp
+// Use Core 4.6.5.2 provided name AMI_EVENT_FLASH_WRITE_LOCK as GUID
+// define for Flash Lock event
+//
+// 3 11/10/11 4:38p Alexp
+// 1. UpdateAutoFlash() updates the AutoFlash Variable installed by
+// ReFlash driver in Recovery/Flash Update flows
+// 2. Issue FlashReadyToLock Event notification based on the Flash Update
+// policy.
+//
+// 2 7/20/11 7:16p Alexp
+// remove dependency on Capsule module
+//
+// 1 7/01/11 4:39p Alexp
+//
+//
+//**********************************************************************
+#include <Token.h>
+#include <AmiDxeLib.h>
+#include <AmiHobs.h>
+#include <FlashUpd.h>
+
+#include <Flash.h>
+#if (defined ReFlash_SUPPORT) && (ReFlash_SUPPORT == 1)
+#include "ReFlash.h"
+#endif
+#include "Capsule.h"
+
+//
+// Global variables
+//
+extern EFI_BOOT_SERVICES *pBS;
+
+#if FLASH_LOCK_EVENT_NOTIFY == 1
+
+VOID *gSbHobList = NULL;
+static EFI_GUID gHobListGuid = HOB_LIST_GUID;
+
+// Core 4.6.5.2 sources GUID
+#ifndef AMI_EVENT_FLASH_WRITE_LOCK
+// {49D34AE7-1348-4551-8F71-467D8C0E4EF5}
+#define AMI_EVENT_FLASH_WRITE_LOCK \
+ { 0x49D34AE7, 0x9454, 0x4551, 0x8F, 0x71, 0x46, 0x7D, 0x8C, 0x0E, 0x4E, 0xF5 }
+#endif
+
+#define BDS_CONNECT_DRIVERS_PROTOCOL_GUID \
+ { 0x3aa83745, 0x9454, 0x4f7a, 0xa7, 0xc0, 0x90, 0xdb, 0xd0, 0x2f, 0xab, 0x8e }
+
+EFI_GUID gBiosLockEnableEventGuid = AMI_EVENT_FLASH_WRITE_LOCK;
+EFI_GUID gBdsConnectDriversProtocolGuid = BDS_CONNECT_DRIVERS_PROTOCOL_GUID;
+
+EFI_EVENT mSecureModEvent;
+VOID *mSecureModReg;
+#endif //#if FLASH_LOCK_EVENT_NOTIFY == 1
+
+//----------------------------------------------------------------------------
+// Function definitions
+//----------------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReadyToLockCallback
+//
+// Description: ready to Lock Flash part
+// Signal a event for ready to lock.
+//
+// Input: Event - The event that triggered this notification function
+// ParentImageHandle - Pointer to the notification functions context
+//
+// Output: VOID
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+#if FLASH_LOCK_EVENT_NOTIFY == 1
+VOID
+ReadyToLockCallback (
+ EFI_EVENT Event,
+ VOID *ParentImageHandle
+ )
+{
+ EFI_HANDLE Handle = NULL;
+ TRACE((-1,"\nSecure Fl Upd: FlashReadyToLock callback\n"));
+
+// Signal Event.....
+ pBS->InstallProtocolInterface (
+ &Handle, &gBiosLockEnableEventGuid, EFI_NATIVE_INTERFACE,NULL
+ );
+ pBS->UninstallProtocolInterface (
+ Handle,&gBiosLockEnableEventGuid, NULL
+ );
+ //
+ //Kill the Event
+ //
+ pBS->CloseEvent(Event);
+}
+
+#endif //#if FLASH_LOCK_EVENT_NOTIFY == 1
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UpdateAutoFlash
+//
+// Description: This is the standard EFI driver entry point called for
+// Recovery flash module initlaization
+// Input: IN EFI_HANDLE ImageHandle - ImageHandle of the loaded driver
+// IN EFI_SYSTEM_TABLE SystemTable - Pointer to the System Table
+//
+// Output: EFI_SUCCESS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS UpdateAutoFlash ()
+{
+ EFI_STATUS Status;
+ UINT32 Attributes;
+ UINTN Size;
+#if (defined ReFlash_SUPPORT) && (ReFlash_SUPPORT == 1)
+ AUTOFLASH AutoFlash;
+ static EFI_GUID guidReFlash = RECOVERY_FORM_SET_GUID;
+#endif //#if (defined ReFlash_SUPPORT) && (ReFlash_SUPPORT == 1)
+ static EFI_GUID FlashUpdGuid = FLASH_UPDATE_GUID;
+ static EFI_GUID CapsuleBootModeGuid = EFI_CAPSULE_AMI_GUID;
+ AMI_FLASH_UPDATE_BLOCK FlashUpdDesc;
+
+// Prep the FlashOp variable
+ Attributes = 0;
+ Size = sizeof(AMI_FLASH_UPDATE_BLOCK);
+ Status = pRS->GetVariable( FLASH_UPDATE_VAR,&FlashUpdGuid,&Attributes,&Size, &FlashUpdDesc);
+ if(!EFI_ERROR(Status))
+ {
+ // Erase Flash Var
+ pRS->SetVariable (FLASH_UPDATE_VAR,&FlashUpdGuid,Attributes,0,NULL);
+ // Clear pending Capsule Update Var
+ // only if FlashOp is pending. We don't want to interfere with other types of Capsule Upd
+ Size = 0;
+ if(pRS->GetVariable(CAPSULE_UPDATE_VAR,&CapsuleBootModeGuid, &Attributes, &Size, NULL)==EFI_BUFFER_TOO_SMALL)
+ pRS->SetVariable(CAPSULE_UPDATE_VAR,&CapsuleBootModeGuid, Attributes, 0, NULL);
+#if (defined ReFlash_SUPPORT) && (ReFlash_SUPPORT == 1)
+ // Update ReFlash parameters
+ Size = sizeof(AUTOFLASH);
+ Status = pRS->GetVariable(L"Setup",&guidReFlash, &Attributes, &Size, &AutoFlash);
+ if(!EFI_ERROR(Status))
+ {
+
+ AutoFlash.UpdateNv = (FlashUpdDesc.ROMSection & (1<<FV_NV)) ? 1 : 0;
+ AutoFlash.UpdateBb = (FlashUpdDesc.ROMSection & (1<<FV_BB)) ? 1 : 0;
+ AutoFlash.UpdateMain=(FlashUpdDesc.ROMSection & (1<<FV_MAIN)) ? 1 : 0;
+ // EC block
+#if (defined EC_FIRMWARE_UPDATE_INTERFACE_SUPPORT) && (EC_FIRMWARE_UPDATE_INTERFACE_SUPPORT == 1)
+ AutoFlash.UpdateEC =(FlashUpdDesc.ROMSection & (1<<ROM_EC)) ? 1 : 0;
+#endif
+ pRS->SetVariable(L"Setup",&guidReFlash, Attributes, sizeof(AUTOFLASH), &AutoFlash);
+ }
+#endif //#if (defined ReFlash_SUPPORT) && (ReFlash_SUPPORT == 1)
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SecFlashUpdDxe_Init
+//
+// Description: Entry point of Flash Update Policy driver
+//
+// Input: EFI_HANDLE ImageHandle,
+// EFI_SYSTEM_TABLE *SystemTable
+//
+// Output: EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SecFlashUpdDxe_Init (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_STATUS Status;
+
+ InitAmiLib(ImageHandle, SystemTable);
+
+ Status = UpdateAutoFlash();
+///////////////////////////////////////////////////////////////////////////////
+//
+// Create Flash Lock event.
+//
+///////////////////////////////////////////////////////////////////////////////
+#if FLASH_LOCK_EVENT_NOTIFY == 1
+ // Get Hob List
+ gSbHobList = GetEfiConfigurationTable(SystemTable, &gHobListGuid);
+ if (!gSbHobList)
+ return EFI_INVALID_PARAMETER;
+
+// Locking SPI before BDS Connect on normal boot
+ if (((EFI_HOB_HANDOFF_INFO_TABLE*)gSbHobList)->BootMode!=BOOT_IN_RECOVERY_MODE &&
+ ((EFI_HOB_HANDOFF_INFO_TABLE*)gSbHobList)->BootMode!=BOOT_ON_FLASH_UPDATE
+ )
+ Status = RegisterProtocolCallback ( &gBdsConnectDriversProtocolGuid, \
+ ReadyToLockCallback, \
+ NULL, \
+ &mSecureModEvent, \
+ &mSecureModReg );
+// Locking SPI after ReFlash(BDS) if in Recoovery/Flash Upd mode
+ else
+ Status = CreateReadyToBootEvent ( TPL_CALLBACK,
+ ReadyToLockCallback,
+ NULL,
+ &mSecureModEvent);
+
+ ASSERT_EFI_ERROR (Status);
+#endif
+
+ return Status;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (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/SecFlashUpd/SecFlashUpdDxe.dxs b/Core/EM/SecurityPkg/SecFlashUpd/SecFlashUpdDxe.dxs
new file mode 100644
index 0000000..f55eee7
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecFlashUpd/SecFlashUpdDxe.dxs
@@ -0,0 +1,58 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/FlashUpdate/SecFlashUpdDxe.dxs 4 3/18/14 3:01p Alexp $
+//
+// $Revision: 4 $
+//
+// $Date: 3/18/14 3:01p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureFlashPkg/FlashUpdate/SecFlashUpdDxe.dxs $
+//
+// 4 3/18/14 3:01p Alexp
+// set 2014 in file hdr & ftr
+//
+// 3 11/10/11 4:38p Alexp
+// 1. UpdateAutoFlash() updates the AutoFlash Variable installed by
+// ReFlash driver in Recovery/Flash Update flows
+// 2. Issue FlashReadyToLock Event notification based on the Flash Update
+// policy.
+//
+// 2 7/20/11 7:16p Alexp
+// remove dependency on Capsule module
+//
+// 1 7/01/11 4:39p Alexp
+//
+//**********************************************************************
+#include <Protocol/AmiDigitalSignature.h>
+
+DEPENDENCY_START
+ AMI_DIGITAL_SIGNATURE_PROTOCOL_GUID
+DEPENDENCY_END
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/SecFlashUpd/VerifyFwCapsule.c b/Core/EM/SecurityPkg/SecFlashUpd/VerifyFwCapsule.c
new file mode 100644
index 0000000..9bc9693
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecFlashUpd/VerifyFwCapsule.c
@@ -0,0 +1,974 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (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/FlashUpdate/VerifyFwCapsule.c 41 9/30/14 3:34p Alexp $
+//
+// $Revision: 41 $
+//
+// $Date: 9/30/14 3:34p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureFlashPkg/FlashUpdate/VerifyFwCapsule.c $
+//
+// 41 9/30/14 3:34p Alexp
+// EIP185686:Build error with Recovery_SUPPORT = 0
+//
+// 40 7/03/14 10:15a Alexp
+// EIP176297: Fix bug in condition expresison inside For loops.
+//
+// [Files] VerifyFwCapsule.c
+//
+// 39 6/13/14 10:08a Alexp
+// VerifyFwCapsule(): With dummy FwKey function returns no error but with
+// set Key flag.
+// The Recovery page must display the warning and user prompt.
+//
+// 38 4/24/14 3:17p Alexp
+// Fix build error when REFLASH_INTERACTIVE is 0
+//
+// 37 3/20/14 11:34a Alexp
+// 1. EIP149817: don't override a default Recovery file name defined by
+// RECOVERY_ROM
+// 2. Add logic to ignore Capsule Verify error if dummy FwKey is detected.
+// The feature is activated only when REFLASH_INTERACTIVE mode is ON
+// 3. VerifyFwCapsule: FwCap RomImageOffset checked against max size
+// (FWCAPSULE_IMAGE_SIZE-FLASH_SIZE)
+//
+// 36 12/12/13 10:11a Alexp
+//
+// 34 8/22/13 11:36a Alexp
+// VerifyFwCertRsa2048Sha256() - Break a loop after RootCert Verify
+// if key match is found. Old code would cycle through all root certs.
+//
+// 33 8/12/13 4:35p Alexp
+// 1. Add check for an end of Certificate block
+// 2. Chnage Ignore_rollback behavior. Won't skip Project Tag check
+//
+// 32 7/11/13 3:39p Alexp
+// Removed check for FWCAPSULE_MAX_HDR_SIZE. Replaced it with fixed 0x8000
+// value
+//
+// 31 6/28/13 12:01p Alexp
+// restore logic to return FwCapsule file name as expected Recovery file
+// name
+//
+// 30 6/21/13 11:02a Alexp
+// HashFwRomMapImage() - add check for 32bit address overflow
+//
+// 29 6/12/13 3:48p Alexp
+// VerifyFwCertRsa2048Sha256() - parse multiple chained RootKey
+// certificate structures in FwCert header
+//
+// 28 5/01/13 6:16p Alexp
+// VerifyFwImage() - ignore verification if no FwKey file is detected in
+// FV_BB
+//
+// 26 2/21/13 4:00p Alexp
+// update IGNORE_IMAGE_ROLLBACK logic.
+//
+// 25 1/24/13 4:05p Alexp
+// Made IGNORE_IMAGE_ROLLBACK depend on REFLASH_INTERACTIVE
+// Disable revision rollback check if interactive flag is set
+//
+// 24 12/17/12 2:45p Alexp
+// fix cppcheck style check finds
+//
+// 23 11/21/12 10:38a Alexp
+// EIP#105015: Add support for Pkcs7# Certificates in Aptio Fw Capsule
+// update packages
+//
+// 22 11/20/12 3:32p Alexp
+// EIP[104046]: Findings from Security review on Aptio4 Image verification
+// Includes the fix for item #10: hardening of RomMap parsing oin
+// FwCapsule update
+//
+// 21 11/13/12 3:29p Alexp
+// 1. Calculate offset to RomLayout table within FwCapsHdr instead of
+// using hardwired location. Pkcs#7 cert may overlap fixed RomMap field
+// 2. Remove dependency on FWSIG_SIGNHDR flag. Use Capsule flags instead.
+//
+// 20 10/18/12 10:43a Alexp
+// VerifyFwImage:
+// sanity check for buffer overruns.
+// Applied for FwCapsules with Hdr on top of the Payload
+//
+// 19 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
+//
+// 18 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
+//
+// 17 5/18/12 4:35p 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
+//
+// 16 4/25/12 2:12p Alexp
+// New logic extends search for matching Platform FW Key inside Signing
+// and then RootKey
+// certificates in the Cap Hdr
+//
+// 14 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
+//
+// 13 2/29/12 4:11p Alexp
+// Update format of Capsule signiing:
+// 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 nee dfor resigning of RootCert each time SignCert is being created
+//
+// 12 2/13/12 2:07p Alexp
+// GetFidData: Use 1 byte alligned pointer in searching "Section Guid".
+// Fixes the issue with RomMap entries that are not 4 byte alligned
+//
+// 11 12/29/11 3:59p Alexp
+// VerifyProjectId().
+// Calculate size of ProjectId string based on SDL Token PROJECT_TAG
+//
+// 10 11/30/11 8:02p Alexp
+// FW Revision searched inside FID structure.
+// Simplified the search throughout FW block by 4byte aligned $FID
+// signature only
+//
+// 9 11/08/11 3:08p Alexp
+// match the name "FW"CAPSULE_FILE_NAME to one defined in SDL token
+//
+// 8 11/03/11 6:39p Alexp
+// restored FwCapsuleInfo()
+//
+// 7 10/17/11 11:33a Alexp
+// Replace old method to detect FlashUpd with single IsFlashUpdate() hook
+// to be called from SbPei.c ->GetBootMode
+//
+// 6 10/11/11 12:24p Alexp
+// VerifyFwRevision(): removed unused input parameter: **PeiServices
+//
+// 5 9/29/11 3:25p Alexp
+// Bug fix. EIP#71244: No Rollback support
+//
+// 4 9/20/11 2:25p Alexp
+// change BootMode from Recovery to BOOT_ON_FLASH_UPDATE if FlUpdate is
+// pending.
+//
+// 3 8/05/11 3:19p Alexp
+// add condition to skip Revision check. Ignore rollback protection
+//
+// 2 7/20/11 7:16p Alexp
+// remove dependency on Capsule module
+//
+// 1 7/01/11 4:39p Alexp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------
+//
+// Name: VerifyFwCapsule.c - PEI secured recovery services
+//
+// Description: File contains VerifyFwCapsule hook to evaluate Fw Capsule
+//
+//----------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//----------------------------------------------------------------------------
+// Includes
+// Statements that include other files
+#include "Efi.h"
+#include "Pei.h"
+#include "token.h"
+#include <AmiPeiLib.h>
+#include <Hob.h>
+#include <RomLayout.h>
+#include <Ffs.h>
+#include <Ppi\ReadOnlyVariable.h>
+#include <FlashUpd.h>
+#include <PPI\CryptoPPI.h>
+#include <PPI\FwVersion.h>
+#include <Protocol\Hash.h>
+#include "AmiCertificate.h"
+#include <BaseCryptLib.h>
+
+//----------------------------------------------------------------------------
+// Function Externs
+
+//----------------------------------------------------------------------------
+// Local prototypes
+EFI_STATUS
+FwCapsuleInfo (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT VOID **pCapsuleName,
+ IN OUT UINTN *pCapsuleSize,
+ OUT BOOLEAN *ExtendedVerification
+);
+
+//----------------------------------------------------------------------------
+typedef struct {
+ EFI_FFS_FILE_HEADER FfsHdr;
+ EFI_COMMON_SECTION_HEADER SecHdr;
+ EFI_GUID SectionGuid;
+ UINT8 FwCapHdr[0];
+} AMI_FFS_COMMON_SECTION_HEADER;
+
+typedef struct _FID_SECTION {
+ EFI_GUID Guid;
+ FW_VERSION FwVersion;
+} FID_SECTION;
+
+//----------------------------------------------------------------------------
+// Local Variables
+static EFI_GUID FwCapFfsGuid = AMI_FW_CAPSULE_FFS_GUID;
+static EFI_GUID FwCapSectionGuid = AMI_FW_CAPSULE_SECTION_GUID;
+static EFI_GUID FidSectionGuid = \
+ { 0x2EBE0275, 0x6458, 0x4AF9, 0x91, 0xed, 0xD3, 0xF4, 0xED, 0xB1, 0x00, 0xAA };
+
+const UINT8 *FidSignature = "$FID";
+
+EFI_PEI_SERVICES **gPeiServices;
+static AMI_CRYPT_DIGITAL_SIGNATURE_PPI *gpAmiSigPPI=NULL;
+
+//static EFI_GUID gAmiDigitalSignaturePPIGuid = AMI_DIGITAL_SIGNATURE_PPI_GUID;
+static EFI_GUID gFWCapsuleGuid = APTIO_FW_CAPSULE_GUID;
+static EFI_GUID gEfiCertRsa2048Guid = EFI_CERT_RSA2048_GUID;
+static EFI_GUID gFWkeyGuid = PR_KEY_GUID;
+static EFI_GUID gEfiHashAlgorithmSha256Guid = EFI_HASH_ALGORITHM_SHA256_GUID;
+static EFI_GUID gEfiCertX509Guid = EFI_CERT_X509;
+static EFI_GUID gEfiCertTypePkcs7Guid = EFI_CERT_TYPE_PKCS7_GUID;
+
+static EFI_GUID gPeiReadOnlyVariablePpiGuid = EFI_PEI_READ_ONLY_VARIABLE_PPI_GUID;
+static AMI_FLASH_UPDATE_BLOCK gFlashUpdDesc;
+
+//const char *RecoveryCapFileName = CONVERT_TO_STRING(FWCAPSULE_FILE_NAME);
+const UINTN RecoveryCapImageSize = FWCAPSULE_IMAGE_SIZE;
+
+static UINT8 gHashDB[SHA256_DIGEST_SIZE];
+// Allocate Hash Descr table
+static UINTN *gAddrList=NULL;
+static UINTN *gLenList=NULL;
+static UINTN gHashNumElem=0;
+
+//----------------------------------------------------------------------------
+// Function Definitions
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: VerifyProjectId
+//
+// Description:
+//
+// Input:
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN
+VerifyProjectId (
+ IN FW_VERSION *FwVersionData,
+ IN OUT UINT32 *FailedVTask
+)
+{
+ 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];
+*/
+ *FailedVTask = Ver;
+// Project ID, Major, Minor rev
+PEI_TRACE((-1, gPeiServices, "\nOrgBiosTag=%s,NewBiosTag=%s\nPrjMajVer=%02d, NewMajVer=%s\nPrjMinorVer=%02d, 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
+// Physically present user may override roll back protection from Setup screen
+ if(Atoi(FwVersionData->ProjectMajorVersion) < PROJECT_MAJOR_VERSION ||
+ Atoi(FwVersionData->ProjectMinorVersion) < PROJECT_MINOR_VERSION)
+#if (defined(REFLASH_INTERACTIVE) && REFLASH_INTERACTIVE==1)
+ return TRUE;
+#else
+ return FALSE;
+#endif
+#endif
+
+ *FailedVTask = 0;
+
+ 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,
+ IN OUT UINT32 *FailedVTask
+)
+{
+ ROM_AREA *Area;
+ EFI_PHYSICAL_ADDRESS FvAddress;
+ FW_VERSION *FwVersionData;
+
+ *FailedVTask = Ver;
+
+ 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, FailedVTask))
+ 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;
+}
+
+//<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 = FwCapFfsGuid.Data1;
+
+ do {
+ if(*SearchPointer == Signature) {
+ FileSection = (AMI_FFS_COMMON_SECTION_HEADER *)SearchPointer;
+ if(!guidcmp(&FwCapFfsGuid, &(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 i, RomMap_size, max_num_elem, num_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;
+ num_elem+=2; // add 2 extra entries
+
+ if(!gAddrList || !gHashNumElem || gHashNumElem<num_elem) {
+ gHashNumElem = num_elem;
+ i = num_elem*sizeof(UINTN);
+ Status = (*gPeiServices)->AllocatePool(gPeiServices, i*2, &gAddrList);
+ ASSERT_PEI_ERROR (gPeiServices, Status);
+ if(EFI_ERROR(Status)) return Status;
+ gLenList = (UINTN*)((UINT8*)gAddrList + i);
+ }
+ num_elem = 0;
+ for(i=0; i < max_num_elem && num_elem < gHashNumElem && 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
+ gAddrList[num_elem] = (UINTN)((UINTN)Payload + RomAreaTbl[i].Offset);
+ gLenList[num_elem] = RomAreaTbl[i].Size;
+
+ num_elem++;
+
+ }
+ if(num_elem >= gHashNumElem) return EFI_SECURITY_VIOLATION;
+//
+// Hash of Capsule Hdr + FW Certificate Hdr
+//
+ if(FWCapsuleHdr->CapHdr.Flags & CAPSULE_FLAGS_CAPHDR_IN_SIGNCERT) {
+ gAddrList[num_elem] = (UINTN) FWCapsuleHdr;
+ gLenList[num_elem] = (UINTN)&FWCapsuleHdr->FWCert.SignCert.CertData - (UINTN)FWCapsuleHdr;
+ num_elem++;
+ if(num_elem >= gHashNumElem) return EFI_SECURITY_VIOLATION;
+ }
+//
+// Hash of the ROM_MAP table
+//
+ gAddrList[num_elem] = (UINTN)RomAreaTbl;
+ gLenList[num_elem] = (i+1)*sizeof(ROM_AREA);
+ num_elem++;
+
+ Status = gpAmiSigPPI->Hash(gpAmiSigPPI, &gEfiHashAlgorithmSha256Guid,
+ num_elem, (const UINT8**)gAddrList, (const UINTN*)gLenList, gHashDB );
+
+// PEI_TRACE((-1, gPeiServices, "Hash the FW Image %r\n", Status));
+
+ 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,
+ IN PEI_CRYPT_HANDLE *PubKeyHndl,
+ IN OUT UINT32 *FailedVTask
+){
+ EFI_STATUS Status;
+ UINT8 *Pkcs7Cert, *pDigest;
+ UINTN Pkcs7Cert_len, DigestLen;
+
+//
+// 1. Validate Root Key
+//
+ *FailedVTask = Key;
+
+ if( PubKeyHndl->Blob==NULL)
+ return EFI_SECURITY_VIOLATION;
+
+ if(guidcmp(&PubKeyHndl->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
+//
+ *FailedVTask = Sig;
+
+ 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);
+
+ return gpAmiSigPPI->VerifyPkcs7Sig( gpAmiSigPPI,
+ Pkcs7Cert, Pkcs7Cert_len, // Pkcs7Cert
+ PubKeyHndl->Blob, PubKeyHndl->BlobSize, // TrustCert
+ &pDigest, &DigestLen // In/OutData
+ );
+}
+
+//<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,
+ IN OUT UINT32 *FailedVTask
+){
+ EFI_STATUS Status;
+ PEI_CRYPT_HANDLE HashHndl;
+ PEI_CRYPT_HANDLE PubKeyHndl;
+ UINT8 *pSig;
+ UINT32 Flags=0;
+ UINT8 *Addr;
+ UINTN Size;
+ EFI_CERT_BLOCK_RSA_2048_SHA256* pRootCert;
+
+// Versions 010 and later support 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 = (UINT8*)&gHashDB;
+//
+// 1. Compare Capsule's Sign Cert key with Platform Root Key
+//
+ *FailedVTask = Key;
+
+ PubKeyHndl.BlobSize = DEFAULT_RSA_KEY_MODULUS_LEN;
+ PubKeyHndl.AlgGuid = gEfiCertRsa2048Guid;
+ PubKeyHndl.Blob = (UINT8*)FWCapsuleHdr->FWCert.SignCert.CertData.PublicKey;
+ Status = gpAmiSigPPI->VerifyKey(gpAmiSigPPI, &gFWkeyGuid, &PubKeyHndl);
+ PEI_TRACE((-1, gPeiServices, "Compare Platform and SignCert Keys : %r\n", Status));
+// Skip the RootCert key checking if SignCert Key and PR Key are matching
+ 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 = (UINT8*)pRootCert->PublicKey;
+ Status = gpAmiSigPPI->VerifyKey(gpAmiSigPPI, &gFWkeyGuid, &PubKeyHndl);
+ PEI_TRACE((-1, gPeiServices, "Compare Platform and RootCert Keys : %r\n", 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 = gpAmiSigPPI->Hash(gpAmiSigPPI,&gEfiHashAlgorithmSha256Guid, 1,&Addr,(const UINTN*)&Size, gHashDB);
+ if (EFI_ERROR(Status)) break;
+
+ pSig = (void*)pRootCert->Signature;
+ Status = gpAmiSigPPI->VerifySig(gpAmiSigPPI, &PubKeyHndl, &HashHndl, pSig, DEFAULT_RSA_SIG_LEN, Flags );
+ PEI_TRACE((-1, gPeiServices, "Verify Root Cert : %r\n", Status));
+ break;
+ }
+ }
+ if (EFI_ERROR(Status)) return EFI_SECURITY_VIOLATION;
+//
+// 3. Verify Signing Cert
+//
+ *FailedVTask = Sig;
+//
+// 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;
+
+ return gpAmiSigPPI->VerifySig(gpAmiSigPPI, &PubKeyHndl, &HashHndl, pSig, DEFAULT_RSA_SIG_LEN, Flags);
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: VerifyFwImage
+//
+// Description: Function verifies various sections of the FW Capsule
+//
+// 0. Locate protocol AMI_CRYPT_DIGITAL_SIGNATURE_PPI
+// 1. Check if FV GUID matches Aptio FW Capsule.
+// - Yes -
+// update Payload ptr to beginning of BIOS ROM data
+// continue with Image Varify
+// - Not found at offs 0 - assume Cap Hdr is in FFS
+// locate FFS by Hole GUID, Sec GUID
+// update FWCapsuleHdr ptr,
+// continue with Image Varify
+// 2. Validate Root Certificate
+// -Compare PubKey in Root Certificate Hdr with local FW Platform Key
+// -Hash SignCert.PubKey
+// -VerifySig for RootCert.Signature and compare with SignCert.Key hash
+// 3. Validate Sign Certificate
+// -Hash the ROM image inside the FW Capsule
+// -VerifySig for SignCert.Signature and compare with ROM hash
+// 4. Update pCapsuleSize = FwPayload and set pCapsule to point to FW Payload
+//
+// Input:
+// PeiServices Pointer to PeiServices instance.
+// pCapsule Points to the start of the Aptio FW Capsule.
+// pCapsuleSize The size of buffer, in bytes.
+// FailedVTask Specifies additional flags to further customize the signing/verifying behavior.
+//
+// Output:
+// pCapsule ptr is set to start of Capsule's Payload - ROM image
+// pCapsuleSize return ROM image size
+// EFI_SUCCESS The signature is successfully verified.
+// EFI_SECURITY_VIOLATION The signature does not match the given message.
+// EFI_ACCESS_DENIED The key could not be used in signature operation.
+// EFI_INVALID_PARAMETER The size of input message or signature does not meet the criteria
+// of the underlying signature algorithm.
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+VerifyFwImage(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT VOID **pCapsule,
+ IN OUT UINT32 *pCapsuleSize,
+ IN OUT UINT32 *FailedVTask
+){
+ EFI_STATUS Status;
+ APTIO_FW_CAPSULE_HEADER *FWCapsuleHdr;
+ UINT8 *Payload;
+ UINTN RomSize;
+ PEI_CRYPT_HANDLE PubKeyHndl;
+ UINT8 Byte;
+ UINTN Size;
+
+ gPeiServices = PeiServices;
+
+ PEI_TRACE((-1, PeiServices, "\nValidate FW Capsule ...\n"));
+
+// Predefined bit mask of checks to perform on Aptio FW Capsule
+ *FailedVTask = Cap;
+
+ Status = (*PeiServices)->LocatePpi(PeiServices, &gAmiDigitalSignaturePPIGuid, 0, NULL, &gpAmiSigPPI);
+ if(EFI_ERROR(Status)) return Status;
+
+ // ignore Verification if FwKey is not detected in the FW.
+ // Works with unsigned Aptio.ROM image or Signed ROM with embedded sig.
+ PubKeyHndl.BlobSize = 0;
+ PubKeyHndl.Blob = NULL;
+ Status = gpAmiSigPPI->GetKey(gpAmiSigPPI, &gFWkeyGuid, &PubKeyHndl);
+ PEI_TRACE((-1, PeiServices, "Get Root Cert Key (%r),0x%8X (%d bytes)\n", Status, (*(UINT32*)PubKeyHndl.Blob), PubKeyHndl.BlobSize));
+ if(EFI_ERROR(Status))
+ {
+#if (defined(REFLASH_INTERACTIVE) && REFLASH_INTERACTIVE==1)
+ if(Status == EFI_NOT_FOUND)
+ return EFI_SUCCESS;
+#endif
+ *FailedVTask = Key;
+ return Status;
+ }
+
+ FWCapsuleHdr = *pCapsule;
+ Payload = (UINT8*)*pCapsule;
+ RomSize = (UINTN)*pCapsuleSize;
+
+// verify Capsule Mailbox points to FW_CAPSULE hdr
+ if(guidcmp((EFI_GUID*)&FWCapsuleHdr->CapHdr.CapsuleGuid, &gFWCapsuleGuid))
+ {
+// looking FwCap hdr inside BIOS.ROM
+ if(EFI_ERROR(FindCapHdrFFS(Payload, (UINT8**)&FWCapsuleHdr)))
+ return EFI_SECURITY_VIOLATION;
+ }
+ PEI_TRACE((-1, PeiServices, "FW Capsule Hdr Detected...\n"));
+
+// 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;
+
+// Applied for FwCapsules with Hdr on top of the Payload
+ if( (UINT8*)*pCapsule ==(UINT8*) FWCapsuleHdr) {
+ if(FWCapsuleHdr->CapHdr.CapsuleImageSize > *pCapsuleSize)
+ return EFI_SECURITY_VIOLATION;
+ // Update pFwCapsule to point to beginning of Bios ROM
+ Payload = (UINT8*)((UINT32)FWCapsuleHdr + FWCapsuleHdr->RomImageOffset);
+ RomSize = (FWCapsuleHdr->CapHdr.CapsuleImageSize - FWCapsuleHdr->RomImageOffset);
+ }
+
+// Capsule Hdr sanity checks
+ if((RomSize > *pCapsuleSize) ||
+ (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 dummy FWkey - skip integrity check - only test the Capsule's structure
+ Byte = PubKeyHndl.Blob[0];
+ for(Size = 1; Size < PubKeyHndl.BlobSize && (Byte == PubKeyHndl.Blob[Size]); Size++);
+ if(Size == PubKeyHndl.BlobSize) {
+ *FailedVTask = Key;
+ PEI_TRACE((-1, PeiServices, "Dummy FW Key detected. Skip image verification...\n"));
+ } else
+ {
+// Begin Authentication
+ if(!guidcmp((EFI_GUID*)&FWCapsuleHdr->FWCert.SignCert.Hdr.CertType, &gEfiCertTypePkcs7Guid))
+ Status = VerifyFwCertPkcs7(FWCapsuleHdr, Payload, RomSize, &PubKeyHndl, FailedVTask);
+ else
+ Status = VerifyFwCertRsa2048Sha256(FWCapsuleHdr, Payload, RomSize, FailedVTask);
+
+ PEI_TRACE((-1, gPeiServices, "Verify Sign Certificate Sig : %r\n", Status));
+ if (EFI_ERROR(Status)) return Status;
+
+ *FailedVTask = 0;
+
+// Local PEI $FID is linked with CspLib. extern FW_VERSION FwVersionData;
+// Find $FID in new Fw FVs. Any instance found should do for us. Use RomMap from Capsule's Hdr
+// compare local BB and Main $Fid BIOS Major/Minor revs with New one.
+ Status = VerifyFwRevision(FWCapsuleHdr, Payload, FailedVTask);
+ PEI_TRACE((-1, PeiServices, "FW Revision test %r (FailedVTask = %x)\n", Status, *FailedVTask));
+ }
+
+ *pCapsule = (UINT32*)Payload;
+ *pCapsuleSize = RomSize;
+
+ return Status;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: FwCapsuleInfo
+//
+// Description: Updates the Recovery File name and size if defaults are
+// overriden in FlashUpd EFI Var.
+// Called from Recovery LoadRecoveryCapsule.
+//
+// pCapsuleName Pointer to the variable containing a Recovery File name
+// pCapsuleSize Pointer to the size of recovery image capsule, in bytes.
+// ExtendedVerification Indicates to Recovery module whether Fw Capsule
+// Recovery path will perform image size check.
+//
+// Output:
+// EFI_SUCCESS
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+FwCapsuleInfo (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT VOID **pCapsuleName,
+ IN OUT UINTN *pCapsuleSize,
+ OUT BOOLEAN *ExtendedVerification
+){
+ EFI_STATUS Status;
+ UINTN Size;
+ EFI_PEI_READ_ONLY_VARIABLE_PPI *ReadOnlyVariable = NULL;
+ EFI_GUID FlashUpdGuid = FLASH_UPDATE_GUID;
+
+ if(!pCapsuleName && !pCapsuleSize && !ExtendedVerification )
+ return EFI_UNSUPPORTED;
+
+ if(ExtendedVerification != NULL)
+ *ExtendedVerification = TRUE;
+
+ if(pCapsuleSize != NULL)
+ {
+ *pCapsuleSize = RecoveryCapImageSize;
+
+ if(pCapsuleName != NULL)
+ {
+// EIP149817: don't override a default recovery file name
+// *pCapsuleName = (VOID*)RecoveryCapFileName;
+
+ // Detect if we are in Flash Update mode and set some recovery global variables
+ // Read "FlashOp" Variable to update global RecoveryFileName, Size
+ Status = (*PeiServices)->LocatePpi( PeiServices,
+ &gPeiReadOnlyVariablePpiGuid,
+ 0,
+ NULL,
+ &ReadOnlyVariable );
+ // ASSERT_PEI_ERROR (PeiServices, Status);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ Size = sizeof(AMI_FLASH_UPDATE_BLOCK);
+ Status = ReadOnlyVariable->GetVariable( PeiServices,
+ FLASH_UPDATE_VAR,
+ &FlashUpdGuid,
+ NULL,
+ &Size,
+ &gFlashUpdDesc );
+ if(!EFI_ERROR(Status))
+ {
+ if(gFlashUpdDesc.FlashOpType == FlRecovery && gFlashUpdDesc.FwImage.AmiRomFileName[0] != 0)
+ *pCapsuleName = (VOID*)gFlashUpdDesc.FwImage.AmiRomFileName;
+
+ *pCapsuleSize = gFlashUpdDesc.ImageSize;
+ Status = (*PeiServices)->SetBootMode(PeiServices, BOOT_ON_FLASH_UPDATE);
+ }
+ PEI_TRACE((-1, PeiServices, "FW Capsule update %r\nImage Name %s, Size %x\n", Status, *pCapsuleName, *pCapsuleSize));
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (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.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 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/EM/SecurityPkg/SecureBootMod.c b/Core/EM/SecurityPkg/SecureBootMod.c
new file mode 100644
index 0000000..d8469fd
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecureBootMod.c
@@ -0,0 +1,2503 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SecureBoot_WIN8/SecureBootMod.c 80 5/14/15 9:45a Alexp $
+//`
+// $Revision: 80 $
+//
+// $Date: 5/14/15 9:45a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureBoot_WIN8/SecureBootMod.c $
+//
+// 80 5/14/15 9:45a Alexp
+// InstallSecureVariables() Update Default Provision logic to handle no
+// key defaults mode.
+// SecureBootMod_Init() Do not issue system reset if BootMode = FlUpdate
+// or Recovery
+//
+// 79 3/09/15 5:05p Alexp
+// 1. Implement User prompt to install Secure Boot key defaults
+// while switching of Secure Boot mode from Custom to Standard
+// (per Windows8+ Hardware Certification requirements).
+// Add callback on SECURE_BOOT_MODE_CHANGE_KEY
+// 2. EIP#200639: When the token DEFAULT_PROVISION_SECURE_VARS enable,
+// the secure boot status is Not Active when first enter setup.
+// [Resolution] Issue SystemReset after initial Secure Boot provisioning
+// 3. EIP#201422: set SecVariables_SUPPORT = 0, code will build fail
+//
+// 78 10/08/14 3:11p Alexp
+// FillAuthhdr(): Default times for Append and Set Variables are
+// different.
+// -Append uses time "2010.1.1.1" in order not to change var time during
+// updates.
+// -Set uses time of BIOS creation(original implementation)
+//
+// 77 4/11/14 10:20a Alexp
+// EIP#163153: [APTIO4] update 4.6.5.5_TCG_43 is build error.
+// Bug: Global var name NvramControl was shared with
+// TpmClearOnRollbackOfbd..
+// Fix: define variable as static
+//
+// 76 4/07/14 2:47p Alexp
+// Add Hii event SECURE_BOOT_MENU_REFRESH on entering of Secure Boot menu
+// The callback to this event refreshes the state of internal Secure Boot
+// setup flags.
+// UpdateSecureVariableBrowserInfo()
+//
+// 75 11/15/13 11:38a Alexp
+// TSE Callbacks return EFI_UNSUPPORTED for unsupported browser actions
+// Always clear RT attribute for SecureBootSetup var.
+//
+// 73 11/04/13 1:13p Alexp
+// ForceSetupModeCallback() . Load defaults fail with new TSE.
+// Return UNSUPPORTED for new TSE 2.16.1240 TSE callback event
+// EFI_BROWSER_ACTION_DEFAULT_STANDARD
+//
+// 72 10/04/13 12:49p Alexp
+// Define EXPOSE_SECURE_BOOT_SETUP_VAR_IF_NOT_SECURE_BOOT_MODE
+// switch to allow OS tools to gain access to Secure Boot setup control
+// only while system is not in Secure Boot mode
+//
+// 71 10/03/13 5:27p Alexp
+// SecureBootMod_Init()
+// Change the logic for clearing of RT attrib for SecureBoot Setup var:
+// only clear it if SecureBoot is active, else let OEM OS tools to see the
+// var
+//
+// 70 10/01/13 10:26a Alexp
+// 1. EIP#134931 :The value of "Secure Boot Option" items on
+// setup menu cannot be kept after flashed BIOS by AFU tool
+// 2. Prevent Preserve-, RestoreSecureVariables to be called out of order.
+//
+// 69 9/30/13 11:49a Alexp
+// EIP#137818 :SecureBootSetup variables are not preserved after flash
+// update even though PRESERVE_SECURE_VARIABLES enabled.
+// Fix: temporary toggle internal SMM NVRAM flag to gain access to non-RT
+// variables
+//
+// 68 8/15/13 10:09a Alexp
+// add handling of x509_SHAxx cert types while adding new certs to dbx
+// variable
+//
+// 67 7/26/13 3:32p Alexp
+// 1. EIP#118850: ECR1009: enable dbt dialogs.
+// 2. Allow selective Key var provisioning. e.g dbx or dbt are optional
+//
+// 66 6/24/13 5:29p Alexp
+// EIP127292: Erase SecureBootSetupVar before setting it with no RT
+// attribute
+//
+// 65 6/22/13 12:24p Alexp
+// EIP:127292: Remove RT attribute from SecureBootSetupVar.
+//
+// 64 5/17/13 6:06p Alexp
+// 1. Add action on KEY_PROVISION_CHANGE_KEY Enable. Prompt user to
+// install keys immediately
+// 2. Always install default Secure Keys as volatile vars based on SDL
+// Token
+// 3. EIP#118850: ECR1009: Add placeholder defines for "dbt"
+//
+// 62 5/01/13 1:54p Alexp
+// InstallSecureVariables() fix build errors if Secure Boot Vars module
+// not detected
+//
+// 61 3/22/13 4:59p Alexp
+// Optimized order in menu selecting option: Key Certificate before Efi
+// Variable
+//
+// 60 12/24/12 12:33p Alexp
+// EIP#108982 : "Secure Boot" Multilanguage Support missing
+// Move all local string defines under .uni
+// Retrieve strings using updated GetHiiString() function
+//
+// 59 12/17/12 3:08p Alexp
+// code fixes according to "cppcheck" style & performance suggestions
+//
+// 58 12/07/12 4:20p Alexp
+// Update Key Management page layout
+//
+// 56 11/26/12 10:45a Alexp
+// EIP#104961: UEFI 2.3.1 SCT test failed in Generic\EfiCompliant case.
+// Fix build warning with PRESERVE_SECURE_VARIABLES flag enabled.
+//
+// 54 11/19/12 4:40p Alexp
+// Fix for Win8 SecureBoot logo requirement: restore Secure Boot state
+// across flash updates.
+// Move all secure boot Setup settings to a separate varstore variable.
+// Preserve var across re-flash
+//
+// 53 11/16/12 7:16p Alexp
+// Fixed ValidateSignatureList() return status for Zero Data or Size
+//
+// 52 11/01/12 5:44p Alexp
+// bug fix: ValidateSignatureList () returned Success even if no sig
+// detected if file size = 0
+//
+// 51 10/22/12 3:53p Alexp
+// Fix interactive menus for Set/Append Key operations
+//
+// 50 10/22/12 10:49a Alexp
+// SetMode callback: fix dependency on SetupMode for SecureBoot Enable
+// switch.
+//
+// 49 10/19/12 5:15p Alexp
+// Serve both Set and Append Hii callbacks with common routine SetAppendDb
+//
+// 48 10/16/12 3:16p Alexp
+// 1. replaced wrong return types for Hi iCallback routines from
+// EFI_SUCCESS to EFI_STATUS
+// 2. Removed Authenticated attribute from generic R/O UEFI Variables
+// PKDefault, etc.
+//
+// 47 9/24/12 12:29p Alexp
+// 1. Update all callback functions to return EFI_STATUS according to
+// newer 4.6.5.4.1 Setup module
+// 2. Block Secure Boot switch from being enabled if CSM is enabled or
+// platform is in Setup Mode: ForceSetupModeCallback()
+// 41 9/07/12 5:13p Alexp
+// Remove dependency on newer Cores 4.6.5.0+:
+// CORE_COMBINED_VERSION >= 0x4028a
+// Win8 compliant BIOS must have upgraded
+// Core components, TSE
+//
+// 40 8/23/12 5:42p Alexp
+// Add user selection for supported file formats in Append SecureBoot
+// operations
+//
+// 39 8/15/12 4:48p Alexp
+// 1. Modify Secure Boot page controls. Hide all controls under new
+// sub-page
+// 2. Refrash Secure Boot Setup screens upon user load Defaults/Previous
+// values
+// 3.
+//
+// 38 8/01/12 3:55p Alexp
+// Link KEY_PROVISION_CHANGE_KEY event with common
+// ForceSetupModeCallback()
+//
+// 37 7/30/12 10:59a Alexp
+// Added code to address UEFI ECR874: Install Factory defaults as
+// Read-only volatile variables for key distribution.
+// Update Secure Boot page layout
+// 1. Security Page
+// 1.3 Replaced standalone SecureBootMode Option to an added value
+// in
+// Secure Boot list (on/off/custom)
+// 1.4 Display SecureBootMode Standard/Custom Status
+// 2. Key Management Page
+// 2.1 Add Append Certificate Options along with Append from File
+// New functions append new Certificates from different types
+// of
+// input Certs (x509, RSA2048 & SHA256) and Signature List
+// blobs
+// 2.2 Use single Save to files option for all Sec Variables
+// 2.3 Set Variable Option gets a Key from a File Browser or a
+// Factory Default storage.
+//
+//
+// 34 7/09/12 2:40p Alexp
+// HiiAddString
+// Fix build error if warning level=3
+//
+// 33 6/13/12 10:01a Alexp
+// Fix build warning for uninitialized VarSize in
+// PreserveSecureVariables()
+//
+// 32 6/11/12 3:21p Alexp
+// EIP:90468 UEFI Secure Boot implementation inquiry. When I export the
+// PK, KEK, DB, and DBX files from the Setup menu, I can't reload them.
+// FIX: Added logic to append dummy AuthHdr on top of exportable Variable
+// data in order to make file importable by Key Management page.
+//
+// 31 6/05/12 4:26p Alexp
+// EIP:91587 Function HiiLibSetBrowserData always return error under new
+// tse
+// Fix in UpdateSecureVariableBrowserInfo() -> call
+// HiiLibSetBrowserData() only when called form HiiCallback
+//
+// 30 5/15/12 9:46a Alexp
+// Preserve/Restore SecureVariables(). Use properly formatted Auth
+// Variable data block.
+//
+// 29 4/20/12 5:03p Alexp
+// EIP:88261: Default Secure Variables are being reinstalled on each
+// system reboot when "DEFAULT_PROVISION_SECURE_VARS" is enabled
+// Fix: Replaced usage of FORCE_SETUP_KEY and FORCE_DEFAULT_KEY with
+// dynamicaly generated values to fixed enum types RESET_NV_KEYS=1,
+// SET_NV_DEFAULT_KEYS
+//
+// 27 3/16/12 12:04p Alexp
+// made "PKeyFileGuid" names "static" to avoid double names across linked
+// modules
+//
+// 26 3/09/12 3:29p Alexp
+// Implementation to PRESERVE_SECURE_VARIABLES on Flash Update is moved
+// here from SecSmiFlash component
+//
+// 25 2/14/12 7:35p Alexp
+// SecureBootMod_Init: Update browser info after DefaultKeys are
+// provisioned.
+//
+// 24 2/02/12 12:59p Alexp
+// 1. AppendSecureBootDBCallback. Removed DEL attribute when do Append
+// 2. SetSecureVariable. optimized the logic
+//
+// 23 12/12/11 6:37p Alexp
+// Add check if "DEFAULT_PROVISION_SECURE_VARS" is defined.
+// Fix build error for condition SET_SECURE_VARS = 0
+//
+// 22 11/18/11 11:13a Alexp
+// ForceSetupModeCallback: Initialize Status as not all execution path
+// update this variable
+//
+// 21 11/10/11 4:02p Alexp
+// conditionallly compile all callback related code if
+// CORE_COMBINED_VERSION
+// >=0x4028a (4.6.5.0+)
+//
+// 19 11/08/11 3:05p Alexp
+// fix spelling errors in displayed messages
+//
+// 18 11/07/11 6:26p Alexp
+// Add Key Management controls to add/get/append and delete Secure
+// Variables from the Setup page
+//
+// 17 11/03/11 6:30p Alexp
+// SecureBootMod.c(sdl, .sd, .uni) Change the appearance of Secure Boot
+// items on Setup Security page. Added information on currently installed
+// Secure Variables.
+//
+// 16 10/17/11 6:55p Alexp
+// Add warning message if User Mode can't be reset due to the lock set on
+// Secure Variable update
+//
+// 13 8/25/11 8:30a Alexp
+// -ForceSetupModeCallback: proceed inside the function after check for
+// action-EFI_BROWSER_ACTION_CHANGING
+// -force manufacturing defaults during first boot if
+// DEFAULT_PROVISION_SECURE_VARS set to 1
+//
+// 11 8/23/11 4:50p Alexp
+//
+// 9 8/22/11 5:19p Alexp
+// restored CallBack notification method to set Manufacturing defaults
+// from TSE SetupPage
+//
+// 8 8/19/11 5:25p Alexp
+// removed callback events on Security Page updates
+// Use static Setup Flags to Update Secure Variables at boot time
+//
+// 5 8/05/11 3:15p Alexp
+// use globally defined names for PK, KEK,.. variable
+//
+// 4 7/18/11 9:57a Alexp
+// Added new protocol SECURITY_VARIABLE_INSTALL_PROTOCOL
+//
+// 3 7/01/11 1:30p Alexp
+// ForceSetupModeCallback: fix for EFI_REVISION < 2.1builds
+//
+//
+// 1 6/30/11 3:49p Alexp
+// Add provisioning of factory default Secure variables. Used Setup page
+// to add/remove sec variables
+//
+// 3 5/16/11 1:07p Alexp
+// include SDL switch to control provisioning of Platform Key EFI
+// variable.
+//
+// 2 5/10/11 5:12p Alexp
+// removed include statement
+//
+// 1 5/10/11 10:01a Alexp
+//
+// 6 4/18/11 7:23p Alexp
+// draft. may not need this file at all
+//
+//
+//**********************************************************************
+#include <Token.h>
+#include <AmiDxeLib.h>
+#include <ImageAuthentication.h>
+#include <AmiCertificate.h>
+#include <Protocol\AmiDigitalSignature.h>
+#include <Setup.h>
+#include <SecureBootMod.h>
+
+#include "timestamp.h"
+
+#include <AutoId.h>
+#include <SetupStrTokens.h>
+
+#include <Protocol\AmiPostMgr.h>
+#include <Protocol\simplefilesystem.h>
+#ifdef SETUP_COMPILE
+#include <Protocol\HiiString.h>
+#include <Protocol\devicepath.h>
+#endif
+
+extern EFI_RUNTIME_SERVICES *pRS;
+
+#if defined(CORE_COMBINED_VERSION) && CORE_COMBINED_VERSION >=0x4028b
+#define RETURN(status) {return status;}
+#else
+#define RETURN(status) {return ;}
+#endif
+//
+// Global variables
+//
+static EFI_GUID gAmiPostManagerProtocolGuid = AMI_POST_MANAGER_PROTOCOL_GUID;
+static EFI_GUID gSimpleFileSystemGuid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
+static EFI_GUID gEfiGlobalVariableGuid = EFI_GLOBAL_VARIABLE;
+
+//static EFI_GUID gEfiCertX509Sha256Guid = EFI_CERT_X509_SHA256_GUID;
+//static EFI_GUID gEfiCertX509Sha384Guid = EFI_CERT_X509_SHA384_GUID;
+//static EFI_GUID gEfiCertX509Sha512Guid = EFI_CERT_X509_SHA512_GUID;
+
+static EFI_GUID PKeyFileGuid = //CC0F8A3F-3DEA-4376-9679-5426BA0A907E
+{ 0xCC0F8A3F, 0x3DEA, 0x4376, 0x96, 0x79, 0x54, 0x26, 0xba, 0x0a, 0x90, 0x7e };
+static EFI_GUID KekFileGuid = // {9FE7DE69-0AEA-470a-B50A-139813649189}
+{ 0x9fe7de69, 0xaea, 0x470a, 0xb5, 0xa, 0x13, 0x98, 0x13, 0x64, 0x91, 0x89 };
+static EFI_GUID DbFileGuid = // {FBF95065-427F-47b3-8077-D13C60710998}
+{ 0xfbf95065, 0x427f, 0x47b3, 0x80, 0x77, 0xd1, 0x3c, 0x60, 0x71, 0x9, 0x98 };
+static EFI_GUID DbxFileGuid = // {9D7A05E9-F740-44c3-858B-75586A8F9C8E}
+{ 0x9d7a05e9, 0xf740, 0x44c3, 0x85, 0x8b, 0x75, 0x58, 0x6a, 0x8f, 0x9c, 0x8e };
+static EFI_GUID DbtFileGuid = // {C246FBBF-F75C-43F7-88A6-B5FD0CF1DB7F}
+{ 0xC246FBBF, 0xF75C, 0x43F7, 0x88, 0xa6, 0xb5, 0xfd, 0x0c, 0xf1, 0xdb, 0x7f };
+
+static AMI_POST_MANAGER_PROTOCOL *mPostMgr = NULL;
+
+static EFI_GUID *SecureVariableFileGuid [] = {
+ &DbxFileGuid,
+ &DbtFileGuid,
+ &DbFileGuid,
+ &KekFileGuid,
+ &PKeyFileGuid,
+ NULL
+};
+
+static CHAR16* SecureVariableFileName[] = {
+ EFI_IMAGE_SECURITY_DATABASE1,
+ EFI_IMAGE_SECURITY_DATABASE2,
+ EFI_IMAGE_SECURITY_DATABASE,
+ EFI_KEY_EXCHANGE_KEY_NAME,
+ EFI_PLATFORM_KEY_NAME,
+ NULL
+};
+
+static CHAR16* SecureVariableFileNameDefault[] = {
+ EFI_IMAGE_SECURITY_DATABASE1_DEFAULT,
+ EFI_IMAGE_SECURITY_DATABASE2_DEFAULT,
+ EFI_IMAGE_SECURITY_DATABASE_DEFAULT,
+ EFI_KEY_EXCHANGE_KEY_NAME_DEFAULT,
+ EFI_PLATFORM_KEY_NAME_DEFAULT,
+ NULL
+};
+
+static SECURE_BOOT_SETUP_VAR SecureBootSetup = {
+ DEFAULT_SECURE_BOOT_ENABLE,
+ DEFAULT_SECURE_BOOT_MODE,
+#ifdef DEFAULT_PROVISION_SECURE_VARS
+ DEFAULT_PROVISION_SECURE_VARS,
+#else
+ 0,
+#endif
+ LOAD_FROM_FV,
+ LOAD_FROM_OROM,
+ LOAD_FROM_REMOVABLE_MEDIA,
+ LOAD_FROM_FIXED_MEDIA};
+
+static EFI_GUID guidSecurity = SECURITY_FORM_SET_GUID;
+static UINT8 bKey[5] = {0, 0, 0, 0, 0};
+typedef enum { RESET_NV_KEYS=1, SET_NV_DEFAULT_KEYS=2, SET_RT_DEFAULT_KEYS=4};
+
+EFI_STATUS InstallSecureVariables (UINT16);
+VOID UpdateSecureVariableBrowserInfo (VOID);
+VOID UpdateSecureBootBrowserInfo (VOID);
+
+//
+//
+// AMI_EFI_VARIABLE_AUTHENTICATION_2 descriptor
+//
+// A time-based authentication method descriptor template
+//
+#pragma pack(1)
+#ifndef AMI_EFI_VARIABLE_AUTHENTICATION_2
+typedef struct {
+ EFI_TIME TimeStamp;
+ WIN_CERTIFICATE_UEFI_GUID_1 AuthInfo;
+} AMI_EFI_VARIABLE_AUTHENTICATION_2;
+#endif
+typedef struct {
+ AMI_EFI_VARIABLE_AUTHENTICATION_2 AuthHdr;
+ EFI_SIGNATURE_LIST SigList;
+ EFI_SIGNATURE_DATA SigData;
+} EFI_VARIABLE_SIG_HDR_2;
+#pragma pack()
+
+#define EFI_CERT_TYPE_RSA2048_SIZE 256
+#define EFI_CERT_TYPE_SHA256_SIZE 32
+#define EFI_CERT_TYPE_CERT_X509_SHA256_GUID_SIZE 48
+#define EFI_CERT_TYPE_CERT_X509_SHA384_GUID_SIZE 64
+#define EFI_CERT_TYPE_CERT_X509_SHA512_GUID_SIZE 80
+
+static EFI_GUID mSignatureSupport[SIGSUPPORT_NUM] = {SIGSUPPORT_LIST};
+
+#ifdef TSEBIN_COMPILE
+extern BOOLEAN gBrowserCallbackEnabled;
+#else
+BOOLEAN gBrowserCallbackEnabled = FALSE;
+#endif
+
+// InstallVars
+#define SET_SECURE_VARIABLE_DEL 1
+#define SET_SECURE_VARIABLE_SET 2
+#define SET_SECURE_VARIABLE_APPEND 4
+
+//#############################################################################################################################
+#ifdef SETUP_COMPILE
+//#############################################################################################################################
+typedef struct
+{
+ UINT64 Type;
+ UINTN Size;
+ CHAR16 *Name;
+ STRING_REF Token;
+} FILE_TYPE;
+
+static BOOLEAN gValidOption = FALSE;
+static EFI_HII_STRING_PROTOCOL *HiiString = NULL;
+static EFI_HII_HANDLE gHiiHandle;
+
+#define StrMaxSize 200
+static CHAR16 StrTitle[StrMaxSize], StrMessage[StrMaxSize];
+static CHAR16 StrTemp[StrMaxSize];
+
+EFI_STATUS DevicePathToStr(EFI_DEVICE_PATH_PROTOCOL *Path,CHAR8 **Str);
+EFI_STATUS FileBrowserLaunchFileSystem(BOOLEAN bSelectFile, OUT EFI_HANDLE **outFsHandle, OUT CHAR16 **outFilePath, OUT UINT8 **outFileBuf,OUT UINTN *size );
+VOID GetHiiString(IN EFI_HII_HANDLE HiiHandle, IN STRING_REF Token, UINTN DataSize, CHAR16 * pData);
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UpdateSecureBootBrowserInfo
+//
+// Description: Update Secure Boot flags status
+//
+// Input: none
+//
+// Output: none
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID UpdateSecureBootBrowserInfo ()
+{
+#if (defined(SETUP_COMPILE) || defined (TSEBIN_COMPILE)) && EFI_SPECIFICATION_VERSION >= 0x2000A
+ EFI_STATUS Status;
+ UINTN Size;
+ UINT8 Byte=0;
+ UINT32 Attributes=0;
+ BOOLEAN tmpBrowserCallbackEnabled = gBrowserCallbackEnabled;
+
+ gBrowserCallbackEnabled = TRUE;
+ Status = HiiLibSetBrowserData( sizeof(bKey), &bKey, &guidSecurity, AMI_SECURE_VAR_PRESENT_VAR);
+ Size = 1;
+ Status=pRS->GetVariable(EFI_SECURE_BOOT_NAME, &gEfiGlobalVariableGuid, (UINT32*)&Attributes, &Size, &Byte);
+ TRACE((-1,"SecureBoot=%x, status=%r\n", Byte, Status));
+ Status = HiiLibSetBrowserData(Size, &Byte, &gEfiGlobalVariableGuid, EFI_SECURE_BOOT_NAME);
+ Size = 1;
+ Status=pRS->GetVariable(EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (UINT32*)&Attributes, &Size, &Byte);
+ TRACE((-1,"SetupMode=%x, Status %r\n", Byte, Status));
+ Status = HiiLibSetBrowserData( Size, &Byte, &gEfiGlobalVariableGuid, EFI_SETUP_MODE_NAME);
+ gBrowserCallbackEnabled = tmpBrowserCallbackEnabled;
+#endif
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UpdateSecureVariableBrowserInfo
+//
+// Description: Detect 5 EFI Variables: PK, KEK, db, dbx, dbt(TBD)
+//
+// Input: none
+//
+// Output: none
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID UpdateSecureVariableBrowserInfo ()
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ UINT8 Index;
+ EFI_GUID *EfiVarGuid;
+
+ Index = 0;
+ while(SecureVariableFileName[Index] != NULL)
+ {
+ if(Index < 3)
+ EfiVarGuid = &gEfiImageSecurityDatabaseGuid;
+ else
+ EfiVarGuid = &gEfiGlobalVariableGuid;
+
+ Size = 0;
+ bKey[Index] = 0;
+ Status = pRS->GetVariable( SecureVariableFileName[Index], EfiVarGuid, NULL, &Size, NULL);
+ TRACE((-1,"NV Var %S, status=%r\n", SecureVariableFileName[Index], Status));
+ if(Status == EFI_BUFFER_TOO_SMALL)
+ bKey[Index] = 1;
+
+ Index++;
+ }
+ pRS->SetVariable(AMI_SECURE_VAR_PRESENT_VAR,&guidSecurity, EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof(bKey), &bKey);
+
+ UpdateSecureBootBrowserInfo();
+}
+
+#if SET_SECURE_VARS == 1
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: CryptoGetRawImage
+//
+// Description: Loads binary from RAW section of X firmware 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
+CryptoGetRawImage (
+ 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,
+ 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;
+}
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InstallSecureVariables
+//
+// Description: Install 4 EFI Variables: PK, KEK, db, dbx & dbt(TBD)
+//
+// Input: BOOLEAN InstallVars
+// TRUE - attempt to install 4 secure variables
+// FALSE - erase 4 secure variables
+//
+// Output: EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+InstallSecureVariables (
+ UINT16 InstallVars
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT8 *pVarBuffer = NULL;
+ UINT8 Index;
+ EFI_GUID *EfiVarGuid;
+ UINT32 Attributes;
+ UINTN FileSize = 0;
+#if SET_SECURE_VARS == 1
+ UINTN Size, Offset;
+ AMI_EFI_VARIABLE_AUTHENTICATION_2 *AuthHdr2;
+#endif
+///////////////////////////////////////////////////////////////////////////////
+// Initial provisioning of Authenticated non-volitile EFI Variables
+////////////////////////////////////////////////////////////////////////////////
+ Attributes = EFI_VARIABLE_RUNTIME_ACCESS |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS;
+ Index = 0;
+ while(/*!EFI_ERROR(Status) &&*/ SecureVariableFileName[Index] != NULL)
+ {
+ if(Index < 3)
+ EfiVarGuid = &gEfiImageSecurityDatabaseGuid;
+ else
+ EfiVarGuid = &gEfiGlobalVariableGuid;
+// if SET_NV_DEFAULT_KEYS set
+/*
+1. check if File is present CryptoGetRawImage
+2. if not - skip to next var
+3. if present -> move to Erase... .
+*/
+#if SET_SECURE_VARS == 1
+ if(InstallVars & (SET_NV_DEFAULT_KEYS | SET_RT_DEFAULT_KEYS)) {
+ pVarBuffer = NULL;
+ FileSize = 0 ;
+ Status = CryptoGetRawImage( SecureVariableFileGuid[Index], &pVarBuffer, (UINTN*)&FileSize);
+ if(EFI_ERROR(Status)) {
+ Index++;
+ continue;
+ }
+ }
+#endif
+ if((InstallVars & RESET_NV_KEYS)== RESET_NV_KEYS) {
+ // try to erase. should succeed if system in pre-boot and Admin mode
+ Status = pRS->SetVariable(SecureVariableFileName[Index],EfiVarGuid,0,0,NULL);
+ TRACE((-1,"Clear NV Var %S, Status %r\n",SecureVariableFileName[Index], Status));
+ if(EFI_ERROR(Status) && Status == EFI_NOT_FOUND)
+ Status = EFI_SUCCESS;
+ }
+#if SET_SECURE_VARS == 1
+ if((InstallVars & (SET_NV_DEFAULT_KEYS | SET_RT_DEFAULT_KEYS)) &&
+ pVarBuffer && FileSize
+ ){
+ if(InstallVars & (SET_RT_DEFAULT_KEYS)) {
+ AuthHdr2 = (AMI_EFI_VARIABLE_AUTHENTICATION_2*)pVarBuffer;
+ Offset = sizeof(EFI_TIME) + AuthHdr2->AuthInfo.Hdr.dwLength;
+ Status = pRS->SetVariable(SecureVariableFileNameDefault[Index],
+ &gEfiGlobalVariableGuid,
+ Attributes,
+ FileSize - Offset,
+ (UINT8*)pVarBuffer + Offset
+ );
+ TRACE((-1,"Set RT Var %S, Status %r\n",SecureVariableFileNameDefault[Index], Status));
+ }
+ if(InstallVars & (SET_NV_DEFAULT_KEYS)) {
+ Size = 0;
+ Status = pRS->GetVariable( SecureVariableFileName[Index], EfiVarGuid, NULL, &Size, NULL);
+ if(EFI_ERROR(Status) && Status == EFI_NOT_FOUND ) {
+ Status = pRS->SetVariable(SecureVariableFileName[Index],
+ EfiVarGuid,
+ (UINT32)(Attributes | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS),
+ FileSize,
+ pVarBuffer
+ );
+ TRACE((-1,"Set NV Var %S, Status %r\n",SecureVariableFileName[Index], Status));
+ }
+ }
+ pBS->FreePool(pVarBuffer);
+ }
+#endif
+ Index++;
+ }
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: FillAuthHdr
+//
+// Description:
+//
+// Input: NONE
+//
+// Output: NONE
+//
+// Returns: NONE
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+static VOID FillAuthHdr(
+ UINT8* pVar,
+ UINT8 VarSetMode
+)
+{
+ AMI_EFI_VARIABLE_AUTHENTICATION_2 *AuthHdr2;
+ static EFI_TIME EfiTime = {
+ FOUR_DIGIT_YEAR_INT,
+ TWO_DIGIT_MONTH_INT,
+ TWO_DIGIT_DAY_INT,
+ TWO_DIGIT_HOUR_INT,
+ TWO_DIGIT_MINUTE_INT,
+ TWO_DIGIT_SECOND_INT,0,0,0,0,0};
+
+ AuthHdr2 = (AMI_EFI_VARIABLE_AUTHENTICATION_2*)pVar;
+ MemCpy (&AuthHdr2->TimeStamp, &EfiTime, sizeof (EFI_TIME));
+ if((VarSetMode & SET_SECURE_VARIABLE_APPEND)== SET_SECURE_VARIABLE_APPEND)
+ AuthHdr2->TimeStamp.Year = 2000; // append should not change the original date the var was created
+ AuthHdr2->AuthInfo.Hdr.dwLength = sizeof(WIN_CERTIFICATE_UEFI_GUID_1);
+ AuthHdr2->AuthInfo.Hdr.wRevision = 0x200;
+ AuthHdr2->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
+ AuthHdr2->AuthInfo.CertType = gEfiCertTypePkcs7Guid;
+
+ return;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: FillAuthVarHdr
+//
+// Description:
+//
+// Input: NONE
+//
+// Output: NONE
+//
+// Returns: NONE
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID FillAuthVarHdr(
+ UINT8 *pVar,
+ UINT8 *pCert,
+ UINTN CertSize,
+ UINT8 VarSetMode
+)
+{
+ EFI_VARIABLE_SIG_HDR_2 *AuthHdr2;
+ static EFI_GUID AmiSigOwner = AMI_APTIO_SIG_OWNER_GUID;
+
+ AuthHdr2 = (EFI_VARIABLE_SIG_HDR_2*)pVar;
+
+ // Append AuthHdr to Var data.
+ FillAuthHdr(pVar, VarSetMode); // Append AuthHdr to Var data.
+
+ // CopyMem (&AuthHdr2->SigList.SignatureType, gEfiCertSha256Guid, sizeof (EFI_GUID));
+ if(CertSize == EFI_CERT_TYPE_SHA256_SIZE)
+ AuthHdr2->SigList.SignatureType = gEfiCertSha256Guid;
+ if(CertSize == EFI_CERT_TYPE_CERT_X509_SHA256_GUID_SIZE)
+ AuthHdr2->SigList.SignatureType = gEfiCertX509Sha256Guid;
+ if(CertSize == EFI_CERT_TYPE_CERT_X509_SHA384_GUID_SIZE)
+ AuthHdr2->SigList.SignatureType = gEfiCertX509Sha384Guid;
+ if(CertSize == EFI_CERT_TYPE_CERT_X509_SHA512_GUID_SIZE)
+ AuthHdr2->SigList.SignatureType = gEfiCertX509Sha512Guid;
+ if(CertSize == EFI_CERT_TYPE_RSA2048_SIZE)
+ AuthHdr2->SigList.SignatureType = gEfiCertRsa2048Guid;
+ if(CertSize > EFI_CERT_TYPE_RSA2048_SIZE)
+ AuthHdr2->SigList.SignatureType = gEfiCertX509Guid;
+
+ AuthHdr2->SigList.SignatureSize = (UINT32)(sizeof(EFI_GUID)+CertSize);
+ AuthHdr2->SigList.SignatureListSize = AuthHdr2->SigList.SignatureSize+sizeof(EFI_SIGNATURE_LIST);
+ AuthHdr2->SigList.SignatureHeaderSize = 0;
+ AuthHdr2->SigData.SignatureOwner = AmiSigOwner;
+
+TRACE((TRACE_ALWAYS,"SigList GUID: %g\nSigSize=%x\nListSize=%x", AuthHdr2->SigList.SignatureType, AuthHdr2->SigList.SignatureSize, AuthHdr2->SigList.SignatureListSize));
+
+// MemCpy(AuthHdr2->SigData.SignatureData, pCert, CertSize);
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ValidateSignatureList
+//
+// Description:
+// Validate the data payload begins with valid Signature List header
+// and based on the results returns Status.
+//
+// Input:
+// IN VOID *Data - pointer to the Var data
+// IN UINTN DataSize - size of Var data
+//
+// Output: EFI_STATUS
+// UINTN RealDataSize - only the size of the combined length of Signature Lists
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ValidateSignatureList (
+ IN VOID *Data,
+ IN UINTN DataSize
+)
+{
+ EFI_STATUS Status;
+ EFI_SIGNATURE_LIST *SigList;
+ UINTN Index;
+
+ Status = EFI_SECURITY_VIOLATION;
+
+ if(DataSize == 0 || Data == NULL)
+ return Status; // Sig not found
+
+ SigList = (EFI_SIGNATURE_LIST *)Data;
+
+// loop till end of DataSize for all available SigLists
+
+// Verify signature is one from SigDatabase list mSignatureSupport / sizeof(EFI_GUID)
+// SigData begins with SigOwner GUID
+// SignatureHdrSize = 0 for known Sig Types
+
+ while ((DataSize > 0) && (DataSize >= SigList->SignatureListSize)) {
+
+ for (Index = 0; Index < SIGSUPPORT_NUM; Index++) {
+ if (!guidcmp ((EFI_GUID*) &(SigList->SignatureType), &mSignatureSupport[Index]))
+ break;
+ }
+TRACE((TRACE_ALWAYS,"SigList.Type-"));
+ if(Index >= SIGSUPPORT_NUM)
+ return EFI_SECURITY_VIOLATION; // Sig not found
+
+TRACE((TRACE_ALWAYS,"OK\nSigList.Size-"));
+ if(SigList->SignatureListSize < 0x4C || // Min size for SHA2 Hash Certificate sig list
+ SigList->SignatureListSize > NVRAM_SIZE)
+ return EFI_SECURITY_VIOLATION;
+
+TRACE((TRACE_ALWAYS,"OK\nSigList.HdrSize-"));
+ if(SigList->SignatureHeaderSize != 0)
+ return EFI_SECURITY_VIOLATION; // Sig not found
+
+TRACE((TRACE_ALWAYS,"OK\n"));
+ DataSize -= SigList->SignatureListSize;
+ SigList = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + SigList->SignatureListSize);
+
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+#ifdef SMIFLASH_COMPILE
+
+#if defined(PRESERVE_SECURE_VARIABLES) && PRESERVE_SECURE_VARIABLES==1
+
+static EFI_GUID AmiNvramControlProtocolGuid = { 0xf7ca7568, 0x5a09, 0x4d2c, { 0x8a, 0x9b, 0x75, 0x84, 0x68, 0x59, 0x2a, 0xe2 } };
+typedef EFI_STATUS (*SHOW_BOOT_TIME_VARIABLES)(BOOLEAN Show);
+
+typedef struct{
+ SHOW_BOOT_TIME_VARIABLES ShowBootTimeVariables;
+} AMI_NVRAM_CONTROL_PROTOCOL;
+
+static AMI_NVRAM_CONTROL_PROTOCOL *NvramControl = NULL;
+
+// Array of pointers to Secure Variables in TSEG.
+static UINT8* SecureFlashVar[6];
+static UINTN SecureFlashVarSize[6];
+static UINT32 SecureFlashVarAttr[6];
+static UINT32 SecBootVar_Attr=0;
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: PreserveSecureVariables
+//
+// Description: Save the PK-KEK-db-dbx
+//
+// Input: NONE
+//
+// Output: NONE
+//
+// Returns: NONE
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID PreserveSecureVariables(VOID)
+{
+ EFI_STATUS Status;
+ UINT8 Index;
+ EFI_GUID *EfiVarGuid;
+ UINTN VarSize;
+
+TRACE((TRACE_ALWAYS,"PreserveVar:\n"));
+// 1. Preserve Secure Boot variables.
+ Index = 0;
+ while(SecureVariableFileName[Index] != NULL)
+ {
+ if(Index < 3)
+ EfiVarGuid = &gEfiImageSecurityDatabaseGuid;
+ else
+ EfiVarGuid = &gEfiGlobalVariableGuid;
+
+ SecureFlashVar[Index] = NULL;
+ SecureFlashVarSize[Index] = 0;
+ SecureFlashVarAttr[Index] = 0;
+ Status = pRS->GetVariable( SecureVariableFileName[Index], EfiVarGuid, &SecureFlashVarAttr[Index], &SecureFlashVarSize[Index], SecureFlashVar[Index]);
+ if(Status == EFI_BUFFER_TOO_SMALL)
+ {
+ VarSize = SecureFlashVarSize[Index]+sizeof(AMI_EFI_VARIABLE_AUTHENTICATION_2);
+ Status = pSmst->SmmAllocatePool(0, VarSize, (void**)&SecureFlashVar[Index]);
+ if(!EFI_ERROR(Status))
+ Status = pRS->GetVariable(
+ SecureVariableFileName[Index],
+ EfiVarGuid,
+ &SecureFlashVarAttr[Index],
+ &SecureFlashVarSize[Index],
+ SecureFlashVar[Index]+sizeof(AMI_EFI_VARIABLE_AUTHENTICATION_2));
+
+ SecureFlashVarSize[Index] = VarSize;
+ FillAuthHdr(SecureFlashVar[Index], SET_SECURE_VARIABLE_SET);
+
+TRACE((TRACE_ALWAYS,"%S (%r) Size=%x\n", SecureVariableFileName[Index], Status, SecureFlashVarSize[Index]));
+ }
+ Index++;
+ }
+// 2. Preserve Secure Boot Setup variables
+ // Set "Show BootTime Variables" flag
+ if (NvramControl == NULL) // first time?
+ NvramControl = GetSmstConfigurationTable(&AmiNvramControlProtocolGuid);
+ if (NvramControl == NULL)
+ return;
+ // Set "Show BootTime Variables" flag
+ NvramControl->ShowBootTimeVariables(TRUE);
+
+ VarSize = sizeof(SECURE_BOOT_SETUP_VAR);
+ Status = pRS->GetVariable (AMI_SECURE_BOOT_SETUP_VAR,&guidSecurity,&SecBootVar_Attr,&VarSize,&SecureBootSetup);
+TRACE((TRACE_ALWAYS,"SecureBootSetup (%r) Size=%x, SecBoot-%d, SecMode-%d,DefaultProvision-%d\n", Status, VarSize, SecureBootSetup.SecureBootSupport, SecureBootSetup.SecureBootMode,SecureBootSetup.DefaultKeyProvision));
+
+ // Clear "Show Boot Time Variables"
+ NvramControl->ShowBootTimeVariables(FALSE);
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: RestoreSecureVariables
+//
+// Description: Restore previous PK-KEK-db-dbx
+//
+// Input: NONE
+//
+// Output: NONE
+//
+// Returns: NONE
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID RestoreSecureVariables (VOID)
+{
+ EFI_STATUS Status;
+ UINT8 Index;
+ EFI_GUID *EfiVarGuid;
+
+TRACE((TRACE_ALWAYS,"RestoreVar:\n"));
+// 1. Restore Secure Boot variables.
+ Index = 0;
+ while(SecureVariableFileName[Index] != NULL)
+ {
+ if(SecureFlashVar[Index] && SecureFlashVarSize[Index])
+ {
+ if(Index < 3)
+ EfiVarGuid = &gEfiImageSecurityDatabaseGuid;
+ else
+ EfiVarGuid = &gEfiGlobalVariableGuid;
+
+ Status = pRS->SetVariable(SecureVariableFileName[Index],
+ EfiVarGuid,
+ SecureFlashVarAttr[Index],
+ SecureFlashVarSize[Index],
+ SecureFlashVar[Index]
+ );
+TRACE((TRACE_ALWAYS,"%S (%r) Size=%x Attr=%x\n", SecureVariableFileName[Index], Status, SecureFlashVarSize[Index], SecureFlashVarAttr[Index]));
+ pSmst->SmmFreePool(SecureFlashVar[Index]);
+ SecureFlashVar[Index] = NULL;
+ }
+ Index++;
+ }
+// 2. Restore Secure Boot Setup variables
+ // Set "Show BootTime Variables" flag
+ if (NvramControl == NULL)
+ return;
+ // Set "Show BootTime Variables" flag
+ NvramControl->ShowBootTimeVariables(TRUE);
+
+ Status = pRS->SetVariable (AMI_SECURE_BOOT_SETUP_VAR, &guidSecurity,SecBootVar_Attr, sizeof(SECURE_BOOT_SETUP_VAR),&SecureBootSetup);
+TRACE((TRACE_ALWAYS,"SecureBootSetup (%r)\n", Status));
+
+ // Clear "Show Boot Time Variables"
+ NvramControl->ShowBootTimeVariables(FALSE);
+
+}
+#endif //#if defined(PRESERVE_SECURE_VARIABLES) && PRESERVE_SECURE_VARIABLES==1
+#endif // #ifdef SMIFLASH_COMPILE
+
+//#############################################################################################################################
+#ifdef SETUP_COMPILE
+//#############################################################################################################################
+#ifndef EFI_LEGACY_BIOS_PROTOCOL_GUID
+// ## Include/Protocol/LegacyBios.h
+#define EFI_LEGACY_BIOS_PROTOCOL_GUID \
+{ 0xdb9a1e3d, 0x45cb, 0x4abb, { 0x85, 0x3b, 0xe5, 0x38, 0x7f, 0xdb, 0x2e, 0x2d }}
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IsCsmEnabled
+//
+// Description: This function checks if CSM is enabled
+//
+// Input:
+// None
+//
+// Output:
+// 0 - CSM is disabled
+// 1 - CSM is enabled
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN
+IsCsmEnabled(VOID)
+{
+ EFI_STATUS Status;
+ UINTN Size = sizeof(EFI_HANDLE);
+ EFI_HANDLE Handle;
+ static EFI_GUID EfiLegacyBiosProtocolGuid = EFI_LEGACY_BIOS_PROTOCOL_GUID;
+
+ Status = pBS->LocateHandle(ByProtocol, &EfiLegacyBiosProtocolGuid, NULL, &Size, &Handle);
+ return (EFI_ERROR(Status)) ? 0 : 1;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ForceSetupModeCallback
+//
+// Description:
+//
+// Input: none
+//
+// Output: VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+// 4.6.5.1
+#if defined(CORE_COMBINED_VERSION) && CORE_COMBINED_VERSION >=0x4028b
+EFI_STATUS
+#else
+VOID
+#endif
+ForceSetupModeCallback(EFI_HII_HANDLE HiiHandle, UINT16 Class, UINT16 SubClass, UINT16 Key)
+{
+ EFI_STATUS Status;
+ UINT8 Sel = 0;
+ UINTN Size;
+ UINT32 Attributes=0;
+
+#if EFI_SPECIFICATION_VERSION>0x20000
+ CALLBACK_PARAMETERS *Callback;
+ EFI_BROWSER_ACTION_REQUEST *rq;
+
+ Callback = GetCallbackParameters();
+ TRACE((-1,"\n====ForceSetupModeCallback==== Key = %d, Callback %x, Value %d\n", Key, Callback, Callback->Value->u8));
+ if(!Callback || Callback->Action != EFI_BROWSER_ACTION_CHANGING)
+ RETURN(EFI_UNSUPPORTED)
+#endif
+ if(mPostMgr == NULL)
+ {
+ Status = pBS->LocateProtocol(&gAmiPostManagerProtocolGuid, NULL, &mPostMgr);
+ if(EFI_ERROR(Status) || !mPostMgr) {
+ RETURN(EFI_UNSUPPORTED)
+ }
+ }
+ Status = EFI_SUCCESS;
+ switch(Key) {
+ case SECURE_BOOT_MENU_REFRESH:
+ UpdateSecureBootBrowserInfo();
+ break;
+ case KEY_MANAGEMENT_MENU_REFRESH:
+ UpdateSecureVariableBrowserInfo();
+ break;
+#if EFI_SPECIFICATION_VERSION>0x20000
+ case SECURE_BOOT_SUPPORT_CHANGE_KEY:
+ if( Callback->Value->u8 == 1) // trying to switch Secure Boot from Disable to Enable
+ {
+ rq = Callback->ActionRequest;
+ *rq = EFI_BROWSER_ACTION_REQUEST_NONE;
+ Size = 1;
+ Status=pRS->GetVariable(EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (UINT32*)&Attributes, &Size, &Sel);
+ if(Sel) {
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_ENABLE_ERROR_MODE_TITLE), sizeof(StrTitle), StrTitle);
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_ENABLE_ERROR_MODE), sizeof(StrMessage),StrMessage);
+ mPostMgr->DisplayMsgBox( StrTitle, StrMessage, MSGBOX_TYPE_OK,NULL);
+ #if DEFAULT_SECURE_BOOT_ENABLE == 0
+ Status = EFI_UNSUPPORTED;
+ #endif
+ } else
+ if (IsCsmEnabled()) {
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_CSM_LOAD_TITLE), sizeof(StrTitle),StrTitle);
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_CSM_LOAD), sizeof(StrMessage),StrMessage);
+ mPostMgr->DisplayMsgBox( StrTitle, StrMessage, MSGBOX_TYPE_OK,NULL);
+/* this should be enough, but TSE has a bug that doesn't support FORM_DISCARD action try a workaround instead
+ {
+ SETUP_DATA Setup;
+ UINTN Size = sizeof(Setup);
+ static EFI_GUID SetupGuid = SETUP_GUID;
+ Status = HiiLibGetBrowserData(&Size, &Setup, &SetupGuid, L"Setup");
+ TRACE((-1, "Setup.CsmSupport=: %x, Size = %x\n", Setup.CsmSupport, Size));
+ if(!EFI_ERROR(Status) && Setup.CsmSupport == 1) {
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_CSM_LOAD_TITLE), sizeof(StrTitle),StrTitle);
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_CSM_LOAD), sizeof(StrMessage),StrMessage);
+ mPostMgr->DisplayMsgBox( StrTitle, StrMessage, (UINT8)MSGBOX_TYPE_YESNO, &Sel);
+ if (Sel == 1) {
+ Setup.CsmSupport = 0;
+ Status = HiiLibSetBrowserData(Size, &Setup, &SetupGuid, L"Setup");
+// pRS->SetVariable ( L"Setup", &SetupGuid, Attributes, Size, &Setup);
+ }
+ }
+ }
+end of workaround */
+
+ #if DEFAULT_SECURE_BOOT_ENABLE == 0
+ Status = EFI_UNSUPPORTED;
+ #endif
+ }
+ }
+ break;
+#endif
+ case SECURE_BOOT_MODE_CHANGE_KEY:
+ if( Callback->Value->u8 == 1) // trying to switch from Custom to Standard
+ break;
+ case KEY_PROVISION_CHANGE_KEY:
+ if(Key == KEY_PROVISION_CHANGE_KEY &&
+ Callback->Value->u8 == 0) // trying to switch from Disable to Enable
+ break;
+ case FORCE_SETUP_KEY:
+ case FORCE_DEFAULT_KEY:
+ if (Key == FORCE_SETUP_KEY)
+ {
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_FORCE_SETUP_MODE), sizeof(StrTitle),StrTitle);
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_RESET_TO_SETUP), sizeof(StrMessage),StrMessage);
+ mPostMgr->DisplayMsgBox( StrTitle, StrMessage, (UINT8)MSGBOX_TYPE_YESNO, &Sel);
+ if (Sel == 0)
+ Status = InstallSecureVariables(RESET_NV_KEYS); // erase
+ }
+#if SET_SECURE_VARS == 1
+ if (Key == FORCE_DEFAULT_KEY || Key == KEY_PROVISION_CHANGE_KEY || Key == SECURE_BOOT_MODE_CHANGE_KEY)
+ {
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_LOAD_DEFAULT_VARS_TITLE), sizeof(StrTitle),StrTitle);
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_LOAD_DEFAULT_VARS), sizeof(StrMessage),StrMessage);
+ mPostMgr->DisplayMsgBox( StrTitle, StrMessage, (UINT8)MSGBOX_TYPE_YESNO, &Sel);
+ if (Sel == 0)
+ Status = InstallSecureVariables(RESET_NV_KEYS | SET_NV_DEFAULT_KEYS); // erase+set
+ }
+#endif
+ UpdateSecureVariableBrowserInfo();
+ if (EFI_ERROR(Status))
+ {
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_VAR_UPDATE_LOCKED_TITLE), sizeof(StrTitle),StrTitle);
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_VAR_UPDATE_LOCKED), sizeof(StrMessage),StrMessage);
+ mPostMgr->DisplayMsgBox( StrTitle, StrMessage, MSGBOX_TYPE_OK,NULL);
+ Status = EFI_SUCCESS;
+ }
+ break;
+
+ default:
+ break;
+ }
+ RETURN(Status)
+}
+// ==========================================
+// (4.6.5.0+)
+// #if defined(CORE_COMBINED_VERSION) && CORE_COMBINED_VERSION >=0x4028a
+// ==========================================
+
+EFI_STATUS SetSecureVariable(UINT8 Index, UINT16 InstallVars, UINT8 *pVarBuffer, UINTN VarSize )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_GUID *EfiVarGuid;
+ UINT32 Attributes;
+
+///////////////////////////////////////////////////////////////////////////////
+// Initial provisioning of Authenticated non-volitile EFI Variables
+///////////////////////////////////////////////////////////////////////////////
+ if(SecureVariableFileName[Index] != NULL)
+ {
+ if(Index < 3)
+ EfiVarGuid = &gEfiImageSecurityDatabaseGuid;
+ else
+ EfiVarGuid = &gEfiGlobalVariableGuid;
+
+ if((InstallVars & SET_SECURE_VARIABLE_DEL) == SET_SECURE_VARIABLE_DEL) {
+ // try to erase. should succeed if system in pre-boot and Admin mode
+ Status = pRS->SetVariable(SecureVariableFileName[Index],EfiVarGuid,0,0,NULL);
+ TRACE((-1,"Set(0) Var %S, Status %r\n",SecureVariableFileName[Index], Status));
+ }
+ if((InstallVars & SET_SECURE_VARIABLE_SET)==SET_SECURE_VARIABLE_SET &&
+ pVarBuffer && VarSize) {
+
+ Attributes = EFI_VARIABLE_RUNTIME_ACCESS |
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+
+ if((InstallVars & SET_SECURE_VARIABLE_APPEND)== SET_SECURE_VARIABLE_APPEND)
+ Attributes |= EFI_VARIABLE_APPEND_WRITE;
+
+ Status = pRS->SetVariable(SecureVariableFileName[Index], EfiVarGuid, Attributes, VarSize, pVarBuffer);
+ TRACE((-1,"Set Var %S, Status %r\n",SecureVariableFileName[Index], Status));
+ }
+ }
+
+ UpdateSecureVariableBrowserInfo();
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetHiiString
+//
+// Description: This function Reads a String from HII
+//
+// Input: IN EFI_HII_HANDLE HiiHandle - Efi Hii Handle
+// IN STRING_REF Token - String Token
+// IN OUT UINTN *pDataSize - Length of the StringBuffer
+// OUT EFI_STRING *ppData - The buffer to receive the characters in the string.
+//
+// Output: EFI_STATUS - Depending on result
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID GetHiiString(
+ IN EFI_HII_HANDLE HiiHandle,
+ IN STRING_REF Token,
+ IN UINTN DataSize,
+ IN OUT CHAR16 *ppData
+ )
+{
+ EFI_STATUS Status;
+
+ if (!ppData) return;
+
+ Status = HiiLibGetString(HiiHandle, Token, &DataSize, (EFI_STRING)ppData);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) ppData=L"??? ";
+
+TRACE((-1,"%r, StrRef '%S', Size %d, Token=%d\n",Status, ppData, DataSize, Token));
+}
+
+// 4.6.5.1
+#if defined(CORE_COMBINED_VERSION) && CORE_COMBINED_VERSION >=0x4028b
+EFI_STATUS
+#else
+VOID
+#endif
+SetAppendSecureBootDBCallback(EFI_HII_HANDLE HiiHandle, UINT16 Class, UINT16 SubClass, UINT16 Key)
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *FsHandle;
+ UINT8 *FileBuf=NULL;
+ UINT8 *Data=NULL;
+ UINTN size, VarSize;
+ CHAR16 *FilePath=NULL;
+ UINT8 index;
+ UINT8 Sel = 1;
+ UINT16 CertSel = 0, AddSize;
+ POSTMENU_TEMPLATE MenuList[2];
+ UINT8 VarSetMode = SET_SECURE_VARIABLE_SET;
+
+#if EFI_SPECIFICATION_VERSION>0x20000
+ CALLBACK_PARAMETERS *Callback;
+
+ Callback = GetCallbackParameters();
+ if(!Callback || Callback->Action != EFI_BROWSER_ACTION_CHANGING)
+ RETURN(EFI_UNSUPPORTED)
+#endif
+
+ switch(Key)
+ {
+ case APPEND_KEK_KEY:
+ index = 3;
+ VarSetMode |= SET_SECURE_VARIABLE_APPEND;
+ break;
+ case APPEND_DB_KEY:
+ index = 2;
+ VarSetMode |= SET_SECURE_VARIABLE_APPEND;
+ break;
+ case APPEND_DBT_KEY:
+ index =1;
+ VarSetMode |= SET_SECURE_VARIABLE_APPEND;
+ break;
+ case APPEND_DBX_KEY:
+ index = 0;
+ VarSetMode |= SET_SECURE_VARIABLE_APPEND;
+ break;
+ case SET_PK_KEY:
+ index = 4;
+ VarSetMode |= SET_SECURE_VARIABLE_DEL;
+ break;
+ case SET_KEK_KEY:
+ index = 3;
+ VarSetMode |= SET_SECURE_VARIABLE_DEL;
+ break;
+ case SET_DB_KEY:
+ index = 2;
+ VarSetMode |= SET_SECURE_VARIABLE_DEL;
+ break;
+ case SET_DBT_KEY:
+ index = 1;
+ VarSetMode |= SET_SECURE_VARIABLE_DEL;
+ break;
+ case SET_DBX_KEY:
+ index = 0;
+ VarSetMode |= SET_SECURE_VARIABLE_DEL;
+ break;
+ default:
+ RETURN(EFI_SUCCESS)
+ }
+
+ if(mPostMgr == NULL)
+ {
+ RETURN(EFI_SUCCESS)
+ }
+
+ gHiiHandle = HiiHandle;
+
+ MemSet(StrTemp, sizeof(StrTemp), 0);
+
+#if SET_SECURE_VARS == 1
+ Sel = 1; // No
+// DataSize = sizeof(StrTitle);
+ if(VarSetMode & SET_SECURE_VARIABLE_APPEND)
+// HiiLibGetString(HiiHandle, STRING_TOKEN(STR_SECURE_APPEND), &DataSize, (EFI_STRING)StrTitle);
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_SECURE_APPEND), sizeof(StrTitle), StrTitle);
+ else
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_SECURE_SET), sizeof(StrTitle), StrTitle);
+
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_UPDATE_FROM_DEFAULTS),sizeof(StrMessage), StrMessage);
+ Swprintf_s(StrTemp, sizeof(StrTemp), StrMessage , SecureVariableFileName[index]);
+ mPostMgr->DisplayMsgBox( StrTitle, StrTemp, (UINT8)MSGBOX_TYPE_YESNO, &Sel);
+
+ if(Sel == 0)
+ {
+ size = 0 ;
+ Status = CryptoGetRawImage( SecureVariableFileGuid[index], &FileBuf, (UINTN*)&size);
+ } else
+#endif
+ {
+ size = 0;
+ AddSize = 0;
+ Status = FileBrowserLaunchFileSystem(TRUE, &FsHandle, &FilePath, &FileBuf, &size);
+ if(!EFI_ERROR(Status) && FileBuf)
+ {
+ // Clear the memory allocated
+ MemSet(MenuList, sizeof(MenuList), 0);
+ MenuList[0].ItemToken = STRING_TOKEN(STR_SECURE_CER);
+ MenuList[1].ItemToken = STRING_TOKEN(STR_SECURE_VAR);
+
+ // Call post manager to display the menu
+ Status = mPostMgr->DisplayPostMenu(gHiiHandle,
+ STRING_TOKEN(STR_SECURE_TITLE), // Change this
+ 0,
+ MenuList,
+ 2,
+ &CertSel);
+
+ if(!EFI_ERROR(Status))
+ {
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_UPDATE_FROM_FILE), sizeof(StrMessage), StrMessage);
+ Swprintf_s(StrTemp, sizeof(StrTemp),StrMessage, SecureVariableFileName[index],FilePath);
+
+ if(CertSel==0) {
+ AddSize = sizeof(EFI_VARIABLE_SIG_HDR_2)-1; // decrement by 1 byte as SIG_DATA adds 1 dummy byte
+ }
+
+ // Validate Signature List integrity
+ if(!EFI_ERROR(ValidateSignatureList (FileBuf, size))) {
+ CertSel=2;
+ AddSize = sizeof(AMI_EFI_VARIABLE_AUTHENTICATION_2);
+ }
+ //
+ // form an AuthVar Hdr on top of Var
+ //
+ //Allocate new Size
+ VarSize = size+AddSize;
+ Status = pBS->AllocatePool(EfiBootServicesData, VarSize, &Data);
+ ASSERT_EFI_ERROR (Status);
+ // Append AuthHdr to Var data.
+ if(CertSel==0)
+ FillAuthVarHdr(Data,FileBuf,size, VarSetMode);
+ else
+ if(CertSel==2) // unsupported - append from SigList
+ FillAuthHdr(Data, VarSetMode);
+
+ MemCpy ((VOID*)((UINTN)Data+AddSize), FileBuf, size);
+ if(FileBuf)
+ pBS->FreePool(FileBuf);
+ FileBuf = Data;
+ size = VarSize;
+ }
+ }
+ }
+
+ if(!EFI_ERROR(Status) && FileBuf){
+ if(Sel == 1)
+ mPostMgr->DisplayMsgBox( StrTitle, StrTemp, (UINT8)MSGBOX_TYPE_YESNO, &Sel);
+
+ if(Sel == 0)
+ {
+ Status = SetSecureVariable(index, VarSetMode, FileBuf, size);
+ if(!EFI_ERROR(Status)){
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_SUCCESS), sizeof(StrMessage),StrMessage);
+ }
+ else
+ {
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_FAILED), sizeof(StrMessage),StrMessage);
+ }
+ mPostMgr->DisplayMsgBox( StrTitle,StrMessage , MSGBOX_TYPE_OK, NULL );
+ }
+ }
+ if(FileBuf)
+ pBS->FreePool(FileBuf);
+
+ if(FilePath)
+ pBS->FreePool(FilePath);
+
+ RETURN(EFI_SUCCESS)
+}
+// 4.6.5.1
+#if defined(CORE_COMBINED_VERSION) && CORE_COMBINED_VERSION >=0x4028b
+EFI_STATUS
+#else
+VOID
+#endif
+GetSecureBootDBCallback(EFI_HII_HANDLE HiiHandle, UINT16 Class, UINT16 SubClass, UINT16 Key)
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *FsHandle;
+ UINT8 *FileBuf=NULL;
+ UINTN size;
+ CHAR16 *FilePath=NULL;
+ UINT8 Index, nVars;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pSFP;
+ EFI_FILE_PROTOCOL *pRoot,*FileHandle;
+ EFI_GUID *EfiVarGuid;
+ UINT8 *Data=NULL;
+ BOOLEAN bFound = TRUE;
+
+#if EFI_SPECIFICATION_VERSION>0x20000
+ CALLBACK_PARAMETERS *Callback;
+
+ Callback = GetCallbackParameters();
+ if(!Callback || Callback->Action != EFI_BROWSER_ACTION_CHANGING)
+ RETURN(EFI_UNSUPPORTED)
+#endif
+
+ gHiiHandle = HiiHandle;
+ size = 0;
+ Status = FileBrowserLaunchFileSystem(FALSE, &FsHandle, &FilePath, &FileBuf, &size);
+ if(EFI_ERROR(Status))
+ goto Done;
+
+ Index = 0;
+ nVars = 0;
+ MemSet(StrTemp, sizeof(StrTemp), 0);
+ while(bFound && SecureVariableFileName[Index] != NULL)
+ {
+ if(Index < 3)
+ EfiVarGuid = &gEfiImageSecurityDatabaseGuid;
+ else
+ EfiVarGuid = &gEfiGlobalVariableGuid;
+
+ size = 0;
+ Status = pRS->GetVariable( SecureVariableFileName[Index], EfiVarGuid, NULL, &size, NULL);
+ if(Status == EFI_BUFFER_TOO_SMALL)
+ {
+ // Append AuthHdr to Var data.
+ //Allocate Size
+ Status = pBS->AllocatePool(EfiBootServicesData, size, &Data);
+ ASSERT_EFI_ERROR (Status);
+
+ // Read the Variable
+ Status = pRS->GetVariable( SecureVariableFileName[Index], EfiVarGuid, NULL, &size, Data);
+ if (!EFI_ERROR(Status))
+ {
+ Status = pBS->HandleProtocol( FsHandle, &gSimpleFileSystemGuid, &pSFP );
+ if (!EFI_ERROR(Status))
+ {
+ Status = pSFP->OpenVolume(pSFP,&pRoot);
+ if (!EFI_ERROR(Status))
+ {
+ Status = pRoot->Open(pRoot,&FileHandle,SecureVariableFileName[Index],
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,0);
+ if(!EFI_ERROR(Status))
+ {
+ // Write
+ FileHandle->Write(FileHandle,&size, Data);
+ FileHandle->Close(FileHandle);
+ nVars++;
+ }
+ }
+ }
+
+ if (EFI_ERROR(Status)) {
+ bFound = FALSE;
+ Swprintf_s(StrTemp, sizeof(StrTemp), L" %s ", SecureVariableFileName[Index]);
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_WRITE_ERROR_TITLE), sizeof(StrTitle),StrTitle);
+ mPostMgr->DisplayMsgBox( StrTitle, StrTemp, MSGBOX_TYPE_OK, NULL );
+ }
+ }
+ if(Data!=NULL)
+ pBS->FreePool(Data);
+ }
+
+ Index++;
+ }
+ if (Index==5 && bFound) {
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_SAVE_SEC_KEY),sizeof(StrMessage), StrMessage);
+ Swprintf_s(StrTemp, sizeof(StrTemp), StrMessage, nVars);
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_SAVE_SEC_KEY_TITLE),sizeof(StrTitle), StrTitle);
+ mPostMgr->DisplayMsgBox(StrTitle , StrTemp, MSGBOX_TYPE_OK, NULL );
+ }
+
+Done:
+
+ if(FileBuf)
+ pBS->FreePool(FileBuf);
+
+ if(FilePath)
+ pBS->FreePool(FilePath);
+
+ RETURN(EFI_SUCCESS)
+}
+
+// 4.6.5.1
+#if defined(CORE_COMBINED_VERSION) && CORE_COMBINED_VERSION >=0x4028b
+EFI_STATUS
+#else
+VOID
+#endif
+DeleteSecureBootDBCallback(EFI_HII_HANDLE HiiHandle, UINT16 Class, UINT16 SubClass, UINT16 Key)
+{
+ EFI_STATUS Status;
+ UINT8 index;
+ UINT8 Sel = 0;
+
+#if EFI_SPECIFICATION_VERSION>0x20000
+ CALLBACK_PARAMETERS *Callback;
+
+ Callback = GetCallbackParameters();
+ if(!Callback || Callback->Action != EFI_BROWSER_ACTION_CHANGING)
+ RETURN(EFI_UNSUPPORTED)
+#endif
+
+ switch(Key)
+ {
+ case DELETE_PK_KEY:
+ index = 4;
+ break;
+ case DELETE_KEK_KEY:
+ index = 3;
+ break;
+ case DELETE_DB_KEY:
+ index = 2;
+ break;
+ case DELETE_DBT_KEY:
+ index = 1;
+ break;
+ case DELETE_DBX_KEY:
+ index = 0;
+ break;
+ default:
+ RETURN(EFI_SUCCESS)
+ }
+
+ if(mPostMgr == NULL)
+ {
+ RETURN(EFI_SUCCESS)
+ }
+
+ gHiiHandle = HiiHandle;
+
+ MemSet(StrTemp, sizeof(StrTemp), 0);
+
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_DELETE_SEC_KEY_TITLE), sizeof(StrTitle),StrTitle);
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_DELETE_SEC_KEY), sizeof(StrMessage),StrMessage);
+ Swprintf_s(StrTemp, sizeof(StrTemp), StrMessage, SecureVariableFileName[index]);
+ mPostMgr->DisplayMsgBox( StrTitle, StrTemp, (UINT8)MSGBOX_TYPE_YESNO, &Sel);
+
+ if(Sel == 0)
+ {
+ Status = SetSecureVariable(index,SET_SECURE_VARIABLE_DEL, NULL, 0);
+
+ if(!EFI_ERROR(Status)){
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_SUCCESS), sizeof(StrMessage),StrMessage);
+ }
+ else
+ {
+ GetHiiString(HiiHandle, STRING_TOKEN(STR_FAILED), sizeof(StrMessage),StrMessage);
+ }
+ mPostMgr->DisplayMsgBox( StrTitle, StrMessage, MSGBOX_TYPE_OK, NULL );
+ }
+
+ RETURN(EFI_SUCCESS)
+}
+//############################################################################################################
+static VOID EfiStrCat (
+ IN CHAR16 *Destination,
+ IN CHAR16 *Source
+ )
+{
+ Wcscpy (Destination + Wcslen (Destination), Source);
+}
+
+static CHAR16 *StrDup8to16( CHAR8 *string )
+{
+ CHAR16 *text;
+ UINTN i;
+
+ if ( string == NULL )
+ return NULL;
+
+ pBS->AllocatePool(EfiBootServicesData, (1 + Strlen( string )) * sizeof(CHAR16), &text);
+
+ if ( text != NULL )
+ {
+ i=0;
+ while(text[i] = (CHAR16)string[i])
+ i++;
+ }
+
+ return text;
+}
+
+
+EFI_STRING_ID HiiAddString(IN EFI_HII_HANDLE HiiHandle,IN CHAR16 *String)
+{
+ EFI_STATUS Status;
+ CHAR8* Languages = NULL;
+ UINTN LangSize = 0;
+ CHAR8* CurrentLanguage;
+ BOOLEAN LastLanguage = FALSE;
+ EFI_STRING_ID StringId = 0;
+ CHAR8 *SupportedLanguages=NULL;
+
+ if(HiiString == NULL) {
+ Status = pBS->LocateProtocol(&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);
+ if(EFI_ERROR(Status))
+ return 0;
+ }
+
+ if(SupportedLanguages == NULL) {
+ Status = HiiString->GetLanguages(HiiString, HiiHandle, Languages, &LangSize);
+ if(Status == EFI_BUFFER_TOO_SMALL) {
+ Status = pBS->AllocatePool(EfiBootServicesData, LangSize, &Languages);
+ if(EFI_ERROR(Status))
+ return 0; //not enough resources to allocate string
+ Status = HiiString->GetLanguages(HiiString, HiiHandle, Languages, &LangSize);
+ }
+ if(EFI_ERROR(Status))
+ return 0;
+ } else {
+ Languages = SupportedLanguages;
+ }
+
+ while(!LastLanguage) {
+ CurrentLanguage = Languages; //point CurrentLanguage to start of new language
+ while(*Languages != ';' && *Languages != 0)
+ Languages++;
+
+ if(*Languages == 0) { //last language in language list
+ LastLanguage = TRUE;
+ if(StringId == 0)
+ Status = HiiString->NewString(HiiString, HiiHandle, &StringId, CurrentLanguage, NULL, String, NULL);
+ else
+ Status = HiiString->SetString(HiiString, HiiHandle, StringId, CurrentLanguage, String, NULL);
+ if(EFI_ERROR(Status))
+ return 0;
+ } else {
+ *Languages = 0; //put null-terminator
+ if(StringId == 0)
+ Status = HiiString->NewString(HiiString, HiiHandle, &StringId, CurrentLanguage, NULL, String, NULL);
+ else
+ Status = HiiString->SetString(HiiString, HiiHandle, StringId, CurrentLanguage, String, NULL);
+ *Languages = ';'; //restore original character
+ Languages++;
+ if(EFI_ERROR(Status))
+ return 0;
+ }
+ }
+ return StringId;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: EfiLibAllocateCopyPool
+//
+// Description: Allocate BootServicesData pool and use a buffer provided by
+// caller to fill it.
+//
+// Input: AllocationSize - The size to allocate
+// Buffer - Buffer that will be filled into the buffer allocated
+//
+// Output: Pointer of the buffer allocated.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID *
+EfiLibAllocateCopyPool (
+ IN UINTN AllocationSize,
+ IN VOID *Buffer
+ )
+{
+ VOID *Memory;
+
+ Memory = NULL;
+ pBS->AllocatePool (EfiBootServicesData, AllocationSize, &Memory);
+ if (Memory != NULL) {
+ pBS->CopyMem (Memory, Buffer, AllocationSize);
+ }
+
+ return Memory;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: CleanFileTypes
+//
+// Description: Frees all allocated memory associated with the FILE_TYPE structure
+// and resets the InternalString current strings next available string token
+// to be the first dynamically added string
+//
+// Input: FILE_TYPE **FileList - The array of FILE_TYPE structures found in
+// a directory
+// UINTN *FileCount - pointer to the number of entries in the FileList
+//
+// Output:
+//
+// Returns:
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID CleanFileTypes(FILE_TYPE **FileList, UINTN *FileCount)
+{
+ UINTN i;
+ for(i = 0; i<*FileCount; i++) pBS->FreePool((*FileList)[i].Name);
+ if(FileList!=NULL && (*FileList!=NULL) && (*FileCount>0)) pBS->FreePool(*FileList);
+ if(FileList!=NULL) *FileList = NULL;
+ *FileCount = 0;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: CheckDirectoryType
+//
+// Description: Checks if the EFI_FILE_INFO is a directory (and not the current directory)
+//
+// Input: EFI_FILE_INFO *File
+//
+// Output:
+//
+// Returns: BOOLEAN - TRUE - item is a directory, and not the current directory
+// FALSE - item is not a directory, or is the current directory
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN CheckDirectoryType(EFI_FILE_INFO *File)
+{
+ BOOLEAN Status = FALSE;
+
+ if((File->Attribute & EFI_FILE_DIRECTORY) && (Wcscmp(File->FileName, L".") != 0)) {
+
+ Status = TRUE;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: CheckExtension
+//
+// Description: Check is the EFI_FILE_INFO has the same extension as the
+// extension passed in the second parameter
+//
+// Input: EFI_FILE_INFO *File - The file entry whose extension should be checked
+// CHAR16 *ExtensionEfi - the extension
+//
+// Output:
+//
+// Returns: BOOLEAN - TRUE - The extension matches
+// FALSE - the extension does not match
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN CheckExtension(EFI_FILE_INFO *File, CHAR16 *ExtensionEfi)
+{
+ BOOLEAN Status = FALSE;
+ UINTN Length = Wcslen(File->FileName);
+
+ if((File->Attribute & EFI_FILE_DIRECTORY) != EFI_FILE_DIRECTORY && Length > 3)
+ if((((File->FileName[Length-1])&0xdf) == ((ExtensionEfi[2])&0xdf)) &&
+ (((File->FileName[Length-2])&0xdf) == ((ExtensionEfi[1])&0xdf)) &&
+ (((File->FileName[Length-3])&0xdf) == ((ExtensionEfi[0])&0xdf)))
+ Status = TRUE;
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: FindInsertionIndex
+//
+// Description: Finds the inded where directories items turn into file items
+//
+// Input: FILE_TYPE *List - the current array of File Type structures
+// UINTN FileCount - the count of File Type structures in the array
+//
+// Output:
+//
+// Returns: the index to insert a new item
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN FindInsertionIndex(FILE_TYPE *List, UINTN FileCount)
+{
+ UINTN i = 0;
+
+ if(FileCount <= 1) return 0;
+
+ for(i = 1; i < (FileCount-1); i++)
+ {
+ if(List[i-1].Type != List[i].Type)
+ break;
+ }
+
+ return i;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: AddFileTypeEntry
+//
+// Description: Creates a new entry in the FILE_TYPE array and adds the current File into
+// the array.
+//
+// Input: FILE_TYPE **List - Array of FILE_TYPE structures alread found
+// UINTN *FileCount - number of entries in the FILE_TYPE array
+// EFI_FILE_INFO *FileInfo - file info of the file that should be added
+//
+// Output:
+//
+// Returns:
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+static VOID AddFileTypeEntry(FILE_TYPE **List, UINTN *FileCount, EFI_FILE_INFO *FileInfo)
+{
+ FILE_TYPE *NewList=NULL;
+ UINTN Length;
+ UINTN Index = 0;
+
+ Length = (Wcslen(FileInfo->FileName)+3)*sizeof(CHAR16);
+
+ // Allocate space for a new list entry plus all the previous list items
+ NewList = EfiLibAllocateCopyPool(sizeof(FILE_TYPE)*(++(*FileCount)), NewList);
+ if (NewList != NULL)
+ {
+ // Clear the memory of the entire list
+ MemSet(NewList, sizeof(FILE_TYPE)*(*FileCount), 0);
+
+ // Copy the old entries (if there are any old entries to copy)
+ if(*List != NULL)
+ {
+ Index = FindInsertionIndex(*List, *FileCount);
+
+ pBS->CopyMem(NewList, *List, sizeof(FILE_TYPE)*(Index));
+ pBS->CopyMem(&(NewList[Index+1]), &((*List)[Index]), sizeof(FILE_TYPE)*((*FileCount)-Index-1));
+
+ pBS->FreePool(*List);
+ }
+
+ // Store the type of this FILE_TYPE entry (non-zero is directory)
+ NewList[Index].Type = ((FileInfo->Attribute) & EFI_FILE_DIRECTORY);
+
+ // Store the size of the file
+ NewList[Index].Size = (UINTN)FileInfo->FileSize;
+
+ // Allocate space for the string
+ NewList[Index].Name = EfiLibAllocateCopyPool(Length, NewList[Index].Name);
+ if((NewList[Index].Name) != NULL )
+ {
+ // Clear the allocated memory
+ MemSet(NewList[Index].Name, Length, 0);
+
+ // Create either a Dir string or a File string for addition to the HiiDataBase
+ if(NewList[Index].Type == EFI_FILE_DIRECTORY)
+ Swprintf_s(NewList[Index].Name, Length, L"<%s>", FileInfo->FileName);
+ else
+ Swprintf_s(NewList[Index].Name, Length, L"%s", FileInfo->FileName);
+
+ // Add the string to the HiiDataBase
+ ///NewList[Index].Token = AddStringToHii(FileInfo->FileName, &gInternalStrings); ///Just by trying using the following line
+ NewList[Index].Token = HiiAddString(gHiiHandle, NewList[Index].Name );
+
+ // Clear the memory and create the string for the File Structure
+ MemSet(NewList[Index].Name, Length, 0);
+ Swprintf_s(NewList[Index].Name, Length, L"%s", FileInfo->FileName);
+ }
+ *List = NewList;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: CreateFileList
+//
+// Description: Parse all the files in the current directory and add valid files to the
+// FILE_TYPE list and update the filecount
+//
+// Input: EFI_FILE_PROTOCOL *FileProtocol - the current direcotry to parse
+//
+// Output: FILE_TYPE **FileList - pointer in which to return the array of FileType items
+// UINTN *FileCount - the count of filetype items discovered
+//
+// Returns: EFI_STATUS
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS CreateFileList(EFI_FILE_PROTOCOL *FileProtocol, FILE_TYPE **FileList, UINTN *FileCount)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ UINTN BufferSize = 1;
+ EFI_FILE_INFO *File = NULL;
+
+// CHAR16 ExtensionEfi[] = L"EFI";
+
+ // Continue parsing the directory until we no longer read valid files
+ while(BufferSize != 0 && !EFI_ERROR(Status))
+ {
+ BufferSize = 0;
+ Status = FileProtocol->Read(FileProtocol, &BufferSize, NULL);
+
+ if(!EFI_ERROR(Status)) break;
+
+ if(Status == EFI_BUFFER_TOO_SMALL)
+ {
+ File = EfiLibAllocateCopyPool(BufferSize, File);
+ if(File != NULL) {
+ MemSet(File, BufferSize, 0);
+ }
+ }
+
+ Status = FileProtocol->Read(FileProtocol, &BufferSize, File);
+
+ // Check if a valid file was read
+ if(!EFI_ERROR(Status) && BufferSize != 0)
+ {
+ // check if the file read was a directory or a ".efi" extension
+// if(CheckDirectoryType(File) || CheckExtension(File, ExtensionEfi))
+// {
+ // the file was valid, add it to the file list
+ AddFileTypeEntry(FileList, FileCount, File);
+// }
+ }
+
+ // free the space allocated for readin the file info structure
+ pBS->FreePool(File);
+
+ // set the pointer to null to prevent the chance of memory corruption
+ File = NULL;
+ }
+
+ if(*FileCount == 0) Status = EFI_NOT_FOUND;
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: DisplayFileListMenu
+//
+// Description: Display a menu of the FILE_TYPE items and return the selected item
+// in the Selection
+//
+// Input: FILE_TYPE *FileList - List of FILE_TYPE items to display in the menu
+// UINTN FileCount - the number of FILE_TYPE items in the list
+//
+// Output: UINT16 *Selection - The index of the selected FILE_TYPE item
+//
+// Returns:
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS DisplayFileListMenu(FILE_TYPE *FileList, UINTN FileCount, UINT16 *Selection)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ UINT16 i = 0;
+
+ POSTMENU_TEMPLATE *List = NULL;
+
+ // Check there are any files to display
+ if(FileCount != 0 && FileList != NULL)
+ {
+ // allocate space for the POSTMENU_TEMPLATE items
+ List = EfiLibAllocateCopyPool(sizeof(POSTMENU_TEMPLATE)*FileCount, List);
+ if(List != NULL)
+ {
+ // Clear the memory allocated
+ MemSet(List, sizeof(POSTMENU_TEMPLATE)*FileCount, 0);
+
+ // Add the STRING_REF tokens to the POSTMENU_TEMPLATE structures
+ for(i = 0; i < FileCount; i++)
+ List[i].ItemToken = FileList[i].Token;
+ }
+
+ // Call post manager to display the menu
+ Status = mPostMgr->DisplayPostMenu(gHiiHandle,
+ STRING_TOKEN(STR_FILE_SELECT), // Change this
+ 0,
+ List,
+ (UINT16)FileCount,
+ Selection);
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: UpdateFilePathString
+//
+// Description: To create the File Path string based on the file selected.
+//
+// Input: CHAR16 *FilePath - Buffer to fill with the file path
+// CHAR16 * CurFile - current file selected
+// UINT16 idx - Index of the file in the current directory
+//
+// Output: CHAR16 *FilePath - Updated File Path
+//
+// Returns:
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID UpdateFilePathString(CHAR16 *FilePath, CHAR16 * CurFile, UINT16 idx)
+{
+ UINTN Length=0;
+
+ if(Wcslen(FilePath))
+ {
+ if( idx==0 ) {
+ if(Wcscmp(CurFile,L"..")) {
+ EfiStrCat(FilePath,L"\\");
+ EfiStrCat(FilePath,CurFile);
+ }
+ else {
+
+ for ( Length = Wcslen(FilePath); ( Length!= 0 ) && (FilePath[Length-1] != L'\\') ; Length -- );
+ if ( Length )
+ FilePath[Length-1] = L'\0';
+ else
+ FilePath[Length] = L'\0';
+ }
+ }
+ else {
+ EfiStrCat(FilePath,L"\\");
+ EfiStrCat(FilePath,CurFile);
+ }
+ }
+ else {
+ Wcscpy(FilePath,CurFile);
+ }
+}
+
+EFI_STATUS FileBrowserLaunchFilePath(IN EFI_HANDLE *FileHandle, OUT CHAR16 **outFilePath, OUT UINT8 **outFileBuf,OUT UINTN *size );
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: FileBrowserLaunchFileSystem
+//
+// Description: To select the File System for the new boot option with the help of file browser.
+//
+// Input: BOOLEAN bSelectFile - TRUE - Select FSHandle and File path
+// FALSE - Select only FSHandle
+//
+// Output: Selected File System Index
+//
+// Returns: EFI_STATUS
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FileBrowserLaunchFileSystem(BOOLEAN bSelectFile, OUT EFI_HANDLE **outFsHandle,OUT CHAR16 **outFilePath, OUT UINT8 **outFileBuf,OUT UINTN *size )
+{
+ EFI_STATUS Status;
+ UINTN Count = 0;
+ UINT16 i = 0;
+ EFI_HANDLE *gSmplFileSysHndlBuf = NULL;
+ UINT16 gSelIdx=0;
+
+ EFI_DEVICE_PATH_PROTOCOL *Dp = NULL;
+
+ POSTMENU_TEMPLATE *PossibleFileSystems = NULL;
+
+ if(mPostMgr == NULL)
+ return EFI_UNSUPPORTED;
+
+ // To launch the files from the selected file system
+ if(!size)
+ return EFI_INVALID_PARAMETER;
+
+ // Locate all the simple file system devices in the system
+ Status = pBS->LocateHandleBuffer(ByProtocol, &gSimpleFileSystemGuid, NULL, &Count, &gSmplFileSysHndlBuf);
+ if(!EFI_ERROR(Status))
+ {
+ // allocate space to display all the simple file system devices
+ PossibleFileSystems = EfiLibAllocateCopyPool(sizeof(POSTMENU_TEMPLATE)*Count,PossibleFileSystems);
+ if(PossibleFileSystems != NULL)
+ {
+ // clear the allocated space
+ MemSet(PossibleFileSystems, sizeof(POSTMENU_TEMPLATE)*Count, 0);
+ for(i = 0; i < Count; i++)
+ {
+ // get the device path for each handle with a simple file system
+ Status = pBS->HandleProtocol(gSmplFileSysHndlBuf[i], &gEfiDevicePathProtocolGuid, &Dp);
+ if(!EFI_ERROR(Status))
+ {
+ CHAR16 *Name;
+ CHAR8 *Name8;
+ // Get the name of the driver installed on the handle
+ // GetControllerName(gHandleBuffer[i],&Name);
+
+ Name8 = NULL;
+ Status = DevicePathToStr(Dp, &Name8 );
+ Name = StrDup8to16(Name8);
+
+ // Add the name to the Hii Database
+ ///PossibleFileSystems[i].ItemToken = AddStringToHii(Name);
+ PossibleFileSystems[i].ItemToken = HiiAddString(gHiiHandle, Name );
+
+ PossibleFileSystems[i].Attribute = AMI_POSTMENU_ATTRIB_FOCUS;
+ pBS->FreePool(Name);
+ pBS->FreePool(Name8);
+ }
+ else
+ {
+ PossibleFileSystems[i].ItemToken = 0;
+ PossibleFileSystems[i].Attribute = AMI_POSTMENU_ATTRIB_HIDDEN;
+ }
+ }
+ // Reset the item selected to be the first item
+ gSelIdx = 0;
+
+ // Display the post menu and wait for user input
+ Status = mPostMgr->DisplayPostMenu(gHiiHandle,
+ STRING_TOKEN(STR_FILE_SYSTEM),
+ 0,
+ PossibleFileSystems,
+ (UINT16)Count,
+ &gSelIdx);
+
+
+ // A valid item was selected by the user
+ if(!EFI_ERROR(Status))
+ {
+ gValidOption = TRUE;
+ }
+ }
+ }
+
+ else {
+ GetHiiString(gHiiHandle, STRING_TOKEN(STR_NO_VALID_FS_TITLE), sizeof(StrTitle) ,StrTitle);
+ GetHiiString(gHiiHandle, STRING_TOKEN(STR_NO_VALID_FS), sizeof(StrMessage),StrMessage);
+ mPostMgr->DisplayMsgBox( StrTitle, StrMessage, MSGBOX_TYPE_OK, NULL );//EIP:41615 To display Warning message when there is no file system connected.
+ }
+
+ // Free the allocated menu list space
+ if(PossibleFileSystems != NULL)
+ pBS->FreePool(PossibleFileSystems);
+
+ *outFsHandle = gSmplFileSysHndlBuf[gSelIdx];
+
+ *size = 0;
+ if(bSelectFile)
+ Status = FileBrowserLaunchFilePath(*outFsHandle,outFilePath, outFileBuf,size );//EIP:41615 Returning the status of Filebrowselaunchfilepath
+
+ if(gSmplFileSysHndlBuf != NULL)
+ pBS->FreePool(gSmplFileSysHndlBuf);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: FileBrowserLaunchFilePath
+//
+// Description: To select the Boot file for the new boot option with the help of file browser.
+//
+// Input: VOID
+//
+// Output: File Path string
+//
+// Returns: EFI_STATUS
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FileBrowserLaunchFilePath(IN EFI_HANDLE *FileHandle,OUT CHAR16 **outFilePath, OUT UINT8 **outFileBuf,OUT UINTN *size )
+{
+ EFI_STATUS Status;
+
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs = NULL;
+ EFI_FILE_PROTOCOL *NewFs = NULL;
+ FILE_TYPE *FileList = NULL;
+ UINTN FileCount = 0;
+ UINT16 i = 0;
+ CHAR16 FilePath[120];
+ EFI_FILE_PROTOCOL *gFs = NULL;
+
+ // Attempt to locate the post manager protocol
+ if(mPostMgr == NULL)
+ return EFI_UNSUPPORTED;
+
+ if( gValidOption == TRUE )
+ {
+ gValidOption = FALSE;
+
+ // Get the simple file system protocol
+ Status = pBS->HandleProtocol(FileHandle, &gSimpleFileSystemGuid, &SimpleFs);
+ if(!EFI_ERROR(Status))
+ {
+ // And open it and return the efi file protocol
+ Status = SimpleFs->OpenVolume(SimpleFs, &gFs);
+ }
+ }
+ else {
+ return EFI_UNSUPPORTED;
+ }
+
+ // clean up the file list and strings used in getting the file system
+ CleanFileTypes(&FileList, &FileCount);
+
+ while(!EFI_ERROR(Status) && gFs != NULL)
+ {
+ i = 0;
+ MemSet(FilePath, sizeof(FilePath), 0);
+
+ // Create a list of the files in the current directory
+ Status = CreateFileList(gFs, &FileList, &FileCount);
+ if(!EFI_ERROR(Status))
+ {
+ // Display the list in a menu and allow the user to select
+ Status = DisplayFileListMenu(FileList, FileCount, &i);
+ if(!EFI_ERROR(Status))
+ {
+ // The user selected something, attempt to open it
+ Status = gFs->Open( gFs,
+ &NewFs,
+ FileList[i].Name,
+ EFI_FILE_MODE_READ,
+ 0);
+
+ // close the old file system protocol and set it to null
+ gFs->Close(gFs);
+ gFs = NULL;
+
+ // Create the File Path based on the file selected
+ UpdateFilePathString(FilePath, FileList[i].Name, i);
+
+ // the newly selected item was opened correctly
+ if(!EFI_ERROR(Status))
+ {
+ // check what type was opened
+ if(FileList[i].Type != EFI_FILE_DIRECTORY)
+ {
+
+
+ Status = pBS->AllocatePool(EfiBootServicesData,FileList[i].Size, (VOID**)outFileBuf);
+ if(!EFI_ERROR(Status))
+ {
+ *size = FileList[i].Size;
+ // The user selected something, attempt to open it
+ Status = NewFs->Read( NewFs, size, *outFileBuf); }
+
+ // the file was read, close the file system protocol and set it to null
+ NewFs->Close(NewFs);
+ NewFs = NULL;
+ //Swprintf_s (FileName, 50, L"%s", FileList[i].Name);
+ //ShowPostMsgBox( L"Selected Boot File Name", FileName, MSGBOX_TYPE_OK, &SelOpt );
+ }
+ gFs = NewFs;
+ }
+ }
+ }
+
+ if(FileCount <= 0) {
+ GetHiiString(gHiiHandle, STRING_TOKEN(STR_NO_VALID_FILE_TITLE),sizeof(StrTitle), StrTitle);
+ GetHiiString(gHiiHandle, STRING_TOKEN(STR_NO_VALID_FILE),sizeof(StrMessage),StrMessage);
+ mPostMgr->DisplayMsgBox( StrTitle, StrMessage, MSGBOX_TYPE_OK, NULL );//EIP:41615 Warning message to show unavailability of the selected file
+ }
+
+ // clean the strings that were used and free allocated space
+ CleanFileTypes(&FileList, &FileCount);
+
+ if(Status == EFI_ABORTED) {
+ return Status;//EIP:41615 Returning the status if its aborted.
+ }
+ }
+ // Set the File path for the new boot option added.
+ Status = pBS->AllocatePool(EfiBootServicesData, ((Wcslen(FilePath)+1)*sizeof(CHAR16)), outFilePath);
+ Wcscpy (*outFilePath, FilePath);
+
+ return Status;
+}
+//#endif //#if defined(CORE_COMBINED_VERSION) && CORE_COMBINED_VERSION >=0x4028a (4.6.5.0)
+#endif // #ifdef SETUP_COMPILE
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SecureMod_Init
+//
+// Description: Entry point of Secure Module DXE driver
+//
+// Input: EFI_HANDLE ImageHandle,
+// EFI_SYSTEM_TABLE *SystemTable
+//
+// Output: EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SecureBootMod_Init (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_STATUS Status;
+ UINTN DataSize;
+ UINT8 Byte;
+ UINT32 Attributes;
+ VOID *pHobList;
+ static EFI_GUID gHobListGuid = HOB_LIST_GUID;
+
+ InitAmiLib(ImageHandle, SystemTable);
+
+ Byte = 0;
+ Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE;
+ //
+ // Look up for Secure Boot policy in "SecureBootSetup" variable. If not defined - create one with SDL defaults
+ //
+ DataSize = sizeof(SECURE_BOOT_SETUP_VAR);
+ Status = pRS->GetVariable (AMI_SECURE_BOOT_SETUP_VAR, &guidSecurity,&Attributes,&DataSize,&SecureBootSetup);
+//TRACE((TRACE_ALWAYS,"SecureBootSetup (%r) Attrib=%x, SecBoot-%d, SecMode-%d,DefaultProvision-%d\n", Status, Attributes, SecureBootSetup.SecureBootSupport, SecureBootSetup.SecureBootMode,SecureBootSetup.DefaultKeyProvision));
+ // Default variable is created with RT attribute which violates
+ // Intel's Secure Boot technical advisory #527669 and MS Windows Secure Boot requirements
+ if((!EFI_ERROR(Status) &&
+ (Attributes & EFI_VARIABLE_RUNTIME_ACCESS)==EFI_VARIABLE_RUNTIME_ACCESS)
+ || Status == EFI_NOT_FOUND) // Var is not yet initialized
+ {
+ // Clear RT attributes if set for "SecureBootSetup"
+ pRS->SetVariable (AMI_SECURE_BOOT_SETUP_VAR, &guidSecurity, 0, 0, NULL);
+ pRS->SetVariable (AMI_SECURE_BOOT_SETUP_VAR, &guidSecurity,(Attributes & ~EFI_VARIABLE_RUNTIME_ACCESS), DataSize, &SecureBootSetup);
+ }
+
+ DataSize = 1;
+ Byte = USER_MODE;
+ // Provision of defaults only if in Setup mode
+ Status = pRS->GetVariable(EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, &Byte);
+ if(SecureBootSetup.DefaultKeyProvision == 1 &&
+ !EFI_ERROR(Status) && Byte == SETUP_MODE)
+ {
+ Status = InstallSecureVariables(SET_NV_DEFAULT_KEYS);
+ // Status of last key to be installed - PK
+ TRACE((TRACE_ALWAYS,"Provision Sec Vars(%r)\n", Status));
+ // Issue reset after key provision only during normal boot with system is in User Mode and SecureBootSupport flag is enabled
+ if(!EFI_ERROR(Status) && SecureBootSetup.SecureBootSupport)
+ {
+ Status = pRS->GetVariable(EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, &Byte);
+ if(!EFI_ERROR(Status) && Byte == USER_MODE)
+ //Get Boot Mode
+ pHobList = GetEfiConfigurationTable(SystemTable, &gHobListGuid);
+ if (pHobList)
+ {
+ if (((EFI_HOB_HANDOFF_INFO_TABLE*)pHobList)->BootMode!=BOOT_IN_RECOVERY_MODE &&
+ ((EFI_HOB_HANDOFF_INFO_TABLE*)pHobList)->BootMode!=BOOT_ON_FLASH_UPDATE
+ )
+ pRS->ResetSystem(EfiResetCold, Status, 0, NULL);
+ }
+ }
+ }
+#if ALWAYS_INSTALL_DEFAULT_RT_KEYS == 0
+ if(Byte == SETUP_MODE)
+#endif
+ InstallSecureVariables(SET_RT_DEFAULT_KEYS);
+
+ return EFI_SUCCESS;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/SecurityPkg/SecureBootMod.chm b/Core/EM/SecurityPkg/SecureBootMod.chm
new file mode 100644
index 0000000..e17830d
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecureBootMod.chm
Binary files differ
diff --git a/Core/EM/SecurityPkg/SecureBootMod.cif b/Core/EM/SecurityPkg/SecureBootMod.cif
new file mode 100644
index 0000000..f51d310
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecureBootMod.cif
@@ -0,0 +1,21 @@
+<component>
+ name = "Secure Boot Pkg"
+ category = eModule
+ LocalRoot = "Core\EM\SecurityPkg\"
+ RefName = "SecureBootMod"
+[files]
+"SecureBootMod.chm"
+"SecureBootMod.sdl"
+"SecureBootMod.uni"
+"SecureBootMod.mak"
+"SecureBootMod.dxs"
+"SecureBootMod.sd"
+"SecureBootMod.c"
+"SecureBootMod.h"
+[parts]
+"AuthVariable"
+"ImageVerificationLib"
+"SecVariables"
+[dependon]
+"CryptoPkg"
+<endComponent>
diff --git a/Core/EM/SecurityPkg/SecureBootMod.dxs b/Core/EM/SecurityPkg/SecureBootMod.dxs
new file mode 100644
index 0000000..a846460
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecureBootMod.dxs
@@ -0,0 +1,51 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SecureBoot_WIN8/SecureBootMod.dxs 1 8/18/11 4:48p Alexp $
+//
+// $Revision: 1 $
+//
+// $Date: 8/18/11 4:48p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureBoot_WIN8/SecureBootMod.dxs $
+//
+// 1 8/18/11 4:48p Alexp
+//
+// 1 5/10/11 10:01a Alexp
+//
+// 1 3/10/11 4:58p Alexp
+//
+// 1 2/24/11 6:57p Alexp
+//
+//**********************************************************************
+#include <Protocol/AmiDigitalSignature.h>
+
+DEPENDENCY_START
+ AMI_DIGITAL_SIGNATURE_PROTOCOL_GUID
+DEPENDENCY_END
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/SecurityPkg/SecureBootMod.h b/Core/EM/SecurityPkg/SecureBootMod.h
new file mode 100644
index 0000000..0ec0642
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecureBootMod.h
@@ -0,0 +1,116 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SecureBoot_WIN8/SecureBootMod.h 6 8/15/13 10:10a Alexp $
+//
+// $Revision: 6 $
+//
+// $Date: 8/15/13 10:10a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureBoot_WIN8/SecureBootMod.h $
+//
+// 6 8/15/13 10:10a Alexp
+// supported Signatures include 3 more: EFI_CERT_X509_SHAXXX_GUID
+//
+// 5 7/26/13 3:30p Alexp
+// add dbt related defines
+//
+// 4 5/17/13 6:02p Alexp
+// add placeholder defines for "dbt"
+//
+// 3 12/06/12 7:32p Alexp
+// define AMI_SECURE_VAR_PRESENT_VAR
+//
+// 2 11/26/12 10:43a Alexp
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: SecureBootMod.h
+//
+// Description: Common Secure Boot definitions
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+#ifndef _SECURE_BOOT_MODE_H_
+#define _SECURE_BOOT_MODE_H_
+
+#define AMI_SECURE_BOOT_SETUP_VAR L"SecureBootSetup"
+#define AMI_SECURE_VAR_PRESENT_VAR L"SecureVarPresent"
+
+#pragma pack(1)
+typedef struct{
+ UINT8 SecureBootSupport;
+ UINT8 SecureBootMode;
+ UINT8 DefaultKeyProvision;
+ UINT8 Load_from_FV;
+ UINT8 Load_from_OROM;
+ UINT8 Load_from_REMOVABLE_MEDIA;
+ UINT8 Load_from_FIXED_MEDIA;
+} SECURE_BOOT_SETUP_VAR;
+
+typedef struct{
+ UINT8 Value;
+} SETUP_MODE_VAR;
+
+typedef struct{
+ UINT8 Value;
+} SECURE_BOOT_VAR;
+
+typedef struct{
+ UINT8 DBX;
+ UINT8 DBT;
+ UINT8 DB;
+ UINT8 KEK;
+ UINT8 PK;
+} SECURE_VAR_INSTALL_VAR;
+
+#pragma pack()
+
+// EFI_IMAGE_SECURITY_DATABASE_DEFAULT must be defined in ImageAuthentication.h (Core 4.6.5.4 +)
+// UEFI ECR874: Install Factory defaults as Read-only volatile variables for key distribution.
+#ifndef EFI_IMAGE_SECURITY_DATABASE_DEFAULT
+#define EFI_IMAGE_SECURITY_DATABASE_DEFAULT L"dbDefault"
+#define EFI_IMAGE_SECURITY_DATABASE1_DEFAULT L"dbxDefault"
+#define EFI_PLATFORM_KEY_NAME_DEFAULT L"PKDefault"
+#define EFI_KEY_EXCHANGE_KEY_NAME_DEFAULT L"KEKDefault"
+#define EFI_IMAGE_SECURITY_DATABASE2_DEFAULT L"dbtDefault"
+#endif
+#ifndef EFI_IMAGE_SECURITY_DATABASE2
+#define EFI_IMAGE_SECURITY_DATABASE2 L"dbt"
+#define EFI_IMAGE_SECURITY_DATABASE2_DEFAULT L"dbtDefault"
+#endif
+
+#define SIGSUPPORT_NUM 8
+#define SIGSUPPORT_LIST EFI_CERT_X509_SHA256_GUID, EFI_CERT_X509_SHA384_GUID, EFI_CERT_X509_SHA512_GUID, EFI_CERT_SHA256_GUID, EFI_CERT_X509, EFI_CERT_RSA2048_GUID, EFI_CERT_RSA2048_SHA256_GUID, EFI_CERT_RSA2048_SHA1_GUID
+
+#endif //_SECURE_BOOT_MODE_H_
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/SecurityPkg/SecureBootMod.mak b/Core/EM/SecurityPkg/SecureBootMod.mak
new file mode 100644
index 0000000..2d30872
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecureBootMod.mak
@@ -0,0 +1,153 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2012, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#*************************************************************************
+# $Header: /Alaska/SOURCE/Modules/SecureBoot_WIN8/SecureBootMod.mak 14 11/19/12 4:40p Alexp $
+#
+# $Revision: 14 $
+#
+# $Date: 11/19/12 4:40p $
+#*************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/SecureBoot_WIN8/SecureBootMod.mak $
+#
+# 14 11/19/12 4:40p Alexp
+# Fix for Win8 SecureBoot logo requirement: restore Secure Boot state
+# across flash updates.
+# Move all secure boot Setup settings to a separate varsore variable.
+# Preserve var across re-flash
+#
+# 13 8/23/12 5:40p Alexp
+# Added SecureBootMod.c file to the list of String Consumers
+#
+# 12 8/15/12 4:48p Alexp
+# 1. Modify Secure Boot page controls. Hide all controls under new
+# sub-page
+# 2. Refrash Secure Boot Setup screens upon user load Defaults/Previous
+# values
+# 3.
+#
+# 11 6/05/12 10:30a Alexp
+# moved build rules for default SecureVariables to SecureVariable eModule
+#
+# 10 6/01/12 4:13p Alexp
+# cleaned up Include list
+#
+# 8 3/09/12 3:29p Alexp
+# Implementation to PRESERVE_SECURE_VARIABLES on Flash Update is moved
+# here from SecSmiFlash component
+#
+# 7 8/25/11 8:33a Alexp
+# add back .dxs dependency on AmiDigitalSig protocol. Needed if Secure
+# Variable provisioning is enabled at Driver's entry point
+#
+# 6 8/24/11 6:23p Alexp
+# link SecureBootMod.obj to SetupBin.
+#
+# 5 8/22/11 5:19p Alexp
+# restored CallBack notification method to set Manufacturing defaults
+# from TSE SetupPage
+#
+# 4 8/18/11 4:50p Alexp
+# 1. removed callback events on Security Page updates
+# 2. Add DEPEX on AmiDigitalSig protocol
+#
+# 3 7/18/11 9:58a Alexp
+# make Variable ffs files compressed
+#
+# 2 6/30/11 4:25p Alexp
+# add dependency on SecureVariable module with OEM defined default
+# variables for PK-KEK-db-dbx
+# if present will add setup control to provision default Secure Variables
+#
+# 1 6/30/11 3:47p Alexp
+#
+#
+#*************************************************************************
+#<AMI_FHDR_START>
+#
+# Name: SecureBootMod.mak
+#
+# Description:
+#
+#
+#<AMI_FHDR_END>
+#*************************************************************************
+all: SecureBootModule
+
+SecureBootModule : $(BUILD_DIR)\SecureBootMod.mak SecureBootModDxe
+
+$(BUILD_DIR)\SecureBootMod.mak : $(SecureBoot_DIR)\SecureBootMod.cif $(BUILD_RULES)
+ $(CIF2MAK) $(SecureBoot_DIR)\SecureBootMod.cif $(CIF2MAK_DEFAULTS)
+
+SecureBootModDxe : $(AMIDXELIB)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\SecureBootMod.mak all\
+ NAME=SecureBootMod\
+ "MY_INCLUDES=/I$(SecureBoot_DIR)"\
+ MAKEFILE=$(BUILD_DIR)\SecureBootMod.mak \
+ GUID=A95C1D60-CB9F-4BD8-A030-3F1C4A185156 \
+ ENTRY_POINT=SecureBootMod_Init\
+ "EXT_HEADERS=$(BUILD_DIR)\SetupStrTokens.h $(BUILD_DIR)\AUTOID.h"\
+ DEPEX1=$(SecureBoot_DIR)\SecureBootMod.DXS DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX \
+ TYPE=BS_DRIVER COMPRESS=1
+
+#---------------------------------------------------------------------------
+# Create Setup Screen(s)
+#---------------------------------------------------------------------------
+SetupSdbs : SecureBootModSDB
+
+SecureBootModSDB : $(BUILD_DIR)\SecureBootMod.mak
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\SecureBootMod.mak all\
+ TYPE=SDB NAME=SecureBootMod\
+ "MY_INCLUDES=/I$(SecureBoot_DIR)"\
+ "STRING_CONSUMERS=$(SecureBoot_DIR)\SecureBootMod.sd $(SecureBoot_DIR)\SecureBootMod.c"
+
+#---------------------------------------------------------------------------
+# Link Callback Lib to Setup
+#---------------------------------------------------------------------------
+SetupBin : $(BUILD_DIR)\$(Setup_DIR)\SecureBootMod.obj
+
+$(BUILD_DIR)\$(Setup_DIR)\SecureBootMod.obj : $(SecureBoot_DIR)\SecureBootMod.c $(BUILD_DIR)\SetupStrTokens.h
+ $(CC) $(CFLAGS) /I$(SecureBoot_DIR) /DSETUP_COMPILE=1 $(SecureBoot_DIR)\SecureBootMod.c /Fo$@
+
+AMITSEBin : $(BUILD_DIR)\$(TSEBIN_DIR)\SecureBootMod.obj
+$(BUILD_DIR)\$(TSEBIN_DIR)\SecureBootMod.obj : $(SecureBoot_DIR)\SecureBootMod.c $(BUILD_DIR)\SetupStrTokens.h
+ $(CC) $(CFLAGS) /DTSEBIN_COMPILE=1 /I$(SecureBoot_DIR) /I $(TSEBIN_DIR)\Inc /I $(TSEBIN_DIR) /I$(CORE_DIR) $(SecureBoot_DIR)\SecureBootMod.c /Fo$@
+
+#---------------------------------------------------------------------------
+# Link SMIFlash hooks to SmiFlash module
+#---------------------------------------------------------------------------
+!IF "$(PRESERVE_SECURE_VARIABLES)" == "1"
+SMIFlashBin : $(BUILD_DIR)\$(SMI_FLASH_DIR)\SecureBootMod.obj
+
+$(BUILD_DIR)\$(SMI_FLASH_DIR)\SecureBootMod.obj: $(SecureBoot_DIR)\SecureBootMod.c
+ $(CC) $(CFLAGS) /I$(SecureBoot_DIR) /I$(CORE_DIR) /DSMIFLASH_COMPILE=1 /DSMM_COMPILE=1 /Fo$@ $**
+!ENDIF
+
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2012, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
diff --git a/Core/EM/SecurityPkg/SecureBootMod.sd b/Core/EM/SecurityPkg/SecureBootMod.sd
new file mode 100644
index 0000000..0584d69
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecureBootMod.sd
@@ -0,0 +1,685 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SecureBoot_WIN8/SecureBootMod.sd 51 3/09/15 5:05p Alexp $
+//
+// $Revision: 51 $
+//
+// $Date: 3/09/15 5:05p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureBoot_WIN8/SecureBootMod.sd $
+//
+// 51 3/09/15 5:05p Alexp
+// 1. Implement User prompt to install Secure Boot key defaults
+// while switching of Secure Boot mode from Custom to Standard
+// (per Windows8+ Hardware Certification requirements).
+// Add callback on SECURE_BOOT_MODE_CHANGE_KEY
+// 2. EIP#200639: When the token DEFAULT_PROVISION_SECURE_VARS enable,
+// the secure boot status is Not Active when first enter setup.
+// [Resolution] Issue SystemReset after initial Secure Boot provisioning
+// 3. EIP#201422: set SecVariables_SUPPORT = 0, code will build fail
+//
+// 50 4/07/14 2:47p Alexp
+// Add Hii event SECURE_BOOT_MENU_REFRESH on entering of Secure Boot menu
+// The callback to this event refreshes the state of internal Secure Boot
+// setup flags.
+// UpdateSecureVariableBrowserInfo()
+//
+// 49 12/05/13 9:05a Alexp
+// don't hide Secure Boot menu if in User mode. Instead - keep all
+// controls greyed out
+//
+// 48 8/15/13 10:08a Alexp
+// add DBT controls
+//
+// 47 7/26/13 3:34p Alexp
+// 1. Add dbt dialogs on Key Management page
+// 2. Image Execution policies options are enabled according to defaults
+// in SDL
+//
+
+// 46 6/22/13 12:22p Alexp
+// Made Image Execution page depend on ENABLE_IMAGE_EXEC_POLICY_OVERRIDE
+//
+// 45 5/17/13 5:50p Alexp
+// add separator
+//
+// 44 3/22/13 5:00p Alexp
+// Put Key Management sub-menu in front of Image Executin Policy.
+//
+// 43 3/21/13 1:16p Alexp
+// Update help strings
+//
+// 42 2/08/13 4:52p Alexp
+// EIP#114350:Need the Token for SecureBootMode default value
+//
+// 41 12/06/12 7:32p Alexp
+// Update Key Management page layout
+//
+// 40 12/04/12 11:23a Alexp
+// Revert the change in #39- do not introduce SETUP_DATA.SecureBootSupport
+// Mudules that had reference to this field must change to use generic
+// UEFI SecureBoot variable
+//
+// 39 11/29/12 11:10a Alexp
+// Include dummy variable to the SetupData structure in case it's
+// referenced by external modules (e.g. old labels of TCG)
+// SETUP_DATA.SecureBootSupport;
+//
+// 38 11/19/12 4:40p Alexp
+// Fix for Win8 SecureBoot logo requirement: restore Secure Boot state
+// across flash updates.
+// Move all secure boot Setup settings to a separate varsore variable.
+// Preserve var across re-flash
+//
+// 37 10/22/12 3:53p Alexp
+// Fix interactive menus for Set/Append Key operations
+//
+// 36 9/18/12 3:51p Alexp
+//
+// 35 9/10/12 2:06p Alexp
+// Link SDL defined defaults for Image Exec Policy settings
+//
+// 34 9/07/12 5:12p Alexp
+// Remove dependency on newer Cores:CORE_COMBINED_VERSION >= 0x4028a
+// Win8 compliant BIOS must have upgraded Core components and Tse
+//
+// 33 9/04/12 12:40p Alexp
+// Change dependency on from Efi Generic Variable: SetupMode to custom
+// Variable: SECURE_VAR_INSTALL
+// Needed to display proper Goto Control symbol in TSE
+//
+// 32 8/30/12 2:05p Alexp
+// Add warning label and steps to overcome Vfr coompatibility issues on
+// older Cores with EfiSpec version less then 2.1
+//
+// 31 8/29/12 5:24p Alexp
+// Fix Display issues with Core 4.6.5.4+
+// Changed oneof parameters in SecureBootSupport.
+//
+// 30 8/28/12 3:46p Alexp
+//
+// 29 8/27/12 6:51p Alexp
+// DEFAULT_SECURE_BOOT_ENABLE changes behavior of SecureBoot Option.
+// If set to 0 - Secure Boot will be kept disabled if in Setup Mode
+//
+// 28 8/27/12 10:46a Alexp
+// SecureBoot Supprt value made dependent on System State = User Mode and
+// Default Provisioning.
+// User should not be able to Enable Secure Boot if Keys are not
+// provisioned.
+//
+// 27 8/23/12 5:43p Alexp
+// Add user selection for supported file formats in Append SecureBoot
+// operations
+//
+// 26 8/15/12 4:48p Alexp
+// 1. Modify Secure Boot page controls. Hide all controls under new
+// sub-page
+// 2. Refrash Secure Boot Setup screens upon user load Defaults/Previous
+// values
+// 3.
+//
+// 25 7/30/12 10:59a Alexp
+//
+// 24 7/27/12 2:00p Alexp
+// Execution Policy page. Made "User Query" visible only if System is in
+// Setup mode
+//
+//
+// 22 7/25/12 6:34p Alexp
+// Update Secure Boot page layout
+// 1. Security Page
+// 1.3 Replaced standalone SecureBootMode Option to an added value in
+// Secure Boot list (on/off/custom)
+// 1.4 Display SecureBootMode Standard/Custom Status
+// 2. Key Management Page
+// 2.1 Add Append Certificate Options along with Append from File
+// New functions append new Certificates from different types of
+// input Certs (x509, RSA2048 & SHA256) and Signature List blobs
+// 2.2 Use single Save to files option for all Sec Variables
+// 2.3 Set Variable Option gets a Key from a File Browser or a Factory
+// Default storage.
+//
+// 21 5/15/12 9:43a Alexp
+// EIP:89280. When secure boot enable with secure flash disable, in
+// Security page of setup menu same items will exist twice
+// FIX: modify rules to suppress lines for installed Variables
+//
+// 20 4/27/12 3:52p Alexp
+//
+// 19 4/23/12 5:25p Alexp
+// Update Key Management Setup page.
+// -Added "Default Key Provisioning" switch
+// -reuse help strings for custom Secure Boot key options
+//
+// 18 4/10/12 6:52p Alexp
+// change control order
+//
+// 17 3/22/12 10:51a Alexp
+// change Secure Boot default to Enabled
+//
+// 16 3/09/12 3:57p Alexp
+// [EIP#82334]-TSE Text Verification test failed
+// -fixed misspelled messages
+// - Win8 Logo requirement: add new Setup switch- Secure Boot mode to
+// toggle between Standard and Custom
+// -changed Security page layout
+//
+// 14 2/15/12 1:57p Alexp
+// Disable "Key Delete" controls if DEFAULT_PROVISION_SECURE_VARS is set
+//
+// 13 2/14/12 7:34p Alexp
+// disable unused controlls when DEFAULT_PROVISION_SECURE_VARS is set
+//
+// 12 11/10/11 2:16p Alexp
+// exclude all HII callback forms based on "EFI_SPECIFICATION_VERSION"
+// ">=" "0x2000A
+//
+// 11 11/08/11 5:58p Alexp
+//
+// 10 11/07/11 6:26p Alexp
+// Add Key Management controls to add/get/append and delete Secure
+// Variables from the Setup page
+//
+// 9 11/03/11 6:30p Alexp
+// SecureBootMod.c(sdl, .sd, .uni) Change the appearance of Secure Boot
+// items on Setup Security page. Added information on currently installed
+// Secure Variables.
+//
+// 8 8/22/11 5:19p Alexp
+// restored CallBack notification method to set Manufacturing defaults
+// from TSE SetupPage
+//
+// 7 8/18/11 4:51p Alexp
+// replaced dynamic removed callback events to static Setup Option
+//
+// 6 8/05/11 3:15p Alexp
+// re-arranged setup page
+//
+// 5 7/18/11 9:57a Alexp
+// rearranged Security Setup page
+//
+// 4 7/01/11 3:35p Alexp
+// Made changes to comply with older VfrCompilers (pre 4.6.5.)
+//
+// 3 6/30/11 4:25p Alexp
+// add dependency on SecureVariable module with OEM defined default
+// variables for PK-KEK-db-dbx
+// if present will add setup control to provision default Secure Variables
+//
+// 2 6/30/11 3:56p Alexp
+// removed comments
+//
+// 1 6/30/11 3:47p Alexp
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: SecureBootMod.sd
+//
+// Description:
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#ifdef SETUP_DATA_DEFINITION
+/***********************************************************/
+/* Put NVRAM data definitions here.
+/* For example: UINT8 Data1;
+/* These definitions will be converted by the build process
+/* to a definitions of SETUP_DATA fields.
+/***********************************************************/
+#endif
+
+#ifdef SECURITY_FORM_SET
+
+#ifdef FORM_SET_TYPEDEF
+ #include "SecureBootMod.h"
+#endif
+ #ifdef FORM_SET_VARSTORE
+ varstore SECURE_BOOT_SETUP_VAR,
+ key = AUTO_ID(SECURE_BOOT_SETUP_ID),
+ name = SecureBootSetup,
+ guid = SECURITY_FORM_SET_GUID;
+ varstore SECURE_VAR_INSTALL_VAR,
+ key = AUTO_ID(SECURE_VAR_INSTALL_ID),
+ name = SecureVarPresent,
+ guid = SECURITY_FORM_SET_GUID;
+ varstore SETUP_MODE_VAR,
+ key = AUTO_ID(SETUP_MODE_ID),
+ name = SetupMode,
+ guid = {0x8BE4DF61,0x93CA,0x11d2,0xAA,0xD,0x0,0xE0,0x98,0x03,0x2B,0x8C};
+ varstore SECURE_BOOT_VAR,
+ key = AUTO_ID(SECURE_BOOT_ID),
+ name = SecureBoot,
+ guid = {0x8BE4DF61,0x93CA,0x11d2,0xAA,0xD,0x0,0xE0,0x98,0x03,0x2B,0x8C};
+ #endif
+
+ #ifdef FORM_SET_ITEM
+ #endif
+
+ #ifdef FORM_SET_GOTO
+
+ SEPARATOR
+ //
+ // Define goto commands for the forms defined in this file
+ //
+ //
+ // Define goto commands for the forms defined in this file
+ //
+ goto SECURE_BOOT_SUBMENU_FORM_ID,
+ prompt = STRING_TOKEN(SECURE_BOOT_MENU_FORM_TITLE),
+ help = STRING_TOKEN(SECURE_BOOT_MENU_FORM_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(SECURE_BOOT_MENU_REFRESH);
+
+ #endif
+
+ #ifdef FORM_SET_FORM
+ //
+ // Define forms
+ //
+ form formid = AUTO_ID(SECURE_BOOT_SUBMENU_FORM_ID),
+ title = STRING_TOKEN(SECURE_BOOT_MENU_FORM_TITLE);
+
+ SEPARATOR
+ suppressif ideqval SETUP_MODE_VAR.Value == 1;
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_PLATFORM_MODE),
+ text = STRING_TOKEN(STR_USER),
+ flags = 0,
+ key = 0;
+ endif;
+ suppressif ideqval SETUP_MODE_VAR.Value == 0;
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_PLATFORM_MODE),
+ text = STRING_TOKEN(STR_SETUP),
+ flags = 0,
+ key = 0;
+ endif;
+ suppressif ideqval SECURE_BOOT_VAR.Value == 1;
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_PLATFORM_SECURE_MODE),
+ text = STRING_TOKEN(STR_INACTIVE),
+ flags = 0,
+ key = 0;
+ endif;
+ suppressif ideqval SECURE_BOOT_VAR.Value == 0;
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_PLATFORM_SECURE_MODE),
+ text = STRING_TOKEN(STR_ACTIVE),
+ flags = 0,
+ key = 0;
+ endif;
+ //
+ // Define controls to be added to the main page of the formset
+ //
+//!!!!!!!!!!!
+// WARNING: On older Aptio Core versions (< 4.6.5.0) VfrCompiler may generate errors in SecureBootMod.sd due to incompatible syntax of `questionid' and
+// `INTERRACTIVE' constructions. User may need to upgrade Aptio Core support for EFI_SPECIFICATION version to 2.1 (SDL:0x2000A) or edit this SecureBootMod.sd to
+// remove unsupported keywords e.g. remove `INTERACTIVE' in `one of' structures and add `, key=0' instead. Also remove `questioned' from `oneof' constructions .
+// Note that above mentioned fixes will disable some of the Secure Boot page functionality
+//!!!!!!!!!!!
+ SEPARATOR
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ oneof varid = SECURE_BOOT_SETUP_VAR.SecureBootSupport,
+ questionid = AUTO_ID(SECURE_BOOT_SUPPORT_CHANGE_KEY),
+ prompt = STRING_TOKEN(STR_SECURE_BOOT_ENABLE),
+ help = STRING_TOKEN(STR_SECURE_BOOT_HELP),
+ default = DEFAULT_SECURE_BOOT_ENABLE,
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = RESET_REQUIRED | INTERACTIVE;
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = MANUFACTURING | RESET_REQUIRED | INTERACTIVE;
+ endoneof;
+ oneof varid = SECURE_BOOT_SETUP_VAR.SecureBootMode,
+ questionid = AUTO_ID(SECURE_BOOT_MODE_CHANGE_KEY),
+ prompt = STRING_TOKEN(STR_SECURE_BOOT_MODE),
+ help = STRING_TOKEN(STR_SECURE_BOOT_MODE_HELP),
+ default = DEFAULT_SECURE_BOOT_MODE,
+ option text = STRING_TOKEN(SECURE_BOOT_STANDARD), value = 0, flags = MANUFACTURING | RESET_REQUIRED | INTERACTIVE;//, key = 0;
+ option text = STRING_TOKEN(SECURE_BOOT_CUSTOM), value = 1, flags = RESET_REQUIRED | INTERACTIVE;//, key = 0;
+ endoneof;
+ endif;
+ //
+ // Define goto commands for the forms defined in this file
+ //
+ suppressif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER OR ideqval SECURE_BOOT_SETUP_VAR.SecureBootMode == 0;
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_KEY_MANAGEMENT_TITLE),
+ help = STRING_TOKEN(STR_KEY_MANAGEMENT_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(KEY_MANAGEMENT_MENU_REFRESH);
+ #if (defined(ENABLE_IMAGE_EXEC_POLICY_OVERRIDE) && ENABLE_IMAGE_EXEC_POLICY_OVERRIDE == 1)
+ goto IMAGE_EXEC_POLICY_FORM_ID,
+ prompt = STRING_TOKEN(IMAGE_EXEC_POLICY_FORM_TITLE),
+ help = STRING_TOKEN(IMAGE_EXEC_POLICY_FORM_HELP);
+ #endif
+ endif;
+ endform;
+
+ form formid = AUTO_ID(SECURE_KEY_MANAGEMENT_FORM_ID),
+ title = STRING_TOKEN(STR_KEY_MANAGEMENT_TITLE);
+
+ oneof varid = SECURE_BOOT_SETUP_VAR.DefaultKeyProvision,
+ questionid = AUTO_ID(KEY_PROVISION_CHANGE_KEY),
+ prompt = STRING_TOKEN(STR_DEFAULT_KEY_PROVISION_MODE),
+ help = STRING_TOKEN(STR_KEY_PROVISION_MODE_HELP),
+ #if (defined(DEFAULT_PROVISION_SECURE_VARS) && DEFAULT_PROVISION_SECURE_VARS == 1)
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = RESET_REQUIRED | INTERACTIVE;
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED | INTERACTIVE;
+ #else
+ #if defined(SET_SECURE_VARS) && SET_SECURE_VARS
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED | INTERACTIVE;
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED | INTERACTIVE;
+ #else
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED | INTERACTIVE;
+ #endif
+ #endif
+
+ endoneof;
+ //
+ // Define goto commands for the forms defined in this file
+ //
+ SEPARATOR
+ suppressif ideqval SECURE_VAR_INSTALL_VAR.PK == 0 OR ideqval SECURE_BOOT_SETUP_VAR.DefaultKeyProvision == 1;
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_FORCE_SETUP_MODE),
+ help = STRING_TOKEN(STR_FORCE_SETUP_MODE_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(FORCE_SETUP_KEY);
+ endif;
+ #if defined(SET_SECURE_VARS) && SET_SECURE_VARS
+ suppressif ideqval SECURE_VAR_INSTALL_VAR.PK == 1 AND ideqval SECURE_BOOT_SETUP_VAR.DefaultKeyProvision == 0;
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_FORCE_DEFAULT_MODE),
+ help = STRING_TOKEN(STR_FORCE_DEFAULT_MODE_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(FORCE_DEFAULT_KEY);
+ endif;
+ #endif // SET_SECURE_VARS
+ grayoutif ideqval SECURE_VAR_INSTALL_VAR.PK == 0 AND ideqval SECURE_VAR_INSTALL_VAR.KEK == 0 AND ideqval SECURE_VAR_INSTALL_VAR.DB == 0 AND ideqval SECURE_VAR_INSTALL_VAR.DBX == 0;
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_GET_ALL_VARS),
+ help = STRING_TOKEN(STR_GET_PK_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(GET_PK_KEY);
+ endif;
+ SEPARATOR
+ suppressif NOT ideqval SECURE_VAR_INSTALL_VAR.PK == 0;
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_MANAGE_PK),
+ text = STRING_TOKEN(STR_NOT_INSTALLED),
+ flags = 0,
+ key = 0;
+ endif;
+ suppressif NOT ideqval SECURE_VAR_INSTALL_VAR.PK == 1;
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_MANAGE_PK),
+ text = STRING_TOKEN(STR_INSTALLED),
+ flags = 0,
+ key = 0;
+ endif;
+
+ grayoutif ideqval SECURE_VAR_INSTALL_VAR.PK == 0;
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_DELETE_PK),
+ help = STRING_TOKEN(STR_DELETE_PK_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(DELETE_PK_KEY);
+ endif;
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_SET_PK),
+ help = STRING_TOKEN(STR_APPEND_KEK_ENTRY_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(SET_PK_KEY);
+
+ SEPARATOR
+
+ suppressif NOT ideqval SECURE_VAR_INSTALL_VAR.KEK == 0;
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_MANAGE_KEK),
+ text = STRING_TOKEN(STR_NOT_INSTALLED),
+ flags = 0,
+ key = 0;
+ endif;
+ suppressif NOT ideqval SECURE_VAR_INSTALL_VAR.KEK == 1;
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_MANAGE_KEK),
+ text = STRING_TOKEN(STR_INSTALLED),
+ flags = 0,
+ key = 0;
+ endif;
+
+ grayoutif ideqval SECURE_VAR_INSTALL_VAR.KEK == 0;
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_DELETE_KEK),
+ help = STRING_TOKEN(STR_DELETE_PK_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(DELETE_KEK_KEY);
+ endif;
+
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_SET_KEK),
+ help = STRING_TOKEN(STR_APPEND_KEK_ENTRY_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(SET_KEK_KEY);
+
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_APPEND_KEK_ENTRY),
+ help = STRING_TOKEN(STR_APPEND_KEK_ENTRY_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(APPEND_KEK_KEY);
+
+ suppressif NOT ideqval SECURE_VAR_INSTALL_VAR.DB == 0;
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_MANAGE_DB),
+ text = STRING_TOKEN(STR_NOT_INSTALLED),
+ flags = 0,
+ key = 0;
+ endif;
+ suppressif NOT ideqval SECURE_VAR_INSTALL_VAR.DB == 1;
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_MANAGE_DB),
+ text = STRING_TOKEN(STR_INSTALLED),
+ flags = 0,
+ key = 0;
+ endif;
+
+ grayoutif ideqval SECURE_VAR_INSTALL_VAR.DB == 0;
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_DELETE_DB),
+ help = STRING_TOKEN(STR_DELETE_PK_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(DELETE_DB_KEY);
+ endif;
+
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_SET_DB),
+ help = STRING_TOKEN(STR_APPEND_KEK_ENTRY_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(SET_DB_KEY);
+
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_APPEND_DB_ENTRY),
+ help = STRING_TOKEN(STR_APPEND_KEK_ENTRY_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(APPEND_DB_KEY);
+
+ suppressif NOT ideqval SECURE_VAR_INSTALL_VAR.DBX == 0;
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_MANAGE_DBX),
+ text = STRING_TOKEN(STR_NOT_INSTALLED),
+ flags = 0,
+ key = 0;
+ endif;
+ suppressif NOT ideqval SECURE_VAR_INSTALL_VAR.DBX == 1;
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_MANAGE_DBX),
+ text = STRING_TOKEN(STR_INSTALLED),
+ flags = 0,
+ key = 0;
+ endif;
+
+ grayoutif ideqval SECURE_VAR_INSTALL_VAR.DBX == 0;
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_DELETE_DBX),
+ help = STRING_TOKEN(STR_DELETE_PK_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(DELETE_DBX_KEY);
+ endif;
+
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_SET_DBX),
+ help = STRING_TOKEN(STR_APPEND_KEK_ENTRY_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(SET_DBX_KEY);
+
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_APPEND_DBX_ENTRY),
+ help = STRING_TOKEN(STR_APPEND_KEK_ENTRY_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(APPEND_DBX_KEY);
+
+ suppressif NOT ideqval SECURE_VAR_INSTALL_VAR.DBT == 0;
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_MANAGE_DBT),
+ text = STRING_TOKEN(STR_NOT_INSTALLED),
+ flags = 0,
+ key = 0;
+ endif;
+ suppressif NOT ideqval SECURE_VAR_INSTALL_VAR.DBT == 1;
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_MANAGE_DBT),
+ text = STRING_TOKEN(STR_INSTALLED),
+ flags = 0,
+ key = 0;
+ endif;
+
+ grayoutif ideqval SECURE_VAR_INSTALL_VAR.DBT == 0;
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_DELETE_DBT),
+ help = STRING_TOKEN(STR_DELETE_PK_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(DELETE_DBT_KEY);
+ endif;
+
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_SET_DBT),
+ help = STRING_TOKEN(STR_APPEND_KEK_ENTRY_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(SET_DBT_KEY);
+
+ goto SECURE_KEY_MANAGEMENT_FORM_ID,
+ prompt = STRING_TOKEN(STR_APPEND_DBT_ENTRY),
+ help = STRING_TOKEN(STR_APPEND_KEK_ENTRY_HELP),
+ flags = INTERACTIVE, key = AUTO_ID(APPEND_DBT_KEY);
+
+ endform;
+
+#if (defined(ENABLE_IMAGE_EXEC_POLICY_OVERRIDE) && ENABLE_IMAGE_EXEC_POLICY_OVERRIDE == 1)
+ form formid = AUTO_ID(IMAGE_EXEC_POLICY_FORM_ID),
+ title = STRING_TOKEN(IMAGE_EXEC_POLICY_FORM_TITLE);
+
+ oneof varid = SECURE_BOOT_SETUP_VAR.Load_from_FV,
+ prompt = STRING_TOKEN(STR_LOAD_FROM_FV),
+ help = STRING_TOKEN(STR_LOAD_FROM_HELP),
+ option text = STRING_TOKEN(ALWAYS_ENABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED, key = 0;
+ endoneof;
+
+ oneof varid = SECURE_BOOT_SETUP_VAR.Load_from_OROM,
+ prompt = STRING_TOKEN(STR_LOAD_FROM_OROM),
+ help = STRING_TOKEN(STR_LOAD_FROM_HELP),
+ default = LOAD_FROM_OROM,
+#if (LOAD_FROM_OROM == 0 )
+ option text = STRING_TOKEN(ALWAYS_ENABLED), value = 0, flags = RESET_REQUIRED, key = 0;
+#endif
+#if (LOAD_FROM_OROM < 2 )
+ option text = STRING_TOKEN(ALWAYS_DISABLED), value = 1, flags = RESET_REQUIRED, key = 0;
+#endif
+#if (LOAD_FROM_OROM < 3 )
+ option text = STRING_TOKEN(ALLOW_EXECUTE_ON_SECURITY_VIOLATION), value = 2, flags = RESET_REQUIRED, key = 0;
+#endif
+#if (LOAD_FROM_OROM < 4 )
+ option text = STRING_TOKEN(DEFER_EXECUTE_ON_SECURITY_VIOLATION), value = 3, flags = RESET_REQUIRED, key = 0;
+#endif
+#if (LOAD_FROM_OROM < 5 )
+ option text = STRING_TOKEN(DENY_EXECUTE_ON_SECURITY_VIOLATION), value = 4, flags = MANUFACTURING | RESET_REQUIRED, key = 0;
+#endif
+ option text = STRING_TOKEN(QUERY_USER_ON_SECURITY_VIOLATION), value = 5, flags = RESET_REQUIRED, key = 0;
+ endoneof;
+
+ oneof varid = SECURE_BOOT_SETUP_VAR.Load_from_REMOVABLE_MEDIA,
+ prompt = STRING_TOKEN(STR_LOAD_FROM_REMOVABLE_MEDIA),
+ help = STRING_TOKEN(STR_LOAD_FROM_HELP),
+ default = LOAD_FROM_REMOVABLE_MEDIA,
+#if (LOAD_FROM_REMOVABLE_MEDIA == 0 )
+ option text = STRING_TOKEN(ALWAYS_ENABLED), value = 0, flags = RESET_REQUIRED, key = 0;
+#endif
+#if (LOAD_FROM_REMOVABLE_MEDIA < 2 )
+ option text = STRING_TOKEN(ALWAYS_DISABLED), value = 1, flags = RESET_REQUIRED, key = 0;
+#endif
+#if (LOAD_FROM_REMOVABLE_MEDIA < 3 )
+ option text = STRING_TOKEN(ALLOW_EXECUTE_ON_SECURITY_VIOLATION), value = 2, flags = RESET_REQUIRED, key = 0;
+#endif
+#if (LOAD_FROM_REMOVABLE_MEDIA < 4 )
+ option text = STRING_TOKEN(DEFER_EXECUTE_ON_SECURITY_VIOLATION), value = 3, flags = RESET_REQUIRED, key = 0;
+#endif
+#if (LOAD_FROM_REMOVABLE_MEDIA < 5 )
+ option text = STRING_TOKEN(DENY_EXECUTE_ON_SECURITY_VIOLATION), value = 4, flags = MANUFACTURING | RESET_REQUIRED, key = 0;
+#endif
+ option text = STRING_TOKEN(QUERY_USER_ON_SECURITY_VIOLATION), value = 5, flags = RESET_REQUIRED, key = 0;
+ endoneof;
+
+ oneof varid = SECURE_BOOT_SETUP_VAR.Load_from_FIXED_MEDIA,
+ prompt = STRING_TOKEN(STR_LOAD_FROM_FIXED_MEDIA),
+ help = STRING_TOKEN(STR_LOAD_FROM_HELP),
+ default = LOAD_FROM_FIXED_MEDIA,
+#if (LOAD_FROM_FIXED_MEDIA == 0 )
+ option text = STRING_TOKEN(ALWAYS_ENABLED), value = 0, flags = RESET_REQUIRED, key = 0;
+#endif
+#if (LOAD_FROM_FIXED_MEDIA < 2 )
+ option text = STRING_TOKEN(ALWAYS_DISABLED), value = 1, flags = RESET_REQUIRED, key = 0;
+#endif
+#if (LOAD_FROM_FIXED_MEDIA < 3 )
+ option text = STRING_TOKEN(ALLOW_EXECUTE_ON_SECURITY_VIOLATION), value = 2, flags = RESET_REQUIRED, key = 0;
+#endif
+#if (LOAD_FROM_FIXED_MEDIA < 4 )
+ option text = STRING_TOKEN(DEFER_EXECUTE_ON_SECURITY_VIOLATION), value = 3, flags = RESET_REQUIRED, key = 0;
+#endif
+#if (LOAD_FROM_FIXED_MEDIA < 5 )
+ option text = STRING_TOKEN(DENY_EXECUTE_ON_SECURITY_VIOLATION), value = 4, flags = MANUFACTURING | RESET_REQUIRED, key = 0;
+#endif
+ option text = STRING_TOKEN(QUERY_USER_ON_SECURITY_VIOLATION), value = 5, flags = RESET_REQUIRED, key = 0;
+ endoneof;
+
+ endform;
+#endif
+ #endif
+
+#endif // SECURITY_FORM_SET
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/SecurityPkg/SecureBootMod.sdl b/Core/EM/SecurityPkg/SecureBootMod.sdl
new file mode 100644
index 0000000..0b75e1b
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecureBootMod.sdl
@@ -0,0 +1,277 @@
+TOKEN
+ Name = "SecureBoot_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable SecureBoot Module support in Project"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+ Token = "CryptoAPI_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "SECURE_BOOT_MODULE_REVISION"
+ Value = "25"
+ Help = "Version of Secure Boot module interfaces"
+ TokenType = Integer
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "DEFAULT_SECURE_BOOT_ENABLE"
+ Value = "1"
+ Help = "Default value of Secure Boot Enable Control.\0-Secure Boot control option will be locked Disabled unless platform in User mode with CSM disabled"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "DEFAULT_SECURE_BOOT_MODE"
+ Value = "0"
+ Help = "Default Secure Boot Mode selector.\0-Standard, 1-Custom Mode allows physically present users more flexibility changing Image Execution policy and Secure Boot Key management."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "DEFAULT_SECURE_BOOT_MODE"
+ Value = "1"
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "DEFAULT_SECURE_BOOT_ENABLE" "=" "0"
+End
+
+TOKEN
+ Name = "DEFAULT_PROVISION_SECURE_VARS"
+ Value = "0"
+ Help = "Install factory default Secure Boot variables: PK, KEK, db, dbx and dbt.\Note: this function will not override existing Secure Boot variables in NVRAM."
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+ Token = "SecVariables_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "SET_SECURE_VARS"
+ Value = "0"
+ Help = "Placeholder token"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "SET_SECURE_VARS"
+ Value = "1"
+ Help = "Includes the code to provision Platform Keys EFI variable from Setup Page and at 1st boot after reFlash"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+ Token = "SecVariables_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "PRESERVE_SECURE_VARIABLES"
+ Value = "1"
+ Help = "1 - Preserve Secure Boot State across flash updates.\0 - Do not preserve Secure Boot State across flash updates.\Note. Same functionality may already exist in SmiFlash eModule"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "ALWAYS_INSTALL_DEFAULT_RT_KEYS"
+ Value = "0"
+ Help = "UEFI 2.3.1c. Install vendor default Secure Boot keys as volatile variables: PKdefault, KEKdefault etc. are set irrespective of Setup mode"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+PATH
+ Name = "SecureBoot_DIR"
+ Help = "Path to SecureBoot Module Module in Project"
+End
+
+MODULE
+ File = "SecureBootMod.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\SecureBootMod.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\SecureBootMod.sdb"
+ Parent = "SETUP_SDBS"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(SecureBoot_DIR)\SecureBootMod.sd"
+ Parent = "SETUP_DEFINITIONS"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "UpdateSecureVariableBrowserInfo,"
+ Parent = "LoadedPreviousValuesHook,"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "UpdateSecureVariableBrowserInfo,"
+ Parent = "LoadedConfigDefaults,"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,SECURE_BOOT_MENU_REFRESH,ForceSetupModeCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,SECURE_BOOT_SUPPORT_CHANGE_KEY,ForceSetupModeCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,SECURE_BOOT_MODE_CHANGE_KEY,ForceSetupModeCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,KEY_MANAGEMENT_MENU_REFRESH,ForceSetupModeCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,FORCE_DEFAULT_KEY,ForceSetupModeCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,FORCE_SETUP_KEY,ForceSetupModeCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,KEY_PROVISION_CHANGE_KEY,ForceSetupModeCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,SET_KEK_KEY,SetAppendSecureBootDBCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,DELETE_KEK_KEY,DeleteSecureBootDBCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,APPEND_KEK_KEY,SetAppendSecureBootDBCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,SET_DB_KEY,SetAppendSecureBootDBCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,DELETE_DB_KEY,DeleteSecureBootDBCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,APPEND_DB_KEY,SetAppendSecureBootDBCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,SET_DBT_KEY,SetAppendSecureBootDBCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,DELETE_DBT_KEY,DeleteSecureBootDBCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,APPEND_DBT_KEY,SetAppendSecureBootDBCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,SET_DBX_KEY,SetAppendSecureBootDBCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,DELETE_DBX_KEY,DeleteSecureBootDBCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,APPEND_DBX_KEY,SetAppendSecureBootDBCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,SET_PK_KEY,SetAppendSecureBootDBCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,GET_PK_KEY,GetSecureBootDBCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ITEM_CALLBACK(SECURITY_FORM_SET_CLASS,0,DELETE_PK_KEY,DeleteSecureBootDBCallback),"
+ Parent = "SetupItemCallbacks"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "PreserveSecureVariables,"
+ Parent = "SMIFlashPreUpdateList"
+ Token = "SMIFlash_SUPPORT" "=" "1"
+ Token = "PRESERVE_SECURE_VARIABLES" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "RestoreSecureVariables,"
+ Parent = "SMIFlashEndUpdateList"
+ Token = "SMIFlash_SUPPORT" "=" "1"
+ Token = "PRESERVE_SECURE_VARIABLES" "=" "1"
+ InvokeOrder = AfterParent
+End
+
diff --git a/Core/EM/SecurityPkg/SecureBootMod.uni b/Core/EM/SecurityPkg/SecureBootMod.uni
new file mode 100644
index 0000000..f712aa3
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecureBootMod.uni
Binary files differ
diff --git a/Core/EM/SecurityPkg/SecureMod.chm b/Core/EM/SecurityPkg/SecureMod.chm
new file mode 100644
index 0000000..85b98e0
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecureMod.chm
Binary files differ
diff --git a/Core/EM/SecurityPkg/SecureMod.cif b/Core/EM/SecurityPkg/SecureMod.cif
new file mode 100644
index 0000000..64a79a1
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecureMod.cif
@@ -0,0 +1,17 @@
+<component>
+ name = "Secure Flash Pkg"
+ category = eModule
+ LocalRoot = "Core\EM\SecurityPkg\"
+ RefName = "SecureFlashMod"
+[files]
+"SecureMod.chm"
+"SecureMod.sdl"
+"SecureMod.mak"
+[parts]
+"SecFlashUpd"
+"SecSMIFlash"
+"FWKey"
+"CryptoUtils"
+[dependOn]
+"CryptoPkg"
+<endComponent>
diff --git a/Core/EM/SecurityPkg/SecureMod.mak b/Core/EM/SecurityPkg/SecureMod.mak
new file mode 100644
index 0000000..be3e8c5
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecureMod.mak
@@ -0,0 +1,458 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (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/SecureMod.mak 35 9/10/14 5:13p Alexp $
+#
+# $Revision: 35 $
+#
+# $Date: 9/10/14 5:13p $
+#*************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/SecureFlashPkg/SecureMod.mak $
+#
+# 35 9/10/14 5:13p Alexp
+# restore generation of make_sign_capsule.bat file
+#
+# 34 5/28/14 12:34p Alexp
+# update format of make_sign_capsule_readme.txt
+#
+# 32 3/21/14 12:30p Alexp
+# 1. Eliminate generation of a .bat file. Instead provide capsule build
+# instructions inside make_sign_capsule_readme file
+# 2. Split the cryptocon command line to 2 sets:
+# 1. for preparing BIOS ROM image with mapping of capsule
+# signing instructions and an extended ROM map layout
+# 2. Actual capsule signing command line.
+#
+#
+# 30 11/11/13 9:43a Alexp
+# file is inlcuded only when create_capsule switch is non-0
+# updated displayed warning messages and content of generated readme
+# file.
+#
+# 29 10/17/13 4:50p Alexp
+# moved FwKey build rules and Guuid defines to a separare FwKey module
+#
+# 28 10/14/13 4:11p Alexp
+# [TAG] EIP139208
+# [Description] Build FwCapsule with Pkcs7 sig fails.
+# 1. Fix Cryptocon.exe to provide proper input line for generation of
+# detached signatures
+# Cryptocon.exe ver 4.10.10
+# 2. Fix mak scripts to invoke msft signtool along with cryptocon if .pfx
+# password is to be provided
+#
+# 27 8/21/13 3:24p Alexp
+#
+# 22 7/12/13 12:41p Alexp
+# Redesigned make file to accommodate more SDL defined build options and
+# generate user friendly messages to deal with different build warnings
+#
+# 21 4/19/13 4:52p Alexp
+# -removed rules to generate igned image. will use external signing
+# ToolKit (e.g. VEB project)
+# -add build rules to generate emptu placeholder for FwKey and FwSig
+# header.
+# -Insert RomLayoutEX into FwSig hdr after AMI.ROM is generated
+#
+# 20 4/10/13 7:04p Alexp
+# Removed all FwCapsule signing build instructions
+#
+# 19 11/13/12 3:11p Alexp
+# add x509 Key format to list of supported FwKey file formats
+#
+# 18 11/12/12 6:09p Alexp
+# Add CREATE_FWCAPSULE token to be able to control Fw Capsule make rules
+# Add FWCAPSULE_CERT_FORMAT to choose format for the digital certificate:
+# PKCS1_v1.5 or PKCS7
+#
+# 17 8/22/12 5:03p Alexp
+# Added FWSIG_KEY_ROOT flag to select which Key is used to sign
+# FwCapsule's FwSig signature.
+#
+# 15 7/26/12 3:03p Alexp
+# Make token:FWSIG_PADDING relevant only if FWSIG_SIGNHDR = 1.
+#
+# 14 6/06/12 9:31a Alexp
+# -New FWSIG_SIGNHDR and FWSIG_PADDING Tokens control input arguments -q
+# and -p in CryptoCon.exe.
+# -New flags control format of signing FwCapHdr and Signature padding
+# scheme
+# -Fix for the issue of backward compatibility when flashing BIOS with
+# SecFlash 008 to new one with label 009 and onwards.
+#
+# 12 5/21/12 4:51p Alexp
+# keep name of signed BIOS image as .CAP. Should match to the default
+# recovery file name.
+#
+# 11 5/18/12 4:13p Alexp
+# 1. Add rebuild dependency on .mak file
+# 2. pass SIGPAD flag to indicate current padding scheme
+# 3. Create rules to translete SDL defined GUID strings to .MAK and .H
+# acceprtable formats
+#
+# 10 4/17/12 4:46p Alexp
+# EIP87889: Signed Aptio Flash Update binary image
+# Supporting new output file format of the BIOS.ROM with
+# embeded FwCapsule Hdr inside the FFS File Section with the special GUID
+#
+# 9 2/29/12 4:06p Alexp
+# Use FWKEY_FORMAT to switch between RSA2048 and SH256 FW Key formats
+#
+# 8 1/05/12 4:19p Alexp
+# Add switch to generate FW Capsule output files based on SDL tokens :
+# FWCAPSULE_FILE_FORMAT and FWCAPSULE_HDR_FILE
+#
+# 6 1/03/12 4:21p Alexp
+# Rearrange build rules, clarify build steps, allow for FW Key to change
+# location from default.
+# Display error if FW Key file is not present
+#
+# 4 12/20/11 5:09p Alexp
+# Use ROM_LAYOUT_EX macro as a name for RomLayout table. New SDL Token is
+# defined by Core.sdl starting from Label:4.6.5.3
+#
+# 3 11/08/11 3:07p Alexp
+# Change names and fix FWCAPSULE_IMAGE_SIZE vallue to depend on
+# FWCAPSULE_IMAGE_ALLIGN
+#
+# 2 11/03/11 6:36p Alexp
+# added FWCAPSULE_ROM_ALLIGN token to control alignment size of generated
+# FW Capsule
+# use new CryptoCon.exe with support for -l key for alignment
+#
+# 1 7/01/11 4:37p Alexp
+#
+#*************************************************************************
+#<AMI_FHDR_START>
+#
+# Name: SecureMod.mak
+#
+# Description: Includes main build module for Secure sub-components
+#
+# Create signed BIOS image (Aptio FW Capsule)
+#
+#<AMI_FHDR_END>
+#*************************************************************************
+all: SecureModule
+!INCLUDE $(BUILD_DIR)\timestamp.mak
+
+SecureModule : $(BUILD_DIR)\SecureMod.mak
+
+#---------------------------------------------------------------------------
+# Generic MAK dependencies
+#---------------------------------------------------------------------------
+$(BUILD_DIR)\SecureMod.mak : $(SecureMod_DIR)\SecureMod.mak $(SecureMod_DIR)\SecureMod.cif $(SecureMod_DIR)\SecureMod.sdl $(BUILD_RULES)
+ $(CIF2MAK) $(SecureMod_DIR)\SecureMod.cif $(CIF2MAK_DEFAULTS)
+
+#---------------------------------------------------------------------------
+# Generic GUID defines. Aptio Tools must support these GUIDs
+#---------------------------------------------------------------------------
+#GUID used to identify FW Capsule Hdr FFS file within the Firmware Volume.
+FWCAPSULE_FFS_GUID = 414D94AD-998D-47D2-BFCD-4E882241DE32
+#Section GUID used to identify FW Capsule Hdr section within FwCap FFS file.
+FWCAPSULE_FFS_SECTION_GUID = 5A88641B-BBB9-4AA6-80F7-498AE407C31F
+
+#---------------------------------------------------------------------------
+# Creating a placeholder FFS for embedded FwCapsule Hdr
+#---------------------------------------------------------------------------
+SecureModule: $(BUILD_DIR)\FwCapsuleHdr.ffs
+
+$(BUILD_DIR)\FwCapsuleHdr.obj: $(BUILD_DIR)\SecureMod.mak
+ $(SILENT)copy << $(BUILD_DIR)\FwCapsuleHdr.c > NUL
+#include <AmiCertificate.h>
+#pragma pack(1)
+APTIO_FW_CAPSULE_HEADER dummyHdr =
+ { { APTIO_FW_CAPSULE_GUID,
+ $(FWCAPSULE_MAX_HDR_SIZE),
+ CAPSULE_FLAGS_PERSIST_ACROSS_RESET |
+ CAPSULE_FLAGS_FWCERTBLOCK_VALID, // 1 - sig is invalid
+ $(FWCAPSULE_MAX_HDR_SIZE)},
+ $(FWCAPSULE_MAX_HDR_SIZE), // Rom Offs
+ sizeof(APTIO_FW_CAPSULE_HEADER) // RomLayout Offs
+ };
+char pad[$(FWCAPSULE_MAX_HDR_SIZE)-sizeof(APTIO_FW_CAPSULE_HEADER)] = {0x55, 0xAA};
+<<KEEP
+ $(CC) /Fo$@ $(CFLAGS) $(BUILD_DIR)\FwCapsuleHdr.c
+
+#The FFS section with Fw Capsule Signature block should be left unsigned and uncompressed.
+#Ignore FFS checksum as the file data will be updated by external utility
+$(BUILD_DIR)\FwCapsuleHdr.ffs : $(BUILD_DIR)\FwCapsuleHdr.obj $(BUILD_DIR)\SecureMod.mak
+ $(MAKE) /$(MAKEFLAGS) EXT_OBJS= $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\SecureMod.mak bin\
+ NAME=FwCapsuleHdr OBJECTS=$(BUILD_DIR)\FwCapsuleHdr.obj\
+ MAKEFILE=$(BUILD_DIR)\SecureMod.mak \
+ TYPE=BINARY
+ $(MAKE) /f Core\FFS.mak \
+ BUILD_DIR=$(BUILD_DIR) \
+ GUID=$(FWCAPSULE_FFS_GUID) \
+ TYPE=EFI_FV_FILETYPE_FREEFORM FFS_CHECKSUM=0\
+ SECTION_GUID=$(FWCAPSULE_FFS_SECTION_GUID) \
+ RESOURCE=$(BUILD_DIR)\FwCapsuleHdr.bin \
+ FFSFILE=$@ COMPRESS=0 NAME=$(@B)
+
+#---------------------------------------------------------------------------
+# Only for PKCS1v2.1 Key files: re-assign FWpub = FWpriv only if
+# following codition is true: FWpub file not defined but full RSA key FWpriv file is defined
+#---------------------------------------------------------------------------
+!IF "$(FWCAPSULE_CERT_FORMAT)"=="0"
+!IF !EXIST($(FWpub))
+!IF EXIST($(FWpriv))
+FWpub = $(FWpriv)
+!ENDIF
+!ENDIF
+!ENDIF
+
+#---------------------------------------------------------------------------
+# Conditions when error log needs to be created
+#---------------------------------------------------------------------------
+!IF !EXIST($(FWpriv))
+FWCAP_BUILD_ERROR_TXT = $(FWCAP_BUILD_ERROR_TXT)&\
+WARNING!!! Missing RSA private key FWpriv="$(FWpriv)" to sign BIOS image.
+!ENDIF
+
+!IF "$(FWCAPSULE_CERT_FORMAT)" == "0" && !EXIST($(FWrootKey))
+FWCAP_BUILD_ERROR_TXT = $(FWCAP_BUILD_ERROR_TXT)&\
+WARNING!!! Missing RSA private key FWrootKey="$(FWrootKey)"
+!ENDIF
+
+!IF !EXIST($(FWpub))
+FWCAP_BUILD_ERROR_TXT = $(FWCAP_BUILD_ERROR_TXT)&\
+WARNING!!! Missing RSA public key FWpub="$(FWpub)" to verify Signed BIOS updates.&\
+$(FWKEY_FILE_SIZE) byte dummy Key is inserted into BIOS RTU (FV_BB).&\
+Flash Updates or Recovery will fail on "$(UNSIGNED_BIOS_ROM)" BIOS&\
+unless the dummy Key is replaced with a valid Platform key during BIOS signing.
+!ENDIF
+
+!IFDEF CONFIG_PEI_PKCS7
+!IF "$(FWCAPSULE_CERT_FORMAT)" == "1" && "$(CONFIG_PEI_PKCS7)" == "0"
+FWCAP_BUILD_ERROR_TXT = $(FWCAP_BUILD_ERROR_TXT)&\
+WARNING!!! Capsule or Recovery Flash updates are disabled for PKCS7 Signed Fw Capsules.&\
+Enable support via SDL Token "CONFIG_PEI_PKCS7" in CryptoAPI.sdl
+!ENDIF
+!ENDIF
+
+!IF "$(FWCAPSULE_FILE_FORMAT)" == "1"
+FWCAP_SIG_HDR_TXT = Attached FW signature (Capsule)
+!ELSE
+FWCAP_SIG_HDR_TXT = Embedded FW signature
+!ENDIF
+!IF "$(FWKEY_FILE_FORMAT)"=="0"
+FWCAP_KEY_STORE_TXT = RSA2048 modulus N
+!ENDIF
+!IF "$(FWKEY_FILE_FORMAT)"=="1"
+FWCAP_KEY_STORE_TXT = SHA-256 digest of a public Key certificate
+!ENDIF
+!IF "$(FWKEY_FILE_FORMAT)"=="2"
+FWCAP_KEY_STORE_TXT = DER-encoded X.509 public key certificate
+!ENDIF
+
+!IF "$(FWCAPSULE_CERT_FORMAT)" == "1"
+FWCAP_SIGN_CERT_TYPE_TXT = PKCS7 Signed data
+FWCAP_SIGN_KEY_TYPE_TXT = RSA, PKCS12 PFX(private) and X.509 DER(public)
+!ELSE
+FWCAP_SIGN_CERT_TYPE_TXT = RSASSA-PKCS1-v1.5 (-PSS)
+FWCAP_SIGN_KEY_TYPE_TXT = RSA-2048, PKCS1-v2.1(DER or PEM)&\
+"$(FWrootKey)" - Root Key Certificate key (full RSA key)
+!ENDIF
+
+#---------------------------------------------------------------------------
+# Prepare Signed Capsule : FWCAPSULE_FILE_NAME
+#---------------------------------------------------------------------------
+SecureModule: CLEAR_FWCAPSULE_FILES MAKE_FWCAPSULE_HELP_FILES
+
+CLEAR_FWCAPSULE_FILES:
+ $(SILENT)if exist $(FWCAPSULE_FILE_NAME) $(SILENT)del $(FWCAPSULE_FILE_NAME)
+ $(SILENT)if exist make_sign_capsule*.* $(SILENT)del make_sign_capsule*.*
+
+#---------------------------------------------------------------------------
+# 1. Create error log and batch files with instructions to sign Fw Capsule
+# using CryptoCon.exe
+#---------------------------------------------------------------------------
+#Create make_sign_capsule.bat - command line to sign BIOS image
+#Create make_sign_capsule_error.log - error log
+#Create make_sign_capsule_readme.txt - simple instructions to create signed FwCapsule
+#---------------------------------------------------------------------------
+MAKE_FWCAPSULE_HELP_FILES:
+#------------------------------------------------------------------------
+#Create make_sign_capsule.bat - command line to sign BIOS image
+#------------------------------------------------------------------------
+ $(SILENT)copy << make_sign_capsule.bat > NUL
+@echo ----update the rom map file $(ROM_LAYOUT_EX)
+@echo ----if the BIOS ROM image was edited
+@echo FWBUILD $(UNSIGNED_BIOS_ROM) /s /m $(ROM_LAYOUT_EX)
+@echo ----sign BIOS image using external rom map
+CRYPTCON -r $(ROM_LAYOUT_EX) $(CRYPTOCON_CMDLINE_SIG)
+<< KEEP
+ $(SILENT)copy << make_sign_capsule_readme.txt > NUL
+#---------------------------------------------------------------------------
+#Create make_sign_capsule_error.log - error log
+#---------------------------------------------------------------------------
+!IFDEF FWCAP_BUILD_ERROR_TXT
+ $(SILENT)copy << make_sign_capsule_error.log > NUL
+$(FWCAP_BUILD_ERROR_TXT:& =^
+ )
+
+<<KEEP
+!ENDIF
+#---------------------------------------------------------------------------
+#Create make_sign_capsule_readme.txt - simple instructions to create signed FwCapsule
+#---------------------------------------------------------------------------
+ $(SILENT)copy << make_sign_capsule_readme.txt > NUL
+===============================================================
+=== Un-signed Aptio FW Image
+===============================================================
+BIOS File name : $(UNSIGNED_BIOS_ROM)
+Project TAG : $(PROJECT_TAG)
+Build Time : $(TODAY), $(NOW)
+BIOS Flash size : $(FLASH_SIZE)
+FW update Key store(FwKey ffs): $(FWCAP_KEY_STORE_TXT)
+Embedded FwCapsule parameters : $(CRYPTOCON_CMDLINE_MAP)
+
+===============================================================
+=== Pre-defined Signed FwCapsule parameters
+===============================================================
+FwCapsule file name : $(FWCAPSULE_FILE_NAME)
+FwCapsule file package : $(FWCAP_SIG_HDR_TXT)
+FwCapsule Signature type : $(FWCAP_SIGN_CERT_TYPE_TXT)
+FwCapsule Sign Key format : $(FWCAP_SIGN_KEY_TYPE_TXT:& =^
+ )
+ "$(FWpriv)" - Signing Certificate key (full RSA key)
+ "$(FWpub)" - Signing Certificate key (public key part)
+
+===============================================================
+=== Cryptocon.exe script to generate signed FwCapsule
+===============================================================
+Cryptocon.exe $(CRYPTOCON_CMDLINE_SIG)
+
+===============================================================
+=== Common Cryptocon FwCapsule build instructions
+===============================================================
+ -c'FWrootPriv' -k'FWsignPriv' Create PKCS#1v1.5 signed FwCapsule (Note1)
+ -c2 -x 'FWpriv'[,'pswd'] Create PKCS#7 signed FwCapsule (Note2, Note3)
+ -f'file' input, un-signed BIOS image
+ -o'file' output, signed FwCapsule image
+ -y update an embedded FwCapsule Header, default-Hdr attached on top of BIOS
+ -l'value' max size of a FwCapsule Header (file alignment)
+ -n -k'key' insert Signer public 'key' into a signed image
+ -r'rom.map' use a rom map from the external file
+ -m embed the FwCapsule sign parameters without creating a signed image
+
+Note1. -c'key1'-k'key2' :take PKCS#1v2.1 DER(PEM) encoded RSA2048 keys
+Note2. -c2 -x'key1'-k'key2':key1-PKCS#12(PFX) with optional PFX password;
+ key2-X.509(DER) with public 'key1'
+Note3. -c2 -x command invokes external Msft signtool.exe
+
+===============================================================
+=== Extended Cryptocon FwCapsule build instructions
+===============================================================
+ -c2 -s Create serialized data block based on the rom map info
+ -c2 -s -x'p7.sig' import PKCS#7 signed data from file into a FwCapsule
+ -r2 use embedded rom map data
+<< KEEP
+
+#---------------------------------------------------------------------------
+# Should be the last step after creating of the ROM image. All fixups to the .ROM must be made prior to this step.
+# check END target in the CORE.MAK and all .MAK files to make sure this step is not overriden
+# Use AFTER_ROM as alternative target.
+#---------------------------------------------------------------------------
+End: $(FWCAPSULE_FILE_NAME)
+
+#------------------------------------------------------------------------
+# 1. Creating Signing descriptor table (RomLayout map) file
+#------------------------------------------------------------------------
+
+#--------------------
+# Older Cores 4.6.3.x didn't generate RomLayout map file
+# 1. Add rules to generate RomLayout.c file. Rules to generate RomLayout.c file are defined in newer versions of Core.mak (4.6.5.x)
+# 2. Create binary file. Build rule is also defined in newer versions of Board.mak (4.6.5.0_Board_27)
+#$(AMI_ROM_TABLE): $(BUILD_DIR)\RomLayout.c $(BUILD_DIR)\RomLayout.obj
+# @CL /Fo$(BUILD_DIR)\ $(CFLAGS) /TC $(BUILD_DIR)\RomLayout.c
+# @LINK /OUT:$(BUILD_DIR)\RomLayout.dll /DLL /SUBSYSTEM:NATIVE /NODEFAULTLIB /NOENTRY $(BUILD_DIR)\RomLayout.obj
+# pe2bin $(BUILD_DIR)\RomLayout.dll $@
+#--------------------
+!IFNDEF ROM_LAYOUT_EX
+ROM_LAYOUT_EX = $(BUILD_DIR)\RomLayoutEx.bin
+!ENDIF
+
+$(ROM_LAYOUT_EX): $(UNSIGNED_BIOS_ROM) $(BUILD_DIR)\RomLayout.bin
+ @if not exist $@ $(FWBUILD) $(UNSIGNED_BIOS_ROM) /s /m $@
+
+#---------------------------------------------------------------------------
+# 3. Embed Signing descriptor table "$(ROM_LAYOUT_EX)" inside "$(UNSIGNED_BIOS_ROM)"
+#--------------------------------------------------------------------------
+MOD_FWCAPSULE_HDR_FFS: $(ROM_LAYOUT_EX) $(UNSIGNED_BIOS_ROM)
+ @echo ----Update "$(UNSIGNED_BIOS_ROM)" with Extended BIOS Rom Map "$(ROM_LAYOUT_EX)" and FwCapsule signing parameters
+ $(CRYPTCON) $(CRYPTOCON_CMDLINE_MAP)
+
+#---------------------------------------------------------------------------
+# 4. Invoke cryptocon.exe to create Signed FwCapsule if CREATE_FWCAPSULE == 1
+#---------------------------------------------------------------------------
+$(FWCAPSULE_FILE_NAME): MOD_FWCAPSULE_HDR_FFS $(UNSIGNED_BIOS_ROM) $(ROM_LAYOUT_EX)
+!IF "$(CREATE_FWCAPSULE)" == "1"
+ @echo ----Create signed BIOS image "$(FWCAPSULE_FILE_NAME)"
+ -$(CRYPTCON) $(CRYPTOCON_CMDLINE_SIG)
+ @if not exist $@ @echo ERROR!!! Failed to create signed BIOS Image.
+!IF "$(FWCAPSULE_FILE_FORMAT)" == "0"
+# Target FWCAPSULE_FILE_NAME file is an original unsigned UNSIGNED_BIOS_ROM with Fw Signature block embedded as Ffs file
+# Replace original UNSIGNED_BIOS_ROM with the signed one if this file will be used as input to Intel fitc or other Flash image packaging tool
+ @if exist $@ @COPY $@ $(UNSIGNED_BIOS_ROM)
+!ENDIF
+!ENDIF #$(CREATE_FWCAPSULE) == 1
+#---------------------------------------------------------------------------
+# Display error log
+#---------------------------------------------------------------------------
+ @if exist make_sign_capsule_error.log @type make_sign_capsule_error.log
+#---------------------------------------------------------------------------
+# Display warning
+#---------------------------------------------------------------------------
+ @if not exist $@ @echo WARNING!!! Do not use un-signed "$(UNSIGNED_BIOS_ROM)" file as a BIOS update image.
+#---------------------------------------------------------------------------
+#
+#####
+#Example of an alternative way to build PKCS#7 signed Fw Capsule using Cryptocon.exe as a packaging tool and signing done by a msft signtool.exe
+#Make sure to use the version of Microsoft SignTool.exe that supports /p7 switch
+#Latest tool version can be downloaded as part of Win8 SDK from http://msdn.microsoft.com/en-us/windows/hardware/hh852363.aspx.
+#
+#1. Optional step if new BIOS verification key $(FWpub) needs to be embedded into $(UNSIGNED_BIOS_ROM)
+#$(CRYPTCON) -c2 -n -k $(FWpub) -f $(UNSIGNED_BIOS_ROM) -o $(UNSIGNED_BIOS_ROM)
+#
+#2. Create serialized data stream "fwcap_serialized" to be signed in step 3.
+#$(CRYPTCON) -c2 -s -f $(UNSIGNED_BIOS_ROM) -o $(BUILD_DIR)\fwcap_serialized
+#
+#3. Create .p7 detached certificate file by signing of "fwcap_serialized":
+# 3.1 sign using a certificate whose private key information is protected by a hardware cryptography module (e.g. HSM).
+# A computer store is specified for the certification authority (CA) store; Certificate is identified by a Subject Name "My High Value Certificate" .
+#Signtool sign /fd sha256 /p7 $(BUILD_DIR) /p7co 1.2.840.113549.1.7.1 /p7ce DetachedSignedData /sm /n "My High Value Certificate" $(BUILD_DIR)\fwcap_serialized
+# 3.2 sign using a certificate stored in a password-protected PFX file "$(FWpriv)"
+#Signtool sign /fd sha256 /p7 $(BUILD_DIR) /p7co 1.2.840.113549.1.7.1 /p7ce DetachedSignedData /f $(FWpriv) /p$(FW_PFX_Password) $(BUILD_DIR)\fwcap_serialized
+#
+#4. Creating Fw Capsule image $(FWCAPSULE_FILE_NAME) with .p7 signature embedded into a FwCap header
+#$(CRYPTCON) -c2 -s -x $(BUILD_DIR)\fwcap_serialized.p7 -f $(UNSIGNED_BIOS_ROM) -o $(FWCAPSULE_FILE_NAME)
+#####
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (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/SecureMod.sdl b/Core/EM/SecurityPkg/SecureMod.sdl
new file mode 100644
index 0000000..c4a3338
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecureMod.sdl
@@ -0,0 +1,315 @@
+TOKEN
+ Name = "SecureMod_SUPPORT"
+ Value = "1"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+ Token = "CryptoAPI_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "SECURE_FLASH_MODULE_REVISION"
+ Value = "17"
+ Help = "Version of Secure Flash module interfaces"
+ TokenType = Integer
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "CREATE_FWCAPSULE"
+ Value = "1"
+ Help = "Mode selector for creating of digitally signed Aptio FW Capsule, to be used for Protected Flash Updates including Recovery.\0 - Enable Secure Flash interfaces, but skip FW Capsule signing;\1 - Create Aptio FW Capsule;\2 - Skip final FW Capsule signing process, e.g to hand off this task to signing server."
+ TokenType = Integer
+ TargetMAK = Yes
+ Range = "0-1-2"
+End
+
+TOKEN
+ Name = "====FWCAPSULE FORMAT TUNE-UP===="
+ Value = "=============================="
+ TokenType = Expression
+End
+
+TOKEN
+ Name = "FWCAPSULE_FILE_FORMAT"
+ Value = "1"
+ Help = "0 - Include Aptio FW Signature Block inside the BIOS ROM as a ROM Hole Ffs.\1 - FW Signature Block is attached on top of BIOS Image."
+ TokenType = Integer
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "FWCAPSULE_CERT_FORMAT"
+ Value = "0"
+ Help = "0 - FwCapsule Hdr includes UEFI RSA2048_SHA256 certificates\1 - PKCS#7 Certificate. Signing keys delivered in PKCS#12 .pfx and X.509.cer"
+ TokenType = Integer
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "UNSIGNED_BIOS_ROM"
+ Value = "$(AMI_ROM)"
+ Help = "File name of the BIOS image to be signed."
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+TOKEN
+ Name = "FWCAPSULE_FILE_NAME"
+ Value = "$(PROJECT_TAG).ROM"
+ Help = "Signed BIOS file name. FwCapsule Hdr with Signature embedded inside the BIOS.ROM.\Note!!!Default Recovery image name is provided by RECOVERY_ROM"
+ TokenType = Expression
+ TargetMAK = Yes
+ TargetH = Yes
+ Token = "FWCAPSULE_FILE_FORMAT" "=" "0"
+End
+
+TOKEN
+ Name = "FWCAPSULE_FILE_NAME"
+ Value = "$(PROJECT_TAG).CAP"
+ Help = "Signed BIOS file name. Aptio FwCapsule Hdr is attached on top of BIOS.ROM.\Note!!!Default Recovery image name is provided by RECOVERY_ROM"
+ TokenType = Expression
+ TargetMAK = Yes
+ TargetH = Yes
+ Token = "FWCAPSULE_FILE_FORMAT" "=" "1"
+End
+
+TOKEN
+ Name = "FWCAPSULE_IMAGE_ALLIGN"
+ Value = "4096"
+ Help = "FW Capsule file size alignment"
+ TokenType = Integer
+ TargetMAK = Yes
+ TargetH = Yes
+ Range = "Min FW Capsule file size allignment is 512"
+End
+
+TOKEN
+ Name = "FWCAPSULE_MAX_HDR_SIZE"
+ Value = "4096"
+ Help = "Maximum Size of the embedded FW Capsule Header"
+ TokenType = Integer
+ TargetMAK = Yes
+ TargetH = Yes
+ Range = "Min FW Capsule Header size is 2048"
+End
+
+TOKEN
+ Name = "FWCAPSULE_IMAGE_SIZE"
+ Value = "$(FLASH_SIZE)+0x4000"
+ Help = "This is the max size of the signed Recovery image with attached 16kb FwCapsule Hdr"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "FWSIG_SIGNHDR"
+ Value = "0"
+ Help = "FwCapsule Hdr Signature Calculation scheme\0-FwSig Cert signs hash of Rom Image and RomMap, FwRoot signs full FwSig Certificate. Fixed in Labels 0-008\1-Add FwCap hdr into a FwSig signature calculation, FwRoot signs FwSig certificate. Supported from Label 009"
+ TokenType = Integer
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "FWSIG_PADDING"
+ Value = "1"
+ Help = "RSA Signature padding scheme.\0-PKCS1v1.5, 1-PSS (default for Secure Flash Module labels 0 to 009), 2-xx reserved"
+ TokenType = Integer
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "FWKEY_FILE_FORMAT"
+ Value = "1"
+ Help = "Data format of Root FW Key FFS inside BIOS RTU (FV_BB).\0-n-modulus of RSA2048 key, 1-SHA256 Hash of RSA2048 n-modulus, 2-x.509 DER Certificate key, 3-xx reserved"
+ TokenType = Integer
+ TargetMAK = Yes
+ Token = "FWCAPSULE_CERT_FORMAT" "=" "0"
+End
+
+TOKEN
+ Name = "FWKEY_FILE_FORMAT"
+ Value = "2"
+ Lock = Yes
+ Help = "Don't change the value."
+ TokenType = Integer
+ TargetMAK = Yes
+ Token = "FWCAPSULE_CERT_FORMAT" "=" "1"
+End
+
+TOKEN
+ Name = "FWKEY_FILE_REPLACE"
+ Value = "1"
+ Help = "Directive to Cryptocon.exe to replace existing Root Platform Key inside BIOS.ROM with the Key used to sign FwCapsule"
+ TokenType = Boolean
+ TargetMAK = Yes
+End
+
+TOKEN
+ Name = "ROM_LAYOUT_EX"
+ Value = "$(BUILD_DIR)\RomLayoutEx.bin"
+ Help = "Name of the extended rom map file used to sign ROM image"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+TOKEN
+ Name = "CRYPTCON"
+ Value = "$(SILENT)CryptoCon.exe"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+TOKEN
+ Name = "CRYPTCON"
+ Value = "$(SILENT)CryptoCon.exe -@"
+ TokenType = Expression
+ TargetMAK = Yes
+ Token = "BRIEF" "=" "1"
+End
+
+TOKEN
+ Name = "CRYPTKEYGEN"
+ Value = "$(SILENT)keygen.exe"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "SecureMod_DIR"
+End
+
+MODULE
+ File = "SecureMod.mak"
+ Token = "CREATE_FWCAPSULE" "!=" "0"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\FwCapsuleHdr.ffs"
+ Parent = "FV_MAIN"
+ Token = "CREATE_FWCAPSULE" "!=" "0"
+ Token = "LZMA_SUPPORT" "=" "0"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\FwCapsuleHdr.ffs"
+ Parent = "FV_MAIN_OUTSIDE_NESTED"
+ Token = "CREATE_FWCAPSULE" "!=" "0"
+ Token = "LZMA_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "CRYPTOCON_CMDLINE"
+ InvokeOrder = ReplaceParent
+ Help = "Cryptocon.exe command line to create signed FwCapsule"
+End
+
+ELINK
+ Name = "CRYPTOCON_CMDLINE_SIG"
+ InvokeOrder = ReplaceParent
+ Help = "Cryptocon.exe command line to create signed FwCapsule"
+End
+
+ELINK
+ Name = "CRYPTOCON_CMDLINE_MAP"
+ InvokeOrder = ReplaceParent
+ Help = "Cryptocon.exe command line to prepare embedded signature block FwCapsule"
+End
+
+ELINK
+ Name = "-c $(FWrootKey) -k $(FWpriv)"
+ Parent = "CRYPTOCON_CMDLINE"
+ Token = "FWCAPSULE_CERT_FORMAT" "=" "0"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "-c2 -x $(FWpriv),$(FW_PFX_Password)"
+ Parent = "CRYPTOCON_CMDLINE"
+ Token = "FWCAPSULE_CERT_FORMAT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "-n"
+ Parent = "CRYPTOCON_CMDLINE"
+ Help = "-n ia a directive to replace Platform Root Key embedded inside BIOS.ROM with the Key used to sign new FwCapsule"
+ Token = "FWKEY_FILE_REPLACE" "=" "1"
+ Token = "FWCAPSULE_CERT_FORMAT" "=" "0"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "-n -k $(FWpub)"
+ Parent = "CRYPTOCON_CMDLINE"
+ Token = "FWKEY_FILE_REPLACE" "=" "1"
+ Token = "FWCAPSULE_CERT_FORMAT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "-m -r $(ROM_LAYOUT_EX)"
+ Parent = "CRYPTOCON_CMDLINE_MAP"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "-y"
+ Parent = "CRYPTOCON_CMDLINE_MAP"
+ Token = "FWCAPSULE_FILE_FORMAT" "=" "0"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "-l $(FWCAPSULE_IMAGE_ALLIGN)"
+ Parent = "CRYPTOCON_CMDLINE_MAP"
+ Token = "FWCAPSULE_FILE_FORMAT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "-q"
+ Parent = "CRYPTOCON_CMDLINE_MAP"
+ Help = "Extended FwCapsule Hdr Signature Calculation scheme"
+ Token = "FWCAPSULE_CERT_FORMAT" "=" "0"
+ Token = "FWSIG_SIGNHDR" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "-p"
+ Parent = "CRYPTOCON_CMDLINE_MAP"
+ Help = "RSA-PSS Signature padding scheme. (Default - PKCS#1v1.5)"
+ Token = "FWCAPSULE_CERT_FORMAT" "=" "0"
+ Token = "FWSIG_PADDING" "=" "1"
+ Token = "FWSIG_SIGNHDR" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "-p"
+ Parent = "CRYPTOCON_CMDLINE_MAP"
+ Token = "FWCAPSULE_CERT_FORMAT" "=" "0"
+ Token = "FWSIG_SIGNHDR" "=" "0"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(CRYPTOCON_CMDLINE) -f $(UNSIGNED_BIOS_ROM) -o $(FWCAPSULE_FILE_NAME)"
+ Parent = "CRYPTOCON_CMDLINE_SIG"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(CRYPTOCON_CMDLINE) -f $(UNSIGNED_BIOS_ROM) -o $(UNSIGNED_BIOS_ROM)"
+ Parent = "CRYPTOCON_CMDLINE_MAP"
+ InvokeOrder = AfterParent
+End