1190 lines
40 KiB
C
1190 lines
40 KiB
C
/** @file
|
|
Implement ReadOnly Variable Services required by PEIM and install
|
|
PEI ReadOnly Varaiable2 PPI. These services operates the non volatile storage space.
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2012 - 2021, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
|
|
/**
|
|
|
|
|
|
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
|
|
#include "Variable.h"
|
|
#include <Library/FlashRegionLib.h>
|
|
#include <Ppi/MemoryDiscovered.h>
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
MemoryDiscoveredNotifyVariableCallback (
|
|
IN EFI_PEI_SERVICES **PeiServices,
|
|
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
|
|
IN VOID *Ppi
|
|
);
|
|
|
|
//
|
|
// Module globals
|
|
//
|
|
EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariable2Ppi = {
|
|
PeiGetVariable,
|
|
PeiGetNextVariableName
|
|
};
|
|
|
|
EFI_PEI_PPI_DESCRIPTOR mPpiListVariable2 = {
|
|
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
|
|
&gEfiPeiReadOnlyVariable2PpiGuid,
|
|
&mVariable2Ppi
|
|
};
|
|
|
|
static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {
|
|
{
|
|
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
|
|
&gEfiPeiMemoryDiscoveredPpiGuid,
|
|
MemoryDiscoveredNotifyVariableCallback
|
|
}
|
|
};
|
|
|
|
STATIC EFI_GUID mVariableDefaultId = FDM_VARIABLE_DEFAULT_ID_VARIABLE_DEFAULT;
|
|
|
|
/**
|
|
This function verifies variable default region if permanent memory is ready.
|
|
|
|
@param PeiServices Indirect reference to the PEI Services Table.
|
|
@param NotifyDescriptor Address of the notification descriptor data structure.
|
|
@param Ppi Address of the PPI that was installed.
|
|
|
|
@return EFI_SUCCESS Verify variable default region successfully.
|
|
@return Others Some error occurs during verifing variable default region.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
MemoryDiscoveredNotifyVariableCallback (
|
|
IN EFI_PEI_SERVICES **PeiServices,
|
|
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
|
|
IN VOID *Ppi
|
|
)
|
|
{
|
|
if (!FeaturePcdGet (PcdH2OFdmChainOfTrustSupported) || IsFirmwareFailureRecovery()) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
return FdmVerifyById (&gH2OFlashMapRegionVarDefaultGuid, &mVariableDefaultId, 1);
|
|
}
|
|
|
|
/**
|
|
Determine need force variable defaults or not.
|
|
|
|
@retval TRUE System need force variable defaults.
|
|
@retval FALSE System need not force variable defaults.
|
|
**/
|
|
STATIC
|
|
BOOLEAN
|
|
ForceVariableDefaults (
|
|
VOID
|
|
)
|
|
{
|
|
H2O_PEI_CP_FORCE_VARIABLE_DEFAULTS_DATA ForceVariableDefaultsData;
|
|
EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
|
|
VARIABLE_STORE_HEADER *VariableStoreHeader;
|
|
|
|
if (!FeaturePcdGet (PcdH2OPeiCpForceVariableDefaultsSupported)) {
|
|
return FALSE;
|
|
}
|
|
|
|
FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FdmGetNAtAddr (&gH2OFlashMapRegionVarGuid, 1);
|
|
if (FvHeader == NULL) {
|
|
return FALSE;
|
|
}
|
|
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINT8 *) FvHeader + FvHeader->HeaderLength);
|
|
ForceVariableDefaultsData.Size = sizeof (H2O_PEI_CP_FORCE_VARIABLE_DEFAULTS_DATA);
|
|
ForceVariableDefaultsData.Status = H2O_CP_TASK_NORMAL;
|
|
ForceVariableDefaultsData.VariableStoreHdr = VariableStoreHeader;
|
|
ForceVariableDefaultsData.ForceVariableDefaults = FALSE;
|
|
DEBUG_CP ((DEBUG_INFO, "Checkpoint Trigger: %g\n", &gH2OPeiCpForceVariableDefaultsGuid));
|
|
H2OCpTrigger (&gH2OPeiCpForceVariableDefaultsGuid, &ForceVariableDefaultsData);
|
|
DEBUG_CP ((DEBUG_INFO, "Checkpoint Result: %x\n", ForceVariableDefaultsData.Status));
|
|
if (ForceVariableDefaultsData.Status == H2O_CP_TASK_UPDATE && ForceVariableDefaultsData.ForceVariableDefaults) {
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
/**
|
|
Provide the functionality of the variable services.
|
|
NOTE: If verification fails, this function will hang.
|
|
|
|
@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() and FdmVerifyById()
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PeimInitializeVariableServices (
|
|
IN EFI_PEI_FILE_HANDLE FileHandle,
|
|
IN CONST EFI_PEI_SERVICES **PeiServices
|
|
)
|
|
{
|
|
BOOLEAN ForceDefaults;
|
|
EFI_STATUS Status;
|
|
|
|
Status = (**PeiServices).NotifyPpi (PeiServices, &mNotifyList[0]);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (ForceVariableDefaults ()) {
|
|
ForceDefaults = TRUE;
|
|
BuildGuidDataHob (&gH2OFlashMapRegionVarGuid, &ForceDefaults, sizeof (BOOLEAN));
|
|
}
|
|
return PeiServicesInstallPpi (&mPpiListVariable2);
|
|
}
|
|
|
|
/**
|
|
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 *) GET_VARIABLE_NAME_PTR (Variable);
|
|
if (CompareMem (VariableName, Point, NameSizeOfVariable (Variable)) == 0) {
|
|
PtrTrack->CurrPtr = Variable;
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
Get HOB variable store.
|
|
|
|
@param[out] VariableStoreHeader Return variable store header.
|
|
|
|
**/
|
|
VOID
|
|
GetHobVariableStore (
|
|
OUT VARIABLE_STORE_HEADER **VariableStoreHeader
|
|
)
|
|
{
|
|
EFI_HOB_GUID_TYPE *GuidHob;
|
|
|
|
//
|
|
// Make sure there is no more than one Variable HOB.
|
|
//
|
|
DEBUG_CODE (
|
|
GuidHob = GetFirstGuidHob (&gEfiAuthenticatedVariableGuid);
|
|
if (GuidHob != NULL) {
|
|
if ((GetNextGuidHob (&gEfiAuthenticatedVariableGuid, GET_NEXT_HOB (GuidHob)) != NULL)) {
|
|
DEBUG ((DEBUG_ERROR, "ERROR: Found two Auth Variable HOBs\n"));
|
|
ASSERT (FALSE);
|
|
}
|
|
}
|
|
);
|
|
|
|
GuidHob = GetFirstGuidHob (&gEfiAuthenticatedVariableGuid);
|
|
if (GuidHob != NULL) {
|
|
*VariableStoreHeader = (VARIABLE_STORE_HEADER *) GET_GUID_HOB_DATA (GuidHob);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
Return the variable store header and the index table based on the Index.
|
|
|
|
@param Type The type of the variable store.
|
|
@param IndexTable Return the index table.
|
|
|
|
@return Pointer to the variable store header.
|
|
**/
|
|
VARIABLE_STORE_HEADER *
|
|
GetVariableStore (
|
|
IN VARIABLE_STORE_TYPE Type,
|
|
OUT VARIABLE_INDEX_TABLE_EX **IndexTable OPTIONAL
|
|
)
|
|
{
|
|
EFI_HOB_GUID_TYPE *GuidHob;
|
|
EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
|
|
VARIABLE_STORE_HEADER *VariableStoreHeader;
|
|
|
|
if (IndexTable != NULL) {
|
|
*IndexTable = NULL;
|
|
}
|
|
VariableStoreHeader = NULL;
|
|
switch (Type) {
|
|
case VariableStoreTypeHob:
|
|
GetHobVariableStore (&VariableStoreHeader);
|
|
break;
|
|
|
|
case VariableStoreTypeNv:
|
|
if (GetBootModeHob () != BOOT_IN_RECOVERY_MODE) {
|
|
//
|
|
// The content of NV storage for variable is not reliable in recovery boot mode.
|
|
//
|
|
FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FdmGetNAtAddr (&gH2OFlashMapRegionVarGuid, 1);
|
|
if (FvHeader == NULL) {
|
|
return NULL;
|
|
}
|
|
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINT8 *) FvHeader + FvHeader->HeaderLength);
|
|
|
|
if (IndexTable != NULL) {
|
|
GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);
|
|
if (GuidHob != NULL) {
|
|
*IndexTable = GET_GUID_HOB_DATA (GuidHob);
|
|
} else {
|
|
//
|
|
// 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 limited number of
|
|
// VAR_ADDED type variables to reduce access time.
|
|
//
|
|
*IndexTable = BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE_EX));
|
|
if (*IndexTable != NULL) {
|
|
(*IndexTable)->Length = 0;
|
|
(*IndexTable)->StartPtr = GetStartPointer (VariableStoreHeader);
|
|
(*IndexTable)->EndPtr = GetEndPointer (VariableStoreHeader);
|
|
(*IndexTable)->GoneThrough = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ASSERT (FALSE);
|
|
break;
|
|
}
|
|
|
|
return VariableStoreHeader;
|
|
}
|
|
|
|
/**
|
|
This code gets the size of variable store.
|
|
|
|
@param VarStoreHeader Pointer to the Variable Store Header.
|
|
|
|
@return Total size of variable store
|
|
|
|
|
|
**/
|
|
UINT32
|
|
GetVariableSize (
|
|
IN VARIABLE_STORE_HEADER *VariableStoreHeader
|
|
)
|
|
{
|
|
ECP_VARIABLE_STORE_HEADER *EcpVariableStoreHeader;
|
|
|
|
if (PcdGetBool (PcdUseEcpVariableStoreHeader)) {
|
|
EcpVariableStoreHeader = (ECP_VARIABLE_STORE_HEADER *) VariableStoreHeader;
|
|
return EcpVariableStoreHeader->Size;
|
|
} else {
|
|
return VariableStoreHeader->Size;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Get the specific config data from MultiConfig region.
|
|
|
|
@param RequireKind Find Setup Setting for SETUP_FOR_BIOS_POST or SETUP_FOR_LOAD_DEFAULT.
|
|
@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 Config data found successfully
|
|
@retval EFI_NOT_FOUND Config data not found
|
|
@retval EFI_INVALID_PARAMETER Data is NULL
|
|
@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.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
GetConfigData (
|
|
IN CONST UINT8 RequireKind,
|
|
IN CONST CHAR16 *VariableName,
|
|
IN CONST EFI_GUID *VariableGuid,
|
|
OUT UINT32 *Attributes,
|
|
IN OUT UINTN *DataSize,
|
|
OUT VOID *Data
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT16 ConfigCount;
|
|
UINT16 Index;
|
|
VOID *NamePtr;
|
|
VOID *DataPtr;
|
|
UINTN VarDataSize;
|
|
|
|
Status = EFI_NOT_FOUND;
|
|
Index = 0;
|
|
DataPtr = NULL;
|
|
ConfigCount = GetConfigCount();
|
|
|
|
for ( ; Index < ConfigCount; Index ++) {
|
|
//
|
|
// Get Active (Attribute: ACTIVE & BIOS_POST) Full Setup Setting from Multi Config Region
|
|
//
|
|
Status = GetFullSetupSetting (
|
|
RequireKind,
|
|
&Index,
|
|
*DataSize,
|
|
&DataPtr,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if (!EFI_ERROR (Status) && DataPtr != NULL) {
|
|
NamePtr = (VOID *) GET_VARIABLE_NAME_PTR (DataPtr);
|
|
if (CompareMem (VariableName, NamePtr, NameSizeOfVariable (DataPtr)) == 0) {
|
|
//
|
|
// Get data size
|
|
//
|
|
VarDataSize = DataSizeOfVariable (DataPtr);
|
|
if (*DataSize >= VarDataSize) {
|
|
if (Data == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
CopyMem (Data, GetVariableDataPtr (DataPtr), VarDataSize);
|
|
|
|
if (Attributes != NULL) {
|
|
*Attributes = ((VARIABLE_HEADER *)DataPtr)->Attributes;
|
|
}
|
|
|
|
*DataSize = VarDataSize;
|
|
return EFI_SUCCESS;
|
|
} else {
|
|
*DataSize = VarDataSize;
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
Find the variable in the specified variable store.
|
|
|
|
@param VariableStoreHeader Pointer to the variable store header.
|
|
@param IndexTable Pointer to the index table.
|
|
@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
|
|
FindVariableEx (
|
|
IN VARIABLE_STORE_HEADER *VariableStoreHeader,
|
|
IN VARIABLE_INDEX_TABLE_EX *IndexTable,
|
|
IN CONST CHAR16 *VariableName,
|
|
IN CONST EFI_GUID *VendorGuid,
|
|
OUT VARIABLE_POINTER_TRACK *PtrTrack
|
|
)
|
|
{
|
|
VARIABLE_HEADER *Variable;
|
|
VARIABLE_HEADER *LastVariable;
|
|
VARIABLE_HEADER *MaxIndex;
|
|
UINTN Index;
|
|
UINTN Offset;
|
|
BOOLEAN StopRecord;
|
|
VARIABLE_HEADER *InDeletedVariable;
|
|
|
|
if (VariableStoreHeader == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
if (~GetVariableSize (VariableStoreHeader) == 0) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader);
|
|
PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader);
|
|
|
|
InDeletedVariable = NULL;
|
|
|
|
//
|
|
// No Variable Address equals zero, so 0 as initial value is safe.
|
|
//
|
|
MaxIndex = NULL;
|
|
|
|
if (IndexTable != NULL) {
|
|
//
|
|
// traverse the variable index table to look for variable.
|
|
// The IndexTable->Index[Index] records the distance of two neighbouring VAR_ADDED type variables.
|
|
//
|
|
for (Offset = 0, Index = 0; Index < IndexTable->Length; Index++) {
|
|
ASSERT (Index < sizeof (IndexTable->Index) / sizeof (IndexTable->Index[0]));
|
|
Offset += IndexTable->Index[Index];
|
|
MaxIndex = (VARIABLE_HEADER *) ((UINT8 *) IndexTable->StartPtr + Offset);
|
|
if (CompareWithValidVariable (MaxIndex, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
|
|
if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
|
|
InDeletedVariable = PtrTrack->CurrPtr;
|
|
} else {
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (IndexTable->GoneThrough != 0) {
|
|
//
|
|
// If the table has all the existing variables indexed, return.
|
|
//
|
|
PtrTrack->CurrPtr = InDeletedVariable;
|
|
return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
if (MaxIndex != NULL) {
|
|
//
|
|
// HOB exists but the variable cannot be found in HOB
|
|
// If not found in HOB, then let's start from the MaxIndex we've found.
|
|
//
|
|
Variable = GetNextVariablePtr (MaxIndex);
|
|
LastVariable = MaxIndex;
|
|
} else {
|
|
//
|
|
// Start Pointers for the variable.
|
|
// Actual Data Pointer where data can be written.
|
|
//
|
|
Variable = PtrTrack->StartPtr;
|
|
LastVariable = PtrTrack->StartPtr;
|
|
}
|
|
|
|
//
|
|
// Find the variable by walk through variable store
|
|
//
|
|
StopRecord = FALSE;
|
|
while ((GetNextVariablePtr (Variable) <= PtrTrack->EndPtr) && IsValidVariableHeader (Variable)) {
|
|
if (Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
|
|
//
|
|
// Record Variable in VariableIndex HOB
|
|
//
|
|
if ((IndexTable != NULL) && !StopRecord) {
|
|
Offset = (UINTN) Variable - (UINTN) LastVariable;
|
|
if (IndexTable->Length >= sizeof (IndexTable->Index) / sizeof (IndexTable->Index[0])) {
|
|
//
|
|
// Stop to record if the record buffer is full.
|
|
//
|
|
StopRecord = TRUE;
|
|
} else {
|
|
IndexTable->Index[IndexTable->Length++] = (UINT32) Offset;
|
|
LastVariable = Variable;
|
|
}
|
|
}
|
|
|
|
if (CompareWithValidVariable (Variable, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
|
|
if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
|
|
InDeletedVariable = PtrTrack->CurrPtr;
|
|
} else {
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
|
|
Variable = GetNextVariablePtr (Variable);
|
|
}
|
|
//
|
|
// If gone through the VariableStore, that means we never find in Firmware any more.
|
|
//
|
|
if ((IndexTable != NULL) && !StopRecord) {
|
|
IndexTable->GoneThrough = 1;
|
|
}
|
|
|
|
PtrTrack->CurrPtr = InDeletedVariable;
|
|
|
|
return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Find the variable in HOB and Non-Volatile variable storages.
|
|
|
|
@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 CHAR16 *VariableName,
|
|
IN CONST EFI_GUID *VendorGuid,
|
|
OUT VARIABLE_POINTER_TRACK *PtrTrack
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
VARIABLE_STORE_HEADER *VariableStoreHeader;
|
|
VARIABLE_INDEX_TABLE_EX *IndexTable;
|
|
VARIABLE_STORE_TYPE Type;
|
|
EFI_HOB_GUID_TYPE *GuidHob;
|
|
BOOLEAN ForceDefaults;
|
|
|
|
|
|
if (VariableName[0] != 0 && VendorGuid == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
ForceDefaults = FALSE;
|
|
GuidHob = GetFirstGuidHob (&gH2OFlashMapRegionVarGuid);
|
|
if (GuidHob != NULL) {
|
|
ForceDefaults = TRUE;
|
|
}
|
|
|
|
for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
|
|
VariableStoreHeader = GetVariableStore (Type, &IndexTable);
|
|
if (Type == VariableStoreTypeNv && ForceDefaults) {
|
|
continue;
|
|
}
|
|
Status = FindVariableEx (
|
|
VariableStoreHeader,
|
|
IndexTable,
|
|
VariableName,
|
|
VendorGuid,
|
|
PtrTrack
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
Internal function to get the start address of variable default header according to
|
|
input SKU ID.
|
|
|
|
@param[in] SkuId Input SKU ID.
|
|
|
|
@return The address of variable store header or NULL if not found.
|
|
**/
|
|
STATIC
|
|
VOID *
|
|
GetVariableDefaultStoreHeaderBySkuId (
|
|
IN H2O_BOARD_ID SkuId
|
|
)
|
|
{
|
|
VARIABLE_STORE_HEADER *VariableStoreHeader;
|
|
ECP_VARIABLE_STORE_HEADER *EcpVariableStoreHeader;
|
|
UINTN VariableDefaultBase;
|
|
UINTN VariableDefaultSize;
|
|
EFI_GUID Id = FDM_VARIABLE_DEFAULT_ID_VARIABLE_DEFAULT;
|
|
|
|
|
|
VariableDefaultBase = (UINTN) FdmGetAddressById (&gH2OFlashMapRegionVarDefaultGuid, &Id, 1);
|
|
if (VariableDefaultBase == 0) {
|
|
return NULL;
|
|
}
|
|
|
|
VariableDefaultSize = (UINTN) FdmGetSizeById (&gH2OFlashMapRegionVarDefaultGuid, &Id, 1);
|
|
|
|
if (PcdGetBool (PcdUseEcpVariableStoreHeader)) {
|
|
for (EcpVariableStoreHeader = (ECP_VARIABLE_STORE_HEADER *) VariableDefaultBase;
|
|
EcpVariableStoreHeader != NULL &&
|
|
EcpVariableStoreHeader->Signature == ECP_VARIABLE_STORE_SIGNATURE &&
|
|
EcpVariableStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
|
|
EcpVariableStoreHeader->State == VARIABLE_STORE_HEALTHY &&
|
|
(EcpVariableStoreHeader->Flags & VARIABLE_STORE_ACTIVE_MASK) == VARIABLE_STORE_ACTIVE &&
|
|
EcpVariableStoreHeader->Size >= sizeof (ECP_VARIABLE_STORE_HEADER) &&
|
|
(UINTN) EcpVariableStoreHeader < VariableDefaultBase + VariableDefaultSize;
|
|
EcpVariableStoreHeader = (ECP_VARIABLE_STORE_HEADER *) ((UINT8 *) EcpVariableStoreHeader + EcpVariableStoreHeader->Size)) {
|
|
|
|
if (EcpVariableStoreHeader->DefaultId == 0 && SkuId == GetBoardIdFromVariableStore ((VARIABLE_STORE_HEADER*) EcpVariableStoreHeader)) {
|
|
return (VOID *) EcpVariableStoreHeader;
|
|
}
|
|
}
|
|
} else {
|
|
for (VariableStoreHeader = (VARIABLE_STORE_HEADER *) VariableDefaultBase;
|
|
VariableStoreHeader != NULL &&
|
|
(CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid) ||
|
|
CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid)) &&
|
|
VariableStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
|
|
VariableStoreHeader->State == VARIABLE_STORE_HEALTHY &&
|
|
(VariableStoreHeader->Flags & VARIABLE_STORE_ACTIVE_MASK) == VARIABLE_STORE_ACTIVE &&
|
|
VariableStoreHeader->Size >= sizeof (VARIABLE_STORE_HEADER) &&
|
|
(UINTN) VariableStoreHeader < VariableDefaultBase + VariableDefaultSize;
|
|
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINT8 *) VariableStoreHeader + VariableStoreHeader->Size)) {
|
|
if (VariableStoreHeader->DefaultId == 0 && SkuId == GetBoardIdFromVariableStore (VariableStoreHeader)) {
|
|
return (VOID *) VariableStoreHeader;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Get default SKU ID variable store header in variable default store.
|
|
|
|
@return The address of variable store header or NULL if not found.
|
|
**/
|
|
STATIC
|
|
VOID *
|
|
GetDefaultVariableDefaultStoreHeader (
|
|
VOID
|
|
)
|
|
{
|
|
return GetVariableDefaultStoreHeaderBySkuId (0);
|
|
}
|
|
|
|
/**
|
|
According to current SKU ID to get variable store header in variable default store.
|
|
|
|
@return The address of variable store header or NULL if not found.
|
|
**/
|
|
STATIC
|
|
VOID *
|
|
GetCurrentVariableDefaultStoreHeader (
|
|
VOID
|
|
)
|
|
{
|
|
//
|
|
// BUG! BUG!
|
|
// Sku value may be changed after PcdSkuInit () is invoked in PlatformStage1Pei entrypoint.
|
|
// Different SKU value may cause the variable data is different.
|
|
//
|
|
//
|
|
return GetVariableDefaultStoreHeaderBySkuId ((H2O_BOARD_ID) LibPcdGetSku ());
|
|
}
|
|
|
|
/**
|
|
Internal function to check whether the variable is stored in variable store.
|
|
|
|
@param[in] VariableName Name of the variable to be found
|
|
@param[in] VendorGuid Vendor GUID to be found.
|
|
|
|
@retval TRUE Can find variable in variable store.
|
|
@retval FALSE Cannot find variable in variable store.
|
|
**/
|
|
STATIC
|
|
BOOLEAN
|
|
VariableInVariableStore (
|
|
IN CONST CHAR16 *VariableName,
|
|
IN CONST EFI_GUID *VendorGuid
|
|
)
|
|
{
|
|
VARIABLE_POINTER_TRACK Variable;
|
|
EFI_STATUS Status;
|
|
|
|
Status = FindVariable (VariableName, VendorGuid, &Variable);
|
|
return Status == EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Get variable from specific variable store region.
|
|
|
|
@param[in] VariableName Name of the variable to be found
|
|
@param[in] VendorGuid Vendor GUID to be found.
|
|
@param[in] VariableStoreHeader Pointer to the start address of variable store header.
|
|
@param[out] PtrTrack Variable Track Pointer structure that contains Variable Information.
|
|
|
|
@return The address of variable store header or NULL if not found.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
GetVariableFromSpecificDefaultRegion (
|
|
IN CONST CHAR16 *VariableName,
|
|
IN CONST EFI_GUID *VendorGuid,
|
|
IN CONST VOID *VariableStoreHeader,
|
|
OUT VARIABLE_POINTER_TRACK *PtrTrack
|
|
)
|
|
{
|
|
VARIABLE_HEADER *Variable;
|
|
|
|
PtrTrack->StartPtr = (VARIABLE_HEADER *) ((UINT8 *) VariableStoreHeader + GetVariableStoreHeaderSize ());
|
|
PtrTrack->EndPtr = (VARIABLE_HEADER *) ((UINT8 *) VariableStoreHeader + GetVariableStoreSize (VariableStoreHeader));
|
|
Variable = PtrTrack->StartPtr;
|
|
while ((GetNextVariablePtr (Variable) <= PtrTrack->EndPtr) && IsValidVariableHeader (Variable)) {
|
|
if ((CompareGuid (VendorGuid, &Variable->VendorGuid) &&
|
|
!StrCmp (VariableName, GET_VARIABLE_NAME_PTR (Variable))) ||
|
|
VariableName [0] == 0) {
|
|
if (Variable->State == VAR_ADDED && !VariableInVariableStore (GET_VARIABLE_NAME_PTR (Variable), &Variable->VendorGuid)) {
|
|
PtrTrack->CurrPtr = Variable;
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
Variable = GetNextVariablePtr (Variable);
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
Get variable from variable default store.
|
|
|
|
@param[in] VariableName Name of the variable to be found
|
|
@param[in] VendorGuid Vendor GUID to be found.
|
|
@param[out] PtrTrack Variable Track Pointer structure that contains Variable Information.
|
|
|
|
@retval EFI_SUCCESS Find variable in variable default store successfully.
|
|
@retval EFI_NOT_FOUND Cannot find variable in variable default store.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
GetVariableFromVariableDefault (
|
|
IN CONST CHAR16 *VariableName,
|
|
IN CONST EFI_GUID *VendorGuid,
|
|
OUT VARIABLE_POINTER_TRACK *PtrTrack
|
|
)
|
|
{
|
|
VOID *VariableStoreHeader;
|
|
VOID *DefaultVariableStoreHeader;
|
|
EFI_STATUS Status;
|
|
|
|
|
|
PtrTrack->CurrPtr = NULL;
|
|
VariableStoreHeader = GetCurrentVariableDefaultStoreHeader ();
|
|
if (VariableStoreHeader != NULL) {
|
|
Status = GetVariableFromSpecificDefaultRegion (VariableName, VendorGuid, VariableStoreHeader, PtrTrack);
|
|
if (Status == EFI_SUCCESS) {
|
|
return Status;
|
|
}
|
|
}
|
|
DefaultVariableStoreHeader = GetDefaultVariableDefaultStoreHeader ();
|
|
if (DefaultVariableStoreHeader != NULL && DefaultVariableStoreHeader != VariableStoreHeader) {
|
|
Status = GetVariableFromSpecificDefaultRegion (VariableName, VendorGuid, DefaultVariableStoreHeader, PtrTrack);
|
|
if (Status == EFI_SUCCESS) {
|
|
return Status;
|
|
}
|
|
}
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
This code Finds the Next available variable in variable default region.
|
|
|
|
@param[in, out] VariableNameSize Size of the variable.
|
|
@param[in, out] VariableName Pointer to variable name.
|
|
@param[in, out] VendorGuid Variable Vendor Guid.
|
|
|
|
@retval EFI_SUCCESS Get variable successfully.
|
|
@retval EFI_NOT_FOUND Not found.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
GetNextDefaultVariableName (
|
|
IN OUT UINTN *VariableNameSize,
|
|
IN OUT CHAR16 *VariableName,
|
|
IN OUT EFI_GUID *VendorGuid
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
VARIABLE_POINTER_TRACK VariableTrack;
|
|
UINTN VarNameSize;
|
|
VARIABLE_HEADER *Variable;
|
|
|
|
Status = GetVariableFromVariableDefault (VariableName, VendorGuid, &VariableTrack);
|
|
if (Status != EFI_SUCCESS) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Only need try to find next variable if first character isn't 0.
|
|
// If first character is 0 and GetVariableFromVariableDefault () return EFI_SUCCESS,
|
|
// It means we already find first valid variable.
|
|
//
|
|
if (VariableName[0] != 0) {
|
|
|
|
VariableTrack.CurrPtr = GetNextVariablePtr (VariableTrack.CurrPtr);
|
|
if (VariableTrack.CurrPtr == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Variable = VariableTrack.CurrPtr;
|
|
VariableTrack.CurrPtr = NULL;
|
|
while ((GetNextVariablePtr (Variable) <= VariableTrack.EndPtr) && IsValidVariableHeader (Variable)) {
|
|
if (Variable->State == VAR_ADDED && !VariableInVariableStore (GET_VARIABLE_NAME_PTR (Variable), &Variable->VendorGuid)) {
|
|
VariableTrack.CurrPtr = Variable;
|
|
break;
|
|
}
|
|
Variable = GetNextVariablePtr (Variable);
|
|
}
|
|
|
|
if (VariableTrack.CurrPtr == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
VarNameSize = NameSizeOfVariable (VariableTrack.CurrPtr);
|
|
if (VarNameSize <= *VariableNameSize) {
|
|
CopyMem (VariableName, GET_VARIABLE_NAME_PTR (VariableTrack.CurrPtr), VarNameSize);
|
|
CopyMem (VendorGuid, &VariableTrack.CurrPtr->VendorGuid, sizeof (EFI_GUID));
|
|
Status = EFI_SUCCESS;
|
|
} else {
|
|
Status = EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
*VariableNameSize = VarNameSize;
|
|
return Status;
|
|
|
|
}
|
|
|
|
/**
|
|
This code Finds the first available variable in variable default region.
|
|
|
|
@param[in, out] VariableNameSize Size of the variable.
|
|
@param[in, out] VariableName Pointer to variable name.
|
|
@param[in, out] VendorGuid Variable Vendor Guid.
|
|
|
|
@retval EFI_SUCCESS Get variable successfully.
|
|
@retval EFI_NOT_FOUND Not found.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
GetFirstDefaultVariableName (
|
|
IN OUT UINTN *VariableNameSize,
|
|
IN OUT CHAR16 *VariableName,
|
|
IN OUT EFI_GUID *VendorGuid
|
|
)
|
|
{
|
|
|
|
CHAR16 SavedChar;
|
|
EFI_STATUS Status;
|
|
|
|
|
|
SavedChar = VariableName[0];
|
|
VariableName[0] = 0;
|
|
Status = GetNextDefaultVariableName (VariableNameSize, VariableName, VendorGuid);
|
|
if (EFI_ERROR (Status)) {
|
|
VariableName[0] = SavedChar;
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
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.
|
|
May be NULL with a zero DataSize in order to determine the size of the buffer needed.
|
|
|
|
@retval EFI_SUCCESS The variable was read successfully.
|
|
@retval EFI_NOT_FOUND The variable was not 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 OPTIONAL
|
|
)
|
|
{
|
|
VARIABLE_POINTER_TRACK Variable;
|
|
UINTN VarDataSize;
|
|
EFI_STATUS Status;
|
|
|
|
if (VariableName == NULL || VariableGuid == NULL || DataSize == NULL || VariableName[0] == 0) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Find existing variable
|
|
//
|
|
Status = FindVariable (VariableName, VariableGuid, &Variable);
|
|
|
|
if (Status == EFI_NOT_FOUND) {
|
|
Status = GetVariableFromVariableDefault (VariableName, VariableGuid, &Variable);
|
|
}
|
|
|
|
if (FeaturePcdGet (PcdMultiConfigSupported) && (Status == EFI_NOT_FOUND)) {
|
|
Status = GetConfigData (SETUP_FOR_BIOS_POST, VariableName, VariableGuid, Attributes, DataSize, Data);
|
|
if (Status == EFI_NOT_FOUND) {
|
|
Status = GetConfigData (SETUP_FOR_LOAD_DEFAULT, VariableName, VariableGuid, Attributes, DataSize, Data);
|
|
}
|
|
if (!EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
}
|
|
if (EFI_ERROR (Status)) {
|
|
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);
|
|
|
|
*DataSize = VarDataSize;
|
|
Status = EFI_SUCCESS;
|
|
} else {
|
|
*DataSize = VarDataSize;
|
|
Status = EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
if (Attributes != NULL) {
|
|
*Attributes = (Variable.CurrPtr->Attributes & ~(EFI_VARIABLE_DEFAULT_READY_ONLY | EFI_VARIABLE_INSYDE_AUTHENTICATED_WRITE_ACCESS));
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
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_STORE_TYPE Type;
|
|
VARIABLE_POINTER_TRACK Variable;
|
|
VARIABLE_POINTER_TRACK VariableInHob;
|
|
VARIABLE_POINTER_TRACK VariablePtrTrack;
|
|
VARIABLE_INDEX_TABLE_EX *IndexTable;
|
|
UINTN VarNameSize;
|
|
EFI_STATUS Status;
|
|
VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];
|
|
|
|
if (VariableName == NULL || VariableGuid == NULL || VariableNameSize == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (StrSize (VariableName) > *VariableNameSize) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = FindVariable (VariableName, VariableGuid, &Variable);
|
|
if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {
|
|
return GetNextDefaultVariableName (VariableNameSize, VariableName, VariableGuid);
|
|
}
|
|
|
|
if (VariableName[0] != 0) {
|
|
//
|
|
// If variable name is not NULL, get next variable
|
|
//
|
|
Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
|
|
}
|
|
|
|
VariableStoreHeader[VariableStoreTypeHob] = GetVariableStore (VariableStoreTypeHob, NULL);
|
|
VariableStoreHeader[VariableStoreTypeNv] = GetVariableStore (VariableStoreTypeNv, NULL);
|
|
|
|
while (TRUE) {
|
|
//
|
|
// Switch from HOB to Non-Volatile.
|
|
//
|
|
while ((Variable.CurrPtr >= Variable.EndPtr) ||
|
|
(Variable.CurrPtr == NULL) ||
|
|
!IsValidVariableHeader (Variable.CurrPtr)
|
|
) {
|
|
//
|
|
// Find current storage index
|
|
//
|
|
for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
|
|
if ((VariableStoreHeader[Type] != NULL) && (Variable.StartPtr == GetStartPointer (VariableStoreHeader[Type]))) {
|
|
break;
|
|
}
|
|
}
|
|
ASSERT (Type < VariableStoreTypeMax);
|
|
//
|
|
// Switch to next storage
|
|
//
|
|
for (Type++; Type < VariableStoreTypeMax; Type++) {
|
|
if (VariableStoreHeader[Type] != NULL) {
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// Capture the case that
|
|
// 1. current storage is the last one, or
|
|
// 2. no further storage
|
|
//
|
|
if (Type >= VariableStoreTypeMax) {
|
|
//
|
|
// Assume secure boot database default variable is at the end of whole data base,
|
|
// so start to get these variables after all variable.
|
|
//
|
|
return GetFirstDefaultVariableName (VariableNameSize, VariableName, VariableGuid);
|
|
}
|
|
Variable.StartPtr = GetStartPointer (VariableStoreHeader[Type]);
|
|
Variable.EndPtr = GetEndPointer (VariableStoreHeader[Type]);
|
|
Variable.CurrPtr = Variable.StartPtr;
|
|
}
|
|
|
|
if (Variable.CurrPtr->State == VAR_ADDED || Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
|
|
if (Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
|
|
//
|
|
// If it is a IN_DELETED_TRANSITION variable,
|
|
// and there is also a same ADDED one at the same time,
|
|
// don't return it.
|
|
//
|
|
for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
|
|
if ((VariableStoreHeader[Type] != NULL) && (Variable.StartPtr == GetStartPointer (VariableStoreHeader[Type]))) {
|
|
break;
|
|
}
|
|
}
|
|
ASSERT (Type < VariableStoreTypeMax);
|
|
if (Type == VariableStoreTypeMax) {
|
|
//
|
|
// Assume secure boot database default variable is at the end of whole data base,
|
|
// so start to get these variables after all variable.
|
|
//
|
|
return GetFirstDefaultVariableName (VariableNameSize, VariableName, VariableGuid);
|
|
}
|
|
GetVariableStore (Type, &IndexTable);
|
|
Status = FindVariableEx (
|
|
VariableStoreHeader[Type],
|
|
IndexTable,
|
|
GET_VARIABLE_NAME_PTR (Variable.CurrPtr),
|
|
&Variable.CurrPtr->VendorGuid,
|
|
&VariablePtrTrack
|
|
);
|
|
if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State == VAR_ADDED) {
|
|
Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Don't return NV variable when HOB overrides it
|
|
//
|
|
if ((VariableStoreHeader[VariableStoreTypeHob] != NULL) && (VariableStoreHeader[VariableStoreTypeNv] != NULL) &&
|
|
(Variable.StartPtr == GetStartPointer (VariableStoreHeader[VariableStoreTypeNv]))
|
|
) {
|
|
Status = FindVariableEx (
|
|
VariableStoreHeader[VariableStoreTypeHob],
|
|
NULL,
|
|
GET_VARIABLE_NAME_PTR (Variable.CurrPtr),
|
|
&Variable.CurrPtr->VendorGuid,
|
|
&VariableInHob
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
VarNameSize = NameSizeOfVariable (Variable.CurrPtr);
|
|
ASSERT (VarNameSize != 0);
|
|
|
|
if (VarNameSize <= *VariableNameSize) {
|
|
CopyMem (VariableName, GET_VARIABLE_NAME_PTR (Variable.CurrPtr), VarNameSize);
|
|
|
|
CopyMem (VariableGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));
|
|
|
|
Status = EFI_SUCCESS;
|
|
} else {
|
|
Status = EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
*VariableNameSize = VarNameSize;
|
|
//
|
|
// Variable is found
|
|
//
|
|
return Status;
|
|
} else {
|
|
Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
|
|
}
|
|
}
|
|
}
|