Add security package to repository.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12261 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@@ -0,0 +1,882 @@
|
||||
/** @file
|
||||
Implement authentication services for the authenticated variable
|
||||
service in UEFI2.2.
|
||||
|
||||
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include "Variable.h"
|
||||
#include "AuthService.h"
|
||||
|
||||
///
|
||||
/// Global database array for scratch
|
||||
///
|
||||
UINT32 mPubKeyNumber;
|
||||
UINT32 mPlatformMode;
|
||||
EFI_GUID mSignatureSupport[SIGSUPPORT_NUM] = {EFI_CERT_RSA2048_SHA256_GUID, EFI_CERT_RSA2048_SHA1_GUID};
|
||||
//
|
||||
// Public Exponent of RSA Key.
|
||||
//
|
||||
CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 };
|
||||
|
||||
/**
|
||||
Initializes for authenticated varibale service.
|
||||
|
||||
@retval EFI_SUCCESS The function successfully executed.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate enough memory resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
AutenticatedVariableServiceInitialize (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
VARIABLE_POINTER_TRACK Variable;
|
||||
UINT8 VarValue;
|
||||
UINT32 VarAttr;
|
||||
UINTN DataSize;
|
||||
UINTN CtxSize;
|
||||
VARIABLE_HEADER VariableHeader;
|
||||
BOOLEAN Valid;
|
||||
|
||||
mVariableModuleGlobal->AuthenticatedVariableGuid[Physical] = &gEfiAuthenticatedVariableGuid;
|
||||
mVariableModuleGlobal->CertRsa2048Sha256Guid[Physical] = &gEfiCertRsa2048Sha256Guid;
|
||||
mVariableModuleGlobal->ImageSecurityDatabaseGuid[Physical] = &gEfiImageSecurityDatabaseGuid;
|
||||
|
||||
//
|
||||
// Initialize hash context.
|
||||
//
|
||||
CtxSize = Sha256GetContextSize ();
|
||||
mVariableModuleGlobal->HashContext[Physical] = AllocateRuntimePool (CtxSize);
|
||||
ASSERT (mVariableModuleGlobal->HashContext[Physical] != NULL);
|
||||
//
|
||||
// Check "AuthVarKeyDatabase" variable's existence.
|
||||
// If it doesn't exist, create a new one with initial value of 0 and EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
|
||||
//
|
||||
Status = FindVariable (
|
||||
mVariableModuleGlobal->VariableName[Physical][VAR_AUTH_KEY_DB],
|
||||
&gEfiAuthenticatedVariableGuid,
|
||||
&Variable,
|
||||
&mVariableModuleGlobal->VariableGlobal[Physical],
|
||||
mVariableModuleGlobal->FvbInstance
|
||||
);
|
||||
|
||||
if (Variable.CurrPtr == 0x0) {
|
||||
VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
|
||||
VarValue = 0;
|
||||
mPubKeyNumber = 0;
|
||||
Status = UpdateVariable (
|
||||
mVariableModuleGlobal->VariableName[Physical][VAR_AUTH_KEY_DB],
|
||||
&gEfiAuthenticatedVariableGuid,
|
||||
&VarValue,
|
||||
sizeof(UINT8),
|
||||
VarAttr,
|
||||
0,
|
||||
0,
|
||||
FALSE,
|
||||
mVariableModuleGlobal,
|
||||
&Variable
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Load database in global variable for cache.
|
||||
//
|
||||
Valid = IsValidVariableHeader (
|
||||
Variable.CurrPtr,
|
||||
Variable.Volatile,
|
||||
&mVariableModuleGlobal->VariableGlobal[Physical],
|
||||
mVariableModuleGlobal->FvbInstance,
|
||||
&VariableHeader
|
||||
);
|
||||
ASSERT (Valid);
|
||||
|
||||
DataSize = DataSizeOfVariable (&VariableHeader);
|
||||
ASSERT (DataSize <= MAX_KEYDB_SIZE);
|
||||
GetVariableDataPtr (
|
||||
Variable.CurrPtr,
|
||||
Variable.Volatile,
|
||||
&mVariableModuleGlobal->VariableGlobal[Physical],
|
||||
mVariableModuleGlobal->FvbInstance,
|
||||
(CHAR16 *) mVariableModuleGlobal->PubKeyStore
|
||||
);
|
||||
|
||||
mPubKeyNumber = (UINT32) (DataSize / EFI_CERT_TYPE_RSA2048_SIZE);
|
||||
}
|
||||
//
|
||||
// Check "SetupMode" variable's existence.
|
||||
// If it doesn't exist, check PK database's existence to determine the value.
|
||||
// Then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
|
||||
//
|
||||
Status = FindVariable (
|
||||
mVariableModuleGlobal->VariableName[Physical][VAR_SETUP_MODE],
|
||||
&gEfiGlobalVariableGuid,
|
||||
&Variable,
|
||||
&mVariableModuleGlobal->VariableGlobal[Physical],
|
||||
mVariableModuleGlobal->FvbInstance
|
||||
);
|
||||
|
||||
if (Variable.CurrPtr == 0x0) {
|
||||
Status = FindVariable (
|
||||
mVariableModuleGlobal->VariableName[Physical][VAR_PLATFORM_KEY],
|
||||
&gEfiGlobalVariableGuid,
|
||||
&Variable,
|
||||
&mVariableModuleGlobal->VariableGlobal[Physical],
|
||||
mVariableModuleGlobal->FvbInstance
|
||||
);
|
||||
if (Variable.CurrPtr == 0x0) {
|
||||
mPlatformMode = SETUP_MODE;
|
||||
} else {
|
||||
mPlatformMode = USER_MODE;
|
||||
}
|
||||
|
||||
VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
|
||||
Status = UpdateVariable (
|
||||
mVariableModuleGlobal->VariableName[Physical][VAR_SETUP_MODE],
|
||||
&gEfiGlobalVariableGuid,
|
||||
&mPlatformMode,
|
||||
sizeof(UINT8),
|
||||
VarAttr,
|
||||
0,
|
||||
0,
|
||||
FALSE,
|
||||
mVariableModuleGlobal,
|
||||
&Variable
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
} else {
|
||||
GetVariableDataPtr (
|
||||
Variable.CurrPtr,
|
||||
Variable.Volatile,
|
||||
&mVariableModuleGlobal->VariableGlobal[Physical],
|
||||
mVariableModuleGlobal->FvbInstance,
|
||||
(CHAR16 *) &mPlatformMode
|
||||
);
|
||||
}
|
||||
//
|
||||
// Check "SignatureSupport" variable's existence.
|
||||
// If it doesn't exist, then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
|
||||
//
|
||||
Status = FindVariable (
|
||||
EFI_SIGNATURE_SUPPORT_NAME,
|
||||
&gEfiGlobalVariableGuid,
|
||||
&Variable,
|
||||
&mVariableModuleGlobal->VariableGlobal[Physical],
|
||||
mVariableModuleGlobal->FvbInstance
|
||||
);
|
||||
|
||||
if (Variable.CurrPtr == 0x0) {
|
||||
VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
|
||||
Status = UpdateVariable (
|
||||
EFI_SIGNATURE_SUPPORT_NAME,
|
||||
&gEfiGlobalVariableGuid,
|
||||
mSignatureSupport,
|
||||
SIGSUPPORT_NUM * sizeof(EFI_GUID),
|
||||
VarAttr,
|
||||
0,
|
||||
0,
|
||||
FALSE,
|
||||
mVariableModuleGlobal,
|
||||
&Variable
|
||||
);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Add public key in store and return its index.
|
||||
|
||||
@param[in] VirtualMode The current calling mode for this function.
|
||||
@param[in] Global The context of this Extended SAL Variable Services Class call.
|
||||
@param[in] PubKey The input pointer to Public Key data.
|
||||
|
||||
@return The index of new added item.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
AddPubKeyInStore (
|
||||
IN BOOLEAN VirtualMode,
|
||||
IN ESAL_VARIABLE_GLOBAL *Global,
|
||||
IN UINT8 *PubKey
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN IsFound;
|
||||
UINT32 Index;
|
||||
VARIABLE_POINTER_TRACK Variable;
|
||||
UINT8 *Ptr;
|
||||
|
||||
if (PubKey == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Status = FindVariable (
|
||||
Global->VariableName[VirtualMode][VAR_AUTH_KEY_DB],
|
||||
Global->AuthenticatedVariableGuid[VirtualMode],
|
||||
&Variable,
|
||||
&Global->VariableGlobal[VirtualMode],
|
||||
Global->FvbInstance
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
//
|
||||
// Check whether the public key entry does exist.
|
||||
//
|
||||
IsFound = FALSE;
|
||||
for (Ptr = Global->PubKeyStore, Index = 1; Index <= mPubKeyNumber; Index++) {
|
||||
if (CompareMem (Ptr, PubKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {
|
||||
IsFound = TRUE;
|
||||
break;
|
||||
}
|
||||
Ptr += EFI_CERT_TYPE_RSA2048_SIZE;
|
||||
}
|
||||
|
||||
if (!IsFound) {
|
||||
//
|
||||
// Add public key in database.
|
||||
//
|
||||
if (mPubKeyNumber == MAX_KEY_NUM) {
|
||||
//
|
||||
// Notes: Database is full, need enhancement here, currently just return 0.
|
||||
//
|
||||
return 0;
|
||||
}
|
||||
|
||||
CopyMem (Global->PubKeyStore + mPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);
|
||||
Index = ++mPubKeyNumber;
|
||||
//
|
||||
// Update public key database variable.
|
||||
//
|
||||
Status = UpdateVariable (
|
||||
Global->VariableName[VirtualMode][VAR_AUTH_KEY_DB],
|
||||
Global->AuthenticatedVariableGuid[VirtualMode],
|
||||
Global->PubKeyStore,
|
||||
mPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE,
|
||||
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS,
|
||||
0,
|
||||
0,
|
||||
VirtualMode,
|
||||
Global,
|
||||
&Variable
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
|
||||
return Index;
|
||||
}
|
||||
|
||||
/**
|
||||
Verify data payload with AuthInfo in EFI_CERT_TYPE_RSA2048_SHA256 type.
|
||||
Follow the steps in UEFI2.2.
|
||||
|
||||
@param[in] VirtualMode The current calling mode for this function.
|
||||
@param[in] Global The context of this Extended SAL Variable Services Class call.
|
||||
@param[in] Data The pointer to data with AuthInfo.
|
||||
@param[in] DataSize The size of Data.
|
||||
@param[in] PubKey The public key used for verification.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||
@retval EFI_SECURITY_VIOLATION Authentication failed.
|
||||
@retval EFI_SUCCESS Authentication successful.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
VerifyDataPayload (
|
||||
IN BOOLEAN VirtualMode,
|
||||
IN ESAL_VARIABLE_GLOBAL *Global,
|
||||
IN UINT8 *Data,
|
||||
IN UINTN DataSize,
|
||||
IN UINT8 *PubKey
|
||||
)
|
||||
{
|
||||
BOOLEAN Status;
|
||||
EFI_VARIABLE_AUTHENTICATION *CertData;
|
||||
EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock;
|
||||
UINT8 Digest[SHA256_DIGEST_SIZE];
|
||||
VOID *Rsa;
|
||||
VOID *HashContext;
|
||||
|
||||
Rsa = NULL;
|
||||
CertData = NULL;
|
||||
CertBlock = NULL;
|
||||
|
||||
if (Data == NULL || PubKey == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;
|
||||
CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);
|
||||
|
||||
//
|
||||
// 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) ||
|
||||
!CompareGuid (&CertData->AuthInfo.CertType, Global->CertRsa2048Sha256Guid[VirtualMode])
|
||||
) {
|
||||
//
|
||||
// Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
|
||||
//
|
||||
return EFI_SECURITY_VIOLATION;
|
||||
}
|
||||
|
||||
//
|
||||
// Hash data payload with SHA256.
|
||||
//
|
||||
ZeroMem (Digest, SHA256_DIGEST_SIZE);
|
||||
HashContext = Global->HashContext[VirtualMode];
|
||||
Status = Sha256Init (HashContext);
|
||||
if (!Status) {
|
||||
goto Done;
|
||||
}
|
||||
Status = Sha256Update (HashContext, Data + AUTHINFO_SIZE, (UINTN) (DataSize - AUTHINFO_SIZE));
|
||||
if (!Status) {
|
||||
goto Done;
|
||||
}
|
||||
//
|
||||
// Hash Monotonic Count.
|
||||
//
|
||||
Status = Sha256Update (HashContext, &CertData->MonotonicCount, sizeof (UINT64));
|
||||
if (!Status) {
|
||||
goto Done;
|
||||
}
|
||||
Status = Sha256Final (HashContext, Digest);
|
||||
if (!Status) {
|
||||
goto Done;
|
||||
}
|
||||
//
|
||||
// Generate & Initialize RSA Context.
|
||||
//
|
||||
Rsa = RsaNew ();
|
||||
ASSERT (Rsa != NULL);
|
||||
//
|
||||
// Set RSA Key Components.
|
||||
// NOTE: Only N and E are needed to be set as RSA public key for signature verification.
|
||||
//
|
||||
Status = RsaSetKey (Rsa, RsaKeyN, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);
|
||||
if (!Status) {
|
||||
goto Done;
|
||||
}
|
||||
Status = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));
|
||||
if (!Status) {
|
||||
goto Done;
|
||||
}
|
||||
//
|
||||
// Verify the signature.
|
||||
//
|
||||
Status = RsaPkcs1Verify (
|
||||
Rsa,
|
||||
Digest,
|
||||
SHA256_DIGEST_SIZE,
|
||||
CertBlock->Signature,
|
||||
EFI_CERT_TYPE_RSA2048_SHA256_SIZE
|
||||
);
|
||||
|
||||
Done:
|
||||
if (Rsa != NULL) {
|
||||
RsaFree (Rsa);
|
||||
}
|
||||
if (Status) {
|
||||
return EFI_SUCCESS;
|
||||
} else {
|
||||
return EFI_SECURITY_VIOLATION;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Update platform mode.
|
||||
|
||||
@param[in] VirtualMode The current calling mode for this function.
|
||||
@param[in] Global The context of this Extended SAL Variable Services Class call.
|
||||
@param[in] Mode SETUP_MODE or USER_MODE.
|
||||
|
||||
**/
|
||||
VOID
|
||||
UpdatePlatformMode (
|
||||
IN BOOLEAN VirtualMode,
|
||||
IN ESAL_VARIABLE_GLOBAL *Global,
|
||||
IN UINT32 Mode
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
VARIABLE_POINTER_TRACK Variable;
|
||||
UINT32 VarAttr;
|
||||
|
||||
Status = FindVariable (
|
||||
Global->VariableName[VirtualMode][VAR_SETUP_MODE],
|
||||
Global->GlobalVariableGuid[VirtualMode],
|
||||
&Variable,
|
||||
&Global->VariableGlobal[VirtualMode],
|
||||
Global->FvbInstance
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
mPlatformMode = Mode;
|
||||
VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
|
||||
Status = UpdateVariable (
|
||||
Global->VariableName[VirtualMode][VAR_SETUP_MODE],
|
||||
Global->GlobalVariableGuid[VirtualMode],
|
||||
&mPlatformMode,
|
||||
sizeof(UINT8),
|
||||
VarAttr,
|
||||
0,
|
||||
0,
|
||||
VirtualMode,
|
||||
Global,
|
||||
&Variable
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
|
||||
/**
|
||||
Process variable with platform key for verification.
|
||||
|
||||
@param[in] VariableName The name of Variable to be found.
|
||||
@param[in] VendorGuid The variable vendor GUID.
|
||||
@param[in] Data The data pointer.
|
||||
@param[in] DataSize The size of Data found. If size is less than the
|
||||
data, this value contains the required size.
|
||||
@param[in] VirtualMode The current calling mode for this function.
|
||||
@param[in] Global The context of this Extended SAL Variable Services Class call.
|
||||
@param[in] Variable The variable information which is used to keep track of variable usage.
|
||||
@param[in] Attributes The attribute value of the variable.
|
||||
@param[in] IsPk Indicates whether to process pk.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||
@retval EFI_SECURITY_VIOLATION The variable does NOT pass the validation
|
||||
check carried out by the firmware.
|
||||
@retval EFI_SUCCESS The variable passed validation successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
ProcessVarWithPk (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
IN VOID *Data,
|
||||
IN UINTN DataSize,
|
||||
IN BOOLEAN VirtualMode,
|
||||
IN ESAL_VARIABLE_GLOBAL *Global,
|
||||
IN VARIABLE_POINTER_TRACK *Variable,
|
||||
IN UINT32 Attributes OPTIONAL,
|
||||
IN BOOLEAN IsPk
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
VARIABLE_POINTER_TRACK PkVariable;
|
||||
EFI_SIGNATURE_LIST *OldPkList;
|
||||
EFI_SIGNATURE_DATA *OldPkData;
|
||||
EFI_VARIABLE_AUTHENTICATION *CertData;
|
||||
VARIABLE_HEADER VariableHeader;
|
||||
BOOLEAN Valid;
|
||||
|
||||
OldPkList = NULL;
|
||||
|
||||
if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
|
||||
//
|
||||
// PK and KEK should set EFI_VARIABLE_NON_VOLATILE attribute.
|
||||
//
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (mPlatformMode == USER_MODE) {
|
||||
if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {
|
||||
//
|
||||
// In user mode, PK and KEK should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute.
|
||||
//
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;
|
||||
|
||||
if (Variable->CurrPtr != 0x0) {
|
||||
Valid = IsValidVariableHeader (
|
||||
Variable->CurrPtr,
|
||||
Variable->Volatile,
|
||||
&Global->VariableGlobal[VirtualMode],
|
||||
Global->FvbInstance,
|
||||
&VariableHeader
|
||||
);
|
||||
ASSERT (Valid);
|
||||
|
||||
if (CertData->MonotonicCount <= VariableHeader.MonotonicCount) {
|
||||
//
|
||||
// Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
|
||||
//
|
||||
return EFI_SECURITY_VIOLATION;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Get platform key from variable.
|
||||
//
|
||||
Status = FindVariable (
|
||||
Global->VariableName[VirtualMode][VAR_PLATFORM_KEY],
|
||||
Global->GlobalVariableGuid[VirtualMode],
|
||||
&PkVariable,
|
||||
&Global->VariableGlobal[VirtualMode],
|
||||
Global->FvbInstance
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
ZeroMem (Global->KeyList, MAX_KEYDB_SIZE);
|
||||
GetVariableDataPtr (
|
||||
PkVariable.CurrPtr,
|
||||
PkVariable.Volatile,
|
||||
&Global->VariableGlobal[VirtualMode],
|
||||
Global->FvbInstance,
|
||||
(CHAR16 *) Global->KeyList
|
||||
);
|
||||
|
||||
OldPkList = (EFI_SIGNATURE_LIST *) Global->KeyList;
|
||||
OldPkData = (EFI_SIGNATURE_DATA *) ((UINT8 *) OldPkList + sizeof (EFI_SIGNATURE_LIST) + OldPkList->SignatureHeaderSize);
|
||||
Status = VerifyDataPayload (VirtualMode, Global, Data, DataSize, OldPkData->SignatureData);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Status = UpdateVariable (
|
||||
VariableName,
|
||||
VendorGuid,
|
||||
(UINT8*)Data + AUTHINFO_SIZE,
|
||||
DataSize - AUTHINFO_SIZE,
|
||||
Attributes,
|
||||
0,
|
||||
CertData->MonotonicCount,
|
||||
VirtualMode,
|
||||
Global,
|
||||
Variable
|
||||
);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// If delete PK in user mode, need change to setup mode.
|
||||
//
|
||||
if ((DataSize == AUTHINFO_SIZE) && IsPk) {
|
||||
UpdatePlatformMode (VirtualMode, Global, SETUP_MODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, 0, 0, VirtualMode, Global, Variable);
|
||||
//
|
||||
// If enroll PK in setup mode, need change to user mode.
|
||||
//
|
||||
if ((DataSize != 0) && IsPk) {
|
||||
UpdatePlatformMode (VirtualMode, Global, USER_MODE);
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Process variable with key exchange key for verification.
|
||||
|
||||
@param[in] VariableName The name of Variable to be found.
|
||||
@param[in] VendorGuid The variable vendor GUID.
|
||||
@param[in] Data The data pointer.
|
||||
@param[in] DataSize The size of Data found. If size is less than the
|
||||
data, this value contains the required size.
|
||||
@param[in] VirtualMode The current calling mode for this function.
|
||||
@param[in] Global The context of this Extended SAL Variable Services Class call.
|
||||
@param[in] Variable The variable information which is used to keep track of variable usage.
|
||||
@param[in] Attributes The attribute value of the variable.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||
@retval EFI_SECURITY_VIOLATION The variable did NOT pass the validation
|
||||
check carried out by the firmware.
|
||||
@retval EFI_SUCCESS The variable passed validation successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
ProcessVarWithKek (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
IN VOID *Data,
|
||||
IN UINTN DataSize,
|
||||
IN BOOLEAN VirtualMode,
|
||||
IN ESAL_VARIABLE_GLOBAL *Global,
|
||||
IN VARIABLE_POINTER_TRACK *Variable,
|
||||
IN UINT32 Attributes OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
VARIABLE_POINTER_TRACK KekVariable;
|
||||
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;
|
||||
VARIABLE_HEADER VariableHeader;
|
||||
BOOLEAN Valid;
|
||||
|
||||
KekList = NULL;
|
||||
|
||||
if (mPlatformMode == USER_MODE) {
|
||||
if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {
|
||||
//
|
||||
// In user mode, should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute.
|
||||
//
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;
|
||||
CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);
|
||||
if (Variable->CurrPtr != 0x0) {
|
||||
Valid = IsValidVariableHeader (
|
||||
Variable->CurrPtr,
|
||||
Variable->Volatile,
|
||||
&Global->VariableGlobal[VirtualMode],
|
||||
Global->FvbInstance,
|
||||
&VariableHeader
|
||||
);
|
||||
ASSERT (Valid);
|
||||
|
||||
if (CertData->MonotonicCount <= VariableHeader.MonotonicCount) {
|
||||
//
|
||||
// Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
|
||||
//
|
||||
return EFI_SECURITY_VIOLATION;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Get KEK database from variable.
|
||||
//
|
||||
Status = FindVariable (
|
||||
Global->VariableName[VirtualMode][VAR_KEY_EXCHANGE_KEY],
|
||||
Global->GlobalVariableGuid[VirtualMode],
|
||||
&KekVariable,
|
||||
&Global->VariableGlobal[VirtualMode],
|
||||
Global->FvbInstance
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
ZeroMem (Global->KeyList, MAX_KEYDB_SIZE);
|
||||
GetVariableDataPtr (
|
||||
KekVariable.CurrPtr,
|
||||
KekVariable.Volatile,
|
||||
&Global->VariableGlobal[VirtualMode],
|
||||
Global->FvbInstance,
|
||||
(CHAR16 *) Global->KeyList
|
||||
);
|
||||
//
|
||||
// Enumerate all Kek items in this list to verify the variable certificate data.
|
||||
// If anyone is authenticated successfully, it means the variable is correct!
|
||||
//
|
||||
KekList = (EFI_SIGNATURE_LIST *) Global->KeyList;
|
||||
IsFound = FALSE;
|
||||
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 (CompareMem (KekItem->SignatureData, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {
|
||||
IsFound = TRUE;
|
||||
break;
|
||||
}
|
||||
KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekItem + KekList->SignatureSize);
|
||||
}
|
||||
|
||||
if (!IsFound) {
|
||||
return EFI_SECURITY_VIOLATION;
|
||||
}
|
||||
|
||||
Status = VerifyDataPayload (VirtualMode, Global, Data, DataSize, CertBlock->PublicKey);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Status = UpdateVariable (
|
||||
VariableName,
|
||||
VendorGuid,
|
||||
(UINT8*)Data + AUTHINFO_SIZE,
|
||||
DataSize - AUTHINFO_SIZE,
|
||||
Attributes,
|
||||
0,
|
||||
CertData->MonotonicCount,
|
||||
VirtualMode,
|
||||
Global,
|
||||
Variable
|
||||
);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// If in setup mode, no authentication needed.
|
||||
//
|
||||
Status = UpdateVariable (
|
||||
VariableName,
|
||||
VendorGuid,
|
||||
Data,
|
||||
DataSize,
|
||||
Attributes,
|
||||
0,
|
||||
0,
|
||||
VirtualMode,
|
||||
Global,
|
||||
Variable
|
||||
);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set, and return the index of associated public key.
|
||||
|
||||
@param[in] Data The data pointer.
|
||||
@param[in] DataSize The size of Data found. If size is less than the
|
||||
data, this value contains the required size.
|
||||
@param[in] VirtualMode The current calling mode for this function.
|
||||
@param[in] Global The context of this Extended SAL Variable Services Class call.
|
||||
@param[in] Variable The variable information which is used to keep track of variable usage.
|
||||
@param[in] Attributes The attribute value of the variable.
|
||||
@param[out] KeyIndex The output index of corresponding public key in database.
|
||||
@param[out] MonotonicCount The output value of corresponding Monotonic Count.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||
@retval EFI_WRITE_PROTECTED The variable is write-protected and needs authentication with
|
||||
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
|
||||
@retval EFI_SECURITY_VIOLATION The variable is with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
|
||||
set, but the AuthInfo does NOT pass the validation
|
||||
check carried out by the firmware.
|
||||
@retval EFI_SUCCESS The variable is not write-protected, or passed validation successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
VerifyVariable (
|
||||
IN VOID *Data,
|
||||
IN UINTN DataSize,
|
||||
IN BOOLEAN VirtualMode,
|
||||
IN ESAL_VARIABLE_GLOBAL *Global,
|
||||
IN VARIABLE_POINTER_TRACK *Variable,
|
||||
IN UINT32 Attributes OPTIONAL,
|
||||
OUT UINT32 *KeyIndex OPTIONAL,
|
||||
OUT UINT64 *MonotonicCount OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN IsDeletion;
|
||||
BOOLEAN IsFirstTime;
|
||||
UINT8 *PubKey;
|
||||
EFI_VARIABLE_AUTHENTICATION *CertData;
|
||||
EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock;
|
||||
VARIABLE_HEADER VariableHeader;
|
||||
BOOLEAN Valid;
|
||||
|
||||
CertData = NULL;
|
||||
CertBlock = NULL;
|
||||
PubKey = NULL;
|
||||
IsDeletion = FALSE;
|
||||
Valid = FALSE;
|
||||
|
||||
if (KeyIndex != NULL) {
|
||||
*KeyIndex = 0;
|
||||
}
|
||||
//
|
||||
// Determine if first time SetVariable with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS.
|
||||
//
|
||||
ZeroMem (&VariableHeader, sizeof (VARIABLE_HEADER));
|
||||
if (Variable->CurrPtr != 0x0) {
|
||||
Valid = IsValidVariableHeader (
|
||||
Variable->CurrPtr,
|
||||
Variable->Volatile,
|
||||
&Global->VariableGlobal[VirtualMode],
|
||||
Global->FvbInstance,
|
||||
&VariableHeader
|
||||
);
|
||||
ASSERT (Valid);
|
||||
}
|
||||
|
||||
if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
|
||||
if (KeyIndex == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Determine current operation type.
|
||||
//
|
||||
if (DataSize == AUTHINFO_SIZE) {
|
||||
IsDeletion = TRUE;
|
||||
}
|
||||
//
|
||||
// Determine whether this is the first time with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
|
||||
//
|
||||
if (Variable->CurrPtr == 0x0) {
|
||||
IsFirstTime = TRUE;
|
||||
} else if (Valid &&(VariableHeader.Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {
|
||||
IsFirstTime = TRUE;
|
||||
} else {
|
||||
*KeyIndex = VariableHeader.PubKeyIndex;
|
||||
IsFirstTime = FALSE;
|
||||
}
|
||||
} else if (Valid && (VariableHeader.Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
|
||||
//
|
||||
// If the variable is already write-protected, it always needs authentication before update.
|
||||
//
|
||||
return EFI_WRITE_PROTECTED;
|
||||
} else {
|
||||
//
|
||||
// If without EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, set and attributes collision.
|
||||
// That means it is not authenticated variable, just return EFI_SUCCESS.
|
||||
//
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Get PubKey and check Monotonic Count value corresponding to the variable.
|
||||
//
|
||||
CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;
|
||||
CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);
|
||||
PubKey = CertBlock->PublicKey;
|
||||
|
||||
if (MonotonicCount != NULL) {
|
||||
//
|
||||
// Update Monotonic Count value.
|
||||
//
|
||||
*MonotonicCount = CertData->MonotonicCount;
|
||||
}
|
||||
|
||||
if (!IsFirstTime) {
|
||||
//
|
||||
// Check input PubKey.
|
||||
//
|
||||
if (CompareMem (PubKey, Global->PubKeyStore + (*KeyIndex - 1) * EFI_CERT_TYPE_RSA2048_SIZE, EFI_CERT_TYPE_RSA2048_SIZE) != 0) {
|
||||
return EFI_SECURITY_VIOLATION;
|
||||
}
|
||||
//
|
||||
// Compare the current monotonic count and ensure that it is greater than the last SetVariable
|
||||
// operation with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute set.
|
||||
//
|
||||
if (CertData->MonotonicCount <= VariableHeader.MonotonicCount) {
|
||||
//
|
||||
// Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
|
||||
//
|
||||
return EFI_SECURITY_VIOLATION;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Verify the certificate in Data payload.
|
||||
//
|
||||
Status = VerifyDataPayload (VirtualMode, Global, Data, DataSize, PubKey);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// Now, the signature has been verified!
|
||||
//
|
||||
if (IsFirstTime && !IsDeletion) {
|
||||
//
|
||||
// Update public key database variable if need and return the index.
|
||||
//
|
||||
*KeyIndex = AddPubKeyInStore (VirtualMode, Global, PubKey);
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@@ -0,0 +1,151 @@
|
||||
/** @file
|
||||
The internal header file includes the common header files, defines
|
||||
internal structure and functions used by AuthService module.
|
||||
|
||||
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _AUTHSERVICE_H_
|
||||
#define _AUTHSERVICE_H_
|
||||
|
||||
#define EFI_CERT_TYPE_RSA2048_SHA256_SIZE 256
|
||||
#define EFI_CERT_TYPE_RSA2048_SIZE 256
|
||||
|
||||
///
|
||||
/// Size of AuthInfo prior to the data payload
|
||||
///
|
||||
#define AUTHINFO_SIZE (((UINTN)(((EFI_VARIABLE_AUTHENTICATION *) 0)->AuthInfo.CertData)) + sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256))
|
||||
|
||||
///
|
||||
/// Item number of support signature types.
|
||||
///
|
||||
#define SIGSUPPORT_NUM 2
|
||||
|
||||
/**
|
||||
Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set, and return the index of associated public key.
|
||||
|
||||
@param[in] Data The data pointer.
|
||||
@param[in] DataSize The size of Data found. If size is less than the
|
||||
data, this value contains the required size.
|
||||
@param[in] VirtualMode The current calling mode for this function.
|
||||
@param[in] Global The context of this Extended SAL Variable Services Class call.
|
||||
@param[in] Variable The variable information which is used to keep track of variable usage.
|
||||
@param[in] Attributes The attribute value of the variable.
|
||||
@param[out] KeyIndex The output index of corresponding public key in database.
|
||||
@param[out] MonotonicCount The output value of corresponding Monotonic Count.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||
@retval EFI_WRITE_PROTECTED The variable is write-protected and needs authentication with
|
||||
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
|
||||
@retval EFI_SECURITY_VIOLATION The variable is with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
|
||||
set, but the AuthInfo does NOT pass the validation
|
||||
check carried out by the firmware.
|
||||
@retval EFI_SUCCESS The variable is not write-protected, or passed validation successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
VerifyVariable (
|
||||
IN VOID *Data,
|
||||
IN UINTN DataSize,
|
||||
IN BOOLEAN VirtualMode,
|
||||
IN ESAL_VARIABLE_GLOBAL *Global,
|
||||
IN VARIABLE_POINTER_TRACK *Variable,
|
||||
IN UINT32 Attributes OPTIONAL,
|
||||
OUT UINT32 *KeyIndex OPTIONAL,
|
||||
OUT UINT64 *MonotonicCount OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Initializes for authenticated varibale service.
|
||||
|
||||
@retval EFI_SUCCESS The function successfully executed.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate enough memory resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
AutenticatedVariableServiceInitialize (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Initializes for cryptlib service before use, include register algrithm and allocate scratch.
|
||||
|
||||
**/
|
||||
VOID
|
||||
CryptLibraryInitialize (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Process variable with platform key for verification.
|
||||
|
||||
@param[in] VariableName The name of Variable to be found.
|
||||
@param[in] VendorGuid Variable vendor GUID.
|
||||
@param[in] Data The data pointer.
|
||||
@param[in] DataSize The size of Data found. If size is less than the
|
||||
data, this value contains the required size.
|
||||
@param[in] VirtualMode The current calling mode for this function.
|
||||
@param[in] Global The context of this Extended SAL Variable Services Class call.
|
||||
@param[in] Variable The variable information which is used to keep track of variable usage.
|
||||
@param[in] Attributes The attribute value of the variable.
|
||||
@param[in] IsPk Indicates whether to process pk.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||
@retval EFI_SECURITY_VIOLATION The variable does NOT pass the validation
|
||||
check carried out by the firmware.
|
||||
@retval EFI_SUCCESS The variable passed validation successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
ProcessVarWithPk (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
IN VOID *Data,
|
||||
IN UINTN DataSize,
|
||||
IN BOOLEAN VirtualMode,
|
||||
IN ESAL_VARIABLE_GLOBAL *Global,
|
||||
IN VARIABLE_POINTER_TRACK *Variable,
|
||||
IN UINT32 Attributes OPTIONAL,
|
||||
IN BOOLEAN IsPk
|
||||
);
|
||||
|
||||
/**
|
||||
Process variable with key exchange key for verification.
|
||||
|
||||
@param[in] VariableName The name of Variable to be found.
|
||||
@param[in] VendorGuid The variable vendor GUID.
|
||||
@param[in] Data The data pointer.
|
||||
@param[in] DataSize Size of Data found. If size is less than the
|
||||
data, this value contains the required size.
|
||||
@param[in] VirtualMode The current calling mode for this function.
|
||||
@param[in] Global The context of this Extended SAL Variable Services Class call.
|
||||
@param[in] Variable The variable information which is used to keep track of variable usage.
|
||||
@param[in] Attributes The attribute value of the variable.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||
@retval EFI_SECURITY_VIOLATION The variable does NOT pass the validation
|
||||
check carried out by the firmware.
|
||||
@retval EFI_SUCCESS The variable passed validation successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
ProcessVarWithKek (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
IN VOID *Data,
|
||||
IN UINTN DataSize,
|
||||
IN BOOLEAN VirtualMode,
|
||||
IN ESAL_VARIABLE_GLOBAL *Global,
|
||||
IN VARIABLE_POINTER_TRACK *Variable,
|
||||
IN UINT32 Attributes OPTIONAL
|
||||
);
|
||||
|
||||
#endif
|
@@ -0,0 +1,85 @@
|
||||
## @file
|
||||
# Component description file for Extended SAL authentication variable
|
||||
# service module.
|
||||
#
|
||||
# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
# 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.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = EsalVariableDxeSal
|
||||
FILE_GUID = 14610837-4E97-4427-96E0-21D9B2956996
|
||||
MODULE_TYPE = DXE_SAL_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
ENTRY_POINT = VariableServiceInitialize
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IPF
|
||||
#
|
||||
# VIRTUAL_ADDRESS_MAP_CALLBACK = VariableClassAddressChangeEvent
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
InitVariable.c
|
||||
Reclaim.c
|
||||
Variable.c
|
||||
Variable.h
|
||||
AuthService.c
|
||||
AuthService.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
CryptoPkg/CryptoPkg.dec
|
||||
SecurityPkg/SecurityPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
MemoryAllocationLib
|
||||
BaseLib
|
||||
SynchronizationLib
|
||||
UefiLib
|
||||
UefiBootServicesTableLib
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
UefiRuntimeLib
|
||||
DxeServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
PcdLib
|
||||
ExtendedSalLib
|
||||
BaseCryptLib
|
||||
|
||||
[Protocols]
|
||||
gEfiFirmwareVolumeBlockProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
|
||||
gEfiFaultTolerantWriteProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
|
||||
|
||||
[Guids]
|
||||
gEfiGlobalVariableGuid
|
||||
gEfiAuthenticatedVariableGuid
|
||||
gEfiEventVirtualAddressChangeGuid
|
||||
gEfiCertRsa2048Sha256Guid
|
||||
gEfiImageSecurityDatabaseGuid
|
||||
|
||||
[Pcd.common]
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize
|
||||
|
||||
[FeaturePcd.common]
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics
|
||||
|
||||
[Depex]
|
||||
gEfiExtendedSalFvBlockServicesProtocolGuid AND gEfiFaultTolerantWriteProtocolGuid
|
||||
|
@@ -0,0 +1,245 @@
|
||||
/** @file
|
||||
Entrypoint of Extended SAL variable service module.
|
||||
|
||||
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include "Variable.h"
|
||||
#include "AuthService.h"
|
||||
|
||||
//
|
||||
// Don't use module globals after the SetVirtualAddress map is signaled
|
||||
//
|
||||
EFI_EVENT mEfiVirtualNotifyEvent;
|
||||
|
||||
/**
|
||||
Common entry for Extended SAL Variable Services Class.
|
||||
|
||||
This is the common entry of all functions of Extended SAL Variable Services Class.
|
||||
|
||||
@param[in] FunctionId The Function ID of member function in Extended SAL Variable Services Class.
|
||||
@param[in] Arg2 The 2nd parameter for SAL procedure call.
|
||||
@param[in] Arg3 The 3rd parameter for SAL procedure call.
|
||||
@param[in] Arg4 The 4th parameter for SAL procedure call.
|
||||
@param[in] Arg5 The 5th parameter for SAL procedure call.
|
||||
@param[in] Arg6 The 6th parameter for SAL procedure call.
|
||||
@param[in] Arg7 The 7th parameter for SAL procedure call.
|
||||
@param[in] Arg8 The 8th parameter for SAL procedure call.
|
||||
@param[in] VirtualMode The current calling mode for this function.
|
||||
@param[in] Global The context of this Extended SAL Variable Services Class call.
|
||||
|
||||
@return The register of SAL.
|
||||
|
||||
**/
|
||||
SAL_RETURN_REGS
|
||||
EFIAPI
|
||||
EsalVariableCommonEntry (
|
||||
IN UINT64 FunctionId,
|
||||
IN UINT64 Arg2,
|
||||
IN UINT64 Arg3,
|
||||
IN UINT64 Arg4,
|
||||
IN UINT64 Arg5,
|
||||
IN UINT64 Arg6,
|
||||
IN UINT64 Arg7,
|
||||
IN UINT64 Arg8,
|
||||
IN BOOLEAN VirtualMode,
|
||||
IN ESAL_VARIABLE_GLOBAL *Global
|
||||
)
|
||||
{
|
||||
SAL_RETURN_REGS ReturnVal;
|
||||
|
||||
ReturnVal.r9 = 0;
|
||||
ReturnVal.r10 = 0;
|
||||
ReturnVal.r11 = 0;
|
||||
|
||||
switch (FunctionId) {
|
||||
case EsalGetVariableFunctionId:
|
||||
ReturnVal.Status = EsalGetVariable (
|
||||
(CHAR16 *) Arg2,
|
||||
(EFI_GUID *) Arg3,
|
||||
(UINT32 *) Arg4,
|
||||
(UINTN *) Arg5,
|
||||
(VOID *) Arg6,
|
||||
VirtualMode,
|
||||
Global
|
||||
);
|
||||
return ReturnVal;
|
||||
|
||||
case EsalGetNextVariableNameFunctionId:
|
||||
ReturnVal.Status = EsalGetNextVariableName (
|
||||
(UINTN *) Arg2,
|
||||
(CHAR16 *) Arg3,
|
||||
(EFI_GUID *) Arg4,
|
||||
VirtualMode,
|
||||
Global
|
||||
);
|
||||
return ReturnVal;
|
||||
|
||||
case EsalSetVariableFunctionId:
|
||||
ReturnVal.Status = EsalSetVariable (
|
||||
(CHAR16 *) Arg2,
|
||||
(EFI_GUID *) Arg3,
|
||||
(UINT32) Arg4,
|
||||
(UINTN) Arg5,
|
||||
(VOID *) Arg6,
|
||||
VirtualMode,
|
||||
Global
|
||||
);
|
||||
return ReturnVal;
|
||||
|
||||
case EsalQueryVariableInfoFunctionId:
|
||||
ReturnVal.Status = EsalQueryVariableInfo (
|
||||
(UINT32) Arg2,
|
||||
(UINT64 *) Arg3,
|
||||
(UINT64 *) Arg4,
|
||||
(UINT64 *) Arg5,
|
||||
VirtualMode,
|
||||
Global
|
||||
);
|
||||
return ReturnVal;
|
||||
|
||||
default:
|
||||
ReturnVal.Status = EFI_SAL_INVALID_ARGUMENT;
|
||||
return ReturnVal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
|
||||
|
||||
This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
|
||||
It convers pointer to new virtual address.
|
||||
|
||||
@param[in] Event The event whose notification function is being invoked.
|
||||
@param[in] Context The pointer to the notification function's context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
VariableClassAddressChangeEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
|
||||
CopyMem (
|
||||
&mVariableModuleGlobal->VariableGlobal[Virtual],
|
||||
&mVariableModuleGlobal->VariableGlobal[Physical],
|
||||
sizeof (VARIABLE_GLOBAL)
|
||||
);
|
||||
|
||||
EfiConvertPointer (
|
||||
0x0,
|
||||
(VOID **) &mVariableModuleGlobal->VariableGlobal[Virtual].NonVolatileVariableBase
|
||||
);
|
||||
EfiConvertPointer (
|
||||
0x0,
|
||||
(VOID **) &mVariableModuleGlobal->VariableGlobal[Virtual].VolatileVariableBase
|
||||
);
|
||||
|
||||
mVariableModuleGlobal->PlatformLangCodes[Virtual] = mVariableModuleGlobal->PlatformLangCodes[Physical];
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLangCodes[Virtual]);
|
||||
|
||||
mVariableModuleGlobal->LangCodes[Virtual] = mVariableModuleGlobal->LangCodes[Physical];
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->LangCodes[Virtual]);
|
||||
|
||||
mVariableModuleGlobal->PlatformLang[Virtual] = mVariableModuleGlobal->PlatformLang[Physical];
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLang[Virtual]);
|
||||
|
||||
CopyMem (
|
||||
mVariableModuleGlobal->VariableName[Virtual],
|
||||
mVariableModuleGlobal->VariableName[Physical],
|
||||
sizeof (mVariableModuleGlobal->VariableName[Physical])
|
||||
);
|
||||
for (Index = 0; Index < NUM_VAR_NAME; Index++) {
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableName[Virtual][Index]);
|
||||
}
|
||||
|
||||
mVariableModuleGlobal->GlobalVariableGuid[Virtual] = &gEfiGlobalVariableGuid;
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->GlobalVariableGuid[Virtual]);
|
||||
|
||||
mVariableModuleGlobal->AuthenticatedVariableGuid[Virtual] = &gEfiAuthenticatedVariableGuid;
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->AuthenticatedVariableGuid[Virtual]);
|
||||
|
||||
mVariableModuleGlobal->CertRsa2048Sha256Guid[Virtual] = &gEfiCertRsa2048Sha256Guid;
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->CertRsa2048Sha256Guid[Virtual]);
|
||||
|
||||
mVariableModuleGlobal->ImageSecurityDatabaseGuid[Virtual] = &gEfiImageSecurityDatabaseGuid;
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->ImageSecurityDatabaseGuid[Virtual]);
|
||||
|
||||
mVariableModuleGlobal->HashContext[Virtual] = mVariableModuleGlobal->HashContext[Physical];
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->HashContext[Virtual]);
|
||||
}
|
||||
|
||||
/**
|
||||
Entry point of Extended SAL Variable service module.
|
||||
|
||||
This function is the entry point of Extended SAL Variable service module.
|
||||
It registers all functions of Extended SAL Variable class, initializes
|
||||
variable store for non-volatile and volatile variables, and registers
|
||||
notification function for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
|
||||
|
||||
@param[in] ImageHandle The Image handle of this driver.
|
||||
@param[in] SystemTable The pointer of EFI_SYSTEM_TABLE.
|
||||
|
||||
@retval EFI_SUCCESS Extended SAL Variable Services Class successfully registered.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
VariableServiceInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = gBS->CreateEventEx (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_NOTIFY,
|
||||
VariableClassAddressChangeEvent,
|
||||
NULL,
|
||||
&gEfiEventVirtualAddressChangeGuid,
|
||||
&mEfiVirtualNotifyEvent
|
||||
);
|
||||
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
Status = VariableCommonInitialize (ImageHandle, SystemTable);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Authenticated variable initialize
|
||||
//
|
||||
Status = AutenticatedVariableServiceInitialize ();
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Register All the Functions with Extended SAL Variable Services Class
|
||||
//
|
||||
RegisterEsalClass (
|
||||
EFI_EXTENDED_SAL_VARIABLE_SERVICES_PROTOCOL_GUID_LO,
|
||||
EFI_EXTENDED_SAL_VARIABLE_SERVICES_PROTOCOL_GUID_HI,
|
||||
mVariableModuleGlobal,
|
||||
EsalVariableCommonEntry,
|
||||
EsalGetVariableFunctionId,
|
||||
EsalVariableCommonEntry,
|
||||
EsalGetNextVariableNameFunctionId,
|
||||
EsalVariableCommonEntry,
|
||||
EsalSetVariableFunctionId,
|
||||
EsalVariableCommonEntry,
|
||||
EsalQueryVariableInfoFunctionId,
|
||||
NULL
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
262
SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/Reclaim.c
Normal file
262
SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/Reclaim.c
Normal file
@@ -0,0 +1,262 @@
|
||||
/** @file
|
||||
Handles non-volatile variable store garbage collection, using FTW
|
||||
(Fault Tolerant Write) protocol.
|
||||
|
||||
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include "Variable.h"
|
||||
|
||||
/**
|
||||
Gets firmware volume block handle by given address.
|
||||
|
||||
This function gets firmware volume block handle whose
|
||||
address range contains the parameter Address.
|
||||
|
||||
@param[in] Address Address which should be contained
|
||||
by returned FVB handle.
|
||||
@param[out] FvbHandle Pointer to FVB handle for output.
|
||||
|
||||
@retval EFI_SUCCESS FVB handle successfully returned.
|
||||
@retval EFI_NOT_FOUND Failed to find FVB handle by address.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetFvbHandleByAddress (
|
||||
IN EFI_PHYSICAL_ADDRESS Address,
|
||||
OUT EFI_HANDLE *FvbHandle
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE *HandleBuffer;
|
||||
UINTN HandleCount;
|
||||
UINTN Index;
|
||||
EFI_PHYSICAL_ADDRESS FvbBaseAddress;
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
||||
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
|
||||
|
||||
*FvbHandle = NULL;
|
||||
//
|
||||
// Locate all handles with Firmware Volume Block protocol
|
||||
//
|
||||
Status = gBS->LocateHandleBuffer (
|
||||
ByProtocol,
|
||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||
NULL,
|
||||
&HandleCount,
|
||||
&HandleBuffer
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
//
|
||||
// Traverse all the handles, searching for the one containing parameter Address
|
||||
//
|
||||
for (Index = 0; Index < HandleCount; Index += 1) {
|
||||
Status = gBS->HandleProtocol (
|
||||
HandleBuffer[Index],
|
||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||
(VOID **) &Fvb
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
//
|
||||
// Checks if the address range of this handle contains parameter Address
|
||||
//
|
||||
Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
|
||||
if ((Address >= FvbBaseAddress) && (Address <= (FvbBaseAddress + FwVolHeader->FvLength))) {
|
||||
*FvbHandle = HandleBuffer[Index];
|
||||
Status = EFI_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FreePool (HandleBuffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Gets LBA of block and offset by given address.
|
||||
|
||||
This function gets the Logical Block Address (LBA) of firmware
|
||||
volume block containing the given address, and the offset of
|
||||
address on the block.
|
||||
|
||||
@param[in] Address Address which should be contained
|
||||
by returned FVB handle.
|
||||
@param[out] Lba The pointer to LBA for output.
|
||||
@param[out] Offset The pointer to offset for output.
|
||||
|
||||
@retval EFI_SUCCESS LBA and offset successfully returned.
|
||||
@retval EFI_NOT_FOUND Failed to find FVB handle by address.
|
||||
@retval EFI_ABORTED Failed to find valid LBA and offset.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetLbaAndOffsetByAddress (
|
||||
IN EFI_PHYSICAL_ADDRESS Address,
|
||||
OUT EFI_LBA *Lba,
|
||||
OUT UINTN *Offset
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE FvbHandle;
|
||||
EFI_PHYSICAL_ADDRESS FvbBaseAddress;
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
||||
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
|
||||
EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry;
|
||||
UINT32 LbaIndex;
|
||||
|
||||
*Lba = (EFI_LBA) (-1);
|
||||
*Offset = 0;
|
||||
|
||||
//
|
||||
// Gets firmware volume block handle by given address.
|
||||
//
|
||||
Status = GetFvbHandleByAddress (Address, &FvbHandle);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = gBS->HandleProtocol (
|
||||
FvbHandle,
|
||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||
(VOID **) &Fvb
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// Get the Base Address of FV
|
||||
//
|
||||
Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
|
||||
|
||||
//
|
||||
// Get the (LBA, Offset) of Address
|
||||
//
|
||||
if ((Address >= FvbBaseAddress) && (Address <= (FvbBaseAddress + FwVolHeader->FvLength))) {
|
||||
if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
|
||||
//
|
||||
// BUGBUG: Assume one FV has one type of BlockLength
|
||||
//
|
||||
FvbMapEntry = &FwVolHeader->BlockMap[0];
|
||||
for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
|
||||
if (Address < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex)) {
|
||||
//
|
||||
// Found the (Lba, Offset)
|
||||
//
|
||||
*Lba = LbaIndex - 1;
|
||||
*Offset = (UINTN) (Address - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Writes a buffer to variable storage space.
|
||||
|
||||
This function writes a buffer to variable storage space into firmware
|
||||
volume block device. The destination is specified by parameter
|
||||
VariableBase. Fault Tolerant Write protocol is used for writing.
|
||||
|
||||
@param[in] VariableBase The base address of the variable to write.
|
||||
@param[in] Buffer Points to the data buffer.
|
||||
@param[in] BufferSize The number of bytes of the data Buffer.
|
||||
|
||||
@retval EFI_SUCCESS The function completed successfully.
|
||||
@retval EFI_NOT_FOUND Fail to locate Fault Tolerant Write protocol.
|
||||
@retval Other The function could not complete successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FtwVariableSpace (
|
||||
IN EFI_PHYSICAL_ADDRESS VariableBase,
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN BufferSize
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE FvbHandle;
|
||||
EFI_LBA VarLba;
|
||||
UINTN VarOffset;
|
||||
UINT8 *FtwBuffer;
|
||||
UINTN FtwBufferSize;
|
||||
EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
|
||||
|
||||
//
|
||||
// Locate Fault Tolerant Write protocol
|
||||
//
|
||||
Status = gBS->LocateProtocol (
|
||||
&gEfiFaultTolerantWriteProtocolGuid,
|
||||
NULL,
|
||||
(VOID **) &FtwProtocol
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
//
|
||||
// Gets firmware volume block handle by VariableBase.
|
||||
//
|
||||
Status = GetFvbHandleByAddress (VariableBase, &FvbHandle);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// Gets LBA of block and offset by VariableBase.
|
||||
//
|
||||
Status = GetLbaAndOffsetByAddress (VariableBase, &VarLba, &VarOffset);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
//
|
||||
// Prepare for the variable data
|
||||
//
|
||||
FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size;
|
||||
FtwBuffer = AllocatePool (FtwBufferSize);
|
||||
if (FtwBuffer == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
SetMem (FtwBuffer, FtwBufferSize, (UINT8) 0xff);
|
||||
CopyMem (FtwBuffer, Buffer, BufferSize);
|
||||
|
||||
//
|
||||
// FTW write record
|
||||
//
|
||||
Status = FtwProtocol->Write (
|
||||
FtwProtocol,
|
||||
VarLba, // LBA
|
||||
VarOffset, // Offset
|
||||
FtwBufferSize, // NumBytes,
|
||||
NULL,
|
||||
FvbHandle,
|
||||
FtwBuffer
|
||||
);
|
||||
|
||||
FreePool (FtwBuffer);
|
||||
return Status;
|
||||
}
|
3198
SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/Variable.c
Normal file
3198
SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/Variable.c
Normal file
File diff suppressed because it is too large
Load Diff
496
SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/Variable.h
Normal file
496
SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/Variable.h
Normal file
@@ -0,0 +1,496 @@
|
||||
/** @file
|
||||
Internal header file for Extended SAL variable service module.
|
||||
|
||||
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _VARIABLE_H_
|
||||
#define _VARIABLE_H_
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Protocol/VariableWrite.h>
|
||||
#include <Protocol/FaultTolerantWrite.h>
|
||||
#include <Protocol/FirmwareVolumeBlock.h>
|
||||
#include <Protocol/Variable.h>
|
||||
#include <Protocol/ExtendedSalBootService.h>
|
||||
#include <Protocol/ExtendedSalServiceClasses.h>
|
||||
|
||||
#include <Guid/GlobalVariable.h>
|
||||
#include <Guid/AuthenticatedVariableFormat.h>
|
||||
#include <Guid/ImageAuthentication.h>
|
||||
#include <Guid/EventGroup.h>
|
||||
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/DxeServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/SynchronizationLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/ExtendedSalLib.h>
|
||||
#include <Library/BaseCryptLib.h>
|
||||
|
||||
#define MAX_NAME_SIZE 0x100
|
||||
#define NUM_VAR_NAME 9 // Number of pre-defined variable name to be referenced
|
||||
#define VAR_PLATFORM_LANG_CODES 0 // Index of "PlatformLangCodes" variable
|
||||
#define VAR_LANG_CODES 1 // Index of "LangCodes" variable
|
||||
#define VAR_PLATFORM_LANG 2 // Index of "PlatformLang" variable
|
||||
#define VAR_LANG 3 // Index of "Lang" variable
|
||||
#define VAR_HW_ERR_REC 4 // Index of "HwErrRecXXXX" variable
|
||||
#define VAR_AUTH_KEY_DB 5 // Index of "AuthVarKeyDatabase" variable
|
||||
#define VAR_SETUP_MODE 6 // Index of "SetupMode" variable
|
||||
#define VAR_PLATFORM_KEY 7 // Index of "PK" variable
|
||||
#define VAR_KEY_EXCHANGE_KEY 8 // Index of "KEK" variable
|
||||
|
||||
///
|
||||
/// "AuthVarKeyDatabase" variable for the Public Key store.
|
||||
///
|
||||
#define AUTHVAR_KEYDB_NAME L"AuthVarKeyDatabase"
|
||||
#define AUTHVAR_KEYDB_NAME_SIZE 38
|
||||
|
||||
///
|
||||
/// The maximum size of the public key database, restricted by maximum individal EFI
|
||||
/// varible size, and excluding the variable header and name size.
|
||||
///
|
||||
#define MAX_KEYDB_SIZE (FixedPcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER) - AUTHVAR_KEYDB_NAME_SIZE)
|
||||
#define MAX_KEY_NUM (MAX_KEYDB_SIZE / EFI_CERT_TYPE_RSA2048_SIZE)
|
||||
|
||||
///
|
||||
/// The size of a 3 character ISO639 language code.
|
||||
///
|
||||
#define ISO_639_2_ENTRY_SIZE 3
|
||||
|
||||
typedef enum {
|
||||
Physical,
|
||||
Virtual
|
||||
} VARIABLE_POINTER_TYPE;
|
||||
|
||||
typedef struct {
|
||||
EFI_PHYSICAL_ADDRESS CurrPtr;
|
||||
EFI_PHYSICAL_ADDRESS EndPtr;
|
||||
EFI_PHYSICAL_ADDRESS StartPtr;
|
||||
BOOLEAN Volatile;
|
||||
} VARIABLE_POINTER_TRACK;
|
||||
|
||||
typedef struct {
|
||||
EFI_PHYSICAL_ADDRESS VolatileVariableBase;
|
||||
EFI_PHYSICAL_ADDRESS NonVolatileVariableBase;
|
||||
EFI_LOCK VariableServicesLock;
|
||||
} VARIABLE_GLOBAL;
|
||||
|
||||
typedef struct {
|
||||
VARIABLE_GLOBAL VariableGlobal[2];
|
||||
CHAR16 *VariableName[2][NUM_VAR_NAME];
|
||||
EFI_GUID *GlobalVariableGuid[2];
|
||||
UINTN VolatileLastVariableOffset;
|
||||
UINTN NonVolatileLastVariableOffset;
|
||||
UINTN CommonVariableTotalSize;
|
||||
UINTN HwErrVariableTotalSize;
|
||||
CHAR8 *PlatformLangCodes[2];
|
||||
CHAR8 *LangCodes[2];
|
||||
CHAR8 *PlatformLang[2];
|
||||
CHAR8 Lang[ISO_639_2_ENTRY_SIZE + 1];
|
||||
UINT32 FvbInstance;
|
||||
UINT32 ReentrantState;
|
||||
EFI_GUID *AuthenticatedVariableGuid[2];
|
||||
EFI_GUID *CertRsa2048Sha256Guid[2];
|
||||
EFI_GUID *ImageSecurityDatabaseGuid[2];
|
||||
VOID *HashContext[2]; // Hash context pointer
|
||||
UINT8 KeyList[MAX_KEYDB_SIZE]; // Cached Platform Key list
|
||||
UINT8 PubKeyStore[MAX_KEYDB_SIZE]; // Cached Public Key list
|
||||
} ESAL_VARIABLE_GLOBAL;
|
||||
|
||||
typedef struct {
|
||||
EFI_GUID *Guid;
|
||||
CHAR16 *Name;
|
||||
UINT32 Attributes;
|
||||
UINTN DataSize;
|
||||
VOID *Data;
|
||||
} VARIABLE_CACHE_ENTRY;
|
||||
|
||||
|
||||
extern ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal;
|
||||
|
||||
//
|
||||
// Functions
|
||||
//
|
||||
|
||||
/**
|
||||
Initializes variable store area for non-volatile and volatile variable.
|
||||
|
||||
This function allocates and initializes memory space for global context of ESAL
|
||||
variable service and variable store area for non-volatile and volatile variable.
|
||||
|
||||
@param[in] ImageHandle The Image handle of this driver.
|
||||
@param[in] SystemTable The pointer of EFI_SYSTEM_TABLE.
|
||||
|
||||
@retval EFI_SUCCESS Function successfully executed.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate enough memory resource.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
VariableCommonInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
);
|
||||
|
||||
/**
|
||||
Entry point of Extended SAL Variable service module.
|
||||
|
||||
This function is the entry point of Extended SAL Variable service module.
|
||||
It registers all functions of Extended SAL Variable class, initializes
|
||||
variable store for non-volatile and volatile variables, and registers
|
||||
notification function for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
|
||||
|
||||
@param[in] ImageHandle The Image handle of this driver.
|
||||
@param[in] SystemTable The pointer of EFI_SYSTEM_TABLE.
|
||||
|
||||
@retval EFI_SUCCESS Extended SAL Variable Services Class successfully registered.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
VariableServiceInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
);
|
||||
|
||||
/**
|
||||
Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
|
||||
|
||||
This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
|
||||
It convers pointer to new virtual address.
|
||||
|
||||
@param[in] Event The event whose notification function is being invoked.
|
||||
@param[in] Context The pointer to the notification function's context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
VariableClassAddressChangeEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Implements EsalGetVariable function of Extended SAL Variable Services Class.
|
||||
|
||||
This function implements EsalGetVariable function of Extended SAL Variable Services Class.
|
||||
It is equivalent in functionality to the EFI Runtime Service GetVariable().
|
||||
|
||||
@param[in] VariableName A Null-terminated Unicode string that is the name of
|
||||
the vendor's variable.
|
||||
@param[in] VendorGuid A unique identifier for the vendor.
|
||||
@param[out] Attributes If not NULL, a pointer to the memory location to return the
|
||||
attributes bitmask for the variable.
|
||||
@param[in, out] DataSize Size of Data found. If size is less than the
|
||||
data, this value contains the required size.
|
||||
@param[out] Data On input, the size in bytes of the return Data buffer.
|
||||
On output, the size of data returned in Data.
|
||||
@param[in] VirtualMode Current calling mode for this function.
|
||||
@param[in] Global Context of this Extended SAL Variable Services Class call.
|
||||
|
||||
@retval EFI_SUCCESS The function completed successfully.
|
||||
@retval EFI_NOT_FOUND The variable was not found.
|
||||
@retval EFI_BUFFER_TOO_SMALL DataSize is too small for the result. DataSize has
|
||||
been updated with the size needed to complete the request.
|
||||
@retval EFI_INVALID_PARAMETER VariableName is NULL.
|
||||
@retval EFI_INVALID_PARAMETER VendorGuid is NULL.
|
||||
@retval EFI_INVALID_PARAMETER DataSize is NULL.
|
||||
@retval EFI_INVALID_PARAMETER DataSize is not too small and Data is NULL.
|
||||
@retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error.
|
||||
@retval EFI_SECURITY_VIOLATION The variable could not be retrieved due to an authentication failure.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EsalGetVariable (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
OUT UINT32 *Attributes OPTIONAL,
|
||||
IN OUT UINTN *DataSize,
|
||||
OUT VOID *Data,
|
||||
IN BOOLEAN VirtualMode,
|
||||
IN ESAL_VARIABLE_GLOBAL *Global
|
||||
);
|
||||
|
||||
/**
|
||||
Implements EsalGetNextVariableName function of Extended SAL Variable Services Class.
|
||||
|
||||
This function implements EsalGetNextVariableName function of Extended SAL Variable Services Class.
|
||||
It is equivalent in functionality to the EFI Runtime Service GetNextVariableName().
|
||||
|
||||
@param[in, out] VariableNameSize Size of the variable
|
||||
@param[in, out] VariableName On input, supplies the last VariableName that was returned by GetNextVariableName().
|
||||
On output, returns the Null-terminated Unicode string of the current variable.
|
||||
@param[in, out] VendorGuid On input, supplies the last VendorGuid that was returned by GetNextVariableName().
|
||||
On output, returns the VendorGuid of the current variable.
|
||||
@param[in] VirtualMode Current calling mode for this function.
|
||||
@param[in] Global Context of this Extended SAL Variable Services Class call.
|
||||
|
||||
@retval EFI_SUCCESS The function completed successfully.
|
||||
@retval EFI_NOT_FOUND The next variable was not found.
|
||||
@retval EFI_BUFFER_TOO_SMALL VariableNameSize is too small for the result.
|
||||
VariableNameSize has been updated with the size needed to complete the request.
|
||||
@retval EFI_INVALID_PARAMETER VariableNameSize is NULL.
|
||||
@retval EFI_INVALID_PARAMETER VariableName is NULL.
|
||||
@retval EFI_INVALID_PARAMETER VendorGuid is NULL.
|
||||
@retval EFI_DEVICE_ERROR The variable name could not be retrieved due to a hardware error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EsalGetNextVariableName (
|
||||
IN OUT UINTN *VariableNameSize,
|
||||
IN OUT CHAR16 *VariableName,
|
||||
IN OUT EFI_GUID *VendorGuid,
|
||||
IN BOOLEAN VirtualMode,
|
||||
IN ESAL_VARIABLE_GLOBAL *Global
|
||||
);
|
||||
|
||||
/**
|
||||
Implements EsalSetVariable function of Extended SAL Variable Services Class.
|
||||
|
||||
This function implements EsalSetVariable function of Extended SAL Variable Services Class.
|
||||
It is equivalent in functionality to the EFI Runtime Service SetVariable().
|
||||
|
||||
@param[in] VariableName A Null-terminated Unicode string that is the name of the vendor's
|
||||
variable. Each VariableName is unique for each
|
||||
VendorGuid. VariableName must contain 1 or more
|
||||
Unicode characters. If VariableName is an empty Unicode
|
||||
string, then EFI_INVALID_PARAMETER is returned.
|
||||
@param[in] VendorGuid A unique identifier for the vendor.
|
||||
@param[in] Attributes Attributes bitmask to set for the variable.
|
||||
@param[in] DataSize The size in bytes of the Data buffer. A size of zero causes the
|
||||
variable to be deleted.
|
||||
@param[in] Data The contents for the variable.
|
||||
@param[in] VirtualMode Current calling mode for this function.
|
||||
@param[in] Global Context of this Extended SAL Variable Services Class call.
|
||||
|
||||
@retval EFI_SUCCESS The firmware has successfully stored the variable and its data as
|
||||
defined by the Attributes.
|
||||
@retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied, or the
|
||||
DataSize exceeds the maximum allowed.
|
||||
@retval EFI_INVALID_PARAMETER VariableName is an empty Unicode string.
|
||||
@retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
|
||||
@retval EFI_DEVICE_ERROR The variable could not be saved due to a hardware failure.
|
||||
@retval EFI_WRITE_PROTECTED The variable in question is read-only.
|
||||
@retval EFI_WRITE_PROTECTED The variable in question cannot be deleted.
|
||||
@retval EFI_SECURITY_VIOLATION The variable could not be retrieved due to an authentication failure.
|
||||
@retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EsalSetVariable (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
IN UINT32 Attributes,
|
||||
IN UINTN DataSize,
|
||||
IN VOID *Data,
|
||||
IN BOOLEAN VirtualMode,
|
||||
IN ESAL_VARIABLE_GLOBAL *Global
|
||||
);
|
||||
|
||||
/**
|
||||
Implements EsalQueryVariableInfo function of Extended SAL Variable Services Class.
|
||||
|
||||
This function implements EsalQueryVariableInfo function of Extended SAL Variable Services Class.
|
||||
It is equivalent in functionality to the EFI Runtime Service QueryVariableInfo().
|
||||
|
||||
@param[in] Attributes Attributes bitmask to specify the type of variables
|
||||
on which to return information.
|
||||
@param[out] MaximumVariableStorageSize On output the maximum size of the storage space available for
|
||||
the EFI variables associated with the attributes specified.
|
||||
@param[out] RemainingVariableStorageSize Returns the remaining size of the storage space available for EFI
|
||||
variables associated with the attributes specified.
|
||||
@param[out] MaximumVariableSize Returns the maximum size of an individual EFI variable
|
||||
associated with the attributes specified.
|
||||
@param[in] VirtualMode Current calling mode for this function
|
||||
@param[in] Global Context of this Extended SAL Variable Services Class call
|
||||
|
||||
@retval EFI_SUCCESS Valid answer returned.
|
||||
@retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.
|
||||
@retval EFI_UNSUPPORTED The attribute is not supported on this platform, and the
|
||||
MaximumVariableStorageSize, RemainingVariableStorageSize,
|
||||
MaximumVariableSize are undefined.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EsalQueryVariableInfo (
|
||||
IN UINT32 Attributes,
|
||||
OUT UINT64 *MaximumVariableStorageSize,
|
||||
OUT UINT64 *RemainingVariableStorageSize,
|
||||
OUT UINT64 *MaximumVariableSize,
|
||||
IN BOOLEAN VirtualMode,
|
||||
IN ESAL_VARIABLE_GLOBAL *Global
|
||||
);
|
||||
|
||||
/**
|
||||
Writes a buffer to variable storage space.
|
||||
|
||||
This function writes a buffer to variable storage space into firmware
|
||||
volume block device. The destination is specified by parameter
|
||||
VariableBase. Fault Tolerant Write protocol is used for writing.
|
||||
|
||||
@param[in] VariableBase The base address of the variable to write.
|
||||
@param[in] Buffer Points to the data buffer.
|
||||
@param[in] BufferSize The number of bytes of the data Buffer.
|
||||
|
||||
@retval EFI_SUCCESS The function completed successfully.
|
||||
@retval EFI_NOT_FOUND Fail to locate Fault Tolerant Write protocol.
|
||||
@retval Other The function could not complete successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FtwVariableSpace (
|
||||
IN EFI_PHYSICAL_ADDRESS VariableBase,
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN BufferSize
|
||||
);
|
||||
|
||||
/**
|
||||
Finds variable in volatile and non-volatile storage areas.
|
||||
|
||||
This code finds variable in volatile and non-volatile storage areas.
|
||||
If VariableName is an empty string, then we just return the first
|
||||
qualified variable without comparing VariableName and VendorGuid.
|
||||
Otherwise, VariableName and VendorGuid are compared.
|
||||
|
||||
@param[in] VariableName Name of the variable to be found.
|
||||
@param[in] VendorGuid Vendor GUID to be found.
|
||||
@param[out] PtrTrack VARIABLE_POINTER_TRACK structure for output,
|
||||
including the range searched and the target position.
|
||||
@param[in] Global Pointer to VARIABLE_GLOBAL structure, including
|
||||
base of volatile variable storage area, base of
|
||||
NV variable storage area, and a lock.
|
||||
@param[in] Instance Instance of FV Block services.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while
|
||||
VendorGuid is NULL.
|
||||
@retval EFI_SUCCESS Variable successfully found.
|
||||
@retval EFI_INVALID_PARAMETER Variable not found.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FindVariable (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
OUT VARIABLE_POINTER_TRACK *PtrTrack,
|
||||
IN VARIABLE_GLOBAL *Global,
|
||||
IN UINTN Instance
|
||||
);
|
||||
|
||||
/**
|
||||
Gets the pointer to variable data area.
|
||||
|
||||
This function gets the pointer to variable data area.
|
||||
The variable is specified by its variable header.
|
||||
|
||||
@param[in] VariableAddress Start address of variable header.
|
||||
@param[in] Volatile TRUE - Variable is volatile.
|
||||
FALSE - Variable is non-volatile.
|
||||
@param[in] Global Pointer to VARAIBLE_GLOBAL structure.
|
||||
@param[in] Instance Instance of FV Block services.
|
||||
@param[out] VariableData Buffer to hold variable data for output.
|
||||
|
||||
**/
|
||||
VOID
|
||||
GetVariableDataPtr (
|
||||
IN EFI_PHYSICAL_ADDRESS VariableAddress,
|
||||
IN BOOLEAN Volatile,
|
||||
IN VARIABLE_GLOBAL *Global,
|
||||
IN UINTN Instance,
|
||||
OUT CHAR16 *VariableData
|
||||
);
|
||||
|
||||
/**
|
||||
Gets the size of variable data area.
|
||||
|
||||
This function gets the size of variable data area.
|
||||
The variable is specified by its variable header.
|
||||
If variable header contains raw data, just return 0.
|
||||
|
||||
@param[in] Variable Pointer to the variable header.
|
||||
|
||||
@return Size of variable data area in bytes.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
DataSizeOfVariable (
|
||||
IN VARIABLE_HEADER *Variable
|
||||
);
|
||||
|
||||
/**
|
||||
Update the variable region with Variable information. These are the same
|
||||
arguments as the EFI Variable services.
|
||||
|
||||
@param[in] VariableName Name of variable.
|
||||
@param[in] VendorGuid Guid of variable.
|
||||
@param[in] Data Variable data.
|
||||
@param[in] DataSize Size of data. 0 means delete.
|
||||
@param[in] Attributes Attributes of the variable.
|
||||
@param[in] KeyIndex Index of associated public key.
|
||||
@param[in] MonotonicCount Value of associated monotonic count.
|
||||
@param[in] VirtualMode Current calling mode for this function.
|
||||
@param[in] Global Context of this Extended SAL Variable Services Class call.
|
||||
@param[in] Variable The variable information which is used to keep track of variable usage.
|
||||
|
||||
@retval EFI_SUCCESS The update operation is success.
|
||||
@retval EFI_OUT_OF_RESOURCES Variable region is full, can not write other data into this region.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UpdateVariable (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
IN VOID *Data,
|
||||
IN UINTN DataSize,
|
||||
IN UINT32 Attributes OPTIONAL,
|
||||
IN UINT32 KeyIndex OPTIONAL,
|
||||
IN UINT64 MonotonicCount OPTIONAL,
|
||||
IN BOOLEAN VirtualMode,
|
||||
IN ESAL_VARIABLE_GLOBAL *Global,
|
||||
IN VARIABLE_POINTER_TRACK *Variable
|
||||
);
|
||||
|
||||
/**
|
||||
Checks variable header.
|
||||
|
||||
This function checks if variable header is valid or not.
|
||||
|
||||
@param[in] VariableAddress Start address of variable header.
|
||||
@param[in] Volatile TRUE - Variable is volatile.
|
||||
FALSE - Variable is non-volatile.
|
||||
@param[in] Global Pointer to VARAIBLE_GLOBAL structure.
|
||||
@param[in] Instance Instance of FV Block services.
|
||||
@param[out] VariableHeader Pointer to VARIABLE_HEADER for output.
|
||||
|
||||
@retval TRUE Variable header is valid.
|
||||
@retval FALSE Variable header is not valid.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsValidVariableHeader (
|
||||
IN EFI_PHYSICAL_ADDRESS VariableAddress,
|
||||
IN BOOLEAN Volatile,
|
||||
IN VARIABLE_GLOBAL *Global,
|
||||
IN UINTN Instance,
|
||||
OUT VARIABLE_HEADER *VariableHeader OPTIONAL
|
||||
);
|
||||
|
||||
#endif
|
671
SecurityPkg/VariableAuthenticated/Pei/Variable.c
Normal file
671
SecurityPkg/VariableAuthenticated/Pei/Variable.c
Normal file
@@ -0,0 +1,671 @@
|
||||
/** @file
|
||||
Implement ReadOnly Variable Services required by PEIM and install PEI
|
||||
ReadOnly Varaiable2 PPI. These services operates the non-volatile
|
||||
storage space.
|
||||
|
||||
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#include "Variable.h"
|
||||
|
||||
//
|
||||
// Module globals
|
||||
//
|
||||
EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariablePpi = {
|
||||
PeiGetVariable,
|
||||
PeiGetNextVariableName
|
||||
};
|
||||
|
||||
EFI_PEI_PPI_DESCRIPTOR mPpiListVariable = {
|
||||
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
|
||||
&gEfiPeiReadOnlyVariable2PpiGuid,
|
||||
&mVariablePpi
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Provide the functionality of the variable services.
|
||||
|
||||
@param FileHandle Handle of the file being invoked.
|
||||
Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile().
|
||||
@param PeiServices General purpose services available to every PEIM.
|
||||
|
||||
@retval EFI_SUCCESS If the interface could be successfully installed
|
||||
@retval Others Returned from PeiServicesInstallPpi()
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PeimInitializeVariableServices (
|
||||
IN EFI_PEI_FILE_HANDLE FileHandle,
|
||||
IN CONST EFI_PEI_SERVICES **PeiServices
|
||||
)
|
||||
{
|
||||
EFI_BOOT_MODE BootMode;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Check if this is recovery boot path. If no, publish the variable access capability
|
||||
// to other modules. If yes, the content of variable area is not reliable. Therefore,
|
||||
// in this case we should not provide variable service to other pei modules.
|
||||
//
|
||||
Status = (*PeiServices)->GetBootMode (PeiServices, &BootMode);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
if (BootMode == BOOT_IN_RECOVERY_MODE) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return PeiServicesInstallPpi (&mPpiListVariable);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Gets the pointer to the first variable header in given variable store area.
|
||||
|
||||
@param VarStoreHeader Pointer to the Variable Store Header.
|
||||
|
||||
@return Pointer to the first variable header
|
||||
|
||||
**/
|
||||
VARIABLE_HEADER *
|
||||
GetStartPointer (
|
||||
IN VARIABLE_STORE_HEADER *VarStoreHeader
|
||||
)
|
||||
{
|
||||
//
|
||||
// The end of variable store
|
||||
//
|
||||
return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This code gets the pointer to the last variable memory pointer byte.
|
||||
|
||||
@param VarStoreHeader Pointer to the Variable Store Header.
|
||||
|
||||
@return VARIABLE_HEADER* pointer to last unavailable Variable Header.
|
||||
|
||||
**/
|
||||
VARIABLE_HEADER *
|
||||
GetEndPointer (
|
||||
IN VARIABLE_STORE_HEADER *VarStoreHeader
|
||||
)
|
||||
{
|
||||
//
|
||||
// The end of variable store
|
||||
//
|
||||
return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This code checks if variable header is valid or not.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@retval TRUE Variable header is valid.
|
||||
@retval FALSE Variable header is not valid.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsValidVariableHeader (
|
||||
IN VARIABLE_HEADER *Variable
|
||||
)
|
||||
{
|
||||
if (Variable == NULL || Variable->StartId != VARIABLE_DATA ) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This code gets the size of name of variable.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@return Size of variable in bytes in type UINTN.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
NameSizeOfVariable (
|
||||
IN VARIABLE_HEADER *Variable
|
||||
)
|
||||
{
|
||||
if (Variable->State == (UINT8) (-1) ||
|
||||
Variable->DataSize == (UINT32) (-1) ||
|
||||
Variable->NameSize == (UINT32) (-1) ||
|
||||
Variable->Attributes == (UINT32) (-1)) {
|
||||
return 0;
|
||||
}
|
||||
return (UINTN) Variable->NameSize;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This code gets the size of data of variable.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@return Size of variable in bytes in type UINTN.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
DataSizeOfVariable (
|
||||
IN VARIABLE_HEADER *Variable
|
||||
)
|
||||
{
|
||||
if (Variable->State == (UINT8) (-1) ||
|
||||
Variable->DataSize == (UINT32) (-1) ||
|
||||
Variable->NameSize == (UINT32) (-1) ||
|
||||
Variable->Attributes == (UINT32) (-1)) {
|
||||
return 0;
|
||||
}
|
||||
return (UINTN) Variable->DataSize;
|
||||
}
|
||||
|
||||
/**
|
||||
This code gets the pointer to the variable name.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@return A CHAR16* pointer to Variable Name.
|
||||
|
||||
**/
|
||||
CHAR16 *
|
||||
GetVariableNamePtr (
|
||||
IN VARIABLE_HEADER *Variable
|
||||
)
|
||||
{
|
||||
|
||||
return (CHAR16 *) (Variable + 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This code gets the pointer to the variable data.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@return A UINT8* pointer to Variable Data.
|
||||
|
||||
**/
|
||||
UINT8 *
|
||||
GetVariableDataPtr (
|
||||
IN VARIABLE_HEADER *Variable
|
||||
)
|
||||
{
|
||||
UINTN Value;
|
||||
|
||||
//
|
||||
// Be careful about pad size for alignment
|
||||
//
|
||||
Value = (UINTN) GetVariableNamePtr (Variable);
|
||||
Value += NameSizeOfVariable (Variable);
|
||||
Value += GET_PAD_SIZE (NameSizeOfVariable (Variable));
|
||||
|
||||
return (UINT8 *) Value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This code gets the pointer to the next variable header.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@return A VARIABLE_HEADER* pointer to next variable header.
|
||||
|
||||
**/
|
||||
VARIABLE_HEADER *
|
||||
GetNextVariablePtr (
|
||||
IN VARIABLE_HEADER *Variable
|
||||
)
|
||||
{
|
||||
UINTN Value;
|
||||
|
||||
if (!IsValidVariableHeader (Variable)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Value = (UINTN) GetVariableDataPtr (Variable);
|
||||
Value += DataSizeOfVariable (Variable);
|
||||
Value += GET_PAD_SIZE (DataSizeOfVariable (Variable));
|
||||
|
||||
//
|
||||
// Be careful about pad size for alignment
|
||||
//
|
||||
return (VARIABLE_HEADER *) HEADER_ALIGN (Value);
|
||||
}
|
||||
|
||||
/**
|
||||
This code gets the pointer to the variable name.
|
||||
|
||||
@param VarStoreHeader Pointer to the Variable Store Header.
|
||||
|
||||
@retval EfiRaw Variable store is raw
|
||||
@retval EfiValid Variable store is valid
|
||||
@retval EfiInvalid Variable store is invalid
|
||||
|
||||
**/
|
||||
VARIABLE_STORE_STATUS
|
||||
GetVariableStoreStatus (
|
||||
IN VARIABLE_STORE_HEADER *VarStoreHeader
|
||||
)
|
||||
{
|
||||
|
||||
if (CompareGuid (&VarStoreHeader->Signature, &gEfiAuthenticatedVariableGuid) &&
|
||||
VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
|
||||
VarStoreHeader->State == VARIABLE_STORE_HEALTHY
|
||||
) {
|
||||
|
||||
return EfiValid;
|
||||
}
|
||||
|
||||
if (((UINT32 *)(&VarStoreHeader->Signature))[0] == 0xffffffff &&
|
||||
((UINT32 *)(&VarStoreHeader->Signature))[1] == 0xffffffff &&
|
||||
((UINT32 *)(&VarStoreHeader->Signature))[2] == 0xffffffff &&
|
||||
((UINT32 *)(&VarStoreHeader->Signature))[3] == 0xffffffff &&
|
||||
VarStoreHeader->Size == 0xffffffff &&
|
||||
VarStoreHeader->Format == 0xff &&
|
||||
VarStoreHeader->State == 0xff
|
||||
) {
|
||||
|
||||
return EfiRaw;
|
||||
} else {
|
||||
return EfiInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This function compares a variable with variable entries in database.
|
||||
|
||||
@param Variable Pointer to the variable in our database
|
||||
@param VariableName Name of the variable to compare to 'Variable'
|
||||
@param VendorGuid GUID of the variable to compare to 'Variable'
|
||||
@param PtrTrack Variable Track Pointer structure that contains Variable Information.
|
||||
|
||||
@retval EFI_SUCCESS Found match variable
|
||||
@retval EFI_NOT_FOUND Variable not found
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
CompareWithValidVariable (
|
||||
IN VARIABLE_HEADER *Variable,
|
||||
IN CONST CHAR16 *VariableName,
|
||||
IN CONST EFI_GUID *VendorGuid,
|
||||
OUT VARIABLE_POINTER_TRACK *PtrTrack
|
||||
)
|
||||
{
|
||||
VOID *Point;
|
||||
|
||||
if (VariableName[0] == 0) {
|
||||
PtrTrack->CurrPtr = Variable;
|
||||
return EFI_SUCCESS;
|
||||
} else {
|
||||
//
|
||||
// Don't use CompareGuid function here for performance reasons.
|
||||
// Instead we compare the GUID a UINT32 at a time and branch
|
||||
// on the first failed comparison.
|
||||
//
|
||||
if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &Variable->VendorGuid)[0]) &&
|
||||
(((INT32 *) VendorGuid)[1] == ((INT32 *) &Variable->VendorGuid)[1]) &&
|
||||
(((INT32 *) VendorGuid)[2] == ((INT32 *) &Variable->VendorGuid)[2]) &&
|
||||
(((INT32 *) VendorGuid)[3] == ((INT32 *) &Variable->VendorGuid)[3])
|
||||
) {
|
||||
ASSERT (NameSizeOfVariable (Variable) != 0);
|
||||
Point = (VOID *) GetVariableNamePtr (Variable);
|
||||
if (CompareMem (VariableName, Point, NameSizeOfVariable (Variable)) == 0) {
|
||||
PtrTrack->CurrPtr = Variable;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This code finds variable in storage blocks (Non-Volatile).
|
||||
|
||||
@param PeiServices General purpose services available to every PEIM.
|
||||
@param VariableName Name of the variable to be found
|
||||
@param VendorGuid Vendor GUID to be found.
|
||||
@param PtrTrack Variable Track Pointer structure that contains Variable Information.
|
||||
|
||||
@retval EFI_SUCCESS Variable found successfully
|
||||
@retval EFI_NOT_FOUND Variable not found
|
||||
@retval EFI_INVALID_PARAMETER Invalid variable name
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FindVariable (
|
||||
IN CONST EFI_PEI_SERVICES **PeiServices,
|
||||
IN CONST CHAR16 *VariableName,
|
||||
IN CONST EFI_GUID *VendorGuid,
|
||||
OUT VARIABLE_POINTER_TRACK *PtrTrack
|
||||
)
|
||||
{
|
||||
EFI_HOB_GUID_TYPE *GuidHob;
|
||||
VARIABLE_STORE_HEADER *VariableStoreHeader;
|
||||
VARIABLE_HEADER *Variable;
|
||||
VARIABLE_HEADER *LastVariable;
|
||||
VARIABLE_HEADER *MaxIndex;
|
||||
VARIABLE_INDEX_TABLE *IndexTable;
|
||||
UINT32 Count;
|
||||
UINT32 Offset;
|
||||
UINT8 *VariableBase;
|
||||
BOOLEAN StopRecord;
|
||||
|
||||
if (VariableName[0] != 0 && VendorGuid == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
//
|
||||
// No Variable Address equals zero, so 0 as initial value is safe.
|
||||
//
|
||||
MaxIndex = 0;
|
||||
StopRecord = FALSE;
|
||||
|
||||
GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);
|
||||
if (GuidHob == NULL) {
|
||||
//
|
||||
// If it's the first time to access variable region in flash, create a guid hob to record
|
||||
// VAR_ADDED type variable info.
|
||||
// Note that as the resource of PEI phase is limited, only store the number of
|
||||
// VARIABLE_INDEX_TABLE_VOLUME of VAR_ADDED type variables to reduce access time.
|
||||
//
|
||||
IndexTable = BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));
|
||||
IndexTable->Length = 0;
|
||||
IndexTable->StartPtr = NULL;
|
||||
IndexTable->EndPtr = NULL;
|
||||
IndexTable->GoneThrough = 0;
|
||||
} else {
|
||||
IndexTable = GET_GUID_HOB_DATA (GuidHob);
|
||||
for (Offset = 0, Count = 0; Count < IndexTable->Length; Count++) {
|
||||
//
|
||||
// traverse the variable info list to look for varible.
|
||||
// The IndexTable->Index[Count] records the distance of two neighbouring VAR_ADDED type variables.
|
||||
//
|
||||
ASSERT (Count < VARIABLE_INDEX_TABLE_VOLUME);
|
||||
Offset += IndexTable->Index[Count];
|
||||
MaxIndex = (VARIABLE_HEADER *)((CHAR8 *)(IndexTable->StartPtr) + Offset);
|
||||
if (CompareWithValidVariable (MaxIndex, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
|
||||
PtrTrack->StartPtr = IndexTable->StartPtr;
|
||||
PtrTrack->EndPtr = IndexTable->EndPtr;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (IndexTable->GoneThrough != 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
//
|
||||
// If not found in HOB, then let's start from the MaxIndex we've found.
|
||||
//
|
||||
if (MaxIndex != NULL) {
|
||||
Variable = GetNextVariablePtr (MaxIndex);
|
||||
LastVariable = MaxIndex;
|
||||
} else {
|
||||
if ((IndexTable->StartPtr != NULL) || (IndexTable->EndPtr != NULL)) {
|
||||
Variable = IndexTable->StartPtr;
|
||||
} else {
|
||||
VariableBase = (UINT8 *) (UINTN) PcdGet64 (PcdFlashNvStorageVariableBase64);
|
||||
if (VariableBase == NULL) {
|
||||
VariableBase = (UINT8 *) (UINTN) PcdGet32 (PcdFlashNvStorageVariableBase);
|
||||
}
|
||||
|
||||
VariableStoreHeader = (VARIABLE_STORE_HEADER *) (VariableBase + \
|
||||
((EFI_FIRMWARE_VOLUME_HEADER *) (VariableBase)) -> HeaderLength);
|
||||
|
||||
if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (~VariableStoreHeader->Size == 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
//
|
||||
// Find the variable by walk through non-volatile variable store
|
||||
//
|
||||
IndexTable->StartPtr = GetStartPointer (VariableStoreHeader);
|
||||
IndexTable->EndPtr = GetEndPointer (VariableStoreHeader);
|
||||
|
||||
//
|
||||
// Start Pointers for the variable.
|
||||
// Actual Data Pointer where data can be written.
|
||||
//
|
||||
Variable = IndexTable->StartPtr;
|
||||
}
|
||||
|
||||
LastVariable = IndexTable->StartPtr;
|
||||
}
|
||||
//
|
||||
// Find the variable by walk through non-volatile variable store
|
||||
//
|
||||
PtrTrack->StartPtr = IndexTable->StartPtr;
|
||||
PtrTrack->EndPtr = IndexTable->EndPtr;
|
||||
|
||||
while ((Variable < IndexTable->EndPtr) && IsValidVariableHeader (Variable)) {
|
||||
if (Variable->State == VAR_ADDED) {
|
||||
//
|
||||
// Record Variable in VariableIndex HOB
|
||||
//
|
||||
if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME && !StopRecord) {
|
||||
Offset = (UINT32)((UINTN)Variable - (UINTN)LastVariable);
|
||||
//
|
||||
// The distance of two neighbouring VAR_ADDED variable is larger than 2^16,
|
||||
// which is beyond the allowable scope(UINT16) of record. In such case, need not to
|
||||
// record the subsequent VAR_ADDED type variables again.
|
||||
//
|
||||
if ((Offset & 0xFFFF0000UL) != 0) {
|
||||
StopRecord = TRUE;
|
||||
}
|
||||
|
||||
if (!StopRecord) {
|
||||
IndexTable->Index[IndexTable->Length++] = (UINT16) Offset;
|
||||
}
|
||||
LastVariable = Variable;
|
||||
}
|
||||
|
||||
if (CompareWithValidVariable (Variable, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
Variable = GetNextVariablePtr (Variable);
|
||||
}
|
||||
//
|
||||
// If gone through the VariableStore, that means we never find in Firmware any more.
|
||||
//
|
||||
if ((IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME) && (!StopRecord)) {
|
||||
IndexTable->GoneThrough = 1;
|
||||
}
|
||||
|
||||
PtrTrack->CurrPtr = NULL;
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
This service retrieves a variable's value using its name and GUID.
|
||||
|
||||
Read the specified variable from the UEFI variable store. If the Data
|
||||
buffer is too small to hold the contents of the variable, the error
|
||||
EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buffer
|
||||
size to obtain the data.
|
||||
|
||||
@param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
|
||||
@param VariableName A pointer to a null-terminated string that is the variable's name.
|
||||
@param VariableGuid A pointer to an EFI_GUID that is the variable's GUID. The combination of
|
||||
VariableGuid and VariableName must be unique.
|
||||
@param Attributes If non-NULL, on return, points to the variable's attributes.
|
||||
@param DataSize On entry, points to the size in bytes of the Data buffer.
|
||||
On return, points to the size of the data returned in Data.
|
||||
@param Data Points to the buffer which will hold the returned variable value.
|
||||
|
||||
@retval EFI_SUCCESS The variable was read successfully.
|
||||
@retval EFI_NOT_FOUND The variable could not be found.
|
||||
@retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the resulting data.
|
||||
DataSize is updated with the size required for
|
||||
the specified variable.
|
||||
@retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Data is NULL.
|
||||
@retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PeiGetVariable (
|
||||
IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
|
||||
IN CONST CHAR16 *VariableName,
|
||||
IN CONST EFI_GUID *VariableGuid,
|
||||
OUT UINT32 *Attributes,
|
||||
IN OUT UINTN *DataSize,
|
||||
OUT VOID *Data
|
||||
)
|
||||
{
|
||||
VARIABLE_POINTER_TRACK Variable;
|
||||
UINTN VarDataSize;
|
||||
EFI_STATUS Status;
|
||||
CONST EFI_PEI_SERVICES **PeiServices;
|
||||
|
||||
PeiServices = GetPeiServicesTablePointer ();
|
||||
if (VariableName == NULL || VariableGuid == NULL || DataSize == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
//
|
||||
// Find existing variable
|
||||
//
|
||||
Status = FindVariable (PeiServices, VariableName, VariableGuid, &Variable);
|
||||
if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// Get data size
|
||||
//
|
||||
VarDataSize = DataSizeOfVariable (Variable.CurrPtr);
|
||||
if (*DataSize >= VarDataSize) {
|
||||
if (Data == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);
|
||||
|
||||
if (Attributes != NULL) {
|
||||
*Attributes = Variable.CurrPtr->Attributes;
|
||||
}
|
||||
|
||||
*DataSize = VarDataSize;
|
||||
return EFI_SUCCESS;
|
||||
} else {
|
||||
*DataSize = VarDataSize;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Return the next variable name and GUID.
|
||||
|
||||
This function is called multiple times to retrieve the VariableName
|
||||
and VariableGuid of all variables currently available in the system.
|
||||
On each call, the previous results are passed into the interface,
|
||||
and, on return, the interface returns the data for the next
|
||||
interface. When the entire variable list has been returned,
|
||||
EFI_NOT_FOUND is returned.
|
||||
|
||||
@param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
|
||||
|
||||
@param VariableNameSize On entry, points to the size of the buffer pointed to by VariableName.
|
||||
On return, the size of the variable name buffer.
|
||||
@param VariableName On entry, a pointer to a null-terminated string that is the variable's name.
|
||||
On return, points to the next variable's null-terminated name string.
|
||||
@param VariableGuid On entry, a pointer to an EFI_GUID that is the variable's GUID.
|
||||
On return, a pointer to the next variable's GUID.
|
||||
|
||||
@retval EFI_SUCCESS The variable was read successfully.
|
||||
@retval EFI_NOT_FOUND The variable could not be found.
|
||||
@retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the resulting
|
||||
data. VariableNameSize is updated with the size
|
||||
required for the specified variable.
|
||||
@retval EFI_INVALID_PARAMETER VariableName, VariableGuid or
|
||||
VariableNameSize is NULL.
|
||||
@retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PeiGetNextVariableName (
|
||||
IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
|
||||
IN OUT UINTN *VariableNameSize,
|
||||
IN OUT CHAR16 *VariableName,
|
||||
IN OUT EFI_GUID *VariableGuid
|
||||
)
|
||||
{
|
||||
VARIABLE_POINTER_TRACK Variable;
|
||||
UINTN VarNameSize;
|
||||
EFI_STATUS Status;
|
||||
CONST EFI_PEI_SERVICES **PeiServices;
|
||||
|
||||
PeiServices = GetPeiServicesTablePointer ();
|
||||
if (VariableName == NULL || VariableGuid == NULL || VariableNameSize == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = FindVariable (PeiServices, VariableName, VariableGuid, &Variable);
|
||||
if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (VariableName[0] != 0) {
|
||||
//
|
||||
// If variable name is not NULL, get next variable
|
||||
//
|
||||
Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
|
||||
}
|
||||
|
||||
while (!(Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL)) {
|
||||
if (IsValidVariableHeader (Variable.CurrPtr)) {
|
||||
if (Variable.CurrPtr->State == VAR_ADDED) {
|
||||
ASSERT (NameSizeOfVariable (Variable.CurrPtr) != 0);
|
||||
|
||||
VarNameSize = (UINTN) NameSizeOfVariable (Variable.CurrPtr);
|
||||
if (VarNameSize <= *VariableNameSize) {
|
||||
CopyMem (VariableName, GetVariableNamePtr (Variable.CurrPtr), VarNameSize);
|
||||
|
||||
CopyMem (VariableGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
} else {
|
||||
Status = EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
*VariableNameSize = VarNameSize;
|
||||
return Status;
|
||||
//
|
||||
// Variable is found
|
||||
//
|
||||
} else {
|
||||
Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
128
SecurityPkg/VariableAuthenticated/Pei/Variable.h
Normal file
128
SecurityPkg/VariableAuthenticated/Pei/Variable.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/** @file
|
||||
The internal header file includes the common header files, defines
|
||||
internal structure and functions used by PeiVariable module.
|
||||
|
||||
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _PEI_VARIABLE_H_
|
||||
#define _PEI_VARIABLE_H_
|
||||
|
||||
#include <PiPei.h>
|
||||
#include <Ppi/ReadOnlyVariable2.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PeimEntryPoint.h>
|
||||
#include <Library/HobLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/PeiServicesTablePointerLib.h>
|
||||
#include <Library/PeiServicesLib.h>
|
||||
|
||||
#include <Guid/AuthenticatedVariableFormat.h>
|
||||
#include <Guid/VariableIndexTable.h>
|
||||
//
|
||||
// Functions
|
||||
//
|
||||
/**
|
||||
Provide the functionality of the variable services.
|
||||
|
||||
@param FileHandle Handle of the file being invoked.
|
||||
Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile().
|
||||
@param PeiServices General purpose services available to every PEIM.
|
||||
|
||||
@retval EFI_SUCCESS If the interface could be successfully installed
|
||||
@retval Others Returned from PeiServicesInstallPpi()
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PeimInitializeVariableServices (
|
||||
IN EFI_PEI_FILE_HANDLE FileHandle,
|
||||
IN CONST EFI_PEI_SERVICES **PeiServices
|
||||
);
|
||||
|
||||
/**
|
||||
This service retrieves a variable's value using its name and GUID.
|
||||
|
||||
Read the specified variable from the UEFI variable store. If the Data
|
||||
buffer is too small to hold the contents of the variable, the error
|
||||
EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buffer
|
||||
size to obtain the data.
|
||||
|
||||
@param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
|
||||
@param VariableName A pointer to a null-terminated string that is the variable's name.
|
||||
@param VariableGuid A pointer to an EFI_GUID that is the variable's GUID. The combination of
|
||||
VariableGuid and VariableName must be unique.
|
||||
@param Attributes If non-NULL, on return, points to the variable's attributes.
|
||||
@param DataSize On entry, points to the size in bytes of the Data buffer.
|
||||
On return, points to the size of the data returned in Data.
|
||||
@param Data Points to the buffer which will hold the returned variable value.
|
||||
|
||||
@retval EFI_SUCCESS The variable was read successfully.
|
||||
@retval EFI_NOT_FOUND The variable could not be found.
|
||||
@retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the resulting data.
|
||||
DataSize is updated with the size required for
|
||||
the specified variable.
|
||||
@retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Data is NULL.
|
||||
@retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PeiGetVariable (
|
||||
IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
|
||||
IN CONST CHAR16 *VariableName,
|
||||
IN CONST EFI_GUID *VariableGuid,
|
||||
OUT UINT32 *Attributes,
|
||||
IN OUT UINTN *DataSize,
|
||||
OUT VOID *Data
|
||||
);
|
||||
|
||||
/**
|
||||
Return the next variable name and GUID.
|
||||
|
||||
This function is called multiple times to retrieve the VariableName
|
||||
and VariableGuid of all variables currently available in the system.
|
||||
On each call, the previous results are passed into the interface,
|
||||
and, on return, the interface returns the data for the next
|
||||
interface. When the entire variable list has been returned,
|
||||
EFI_NOT_FOUND is returned.
|
||||
|
||||
@param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
|
||||
|
||||
@param VariableNameSize On entry, points to the size of the buffer pointed to by VariableName.
|
||||
@param VariableName On entry, a pointer to a null-terminated string that is the variable's name.
|
||||
On return, points to the next variable's null-terminated name string.
|
||||
|
||||
@param VariableGuid On entry, a pointer to an UEFI _GUID that is the variable's GUID.
|
||||
On return, a pointer to the next variable's GUID.
|
||||
|
||||
@retval EFI_SUCCESS The variable was read successfully.
|
||||
@retval EFI_NOT_FOUND The variable could not be found.
|
||||
@retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the resulting
|
||||
data. VariableNameSize is updated with the size
|
||||
required for the specified variable.
|
||||
@retval EFI_INVALID_PARAMETER VariableName, VariableGuid or
|
||||
VariableNameSize is NULL.
|
||||
@retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PeiGetNextVariableName (
|
||||
IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
|
||||
IN OUT UINTN *VariableNameSize,
|
||||
IN OUT CHAR16 *VariableName,
|
||||
IN OUT EFI_GUID *VariableGuid
|
||||
);
|
||||
|
||||
#endif
|
64
SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf
Normal file
64
SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf
Normal file
@@ -0,0 +1,64 @@
|
||||
## @file
|
||||
# The component description for PEI variable driver.
|
||||
#
|
||||
# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
# 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.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = PeiVariable
|
||||
FILE_GUID = B1F7AF2F-2807-478c-A893-2BF4DDD1F62B
|
||||
MODULE_TYPE = PEIM
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = PeimInitializeVariableServices
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources]
|
||||
Variable.c
|
||||
Variable.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
SecurityPkg/SecurityPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseMemoryLib
|
||||
PcdLib
|
||||
HobLib
|
||||
PeimEntryPoint
|
||||
DebugLib
|
||||
PeiServicesTablePointerLib
|
||||
PeiServicesLib
|
||||
|
||||
[Guids]
|
||||
gEfiAuthenticatedVariableGuid
|
||||
gEfiVariableIndexTableGuid
|
||||
|
||||
[Ppis]
|
||||
gEfiPeiReadOnlyVariable2PpiGuid ## SOMETIMES_PRODUCES (Not for boot mode RECOVERY)
|
||||
|
||||
[Pcd]
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ## CONSUMES
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 ## CONSUMES
|
||||
|
||||
[Depex]
|
||||
TRUE
|
||||
|
||||
#
|
||||
# [BootMode]
|
||||
# RECOVERY ## CONSUMES
|
||||
#
|
||||
|
1205
SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c
Normal file
1205
SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c
Normal file
File diff suppressed because it is too large
Load Diff
209
SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.h
Normal file
209
SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.h
Normal file
@@ -0,0 +1,209 @@
|
||||
/** @file
|
||||
The internal header file includes the common header files, defines
|
||||
internal structure and functions used by AuthService module.
|
||||
|
||||
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _AUTHSERVICE_H_
|
||||
#define _AUTHSERVICE_H_
|
||||
|
||||
#define EFI_CERT_TYPE_RSA2048_SHA256_SIZE 256
|
||||
#define EFI_CERT_TYPE_RSA2048_SIZE 256
|
||||
|
||||
///
|
||||
/// Size of AuthInfo prior to the data payload
|
||||
///
|
||||
#define AUTHINFO_SIZE (((UINTN)(((EFI_VARIABLE_AUTHENTICATION *) 0)->AuthInfo.CertData)) + sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256))
|
||||
|
||||
///
|
||||
/// "AuthVarKeyDatabase" variable for the Public Key store.
|
||||
///
|
||||
#define AUTHVAR_KEYDB_NAME L"AuthVarKeyDatabase"
|
||||
#define AUTHVAR_KEYDB_NAME_SIZE 38
|
||||
|
||||
///
|
||||
/// Max size of public key database, restricted by max individal EFI varible size, exclude variable header and name size.
|
||||
///
|
||||
#define MAX_KEYDB_SIZE (FixedPcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER) - AUTHVAR_KEYDB_NAME_SIZE)
|
||||
#define MAX_KEY_NUM (MAX_KEYDB_SIZE / EFI_CERT_TYPE_RSA2048_SIZE)
|
||||
|
||||
///
|
||||
/// Item number of support signature types.
|
||||
///
|
||||
#define SIGSUPPORT_NUM 2
|
||||
|
||||
|
||||
/**
|
||||
Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set.
|
||||
|
||||
@param[in] VariableName Name of Variable to be found.
|
||||
@param[in] VendorGuid Variable vendor GUID.
|
||||
|
||||
@param[in] Data Data pointer.
|
||||
@param[in] DataSize Size of Data found. If size is less than the
|
||||
data, this value contains the required size.
|
||||
@param[in] Variable The variable information which is used to keep track of variable usage.
|
||||
@param[in] Attributes Attribute value of the variable.
|
||||
|
||||
@return EFI_INVALID_PARAMETER Invalid parameter
|
||||
@return EFI_WRITE_PROTECTED Variable is write-protected and needs authentication with
|
||||
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
|
||||
@return EFI_SECURITY_VIOLATION The variable is with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
|
||||
set, but the AuthInfo does NOT pass the validation
|
||||
check carried out by the firmware.
|
||||
@return EFI_SUCCESS Variable is not write-protected, or passed validation successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
ProcessVariable (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
IN VOID *Data,
|
||||
IN UINTN DataSize,
|
||||
IN VARIABLE_POINTER_TRACK *Variable,
|
||||
IN UINT32 Attributes
|
||||
);
|
||||
|
||||
/**
|
||||
Initializes for authenticated varibale service.
|
||||
|
||||
@retval EFI_SUCCESS Function successfully executed.
|
||||
@retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
AutenticatedVariableServiceInitialize (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Initializes for cryptlib service before use, include register algrithm and allocate scratch.
|
||||
|
||||
**/
|
||||
VOID
|
||||
CryptLibraryInitialize (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Process variable with platform key for verification.
|
||||
|
||||
@param[in] VariableName Name of Variable to be found.
|
||||
@param[in] VendorGuid Variable vendor GUID.
|
||||
@param[in] Data Data pointer.
|
||||
@param[in] DataSize Size of Data found. If size is less than the
|
||||
data, this value contains the required size.
|
||||
@param[in] Variable The variable information which is used to keep track of variable usage.
|
||||
@param[in] Attributes Attribute value of the variable.
|
||||
@param[in] IsPk Indicate whether it is to process pk.
|
||||
|
||||
@return EFI_INVALID_PARAMETER Invalid parameter
|
||||
@return EFI_SECURITY_VIOLATION The variable does NOT pass the validation
|
||||
check carried out by the firmware.
|
||||
@return EFI_SUCCESS Variable passed validation successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
ProcessVarWithPk (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
IN VOID *Data,
|
||||
IN UINTN DataSize,
|
||||
IN VARIABLE_POINTER_TRACK *Variable,
|
||||
IN UINT32 Attributes OPTIONAL,
|
||||
IN BOOLEAN IsPk
|
||||
);
|
||||
|
||||
/**
|
||||
Process variable with key exchange key for verification.
|
||||
|
||||
@param[in] VariableName Name of Variable to be found.
|
||||
@param[in] VendorGuid Variable vendor GUID.
|
||||
@param[in] Data Data pointer.
|
||||
@param[in] DataSize Size of Data found. If size is less than the
|
||||
data, this value contains the required size.
|
||||
@param[in] Variable The variable information that is used to keep track of variable usage.
|
||||
@param[in] Attributes Attribute value of the variable.
|
||||
|
||||
@return EFI_INVALID_PARAMETER Invalid parameter.
|
||||
@return EFI_SECURITY_VIOLATION The variable does NOT pass the validation
|
||||
check carried out by the firmware.
|
||||
@return EFI_SUCCESS Variable passed validation successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
ProcessVarWithKek (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
IN VOID *Data,
|
||||
IN UINTN DataSize,
|
||||
IN VARIABLE_POINTER_TRACK *Variable,
|
||||
IN UINT32 Attributes OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Compare two EFI_TIME data.
|
||||
|
||||
|
||||
@param FirstTime A pointer to the first EFI_TIME data.
|
||||
@param SecondTime A pointer to the second EFI_TIME data.
|
||||
|
||||
@retval TRUE The FirstTime is not later than the SecondTime.
|
||||
@retval FALSE The FirstTime is later than the SecondTime.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
CompareTimeStamp (
|
||||
IN EFI_TIME *FirstTime,
|
||||
IN EFI_TIME *SecondTime
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
|
||||
|
||||
@param[in] VariableName Name of Variable to be found.
|
||||
@param[in] VendorGuid Variable vendor GUID.
|
||||
@param[in] Data Data pointer.
|
||||
@param[in] DataSize Size of Data found. If size is less than the
|
||||
data, this value contains the required size.
|
||||
@param[in] Variable The variable information which is used to keep track of variable usage.
|
||||
@param[in] Attributes Attribute value of the variable.
|
||||
@param[in] Pk Verify against PK or KEK database.
|
||||
@param[out] VarDel Delete the variable or not.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||
@retval EFI_SECURITY_VIOLATION The variable does NOT pass the validation
|
||||
check carried out by the firmware.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to process variable due to lack
|
||||
of resources.
|
||||
@retval EFI_SUCCESS Variable pass validation successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
VerifyTimeBasedPayload (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
IN VOID *Data,
|
||||
IN UINTN DataSize,
|
||||
IN VARIABLE_POINTER_TRACK *Variable,
|
||||
IN UINT32 Attributes,
|
||||
IN BOOLEAN Pk,
|
||||
OUT BOOLEAN *VarDel
|
||||
);
|
||||
|
||||
extern UINT8 mPubKeyStore[MAX_KEYDB_SIZE];
|
||||
extern UINT32 mPubKeyNumber;
|
||||
extern VOID *mHashCtx;
|
||||
extern VOID *mStorageArea;
|
||||
|
||||
#endif
|
172
SecurityPkg/VariableAuthenticated/RuntimeDxe/Reclaim.c
Normal file
172
SecurityPkg/VariableAuthenticated/RuntimeDxe/Reclaim.c
Normal file
@@ -0,0 +1,172 @@
|
||||
/** @file
|
||||
Handles non-volatile variable store garbage collection, using FTW
|
||||
(Fault Tolerant Write) protocol.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include "Variable.h"
|
||||
|
||||
/**
|
||||
Gets LBA of block and offset by given address.
|
||||
|
||||
This function gets the Logical Block Address (LBA) of a firmware
|
||||
volume block containing the given address, and the offset of the
|
||||
address on the block.
|
||||
|
||||
@param Address Address which should be contained
|
||||
by returned FVB handle.
|
||||
@param Lba Pointer to LBA for output.
|
||||
@param Offset Pointer to offset for output.
|
||||
|
||||
@retval EFI_SUCCESS LBA and offset successfully returned.
|
||||
@retval EFI_NOT_FOUND Fail to find FVB handle by address.
|
||||
@retval EFI_ABORTED Fail to find valid LBA and offset.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetLbaAndOffsetByAddress (
|
||||
IN EFI_PHYSICAL_ADDRESS Address,
|
||||
OUT EFI_LBA *Lba,
|
||||
OUT UINTN *Offset
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_PHYSICAL_ADDRESS FvbBaseAddress;
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
||||
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
|
||||
EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry;
|
||||
UINT32 LbaIndex;
|
||||
|
||||
*Lba = (EFI_LBA) (-1);
|
||||
*Offset = 0;
|
||||
|
||||
//
|
||||
// Get the proper FVB protocol.
|
||||
//
|
||||
Status = GetFvbInfoByAddress (Address, NULL, &Fvb);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the Base Address of FV.
|
||||
//
|
||||
Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
|
||||
|
||||
//
|
||||
// Get the (LBA, Offset) of Address.
|
||||
//
|
||||
if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
|
||||
//
|
||||
// BUGBUG: Assume one FV has one type of BlockLength.
|
||||
//
|
||||
FvbMapEntry = &FwVolHeader->BlockMap[0];
|
||||
for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
|
||||
if (Address < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex)) {
|
||||
//
|
||||
// Found the (Lba, Offset).
|
||||
//
|
||||
*Lba = LbaIndex - 1;
|
||||
*Offset = (UINTN) (Address - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Writes a buffer to variable storage space, in the working block.
|
||||
|
||||
This function writes a buffer to variable storage space into a firmware
|
||||
volume block device. The destination is specified by parameter
|
||||
VariableBase. Fault Tolerant Write protocol is used for writing.
|
||||
|
||||
@param VariableBase Base address of variable to write
|
||||
@param Buffer Point to the data buffer.
|
||||
@param BufferSize The number of bytes of the data Buffer.
|
||||
|
||||
@retval EFI_SUCCESS The function completed successfully.
|
||||
@retval EFI_NOT_FOUND Fail to locate Fault Tolerant Write protocol.
|
||||
@retval EFI_ABORTED The function could not complete successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FtwVariableSpace (
|
||||
IN EFI_PHYSICAL_ADDRESS VariableBase,
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN BufferSize
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE FvbHandle;
|
||||
EFI_LBA VarLba;
|
||||
UINTN VarOffset;
|
||||
UINT8 *FtwBuffer;
|
||||
UINTN FtwBufferSize;
|
||||
EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
|
||||
|
||||
//
|
||||
// Locate fault tolerant write protocol.
|
||||
//
|
||||
Status = GetFtwProtocol((VOID **) &FtwProtocol);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
//
|
||||
// Locate Fvb handle by address.
|
||||
//
|
||||
Status = GetFvbInfoByAddress (VariableBase, &FvbHandle, NULL);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// Get LBA and Offset by address.
|
||||
//
|
||||
Status = GetLbaAndOffsetByAddress (VariableBase, &VarLba, &VarOffset);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
//
|
||||
// Prepare for the variable data.
|
||||
//
|
||||
FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size;
|
||||
FtwBuffer = AllocatePool (FtwBufferSize);
|
||||
if (FtwBuffer == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
SetMem (FtwBuffer, FtwBufferSize, (UINT8) 0xff);
|
||||
CopyMem (FtwBuffer, Buffer, BufferSize);
|
||||
|
||||
//
|
||||
// FTW write record.
|
||||
//
|
||||
Status = FtwProtocol->Write (
|
||||
FtwProtocol,
|
||||
VarLba, // LBA
|
||||
VarOffset, // Offset
|
||||
FtwBufferSize, // NumBytes
|
||||
NULL, // PrivateData NULL
|
||||
FvbHandle, // Fvb Handle
|
||||
FtwBuffer // write buffer
|
||||
);
|
||||
|
||||
FreePool (FtwBuffer);
|
||||
return Status;
|
||||
}
|
2618
SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c
Normal file
2618
SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c
Normal file
File diff suppressed because it is too large
Load Diff
491
SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h
Normal file
491
SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h
Normal file
@@ -0,0 +1,491 @@
|
||||
/** @file
|
||||
The internal header file includes the common header files, defines
|
||||
internal structure and functions used by Variable modules.
|
||||
|
||||
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _VARIABLE_H_
|
||||
#define _VARIABLE_H_
|
||||
|
||||
#include <PiDxe.h>
|
||||
#include <Protocol/VariableWrite.h>
|
||||
#include <Protocol/FaultTolerantWrite.h>
|
||||
#include <Protocol/FirmwareVolumeBlock.h>
|
||||
#include <Protocol/Variable.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/DxeServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/SynchronizationLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/BaseCryptLib.h>
|
||||
#include <Library/PlatformSecureLib.h>
|
||||
#include <Guid/GlobalVariable.h>
|
||||
#include <Guid/EventGroup.h>
|
||||
#include <Guid/AuthenticatedVariableFormat.h>
|
||||
#include <Guid/ImageAuthentication.h>
|
||||
|
||||
#define VARIABLE_RECLAIM_THRESHOLD (1024)
|
||||
|
||||
///
|
||||
/// The size of a 3 character ISO639 language code.
|
||||
///
|
||||
#define ISO_639_2_ENTRY_SIZE 3
|
||||
|
||||
typedef struct {
|
||||
VARIABLE_HEADER *CurrPtr;
|
||||
VARIABLE_HEADER *EndPtr;
|
||||
VARIABLE_HEADER *StartPtr;
|
||||
BOOLEAN Volatile;
|
||||
} VARIABLE_POINTER_TRACK;
|
||||
|
||||
typedef struct {
|
||||
EFI_PHYSICAL_ADDRESS VolatileVariableBase;
|
||||
EFI_PHYSICAL_ADDRESS NonVolatileVariableBase;
|
||||
EFI_LOCK VariableServicesLock;
|
||||
UINT32 ReentrantState;
|
||||
} VARIABLE_GLOBAL;
|
||||
|
||||
typedef struct {
|
||||
VARIABLE_GLOBAL VariableGlobal;
|
||||
UINTN VolatileLastVariableOffset;
|
||||
UINTN NonVolatileLastVariableOffset;
|
||||
UINTN CommonVariableTotalSize;
|
||||
UINTN HwErrVariableTotalSize;
|
||||
CHAR8 *PlatformLangCodes;
|
||||
CHAR8 *LangCodes;
|
||||
CHAR8 *PlatformLang;
|
||||
CHAR8 Lang[ISO_639_2_ENTRY_SIZE + 1];
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbInstance;
|
||||
} VARIABLE_MODULE_GLOBAL;
|
||||
|
||||
typedef struct {
|
||||
EFI_GUID *Guid;
|
||||
CHAR16 *Name;
|
||||
UINT32 Attributes;
|
||||
UINTN DataSize;
|
||||
VOID *Data;
|
||||
} VARIABLE_CACHE_ENTRY;
|
||||
|
||||
/**
|
||||
Writes a buffer to variable storage space, in the working block.
|
||||
|
||||
This function writes a buffer to variable storage space into a firmware
|
||||
volume block device. The destination is specified by the parameter
|
||||
VariableBase. Fault Tolerant Write protocol is used for writing.
|
||||
|
||||
@param VariableBase Base address of the variable to write.
|
||||
@param Buffer Point to the data buffer.
|
||||
@param BufferSize The number of bytes of the data Buffer.
|
||||
|
||||
@retval EFI_SUCCESS The function completed successfully.
|
||||
@retval EFI_NOT_FOUND Fail to locate Fault Tolerant Write protocol.
|
||||
@retval EFI_ABORTED The function could not complete successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FtwVariableSpace (
|
||||
IN EFI_PHYSICAL_ADDRESS VariableBase,
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN BufferSize
|
||||
);
|
||||
|
||||
/**
|
||||
Finds variable in storage blocks of volatile and non-volatile storage areas.
|
||||
|
||||
This code finds variable in storage blocks of volatile and non-volatile storage areas.
|
||||
If VariableName is an empty string, then we just return the first
|
||||
qualified variable without comparing VariableName and VendorGuid.
|
||||
Otherwise, VariableName and VendorGuid are compared.
|
||||
|
||||
@param VariableName Name of the variable to be found.
|
||||
@param VendorGuid Vendor GUID to be found.
|
||||
@param PtrTrack VARIABLE_POINTER_TRACK structure for output,
|
||||
including the range searched and the target position.
|
||||
@param Global Pointer to VARIABLE_GLOBAL structure, including
|
||||
base of volatile variable storage area, base of
|
||||
NV variable storage area, and a lock.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while
|
||||
VendorGuid is NULL.
|
||||
@retval EFI_SUCCESS Variable successfully found.
|
||||
@retval EFI_INVALID_PARAMETER Variable not found.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FindVariable (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
OUT VARIABLE_POINTER_TRACK *PtrTrack,
|
||||
IN VARIABLE_GLOBAL *Global
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
This code gets the pointer to the variable data.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@return Pointer to Variable Data.
|
||||
|
||||
**/
|
||||
UINT8 *
|
||||
GetVariableDataPtr (
|
||||
IN VARIABLE_HEADER *Variable
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
This code gets the size of variable data.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@return Size of variable in bytes.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
DataSizeOfVariable (
|
||||
IN VARIABLE_HEADER *Variable
|
||||
);
|
||||
|
||||
/**
|
||||
Update the variable region with Variable information. If EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS is set,
|
||||
index of associated public key is needed.
|
||||
|
||||
@param[in] VariableName Name of variable.
|
||||
@param[in] VendorGuid Guid of variable.
|
||||
@param[in] Data Variable data.
|
||||
@param[in] DataSize Size of data. 0 means delete.
|
||||
@param[in] Attributes Attributes of the variable.
|
||||
@param[in] KeyIndex Index of associated public key.
|
||||
@param[in] MonotonicCount Value of associated monotonic count.
|
||||
@param[in] Variable The variable information that is used to keep track of variable usage.
|
||||
|
||||
@param[in] TimeStamp Value of associated TimeStamp.
|
||||
|
||||
@retval EFI_SUCCESS The update operation is success.
|
||||
@retval EFI_OUT_OF_RESOURCES Variable region is full, cannot write other data into this region.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UpdateVariable (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
IN VOID *Data,
|
||||
IN UINTN DataSize,
|
||||
IN UINT32 Attributes OPTIONAL,
|
||||
IN UINT32 KeyIndex OPTIONAL,
|
||||
IN UINT64 MonotonicCount OPTIONAL,
|
||||
IN VARIABLE_POINTER_TRACK *Variable,
|
||||
IN EFI_TIME *TimeStamp OPTIONAL
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Return TRUE if ExitBootServices () has been called.
|
||||
|
||||
@retval TRUE If ExitBootServices () has been called.
|
||||
**/
|
||||
BOOLEAN
|
||||
AtRuntime (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Initializes a basic mutual exclusion lock.
|
||||
|
||||
This function initializes a basic mutual exclusion lock to the released state
|
||||
and returns the lock. Each lock provides mutual exclusion access at its task
|
||||
priority level. Since there is no preemption or multiprocessor support in EFI,
|
||||
acquiring the lock only consists of raising to the locks TPL.
|
||||
If Lock is NULL, then ASSERT().
|
||||
If Priority is not a valid TPL value, then ASSERT().
|
||||
|
||||
@param Lock A pointer to the lock data structure to initialize.
|
||||
@param Priority EFI TPL is associated with the lock.
|
||||
|
||||
@return The lock.
|
||||
|
||||
**/
|
||||
EFI_LOCK *
|
||||
InitializeLock (
|
||||
IN OUT EFI_LOCK *Lock,
|
||||
IN EFI_TPL Priority
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Acquires lock only at boot time. Simply returns at runtime.
|
||||
|
||||
This is a temperary function that will be removed when
|
||||
EfiAcquireLock() in UefiLib can handle the call in UEFI
|
||||
Runtimer driver in RT phase.
|
||||
It calls EfiAcquireLock() at boot time, and simply returns
|
||||
at runtime.
|
||||
|
||||
@param Lock A pointer to the lock to acquire.
|
||||
|
||||
**/
|
||||
VOID
|
||||
AcquireLockOnlyAtBootTime (
|
||||
IN EFI_LOCK *Lock
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Releases lock only at boot time. Simply returns at runtime.
|
||||
|
||||
This is a temperary function which will be removed when
|
||||
EfiReleaseLock() in UefiLib can handle the call in UEFI
|
||||
Runtimer driver in RT phase.
|
||||
It calls EfiReleaseLock() at boot time and simply returns
|
||||
at runtime.
|
||||
|
||||
@param Lock A pointer to the lock to release.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReleaseLockOnlyAtBootTime (
|
||||
IN EFI_LOCK *Lock
|
||||
);
|
||||
|
||||
/**
|
||||
Retrive the FVB protocol interface by HANDLE.
|
||||
|
||||
@param[in] FvBlockHandle The handle of FVB protocol that provides services for
|
||||
reading, writing, and erasing the target block.
|
||||
@param[out] FvBlock The interface of FVB protocol
|
||||
|
||||
@retval EFI_SUCCESS The interface information for the specified protocol was returned.
|
||||
@retval EFI_UNSUPPORTED The device does not support the FVB protocol.
|
||||
@retval EFI_INVALID_PARAMETER FvBlockHandle is not a valid EFI_HANDLE or FvBlock is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetFvbByHandle (
|
||||
IN EFI_HANDLE FvBlockHandle,
|
||||
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Retrive the Swap Address Range protocol interface.
|
||||
|
||||
@param[out] SarProtocol The interface of SAR protocol
|
||||
|
||||
@retval EFI_SUCCESS The SAR protocol instance was found and returned in SarProtocol.
|
||||
@retval EFI_NOT_FOUND The SAR protocol instance was not found.
|
||||
@retval EFI_INVALID_PARAMETER SarProtocol is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetSarProtocol (
|
||||
OUT VOID **SarProtocol
|
||||
);
|
||||
|
||||
/**
|
||||
Function returns an array of handles that support the FVB protocol
|
||||
in a buffer allocated from pool.
|
||||
|
||||
@param[out] NumberHandles The number of handles returned in Buffer.
|
||||
@param[out] Buffer A pointer to the buffer to return the requested
|
||||
array of handles that support FVB protocol.
|
||||
|
||||
@retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
|
||||
handles in Buffer was returned in NumberHandles.
|
||||
@retval EFI_NOT_FOUND No FVB handle was found.
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
|
||||
@retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetFvbCountAndBuffer (
|
||||
OUT UINTN *NumberHandles,
|
||||
OUT EFI_HANDLE **Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Initializes variable store area for non-volatile and volatile variable.
|
||||
|
||||
@retval EFI_SUCCESS Function successfully executed.
|
||||
@retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
VariableCommonInitialize (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
This function reclaims variable storage if free size is below the threshold.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReclaimForOS(
|
||||
VOID
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Initializes variable write service after FVB was ready.
|
||||
|
||||
@retval EFI_SUCCESS Function successfully executed.
|
||||
@retval Others Fail to initialize the variable service.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
VariableWriteServiceInitialize (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Retrive the SMM Fault Tolerent Write protocol interface.
|
||||
|
||||
@param[out] FtwProtocol The interface of SMM Ftw protocol
|
||||
|
||||
@retval EFI_SUCCESS The SMM SAR protocol instance was found and returned in SarProtocol.
|
||||
@retval EFI_NOT_FOUND The SMM SAR protocol instance was not found.
|
||||
@retval EFI_INVALID_PARAMETER SarProtocol is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetFtwProtocol (
|
||||
OUT VOID **FtwProtocol
|
||||
);
|
||||
|
||||
/**
|
||||
Get the proper fvb handle and/or fvb protocol by the given Flash address.
|
||||
|
||||
@param[in] Address The Flash address.
|
||||
@param[out] FvbHandle In output, if it is not NULL, it points to the proper FVB handle.
|
||||
@param[out] FvbProtocol In output, if it is not NULL, it points to the proper FVB protocol.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetFvbInfoByAddress (
|
||||
IN EFI_PHYSICAL_ADDRESS Address,
|
||||
OUT EFI_HANDLE *FvbHandle OPTIONAL,
|
||||
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvbProtocol OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
This code finds variable in storage blocks (Volatile or Non-Volatile).
|
||||
|
||||
@param VariableName Name of Variable to be found.
|
||||
@param VendorGuid Variable vendor GUID.
|
||||
@param Attributes Attribute value of the variable found.
|
||||
@param DataSize Size of Data found. If size is less than the
|
||||
data, this value contains the required size.
|
||||
@param Data Data pointer.
|
||||
|
||||
@return EFI_INVALID_PARAMETER Invalid parameter.
|
||||
@return EFI_SUCCESS Find the specified variable.
|
||||
@return EFI_NOT_FOUND Not found.
|
||||
@return EFI_BUFFER_TO_SMALL DataSize is too small for the result.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
VariableServiceGetVariable (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
OUT UINT32 *Attributes OPTIONAL,
|
||||
IN OUT UINTN *DataSize,
|
||||
OUT VOID *Data
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
This code Finds the Next available variable.
|
||||
|
||||
@param VariableNameSize Size of the variable name.
|
||||
@param VariableName Pointer to variable name.
|
||||
@param VendorGuid Variable Vendor Guid.
|
||||
|
||||
@return EFI_INVALID_PARAMETER Invalid parameter.
|
||||
@return EFI_SUCCESS Find the specified variable.
|
||||
@return EFI_NOT_FOUND Not found.
|
||||
@return EFI_BUFFER_TO_SMALL DataSize is too small for the result.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
VariableServiceGetNextVariableName (
|
||||
IN OUT UINTN *VariableNameSize,
|
||||
IN OUT CHAR16 *VariableName,
|
||||
IN OUT EFI_GUID *VendorGuid
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
This code sets variable in storage blocks (Volatile or Non-Volatile).
|
||||
|
||||
@param VariableName Name of Variable to be found.
|
||||
@param VendorGuid Variable vendor GUID.
|
||||
@param Attributes Attribute value of the variable found
|
||||
@param DataSize Size of Data found. If size is less than the
|
||||
data, this value contains the required size.
|
||||
@param Data Data pointer.
|
||||
|
||||
@return EFI_INVALID_PARAMETER Invalid parameter.
|
||||
@return EFI_SUCCESS Set successfully.
|
||||
@return EFI_OUT_OF_RESOURCES Resource not enough to set variable.
|
||||
@return EFI_NOT_FOUND Not found.
|
||||
@return EFI_WRITE_PROTECTED Variable is read-only.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
VariableServiceSetVariable (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
IN UINT32 Attributes,
|
||||
IN UINTN DataSize,
|
||||
IN VOID *Data
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
This code returns information about the EFI variables.
|
||||
|
||||
@param Attributes Attributes bitmask to specify the type of variables
|
||||
on which to return information.
|
||||
@param MaximumVariableStorageSize Pointer to the maximum size of the storage space available
|
||||
for the EFI variables associated with the attributes specified.
|
||||
@param RemainingVariableStorageSize Pointer to the remaining size of the storage space available
|
||||
for EFI variables associated with the attributes specified.
|
||||
@param MaximumVariableSize Pointer to the maximum size of an individual EFI variables
|
||||
associated with the attributes specified.
|
||||
|
||||
@return EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.
|
||||
@return EFI_SUCCESS Query successfully.
|
||||
@return EFI_UNSUPPORTED The attribute is not supported on this platform.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
VariableServiceQueryVariableInfo (
|
||||
IN UINT32 Attributes,
|
||||
OUT UINT64 *MaximumVariableStorageSize,
|
||||
OUT UINT64 *RemainingVariableStorageSize,
|
||||
OUT UINT64 *MaximumVariableSize
|
||||
);
|
||||
|
||||
extern VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal;
|
||||
|
||||
#endif
|
433
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableDxe.c
Normal file
433
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableDxe.c
Normal file
@@ -0,0 +1,433 @@
|
||||
/** @file
|
||||
Implement all four UEFI Runtime Variable services for the nonvolatile
|
||||
and volatile storage space and install variable architecture protocol.
|
||||
|
||||
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include "Variable.h"
|
||||
#include "AuthService.h"
|
||||
|
||||
extern VARIABLE_STORE_HEADER *mNvVariableCache;
|
||||
extern VARIABLE_INFO_ENTRY *gVariableInfo;
|
||||
EFI_HANDLE mHandle = NULL;
|
||||
EFI_EVENT mVirtualAddressChangeEvent = NULL;
|
||||
EFI_EVENT mFtwRegistration = NULL;
|
||||
|
||||
/**
|
||||
Return TRUE if ExitBootServices () has been called.
|
||||
|
||||
@retval TRUE If ExitBootServices () has been called.
|
||||
**/
|
||||
BOOLEAN
|
||||
AtRuntime (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return EfiAtRuntime ();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initializes a basic mutual exclusion lock.
|
||||
|
||||
This function initializes a basic mutual exclusion lock to the released state
|
||||
and returns the lock. Each lock provides mutual exclusion access at its task
|
||||
priority level. Since there is no preemption or multiprocessor support in EFI,
|
||||
acquiring the lock only consists of raising to the locks TPL.
|
||||
If Lock is NULL, then ASSERT().
|
||||
If Priority is not a valid TPL value, then ASSERT().
|
||||
|
||||
@param Lock A pointer to the lock data structure to initialize.
|
||||
@param Priority EFI TPL is associated with the lock.
|
||||
|
||||
@return The lock.
|
||||
|
||||
**/
|
||||
EFI_LOCK *
|
||||
InitializeLock (
|
||||
IN OUT EFI_LOCK *Lock,
|
||||
IN EFI_TPL Priority
|
||||
)
|
||||
{
|
||||
return EfiInitializeLock (Lock, Priority);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Acquires lock only at boot time. Simply returns at runtime.
|
||||
|
||||
This is a temperary function that will be removed when
|
||||
EfiAcquireLock() in UefiLib can handle the call in UEFI
|
||||
Runtimer driver in RT phase.
|
||||
It calls EfiAcquireLock() at boot time, and simply returns
|
||||
at runtime.
|
||||
|
||||
@param Lock A pointer to the lock to acquire.
|
||||
|
||||
**/
|
||||
VOID
|
||||
AcquireLockOnlyAtBootTime (
|
||||
IN EFI_LOCK *Lock
|
||||
)
|
||||
{
|
||||
if (!AtRuntime ()) {
|
||||
EfiAcquireLock (Lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Releases lock only at boot time. Simply returns at runtime.
|
||||
|
||||
This is a temperary function which will be removed when
|
||||
EfiReleaseLock() in UefiLib can handle the call in UEFI
|
||||
Runtimer driver in RT phase.
|
||||
It calls EfiReleaseLock() at boot time and simply returns
|
||||
at runtime.
|
||||
|
||||
@param Lock A pointer to the lock to release.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReleaseLockOnlyAtBootTime (
|
||||
IN EFI_LOCK *Lock
|
||||
)
|
||||
{
|
||||
if (!AtRuntime ()) {
|
||||
EfiReleaseLock (Lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Retrive the Fault Tolerent Write protocol interface.
|
||||
|
||||
@param[out] FtwProtocol The interface of Ftw protocol
|
||||
|
||||
@retval EFI_SUCCESS The FTW protocol instance was found and returned in FtwProtocol.
|
||||
@retval EFI_NOT_FOUND The FTW protocol instance was not found.
|
||||
@retval EFI_INVALID_PARAMETER SarProtocol is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetFtwProtocol (
|
||||
OUT VOID **FtwProtocol
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Locate Fault Tolerent Write protocol
|
||||
//
|
||||
Status = gBS->LocateProtocol (
|
||||
&gEfiFaultTolerantWriteProtocolGuid,
|
||||
NULL,
|
||||
FtwProtocol
|
||||
);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Retrive the FVB protocol interface by HANDLE.
|
||||
|
||||
@param[in] FvBlockHandle The handle of FVB protocol that provides services for
|
||||
reading, writing, and erasing the target block.
|
||||
@param[out] FvBlock The interface of FVB protocol
|
||||
|
||||
@retval EFI_SUCCESS The interface information for the specified protocol was returned.
|
||||
@retval EFI_UNSUPPORTED The device does not support the FVB protocol.
|
||||
@retval EFI_INVALID_PARAMETER FvBlockHandle is not a valid EFI_HANDLE or FvBlock is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetFvbByHandle (
|
||||
IN EFI_HANDLE FvBlockHandle,
|
||||
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
|
||||
)
|
||||
{
|
||||
//
|
||||
// To get the FVB protocol interface on the handle
|
||||
//
|
||||
return gBS->HandleProtocol (
|
||||
FvBlockHandle,
|
||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||
(VOID **) FvBlock
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Function returns an array of handles that support the FVB protocol
|
||||
in a buffer allocated from pool.
|
||||
|
||||
@param[out] NumberHandles The number of handles returned in Buffer.
|
||||
@param[out] Buffer A pointer to the buffer to return the requested
|
||||
array of handles that support FVB protocol.
|
||||
|
||||
@retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
|
||||
handles in Buffer was returned in NumberHandles.
|
||||
@retval EFI_NOT_FOUND No FVB handle was found.
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
|
||||
@retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetFvbCountAndBuffer (
|
||||
OUT UINTN *NumberHandles,
|
||||
OUT EFI_HANDLE **Buffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Locate all handles of Fvb protocol
|
||||
//
|
||||
Status = gBS->LocateHandleBuffer (
|
||||
ByProtocol,
|
||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||
NULL,
|
||||
NumberHandles,
|
||||
Buffer
|
||||
);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
|
||||
|
||||
This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
|
||||
It convers pointer to new virtual address.
|
||||
|
||||
@param Event Event whose notification function is being invoked.
|
||||
@param Context Pointer to the notification function's context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
VariableClassAddressChangeEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetBlockSize);
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetPhysicalAddress);
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetAttributes);
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->SetAttributes);
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Read);
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Write);
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->EraseBlocks);
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance);
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLangCodes);
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->LangCodes);
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLang);
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);
|
||||
EfiConvertPointer (0x0, (VOID **) &mHashCtx);
|
||||
EfiConvertPointer (0x0, (VOID **) &mStorageArea);
|
||||
EfiConvertPointer (0x0, (VOID **) &mNvVariableCache);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Notification function of EVT_GROUP_READY_TO_BOOT event group.
|
||||
|
||||
This is a notification function registered on EVT_GROUP_READY_TO_BOOT event group.
|
||||
When the Boot Manager is about to load and execute a boot option, it reclaims variable
|
||||
storage if free size is below the threshold.
|
||||
|
||||
@param Event Event whose notification function is being invoked.
|
||||
@param Context Pointer to the notification function's context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
OnReadyToBoot (
|
||||
EFI_EVENT Event,
|
||||
VOID *Context
|
||||
)
|
||||
{
|
||||
ReclaimForOS ();
|
||||
if (FeaturePcdGet (PcdVariableCollectStatistics)) {
|
||||
gBS->InstallConfigurationTable (&gEfiAuthenticatedVariableGuid, gVariableInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Fault Tolerant Write protocol notification event handler.
|
||||
|
||||
Non-Volatile variable write may needs FTW protocol to reclaim when
|
||||
writting variable.
|
||||
|
||||
@param[in] Event Event whose notification function is being invoked.
|
||||
@param[in] Context Pointer to the notification function's context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
FtwNotificationEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;
|
||||
EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
|
||||
EFI_PHYSICAL_ADDRESS NvStorageVariableBase;
|
||||
EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
|
||||
EFI_PHYSICAL_ADDRESS BaseAddress;
|
||||
UINT64 Length;
|
||||
EFI_PHYSICAL_ADDRESS VariableStoreBase;
|
||||
UINT64 VariableStoreLength;
|
||||
|
||||
//
|
||||
// Ensure FTW protocol is installed.
|
||||
//
|
||||
Status = GetFtwProtocol ((VOID**) &FtwProtocol);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return ;
|
||||
}
|
||||
|
||||
//
|
||||
// Find the proper FVB protocol for variable.
|
||||
//
|
||||
NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
|
||||
if (NvStorageVariableBase == 0) {
|
||||
NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
|
||||
}
|
||||
Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return ;
|
||||
}
|
||||
mVariableModuleGlobal->FvbInstance = FvbProtocol;
|
||||
|
||||
//
|
||||
// Mark the variable storage region of the FLASH as RUNTIME.
|
||||
//
|
||||
VariableStoreBase = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
|
||||
VariableStoreLength = ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase)->Size;
|
||||
BaseAddress = VariableStoreBase & (~EFI_PAGE_MASK);
|
||||
Length = VariableStoreLength + (VariableStoreBase - BaseAddress);
|
||||
Length = (Length + EFI_PAGE_SIZE - 1) & (~EFI_PAGE_MASK);
|
||||
|
||||
Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n"));
|
||||
} else {
|
||||
Status = gDS->SetMemorySpaceAttributes (
|
||||
BaseAddress,
|
||||
Length,
|
||||
GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n"));
|
||||
}
|
||||
}
|
||||
|
||||
Status = VariableWriteServiceInitialize ();
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Install the Variable Write Architectural protocol.
|
||||
//
|
||||
Status = gBS->InstallProtocolInterface (
|
||||
&mHandle,
|
||||
&gEfiVariableWriteArchProtocolGuid,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Close the notify event to avoid install gEfiVariableWriteArchProtocolGuid again.
|
||||
//
|
||||
gBS->CloseEvent (Event);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Variable Driver main entry point. The Variable driver places the 4 EFI
|
||||
runtime services in the EFI System Table and installs arch protocols
|
||||
for variable read and write services being available. It also registers
|
||||
a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
|
||||
|
||||
@param[in] ImageHandle The firmware allocated handle for the EFI image.
|
||||
@param[in] SystemTable A pointer to the EFI System Table.
|
||||
|
||||
@retval EFI_SUCCESS Variable service successfully initialized.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
VariableServiceInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_EVENT ReadyToBootEvent;
|
||||
|
||||
Status = VariableCommonInitialize ();
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
SystemTable->RuntimeServices->GetVariable = VariableServiceGetVariable;
|
||||
SystemTable->RuntimeServices->GetNextVariableName = VariableServiceGetNextVariableName;
|
||||
SystemTable->RuntimeServices->SetVariable = VariableServiceSetVariable;
|
||||
SystemTable->RuntimeServices->QueryVariableInfo = VariableServiceQueryVariableInfo;
|
||||
|
||||
//
|
||||
// Now install the Variable Runtime Architectural protocol on a new handle.
|
||||
//
|
||||
Status = gBS->InstallProtocolInterface (
|
||||
&mHandle,
|
||||
&gEfiVariableArchProtocolGuid,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Register FtwNotificationEvent () notify function.
|
||||
//
|
||||
EfiCreateProtocolNotifyEvent (
|
||||
&gEfiFaultTolerantWriteProtocolGuid,
|
||||
TPL_CALLBACK,
|
||||
FtwNotificationEvent,
|
||||
(VOID *)SystemTable,
|
||||
&mFtwRegistration
|
||||
);
|
||||
|
||||
Status = gBS->CreateEventEx (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_NOTIFY,
|
||||
VariableClassAddressChangeEvent,
|
||||
NULL,
|
||||
&gEfiEventVirtualAddressChangeGuid,
|
||||
&mVirtualAddressChangeEvent
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Register the event handling function to reclaim variable for OS usage.
|
||||
//
|
||||
Status = EfiCreateEventReadyToBootEx (
|
||||
TPL_NOTIFY,
|
||||
OnReadyToBoot,
|
||||
NULL,
|
||||
&ReadyToBootEvent
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@@ -0,0 +1,98 @@
|
||||
## @file
|
||||
# Component description file for Authenticated Variable module.
|
||||
#
|
||||
# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
# 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.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = VariableRuntimeDxe
|
||||
FILE_GUID = 2226F30F-3D5B-402d-9936-A97184EB4516
|
||||
MODULE_TYPE = DXE_RUNTIME_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = VariableServiceInitialize
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 EBC
|
||||
#
|
||||
# VIRTUAL_ADDRESS_MAP_CALLBACK = VariableClassAddressChangeEvent
|
||||
#
|
||||
|
||||
[Sources]
|
||||
Reclaim.c
|
||||
Variable.c
|
||||
VariableDxe.c
|
||||
Variable.h
|
||||
AuthService.c
|
||||
AuthService.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
CryptoPkg/CryptoPkg.dec
|
||||
SecurityPkg/SecurityPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
MemoryAllocationLib
|
||||
BaseLib
|
||||
SynchronizationLib
|
||||
UefiLib
|
||||
UefiBootServicesTableLib
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
UefiRuntimeLib
|
||||
DxeServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
PcdLib
|
||||
BaseCryptLib
|
||||
PlatformSecureLib
|
||||
|
||||
[Protocols]
|
||||
gEfiFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gEfiVariableWriteArchProtocolGuid ## ALWAYS_PRODUCES
|
||||
gEfiVariableArchProtocolGuid ## ALWAYS_PRODUCES
|
||||
gEfiFaultTolerantWriteProtocolGuid ## SOMETIMES_CONSUMES
|
||||
|
||||
[Guids]
|
||||
gEfiAuthenticatedVariableGuid ## PRODUCES ## Configuration Table Guid
|
||||
gEfiGlobalVariableGuid ## PRODUCES ## Variable Guid
|
||||
gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event
|
||||
gEfiCertRsa2048Sha256Guid
|
||||
gEfiImageSecurityDatabaseGuid
|
||||
gEfiCertX509Guid
|
||||
gEfiCertPkcs7Guid
|
||||
gEfiCertRsa2048Guid
|
||||
|
||||
[Pcd]
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize
|
||||
gEfiSecurityPkgTokenSpaceGuid.PcdMaxAppendVariableSize
|
||||
|
||||
[FeaturePcd]
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## SOMETIME_CONSUMES (statistic the information of variable.)
|
||||
|
||||
[Depex]
|
||||
gEfiFirmwareVolumeBlockProtocolGuid AND gEfiFaultTolerantWriteProtocolGuid
|
||||
|
||||
# [Event]
|
||||
# ##
|
||||
# # Event will be signaled for VIRTUAL_ADDRESS_CHANGE event.
|
||||
# #
|
||||
# EVENT_TYPE_NOTIFY_SIGNAL ## PRODUCES
|
||||
#
|
||||
#
|
||||
|
587
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c
Normal file
587
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c
Normal file
@@ -0,0 +1,587 @@
|
||||
/** @file
|
||||
The sample implementation for SMM variable protocol. And this driver
|
||||
implements an SMI handler to communicate with the DXE runtime driver
|
||||
to provide variable services.
|
||||
|
||||
Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include <Protocol/SmmVariable.h>
|
||||
#include <Protocol/SmmFirmwareVolumeBlock.h>
|
||||
#include <Protocol/SmmFaultTolerantWrite.h>
|
||||
#include <Library/SmmServicesTableLib.h>
|
||||
|
||||
#include <Guid/AuthenticatedVariableFormat.h>
|
||||
#include <Guid/SmmVariableCommon.h>
|
||||
#include "Variable.h"
|
||||
|
||||
extern VARIABLE_INFO_ENTRY *gVariableInfo;
|
||||
EFI_HANDLE mSmmVariableHandle = NULL;
|
||||
EFI_HANDLE mVariableHandle = NULL;
|
||||
BOOLEAN mAtRuntime = FALSE;
|
||||
EFI_GUID mZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
|
||||
EFI_SMM_VARIABLE_PROTOCOL gSmmVariable = {
|
||||
VariableServiceGetVariable,
|
||||
VariableServiceGetNextVariableName,
|
||||
VariableServiceSetVariable,
|
||||
VariableServiceQueryVariableInfo
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Return TRUE if ExitBootServices () has been called.
|
||||
|
||||
@retval TRUE If ExitBootServices () has been called.
|
||||
**/
|
||||
BOOLEAN
|
||||
AtRuntime (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return mAtRuntime;
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a basic mutual exclusion lock.
|
||||
|
||||
This function initializes a basic mutual exclusion lock to the released state
|
||||
and returns the lock. Each lock provides mutual exclusion access at its task
|
||||
priority level. Since there is no preemption or multiprocessor support in EFI,
|
||||
acquiring the lock only consists of raising to the locks TPL.
|
||||
If Lock is NULL, then ASSERT().
|
||||
If Priority is not a valid TPL value, then ASSERT().
|
||||
|
||||
@param Lock A pointer to the lock data structure to initialize.
|
||||
@param Priority EFI TPL is associated with the lock.
|
||||
|
||||
@return The lock.
|
||||
|
||||
**/
|
||||
EFI_LOCK *
|
||||
InitializeLock (
|
||||
IN OUT EFI_LOCK *Lock,
|
||||
IN EFI_TPL Priority
|
||||
)
|
||||
{
|
||||
return Lock;
|
||||
}
|
||||
|
||||
/**
|
||||
Acquires lock only at boot time. Simply returns at runtime.
|
||||
|
||||
This is a temperary function that will be removed when
|
||||
EfiAcquireLock() in UefiLib can handle the call in UEFI
|
||||
Runtimer driver in RT phase.
|
||||
It calls EfiAcquireLock() at boot time, and simply returns
|
||||
at runtime.
|
||||
|
||||
@param Lock A pointer to the lock to acquire.
|
||||
|
||||
**/
|
||||
VOID
|
||||
AcquireLockOnlyAtBootTime (
|
||||
IN EFI_LOCK *Lock
|
||||
)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Releases lock only at boot time. Simply returns at runtime.
|
||||
|
||||
This is a temperary function which will be removed when
|
||||
EfiReleaseLock() in UefiLib can handle the call in UEFI
|
||||
Runtimer driver in RT phase.
|
||||
It calls EfiReleaseLock() at boot time and simply returns
|
||||
at runtime.
|
||||
|
||||
@param Lock A pointer to the lock to release.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReleaseLockOnlyAtBootTime (
|
||||
IN EFI_LOCK *Lock
|
||||
)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Retrive the SMM Fault Tolerent Write protocol interface.
|
||||
|
||||
@param[out] FtwProtocol The interface of SMM Ftw protocol
|
||||
|
||||
@retval EFI_SUCCESS The SMM FTW protocol instance was found and returned in FtwProtocol.
|
||||
@retval EFI_NOT_FOUND The SMM FTW protocol instance was not found.
|
||||
@retval EFI_INVALID_PARAMETER SarProtocol is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetFtwProtocol (
|
||||
OUT VOID **FtwProtocol
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Locate Smm Fault Tolerent Write protocol
|
||||
//
|
||||
Status = gSmst->SmmLocateProtocol (
|
||||
&gEfiSmmFaultTolerantWriteProtocolGuid,
|
||||
NULL,
|
||||
FtwProtocol
|
||||
);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Retrive the SMM FVB protocol interface by HANDLE.
|
||||
|
||||
@param[in] FvBlockHandle The handle of SMM FVB protocol that provides services for
|
||||
reading, writing, and erasing the target block.
|
||||
@param[out] FvBlock The interface of SMM FVB protocol
|
||||
|
||||
@retval EFI_SUCCESS The interface information for the specified protocol was returned.
|
||||
@retval EFI_UNSUPPORTED The device does not support the SMM FVB protocol.
|
||||
@retval EFI_INVALID_PARAMETER FvBlockHandle is not a valid EFI_HANDLE or FvBlock is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetFvbByHandle (
|
||||
IN EFI_HANDLE FvBlockHandle,
|
||||
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
|
||||
)
|
||||
{
|
||||
//
|
||||
// To get the SMM FVB protocol interface on the handle
|
||||
//
|
||||
return gSmst->SmmHandleProtocol (
|
||||
FvBlockHandle,
|
||||
&gEfiSmmFirmwareVolumeBlockProtocolGuid,
|
||||
(VOID **) FvBlock
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Function returns an array of handles that support the SMM FVB protocol
|
||||
in a buffer allocated from pool.
|
||||
|
||||
@param[out] NumberHandles The number of handles returned in Buffer.
|
||||
@param[out] Buffer A pointer to the buffer to return the requested
|
||||
array of handles that support SMM FVB protocol.
|
||||
|
||||
@retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
|
||||
handles in Buffer was returned in NumberHandles.
|
||||
@retval EFI_NOT_FOUND No SMM FVB handle was found.
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
|
||||
@retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetFvbCountAndBuffer (
|
||||
OUT UINTN *NumberHandles,
|
||||
OUT EFI_HANDLE **Buffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN BufferSize;
|
||||
|
||||
if ((NumberHandles == NULL) || (Buffer == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
BufferSize = 0;
|
||||
*NumberHandles = 0;
|
||||
*Buffer = NULL;
|
||||
Status = gSmst->SmmLocateHandle (
|
||||
ByProtocol,
|
||||
&gEfiSmmFirmwareVolumeBlockProtocolGuid,
|
||||
NULL,
|
||||
&BufferSize,
|
||||
*Buffer
|
||||
);
|
||||
if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
*Buffer = AllocatePool (BufferSize);
|
||||
if (*Buffer == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Status = gSmst->SmmLocateHandle (
|
||||
ByProtocol,
|
||||
&gEfiSmmFirmwareVolumeBlockProtocolGuid,
|
||||
NULL,
|
||||
&BufferSize,
|
||||
*Buffer
|
||||
);
|
||||
|
||||
*NumberHandles = BufferSize / sizeof(EFI_HANDLE);
|
||||
if (EFI_ERROR(Status)) {
|
||||
*NumberHandles = 0;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get the variable statistics information from the information buffer pointed by gVariableInfo.
|
||||
|
||||
@param[in, out] InfoEntry A pointer to the buffer of variable information entry.
|
||||
On input, point to the variable information returned last time. if
|
||||
InfoEntry->VendorGuid is zero, return the first information.
|
||||
On output, point to the next variable information.
|
||||
@param[in, out] InfoSize On input, the size of the variable information buffer.
|
||||
On output, the returned variable information size.
|
||||
|
||||
@retval EFI_SUCCESS The variable information is found and returned successfully.
|
||||
@retval EFI_UNSUPPORTED No variable inoformation exists in variable driver. The
|
||||
PcdVariableCollectStatistics should be set TRUE to support it.
|
||||
@retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the next variable information.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SmmVariableGetStatistics (
|
||||
IN OUT VARIABLE_INFO_ENTRY *InfoEntry,
|
||||
IN OUT UINTN *InfoSize
|
||||
)
|
||||
{
|
||||
VARIABLE_INFO_ENTRY *VariableInfo;
|
||||
UINTN NameLength;
|
||||
UINTN StatisticsInfoSize;
|
||||
CHAR16 *InfoName;
|
||||
|
||||
ASSERT (InfoEntry != NULL);
|
||||
VariableInfo = gVariableInfo;
|
||||
if (VariableInfo == NULL) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name);
|
||||
if (*InfoSize < sizeof (VARIABLE_INFO_ENTRY)) {
|
||||
*InfoSize = StatisticsInfoSize;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
InfoName = (CHAR16 *)(InfoEntry + 1);
|
||||
|
||||
if (CompareGuid (&InfoEntry->VendorGuid, &mZeroGuid)) {
|
||||
//
|
||||
// Return the first variable info
|
||||
//
|
||||
CopyMem (InfoEntry, VariableInfo, sizeof (VARIABLE_INFO_ENTRY));
|
||||
CopyMem (InfoName, VariableInfo->Name, StrSize (VariableInfo->Name));
|
||||
*InfoSize = StatisticsInfoSize;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the next variable info
|
||||
//
|
||||
while (VariableInfo != NULL) {
|
||||
if (CompareGuid (&VariableInfo->VendorGuid, &InfoEntry->VendorGuid)) {
|
||||
NameLength = StrSize (VariableInfo->Name);
|
||||
if (NameLength == StrSize (InfoName)) {
|
||||
if (CompareMem (VariableInfo->Name, InfoName, NameLength) == 0) {
|
||||
//
|
||||
// Find the match one
|
||||
//
|
||||
VariableInfo = VariableInfo->Next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
VariableInfo = VariableInfo->Next;
|
||||
};
|
||||
|
||||
if (VariableInfo == NULL) {
|
||||
*InfoSize = 0;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Output the new variable info
|
||||
//
|
||||
StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name);
|
||||
if (*InfoSize < StatisticsInfoSize) {
|
||||
*InfoSize = StatisticsInfoSize;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
CopyMem (InfoEntry, VariableInfo, sizeof (VARIABLE_INFO_ENTRY));
|
||||
CopyMem (InfoName, VariableInfo->Name, StrSize (VariableInfo->Name));
|
||||
*InfoSize = StatisticsInfoSize;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Communication service SMI Handler entry.
|
||||
|
||||
This SMI handler provides services for the variable wrapper driver.
|
||||
|
||||
@param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
|
||||
@param[in] RegisterContext Points to an optional handler context which was specified when the
|
||||
handler was registered.
|
||||
@param[in, out] CommBuffer A pointer to a collection of data in memory that will
|
||||
be conveyed from a non-SMM environment into an SMM environment.
|
||||
@param[in, out] CommBufferSize The size of the CommBuffer.
|
||||
|
||||
@retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
|
||||
should still be called.
|
||||
@retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
|
||||
still be called.
|
||||
@retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
|
||||
be called.
|
||||
@retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmVariableHandler (
|
||||
IN EFI_HANDLE DispatchHandle,
|
||||
IN CONST VOID *RegisterContext,
|
||||
IN OUT VOID *CommBuffer,
|
||||
IN OUT UINTN *CommBufferSize
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
|
||||
SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;
|
||||
SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *GetNextVariableName;
|
||||
SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *QueryVariableInfo;
|
||||
VARIABLE_INFO_ENTRY *VariableInfo;
|
||||
UINTN InfoSize;
|
||||
|
||||
ASSERT (CommBuffer != NULL);
|
||||
|
||||
SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)CommBuffer;
|
||||
switch (SmmVariableFunctionHeader->Function) {
|
||||
case SMM_VARIABLE_FUNCTION_GET_VARIABLE:
|
||||
SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) SmmVariableFunctionHeader->Data;
|
||||
Status = VariableServiceGetVariable (
|
||||
SmmVariableHeader->Name,
|
||||
&SmmVariableHeader->Guid,
|
||||
&SmmVariableHeader->Attributes,
|
||||
&SmmVariableHeader->DataSize,
|
||||
(UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize
|
||||
);
|
||||
break;
|
||||
|
||||
case SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME:
|
||||
GetNextVariableName = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *) SmmVariableFunctionHeader->Data;
|
||||
Status = VariableServiceGetNextVariableName (
|
||||
&GetNextVariableName->NameSize,
|
||||
GetNextVariableName->Name,
|
||||
&GetNextVariableName->Guid
|
||||
);
|
||||
break;
|
||||
|
||||
case SMM_VARIABLE_FUNCTION_SET_VARIABLE:
|
||||
SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) SmmVariableFunctionHeader->Data;
|
||||
Status = VariableServiceSetVariable (
|
||||
SmmVariableHeader->Name,
|
||||
&SmmVariableHeader->Guid,
|
||||
SmmVariableHeader->Attributes,
|
||||
SmmVariableHeader->DataSize,
|
||||
(UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize
|
||||
);
|
||||
break;
|
||||
|
||||
case SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO:
|
||||
QueryVariableInfo = (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *) SmmVariableFunctionHeader->Data;
|
||||
Status = VariableServiceQueryVariableInfo (
|
||||
QueryVariableInfo->Attributes,
|
||||
&QueryVariableInfo->MaximumVariableStorageSize,
|
||||
&QueryVariableInfo->RemainingVariableStorageSize,
|
||||
&QueryVariableInfo->MaximumVariableSize
|
||||
);
|
||||
break;
|
||||
|
||||
case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:
|
||||
ReclaimForOS ();
|
||||
Status = EFI_SUCCESS;
|
||||
break;
|
||||
|
||||
case SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE:
|
||||
mAtRuntime = TRUE;
|
||||
Status = EFI_SUCCESS;
|
||||
break;
|
||||
|
||||
case SMM_VARIABLE_FUNCTION_GET_STATISTICS:
|
||||
VariableInfo = (VARIABLE_INFO_ENTRY *) SmmVariableFunctionHeader->Data;
|
||||
InfoSize = *CommBufferSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_HEADER, Data);
|
||||
Status = SmmVariableGetStatistics (VariableInfo, &InfoSize);
|
||||
*CommBufferSize = InfoSize + OFFSET_OF (SMM_VARIABLE_COMMUNICATE_HEADER, Data);
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT (FALSE);
|
||||
Status = EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
SmmVariableFunctionHeader->ReturnStatus = Status;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
SMM Fault Tolerant Write protocol notification event handler.
|
||||
|
||||
Non-Volatile variable write may needs FTW protocol to reclaim when
|
||||
writting variable.
|
||||
|
||||
@param Protocol Points to the protocol's unique identifier
|
||||
@param Interface Points to the interface instance
|
||||
@param Handle The handle on which the interface was installed
|
||||
|
||||
@retval EFI_SUCCESS SmmEventCallback runs successfully
|
||||
@retval EFI_NOT_FOUND The Fvb protocol for variable is not found.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmFtwNotificationEvent (
|
||||
IN CONST EFI_GUID *Protocol,
|
||||
IN VOID *Interface,
|
||||
IN EFI_HANDLE Handle
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;
|
||||
EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
|
||||
EFI_PHYSICAL_ADDRESS NvStorageVariableBase;
|
||||
|
||||
if (mVariableModuleGlobal->FvbInstance != NULL) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Ensure SMM FTW protocol is installed.
|
||||
//
|
||||
Status = GetFtwProtocol ((VOID **)&FtwProtocol);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Find the proper FVB protocol for variable.
|
||||
//
|
||||
NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
|
||||
if (NvStorageVariableBase == 0) {
|
||||
NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
|
||||
}
|
||||
Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
mVariableModuleGlobal->FvbInstance = FvbProtocol;
|
||||
|
||||
Status = VariableWriteServiceInitialize ();
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Notify the variable wrapper driver the variable write service is ready
|
||||
//
|
||||
Status = gBS->InstallProtocolInterface (
|
||||
&mSmmVariableHandle,
|
||||
&gSmmVariableWriteGuid,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Variable Driver main entry point. The Variable driver places the 4 EFI
|
||||
runtime services in the EFI System Table and installs arch protocols
|
||||
for variable read and write services being available. It also registers
|
||||
a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
|
||||
|
||||
@param[in] ImageHandle The firmware allocated handle for the EFI image.
|
||||
@param[in] SystemTable A pointer to the EFI System Table.
|
||||
|
||||
@retval EFI_SUCCESS Variable service successfully initialized.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
VariableServiceInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE VariableHandle;
|
||||
VOID *SmmFtwRegistration;
|
||||
|
||||
//
|
||||
// Variable initialize.
|
||||
//
|
||||
Status = VariableCommonInitialize ();
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Install the Smm Variable Protocol on a new handle.
|
||||
//
|
||||
VariableHandle = NULL;
|
||||
Status = gSmst->SmmInstallProtocolInterface (
|
||||
&VariableHandle,
|
||||
&gEfiSmmVariableProtocolGuid,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
&gSmmVariable
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
///
|
||||
/// Register SMM variable SMI handler
|
||||
///
|
||||
VariableHandle = NULL;
|
||||
Status = gSmst->SmiHandlerRegister (SmmVariableHandler, &gEfiSmmVariableProtocolGuid, &VariableHandle);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Notify the variable wrapper driver the variable service is ready
|
||||
//
|
||||
Status = SystemTable->BootServices->InstallProtocolInterface (
|
||||
&mVariableHandle,
|
||||
&gEfiSmmVariableProtocolGuid,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
&gSmmVariable
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Register FtwNotificationEvent () notify function.
|
||||
//
|
||||
Status = gSmst->SmmRegisterProtocolNotify (
|
||||
&gEfiSmmFaultTolerantWriteProtocolGuid,
|
||||
SmmFtwNotificationEvent,
|
||||
&SmmFtwRegistration
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
SmmFtwNotificationEvent (NULL, NULL, NULL);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
96
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf
Normal file
96
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf
Normal file
@@ -0,0 +1,96 @@
|
||||
## @file
|
||||
# Component description file for SMM Authenticated Variable module.
|
||||
#
|
||||
# This module installs SMM variable protocol into SMM protocol database,
|
||||
# which can be used by SMM driver, and installs SMM variable protocol
|
||||
# into BS protocol database, which can be used to notify the SMM Runtime
|
||||
# Dxe driver that the SMM variable service is ready.
|
||||
# This module should be used with SMM Runtime DXE module together. The
|
||||
# SMM Runtime DXE module would install variable arch protocol and variable
|
||||
# write arch protocol based on SMM variable module.
|
||||
#
|
||||
# Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
# 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.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = VariableSmm
|
||||
FILE_GUID = D34BDC5E-968A-40f5-A48C-E594F45AE211
|
||||
MODULE_TYPE = DXE_SMM_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
PI_SPECIFICATION_VERSION = 0x0001000A
|
||||
ENTRY_POINT = VariableServiceInitialize
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
|
||||
[Sources]
|
||||
Reclaim.c
|
||||
Variable.c
|
||||
VariableSmm.c
|
||||
AuthService.c
|
||||
Variable.h
|
||||
AuthService.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
CryptoPkg/CryptoPkg.dec
|
||||
SecurityPkg/SecurityPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
UefiDriverEntryPoint
|
||||
MemoryAllocationLib
|
||||
BaseLib
|
||||
SynchronizationLib
|
||||
UefiLib
|
||||
SmmServicesTableLib
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
DxeServicesTableLib
|
||||
BaseCryptLib
|
||||
PlatformSecureLib
|
||||
|
||||
[Protocols]
|
||||
gEfiSmmFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gEfiSmmVariableProtocolGuid ## ALWAYS_PRODUCES
|
||||
gEfiSmmFaultTolerantWriteProtocolGuid ## SOMETIMES_CONSUMES
|
||||
|
||||
[Guids]
|
||||
gEfiAuthenticatedVariableGuid ## PRODUCES ## Configuration Table Guid
|
||||
gEfiGlobalVariableGuid ## PRODUCES ## Variable Guid
|
||||
gSmmVariableWriteGuid ## PRODUCES ## SMM Variable Write Guid
|
||||
gEfiCertRsa2048Sha256Guid
|
||||
gEfiImageSecurityDatabaseGuid
|
||||
gEfiCertX509Guid
|
||||
gEfiCertPkcs7Guid
|
||||
gEfiCertRsa2048Guid
|
||||
|
||||
[Pcd]
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize
|
||||
gEfiSecurityPkgTokenSpaceGuid.PcdMaxAppendVariableSize
|
||||
|
||||
[FeaturePcd]
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## SOMETIME_CONSUMES (statistic the information of variable.)
|
||||
|
||||
[Depex]
|
||||
TRUE
|
||||
|
||||
|
@@ -0,0 +1,651 @@
|
||||
/** @file
|
||||
Implement all four UEFI Runtime Variable services for the nonvolatile
|
||||
and volatile storage space and install variable architecture protocol
|
||||
based on SMM variable module.
|
||||
|
||||
Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include <PiDxe.h>
|
||||
#include <Protocol/VariableWrite.h>
|
||||
#include <Protocol/Variable.h>
|
||||
#include <Protocol/SmmCommunication.h>
|
||||
#include <Protocol/SmmVariable.h>
|
||||
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/UefiRuntimeLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
|
||||
#include <Guid/EventGroup.h>
|
||||
#include <Guid/AuthenticatedVariableFormat.h>
|
||||
#include <Guid/SmmVariableCommon.h>
|
||||
|
||||
EFI_HANDLE mHandle = NULL;
|
||||
EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable = NULL;
|
||||
EFI_EVENT mVirtualAddressChangeEvent = NULL;
|
||||
EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication = NULL;
|
||||
UINT8 *mVariableBuffer = NULL;
|
||||
UINT8 *mVariableBufferPhysical = NULL;
|
||||
UINTN mVariableBufferSize;
|
||||
|
||||
|
||||
/**
|
||||
Initialize the communicate buffer using DataSize and Function.
|
||||
|
||||
The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE +
|
||||
DataSize.
|
||||
|
||||
@param[out] DataPtr Points to the data in the communicate buffer.
|
||||
@param[in] DataSize The data size to send to SMM.
|
||||
@param[in] Function The function number to initialize the communicate header.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The data size is too big.
|
||||
@retval EFI_SUCCESS Find the specified variable.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
InitCommunicateBuffer (
|
||||
OUT VOID **DataPtr OPTIONAL,
|
||||
IN UINTN DataSize,
|
||||
IN UINTN Function
|
||||
)
|
||||
{
|
||||
EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
|
||||
SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
|
||||
|
||||
|
||||
if (DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE > mVariableBufferSize) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) mVariableBuffer;
|
||||
CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
|
||||
SmmCommunicateHeader->MessageLength = DataSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
|
||||
|
||||
SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) SmmCommunicateHeader->Data;
|
||||
SmmVariableFunctionHeader->Function = Function;
|
||||
if (DataPtr != NULL) {
|
||||
*DataPtr = SmmVariableFunctionHeader->Data;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Send the data in communicate buffer to SMM.
|
||||
|
||||
@param[in] DataSize This size of the function header and the data.
|
||||
|
||||
@retval EFI_SUCCESS Success is returned from the functin in SMM.
|
||||
@retval Others Failure is returned from the function in SMM.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SendCommunicateBuffer (
|
||||
IN UINTN DataSize
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN CommSize;
|
||||
EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
|
||||
SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
|
||||
|
||||
CommSize = DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
|
||||
Status = mSmmCommunication->Communicate (mSmmCommunication, mVariableBufferPhysical, &CommSize);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) mVariableBuffer;
|
||||
SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
|
||||
return SmmVariableFunctionHeader->ReturnStatus;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This code finds variable in storage blocks (Volatile or Non-Volatile).
|
||||
|
||||
@param[in] VariableName Name of Variable to be found.
|
||||
@param[in] VendorGuid Variable vendor GUID.
|
||||
@param[out] Attributes Attribute value of the variable found.
|
||||
@param[in, out] DataSize Size of Data found. If size is less than the
|
||||
data, this value contains the required size.
|
||||
@param[out] Data Data pointer.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||
@retval EFI_SUCCESS Find the specified variable.
|
||||
@retval EFI_NOT_FOUND Not found.
|
||||
@retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
RuntimeServiceGetVariable (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
OUT UINT32 *Attributes OPTIONAL,
|
||||
IN OUT UINTN *DataSize,
|
||||
OUT VOID *Data
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN PayloadSize;
|
||||
SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;
|
||||
|
||||
if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((*DataSize != 0) && (Data == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Init the communicate buffer. The buffer data size is:
|
||||
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
|
||||
//
|
||||
PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName);
|
||||
Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
ASSERT (SmmVariableHeader != NULL);
|
||||
|
||||
CopyGuid (&SmmVariableHeader->Guid, VendorGuid);
|
||||
SmmVariableHeader->DataSize = *DataSize;
|
||||
SmmVariableHeader->NameSize = StrSize (VariableName);
|
||||
if (Attributes == NULL) {
|
||||
SmmVariableHeader->Attributes = 0;
|
||||
} else {
|
||||
SmmVariableHeader->Attributes = *Attributes;
|
||||
}
|
||||
CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);
|
||||
|
||||
//
|
||||
// Send data to SMM.
|
||||
//
|
||||
Status = SendCommunicateBuffer (PayloadSize);
|
||||
|
||||
//
|
||||
// Get data from SMM.
|
||||
//
|
||||
*DataSize = SmmVariableHeader->DataSize;
|
||||
if (Attributes != NULL) {
|
||||
*Attributes = SmmVariableHeader->Attributes;
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
CopyMem (Data, (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize, SmmVariableHeader->DataSize);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This code Finds the Next available variable.
|
||||
|
||||
@param[in, out] VariableNameSize Size of the variable name.
|
||||
@param[in, out] VariableName Pointer to variable name.
|
||||
@param[in, out] VendorGuid Variable Vendor Guid.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||
@retval EFI_SUCCESS Find the specified variable.
|
||||
@retval EFI_NOT_FOUND Not found.
|
||||
@retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
RuntimeServiceGetNextVariableName (
|
||||
IN OUT UINTN *VariableNameSize,
|
||||
IN OUT CHAR16 *VariableName,
|
||||
IN OUT EFI_GUID *VendorGuid
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN PayloadSize;
|
||||
SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *SmmGetNextVariableName;
|
||||
|
||||
if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Init the communicate buffer. The buffer data size is:
|
||||
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
|
||||
//
|
||||
PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + *VariableNameSize;
|
||||
Status = InitCommunicateBuffer ((VOID **)&SmmGetNextVariableName, PayloadSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
ASSERT (SmmGetNextVariableName != NULL);
|
||||
|
||||
SmmGetNextVariableName->NameSize = *VariableNameSize;
|
||||
CopyGuid (&SmmGetNextVariableName->Guid, VendorGuid);
|
||||
CopyMem (SmmGetNextVariableName->Name, VariableName, *VariableNameSize);
|
||||
|
||||
//
|
||||
// Send data to SMM
|
||||
//
|
||||
Status = SendCommunicateBuffer (PayloadSize);
|
||||
|
||||
//
|
||||
// Get data from SMM.
|
||||
//
|
||||
*VariableNameSize = SmmGetNextVariableName->NameSize;
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
CopyGuid (VendorGuid, &SmmGetNextVariableName->Guid);
|
||||
CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
This code sets variable in storage blocks (Volatile or Non-Volatile).
|
||||
|
||||
@param[in] VariableName Name of Variable to be found.
|
||||
@param[in] VendorGuid Variable vendor GUID.
|
||||
@param[in] Attributes Attribute value of the variable found
|
||||
@param[in] DataSize Size of Data found. If size is less than the
|
||||
data, this value contains the required size.
|
||||
@param[in] Data Data pointer.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||
@retval EFI_SUCCESS Set successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.
|
||||
@retval EFI_NOT_FOUND Not found.
|
||||
@retval EFI_WRITE_PROTECTED Variable is read-only.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
RuntimeServiceSetVariable (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
IN UINT32 Attributes,
|
||||
IN UINTN DataSize,
|
||||
IN VOID *Data
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN PayloadSize;
|
||||
SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;
|
||||
|
||||
//
|
||||
// Check input parameters.
|
||||
//
|
||||
if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (DataSize != 0 && Data == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Init the communicate buffer. The buffer data size is:
|
||||
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
|
||||
//
|
||||
PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName) + DataSize;
|
||||
Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_SET_VARIABLE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
ASSERT (SmmVariableHeader != NULL);
|
||||
|
||||
CopyGuid ((EFI_GUID *) &SmmVariableHeader->Guid, VendorGuid);
|
||||
SmmVariableHeader->DataSize = DataSize;
|
||||
SmmVariableHeader->NameSize = StrSize (VariableName);
|
||||
SmmVariableHeader->Attributes = Attributes;
|
||||
CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);
|
||||
CopyMem ((UINT8 *) SmmVariableHeader->Name + SmmVariableHeader->NameSize, Data, DataSize);
|
||||
|
||||
//
|
||||
// Send data to SMM.
|
||||
//
|
||||
Status = SendCommunicateBuffer (PayloadSize);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This code returns information about the EFI variables.
|
||||
|
||||
@param[in] Attributes Attributes bitmask to specify the type of variables
|
||||
on which to return information.
|
||||
@param[out] MaximumVariableStorageSize Pointer to the maximum size of the storage space available
|
||||
for the EFI variables associated with the attributes specified.
|
||||
@param[out] RemainingVariableStorageSize Pointer to the remaining size of the storage space available
|
||||
for EFI variables associated with the attributes specified.
|
||||
@param[out] MaximumVariableSize Pointer to the maximum size of an individual EFI variables
|
||||
associated with the attributes specified.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.
|
||||
@retval EFI_SUCCESS Query successfully.
|
||||
@retval EFI_UNSUPPORTED The attribute is not supported on this platform.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
RuntimeServiceQueryVariableInfo (
|
||||
IN UINT32 Attributes,
|
||||
OUT UINT64 *MaximumVariableStorageSize,
|
||||
OUT UINT64 *RemainingVariableStorageSize,
|
||||
OUT UINT64 *MaximumVariableSize
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN PayloadSize;
|
||||
SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *SmmQueryVariableInfo;
|
||||
|
||||
if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Init the communicate buffer. The buffer data size is:
|
||||
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize;
|
||||
//
|
||||
PayloadSize = sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO);
|
||||
Status = InitCommunicateBuffer ((VOID **)&SmmQueryVariableInfo, PayloadSize, SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
ASSERT (SmmQueryVariableInfo != NULL);
|
||||
|
||||
SmmQueryVariableInfo->Attributes = Attributes;
|
||||
|
||||
//
|
||||
// Send data to SMM.
|
||||
//
|
||||
Status = SendCommunicateBuffer (PayloadSize);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Get data from SMM.
|
||||
//
|
||||
*MaximumVariableSize = SmmQueryVariableInfo->MaximumVariableSize;
|
||||
*MaximumVariableStorageSize = SmmQueryVariableInfo->MaximumVariableStorageSize;
|
||||
*RemainingVariableStorageSize = SmmQueryVariableInfo->RemainingVariableStorageSize;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Exit Boot Services Event notification handler.
|
||||
|
||||
Notify SMM variable driver about the event.
|
||||
|
||||
@param[in] Event Event whose notification function is being invoked.
|
||||
@param[in] Context Pointer to the notification function's context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
OnExitBootServices (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
//
|
||||
// Init the communicate buffer. The buffer data size is:
|
||||
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
|
||||
//
|
||||
InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE);
|
||||
|
||||
//
|
||||
// Send data to SMM.
|
||||
//
|
||||
SendCommunicateBuffer (0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
On Ready To Boot Services Event notification handler.
|
||||
|
||||
Notify SMM variable driver about the event.
|
||||
|
||||
@param[in] Event Event whose notification function is being invoked
|
||||
@param[in] Context Pointer to the notification function's context
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
OnReadyToBoot (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
//
|
||||
// Init the communicate buffer. The buffer data size is:
|
||||
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
|
||||
//
|
||||
InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_READY_TO_BOOT);
|
||||
|
||||
//
|
||||
// Send data to SMM.
|
||||
//
|
||||
SendCommunicateBuffer (0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
|
||||
|
||||
This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
|
||||
It convers pointer to new virtual address.
|
||||
|
||||
@param[in] Event Event whose notification function is being invoked.
|
||||
@param[in] Context Pointer to the notification function's context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
VariableAddressChangeEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EfiConvertPointer (0x0, (VOID **) &mVariableBuffer);
|
||||
EfiConvertPointer (0x0, (VOID **) &mSmmCommunication);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initialize variable service and install Variable Architectural protocol.
|
||||
|
||||
@param[in] Event Event whose notification function is being invoked.
|
||||
@param[in] Context Pointer to the notification function's context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmVariableReady (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **)&mSmmVariable);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &mSmmCommunication);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Allocate memory for variable store.
|
||||
//
|
||||
mVariableBufferSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
|
||||
mVariableBufferSize += MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));
|
||||
mVariableBuffer = AllocateRuntimePool (mVariableBufferSize);
|
||||
ASSERT (mVariableBuffer != NULL);
|
||||
|
||||
//
|
||||
// Save the buffer physical address used for SMM conmunication.
|
||||
//
|
||||
mVariableBufferPhysical = mVariableBuffer;
|
||||
|
||||
gRT->GetVariable = RuntimeServiceGetVariable;
|
||||
gRT->GetNextVariableName = RuntimeServiceGetNextVariableName;
|
||||
gRT->SetVariable = RuntimeServiceSetVariable;
|
||||
gRT->QueryVariableInfo = RuntimeServiceQueryVariableInfo;
|
||||
|
||||
//
|
||||
// Install the Variable Architectural Protocol on a new handle.
|
||||
//
|
||||
Status = gBS->InstallProtocolInterface (
|
||||
&mHandle,
|
||||
&gEfiVariableArchProtocolGuid,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
SMM Non-Volatile variable write service is ready notify event handler.
|
||||
|
||||
@param[in] Event Event whose notification function is being invoked.
|
||||
@param[in] Context Pointer to the notification function's context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmVariableWriteReady (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
VOID *ProtocolOps;
|
||||
|
||||
//
|
||||
// Check whether the protocol is installed or not.
|
||||
//
|
||||
Status = gBS->LocateProtocol (&gSmmVariableWriteGuid, NULL, (VOID **) &ProtocolOps);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Status = gBS->InstallProtocolInterface (
|
||||
&mHandle,
|
||||
&gEfiVariableWriteArchProtocolGuid,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Variable Driver main entry point. The Variable driver places the 4 EFI
|
||||
runtime services in the EFI System Table and installs arch protocols
|
||||
for variable read and write services being available. It also registers
|
||||
a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
|
||||
|
||||
@param[in] ImageHandle The firmware allocated handle for the EFI image.
|
||||
@param[in] SystemTable A pointer to the EFI System Table.
|
||||
|
||||
@retval EFI_SUCCESS Variable service successfully initialized.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
VariableSmmRuntimeInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
VOID *SmmVariableRegistration;
|
||||
VOID *SmmVariableWriteRegistration;
|
||||
EFI_EVENT OnReadyToBootEvent;
|
||||
EFI_EVENT ExitBootServiceEvent;
|
||||
|
||||
//
|
||||
// Smm variable service is ready
|
||||
//
|
||||
EfiCreateProtocolNotifyEvent (
|
||||
&gEfiSmmVariableProtocolGuid,
|
||||
TPL_CALLBACK,
|
||||
SmmVariableReady,
|
||||
NULL,
|
||||
&SmmVariableRegistration
|
||||
);
|
||||
|
||||
//
|
||||
// Smm Non-Volatile variable write service is ready
|
||||
//
|
||||
EfiCreateProtocolNotifyEvent (
|
||||
&gSmmVariableWriteGuid,
|
||||
TPL_CALLBACK,
|
||||
SmmVariableWriteReady,
|
||||
NULL,
|
||||
&SmmVariableWriteRegistration
|
||||
);
|
||||
|
||||
//
|
||||
// Register the event to reclaim variable for OS usage.
|
||||
//
|
||||
EfiCreateEventReadyToBootEx (
|
||||
TPL_NOTIFY,
|
||||
OnReadyToBoot,
|
||||
NULL,
|
||||
&OnReadyToBootEvent
|
||||
);
|
||||
|
||||
//
|
||||
// Register the event to inform SMM variable that it is at runtime.
|
||||
//
|
||||
gBS->CreateEventEx (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_NOTIFY,
|
||||
OnExitBootServices,
|
||||
NULL,
|
||||
&gEfiEventExitBootServicesGuid,
|
||||
&ExitBootServiceEvent
|
||||
);
|
||||
|
||||
//
|
||||
// Register the event to convert the pointer for runtime.
|
||||
//
|
||||
gBS->CreateEventEx (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_NOTIFY,
|
||||
VariableAddressChangeEvent,
|
||||
NULL,
|
||||
&gEfiEventVirtualAddressChangeGuid,
|
||||
&mVirtualAddressChangeEvent
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@@ -0,0 +1,68 @@
|
||||
## @file
|
||||
# Component description file for Authenticated Variable SmmRuntimeDxe module.
|
||||
#
|
||||
# This module is the Runtime DXE part correspond to SMM variable module. It
|
||||
# installs variable arch protocol and variable write arch protocol and works
|
||||
# with SMM variable module together.
|
||||
#
|
||||
# Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
# 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.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = VariableSmmRuntimeDxe
|
||||
FILE_GUID = 067E2381-7234-4798-B49C-D5FECBFF6D07
|
||||
MODULE_TYPE = DXE_RUNTIME_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = VariableSmmRuntimeInitialize
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
# VIRTUAL_ADDRESS_MAP_CALLBACK = VariableAddressChangeEvent
|
||||
#
|
||||
|
||||
[Sources]
|
||||
VariableSmmRuntimeDxe.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
SecurityPkg/SecurityPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
MemoryAllocationLib
|
||||
BaseLib
|
||||
UefiBootServicesTableLib
|
||||
DebugLib
|
||||
UefiRuntimeLib
|
||||
DxeServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
PcdLib
|
||||
|
||||
[Protocols]
|
||||
gEfiVariableWriteArchProtocolGuid ## ALWAYS_PRODUCES
|
||||
gEfiVariableArchProtocolGuid ## ALWAYS_PRODUCES
|
||||
gEfiSmmCommunicationProtocolGuid
|
||||
gEfiSmmVariableProtocolGuid
|
||||
|
||||
[Guids]
|
||||
gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event
|
||||
gSmmVariableWriteGuid
|
||||
|
||||
[Pcd]
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
|
||||
|
||||
[Depex]
|
||||
gEfiSmmCommunicationProtocolGuid
|
Reference in New Issue
Block a user