summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/Variable
diff options
context:
space:
mode:
authorniruiyu <niruiyu@6f19259b-4bc3-4df7-8a09-765794883524>2011-10-14 05:19:39 +0000
committerniruiyu <niruiyu@6f19259b-4bc3-4df7-8a09-765794883524>2011-10-14 05:19:39 +0000
commit0f7aff7249ac162915c6869f30e50a9d6b33b61c (patch)
tree4040c2fdb07c9a1507e38719b24f4d627c852f31 /MdeModulePkg/Universal/Variable
parent3b4151bcb43ec74e0a350c7b93f75531cc8df003 (diff)
Change Variable driver (Pei/RuntimeDxe) to support the default variable data stored in HOB.
Signed-off-by: niruiyu Reviewed-by: erictian git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12538 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Universal/Variable')
-rw-r--r--MdeModulePkg/Universal/Variable/Pei/Variable.c418
-rw-r--r--MdeModulePkg/Universal/Variable/Pei/Variable.h7
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c295
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h9
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf1
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf3
6 files changed, 463 insertions, 270 deletions
diff --git a/MdeModulePkg/Universal/Variable/Pei/Variable.c b/MdeModulePkg/Universal/Variable/Pei/Variable.c
index a20600b8b..c03d2b5df 100644
--- a/MdeModulePkg/Universal/Variable/Pei/Variable.c
+++ b/MdeModulePkg/Universal/Variable/Pei/Variable.c
@@ -34,32 +34,6 @@ EFI_PEI_PPI_DESCRIPTOR mPpiListVariable = {
/**
- Check if it runs in Recovery mode.
-
- @param PeiServices General purpose services available to every PEIM.
-
- @retval TRUE It's in Recovery mode.
- @retval FALSE It's not in Recovery mode.
-
-**/
-BOOLEAN
-IsInRecoveryMode (
- IN CONST EFI_PEI_SERVICES **PeiServices
- )
-{
- EFI_STATUS Status;
- EFI_BOOT_MODE BootMode;
-
- Status = (*PeiServices)->GetBootMode (PeiServices, &BootMode);
- ASSERT_EFI_ERROR (Status);
-
- if (BootMode == BOOT_IN_RECOVERY_MODE) {
- return TRUE;
- }
- return FALSE;
-}
-
-/**
Provide the functionality of the variable services.
@param FileHandle Handle of the file being invoked.
@@ -68,7 +42,6 @@ IsInRecoveryMode (
@retval EFI_SUCCESS If the interface could be successfully installed
@retval Others Returned from PeiServicesInstallPpi()
-
**/
EFI_STATUS
EFIAPI
@@ -349,14 +322,80 @@ CompareWithValidVariable (
return EFI_NOT_FOUND;
}
+/**
+ Return the variable store header and the index table based on the Index.
+
+ @param Index The index 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 **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:
+ GuidHob = GetFirstGuidHob (&gEfiVariableGuid);
+ if (GuidHob != NULL) {
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *) GET_GUID_HOB_DATA (GuidHob);
+ }
+ 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) (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0 ?
+ PcdGet64 (PcdFlashNvStorageVariableBase64) :
+ PcdGet32 (PcdFlashNvStorageVariableBase)
+ );
+ 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));
+ (*IndexTable)->Length = 0;
+ (*IndexTable)->StartPtr = GetStartPointer (VariableStoreHeader);
+ (*IndexTable)->EndPtr = GetEndPointer (VariableStoreHeader);
+ (*IndexTable)->GoneThrough = 0;
+ }
+ }
+ }
+ break;
+ }
+
+ return VariableStoreHeader;
+}
/**
- This code finds variable in storage blocks (Non-Volatile).
+ Find the variable in the specified variable store.
- @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.
+ @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
@@ -364,134 +403,100 @@ CompareWithValidVariable (
**/
EFI_STATUS
-FindVariable (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST CHAR16 *VariableName,
- IN CONST EFI_GUID *VendorGuid,
- OUT VARIABLE_POINTER_TRACK *PtrTrack
+FindVariableEx (
+ IN VARIABLE_STORE_HEADER *VariableStoreHeader,
+ IN VARIABLE_INDEX_TABLE *IndexTable,
+ 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;
+ UINTN Index;
+ UINTN Offset;
BOOLEAN StopRecord;
- if (VariableName[0] != 0 && VendorGuid == NULL) {
+ if (VariableStoreHeader == NULL) {
return EFI_INVALID_PARAMETER;
}
+
+ if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (~VariableStoreHeader->Size == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader);
+ PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader);
+
//
// No Variable Address equals zero, so 0 as initial value is safe.
//
- MaxIndex = 0;
- StopRecord = FALSE;
+ MaxIndex = NULL;
- GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);
- if (GuidHob == NULL) {
+ if (IndexTable != 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.
+ // traverse the variable index table to look for varible.
+ // The IndexTable->Index[Index] records the distance of two neighbouring VAR_ADDED type variables.
//
- 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);
+ 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) {
- PtrTrack->StartPtr = IndexTable->StartPtr;
- PtrTrack->EndPtr = IndexTable->EndPtr;
-
return EFI_SUCCESS;
}
}
if (IndexTable->GoneThrough != 0) {
+ //
+ // If the table has all the existing variables indexed and we still cannot find it.
+ //
return EFI_NOT_FOUND;
}
}
- //
- // If not found in HOB, then let's start from the MaxIndex we've found.
- //
+
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 {
- 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;
+ //
+ // 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 non-volatile variable store
//
- PtrTrack->StartPtr = IndexTable->StartPtr;
- PtrTrack->EndPtr = IndexTable->EndPtr;
-
- while ((Variable < IndexTable->EndPtr) && IsValidVariableHeader (Variable)) {
+ StopRecord = FALSE;
+ while ((Variable < PtrTrack->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) {
+ if ((IndexTable != NULL) && !StopRecord) {
+ Offset = (UINTN) Variable - (UINTN) LastVariable;
+ if ((Offset > 0x0FFFF) || (IndexTable->Length == sizeof (IndexTable->Index) / sizeof (IndexTable->Index[0]))) {
+ //
+ // Stop to record if the distance of two neighbouring VAR_ADDED variable is larger than the allowable scope(UINT16),
+ // or the record buffer is full.
+ //
StopRecord = TRUE;
- }
-
- if (!StopRecord) {
+ } else {
IndexTable->Index[IndexTable->Length++] = (UINT16) Offset;
+ LastVariable = Variable;
}
- LastVariable = Variable;
}
if (CompareWithValidVariable (Variable, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
@@ -504,7 +509,7 @@ FindVariable (
//
// If gone through the VariableStore, that means we never find in Firmware any more.
//
- if ((IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME) && (!StopRecord)) {
+ if ((IndexTable != NULL) && !StopRecord) {
IndexTable->GoneThrough = 1;
}
@@ -514,6 +519,50 @@ FindVariable (
}
/**
+ 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 *IndexTable;
+ VARIABLE_STORE_TYPE Type;
+
+ if (VariableName[0] != 0 && VendorGuid == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
+ VariableStoreHeader = GetVariableStore (Type, &IndexTable);
+ Status = FindVariableEx (
+ VariableStoreHeader,
+ IndexTable,
+ VariableName,
+ VendorGuid,
+ PtrTrack
+ );
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ 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
@@ -553,27 +602,16 @@ PeiGetVariable (
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;
}
//
- // Check if this is recovery boot path.
- // If yes, the content of variable area is not reliable. Therefore we directly
- // return EFI_NOT_FOUND.
- //
- if (IsInRecoveryMode(PeiServices)) {
- return EFI_NOT_FOUND;
- }
-
- //
// Find existing variable
//
- Status = FindVariable (PeiServices, VariableName, VariableGuid, &Variable);
- if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {
+ Status = FindVariable (VariableName, VariableGuid, &Variable);
+ if (EFI_ERROR (Status)) {
return Status;
}
//
@@ -637,26 +675,18 @@ PeiGetNextVariableName (
IN OUT EFI_GUID *VariableGuid
)
{
+ VARIABLE_STORE_TYPE Type;
VARIABLE_POINTER_TRACK Variable;
+ VARIABLE_POINTER_TRACK VariableInHob;
UINTN VarNameSize;
EFI_STATUS Status;
- CONST EFI_PEI_SERVICES **PeiServices;
+ VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];
- PeiServices = GetPeiServicesTablePointer ();
if (VariableName == NULL || VariableGuid == NULL || VariableNameSize == NULL) {
return EFI_INVALID_PARAMETER;
}
- //
- // Check if this is recovery boot path.
- // If yes, the content of variable area is not reliable. Therefore we directly
- // return EFI_NOT_FOUND.
- //
- if (IsInRecoveryMode(PeiServices)) {
- return EFI_NOT_FOUND;
- }
-
- Status = FindVariable (PeiServices, VariableName, VariableGuid, &Variable);
+ Status = FindVariable (VariableName, VariableGuid, &Variable);
if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {
return Status;
}
@@ -668,34 +698,88 @@ PeiGetNextVariableName (
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);
+ VariableStoreHeader[VariableStoreTypeHob] = GetVariableStore (VariableStoreTypeHob, NULL);
+ VariableStoreHeader[VariableStoreTypeNv] = GetVariableStore (VariableStoreTypeNv, NULL);
- VarNameSize = (UINTN) NameSizeOfVariable (Variable.CurrPtr);
- if (VarNameSize <= *VariableNameSize) {
- CopyMem (VariableName, GetVariableNamePtr (Variable.CurrPtr), VarNameSize);
+ 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) {
+ return EFI_NOT_FOUND;
+ }
+ Variable.StartPtr = GetStartPointer (VariableStoreHeader[Type]);
+ Variable.EndPtr = GetEndPointer (VariableStoreHeader[Type]);
+ Variable.CurrPtr = Variable.StartPtr;
+ }
- CopyMem (VariableGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));
+ if (Variable.CurrPtr->State == VAR_ADDED) {
- Status = EFI_SUCCESS;
- } else {
- Status = EFI_BUFFER_TOO_SMALL;
+ //
+ // 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,
+ GetVariableNamePtr (Variable.CurrPtr),
+ &Variable.CurrPtr->VendorGuid,
+ &VariableInHob
+ );
+ if (!EFI_ERROR (Status)) {
+ Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
+ continue;
}
+ }
- *VariableNameSize = VarNameSize;
- return Status;
- //
- // Variable is found
- //
+ VarNameSize = NameSizeOfVariable (Variable.CurrPtr);
+ ASSERT (VarNameSize != 0);
+
+ if (VarNameSize <= *VariableNameSize) {
+ CopyMem (VariableName, GetVariableNamePtr (Variable.CurrPtr), VarNameSize);
+
+ CopyMem (VariableGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));
+
+ Status = EFI_SUCCESS;
} else {
- Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
+ Status = EFI_BUFFER_TOO_SMALL;
}
+
+ *VariableNameSize = VarNameSize;
+ //
+ // Variable is found
+ //
+ return Status;
} else {
- break;
+ Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
}
}
-
- return EFI_NOT_FOUND;
}
diff --git a/MdeModulePkg/Universal/Variable/Pei/Variable.h b/MdeModulePkg/Universal/Variable/Pei/Variable.h
index f89bcae63..292acb974 100644
--- a/MdeModulePkg/Universal/Variable/Pei/Variable.h
+++ b/MdeModulePkg/Universal/Variable/Pei/Variable.h
@@ -30,6 +30,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Guid/VariableFormat.h>
#include <Guid/VariableIndexTable.h>
+
+typedef enum {
+ VariableStoreTypeHob,
+ VariableStoreTypeNv,
+ VariableStoreTypeMax
+} VARIABLE_STORE_TYPE;
+
//
// Functions
//
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
index 173693d94..17c4ef147 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
@@ -713,6 +713,67 @@ Reclaim (
return Status;
}
+/**
+ Find the variable in the specified variable store.
+
+ @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
+**/
+EFI_STATUS
+FindVariableEx (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN OUT VARIABLE_POINTER_TRACK *PtrTrack
+ )
+{
+ VARIABLE_HEADER *InDeletedVariable;
+ VOID *Point;
+
+ //
+ // Find the variable by walk through HOB, volatile and non-volatile variable store.
+ //
+ InDeletedVariable = NULL;
+
+ for ( PtrTrack->CurrPtr = PtrTrack->StartPtr
+ ; (PtrTrack->CurrPtr < PtrTrack->EndPtr) && IsValidVariableHeader (PtrTrack->CurrPtr)
+ ; PtrTrack->CurrPtr = GetNextVariablePtr (PtrTrack->CurrPtr)
+ ) {
+ if (PtrTrack->CurrPtr->State == VAR_ADDED ||
+ PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)
+ ) {
+ if (!AtRuntime () || ((PtrTrack->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {
+ if (VariableName[0] == 0) {
+ if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+ InDeletedVariable = PtrTrack->CurrPtr;
+ } else {
+ return EFI_SUCCESS;
+ }
+ } else {
+ if (CompareGuid (VendorGuid, &PtrTrack->CurrPtr->VendorGuid)) {
+ Point = (VOID *) GetVariableNamePtr (PtrTrack->CurrPtr);
+
+ ASSERT (NameSizeOfVariable (PtrTrack->CurrPtr) != 0);
+ if (CompareMem (VariableName, Point, NameSizeOfVariable (PtrTrack->CurrPtr)) == 0) {
+ if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+ InDeletedVariable = PtrTrack->CurrPtr;
+ } else {
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ PtrTrack->CurrPtr = InDeletedVariable;
+ return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;
+}
+
/**
Finds variable in storage blocks of volatile and non-volatile storage areas.
@@ -744,89 +805,40 @@ FindVariable (
IN VARIABLE_GLOBAL *Global
)
{
- VARIABLE_HEADER *Variable[2];
- VARIABLE_HEADER *InDeletedVariable;
- VARIABLE_STORE_HEADER *VariableStoreHeader[2];
- UINTN InDeletedStorageIndex;
- UINTN Index;
- VOID *Point;
+ EFI_STATUS Status;
+ VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];
+ VARIABLE_STORE_TYPE Type;
+
+ if (VariableName[0] != 0 && VendorGuid == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
//
- // 0: Volatile, 1: Non-Volatile.
+ // 0: Volatile, 1: HOB, 2: Non-Volatile.
// The index and attributes mapping must be kept in this order as RuntimeServiceGetNextVariableName
// make use of this mapping to implement search algorithm.
//
- VariableStoreHeader[0] = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);
- VariableStoreHeader[1] = mNvVariableCache;
+ VariableStoreHeader[VariableStoreTypeVolatile] = (VARIABLE_STORE_HEADER *) (UINTN) Global->VolatileVariableBase;
+ VariableStoreHeader[VariableStoreTypeHob] = (VARIABLE_STORE_HEADER *) (UINTN) Global->HobVariableBase;
+ VariableStoreHeader[VariableStoreTypeNv] = mNvVariableCache;
//
- // Start Pointers for the variable.
- // Actual Data Pointer where data can be written.
+ // Find the variable by walk through HOB, volatile and non-volatile variable store.
//
- Variable[0] = GetStartPointer (VariableStoreHeader[0]);
- Variable[1] = GetStartPointer (VariableStoreHeader[1]);
-
- if (VariableName[0] != 0 && VendorGuid == NULL) {
- return EFI_INVALID_PARAMETER;
- }
+ for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
+ if (VariableStoreHeader[Type] == NULL) {
+ continue;
+ }
- //
- // Find the variable by walk through volatile and then non-volatile variable store.
- //
- InDeletedVariable = NULL;
- InDeletedStorageIndex = 0;
- for (Index = 0; Index < 2; Index++) {
- while ((Variable[Index] < GetEndPointer (VariableStoreHeader[Index])) && IsValidVariableHeader (Variable[Index])) {
- if (Variable[Index]->State == VAR_ADDED ||
- Variable[Index]->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)
- ) {
- if (!AtRuntime () || ((Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {
- if (VariableName[0] == 0) {
- if (Variable[Index]->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
- InDeletedVariable = Variable[Index];
- InDeletedStorageIndex = Index;
- } else {
- PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader[Index]);
- PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]);
- PtrTrack->CurrPtr = Variable[Index];
- PtrTrack->Volatile = (BOOLEAN)(Index == 0);
-
- return EFI_SUCCESS;
- }
- } else {
- if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) {
- Point = (VOID *) GetVariableNamePtr (Variable[Index]);
-
- ASSERT (NameSizeOfVariable (Variable[Index]) != 0);
- if (CompareMem (VariableName, Point, NameSizeOfVariable (Variable[Index])) == 0) {
- if (Variable[Index]->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
- InDeletedVariable = Variable[Index];
- InDeletedStorageIndex = Index;
- } else {
- PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader[Index]);
- PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]);
- PtrTrack->CurrPtr = Variable[Index];
- PtrTrack->Volatile = (BOOLEAN)(Index == 0);
-
- return EFI_SUCCESS;
- }
- }
- }
- }
- }
- }
+ PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader[Type]);
+ PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Type]);
+ PtrTrack->Volatile = (BOOLEAN) (Type == VariableStoreTypeVolatile);
- Variable[Index] = GetNextVariablePtr (Variable[Index]);
- }
- if (InDeletedVariable != NULL) {
- PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader[InDeletedStorageIndex]);
- PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[InDeletedStorageIndex]);
- PtrTrack->CurrPtr = InDeletedVariable;
- PtrTrack->Volatile = (BOOLEAN)(InDeletedStorageIndex == 0);
- return EFI_SUCCESS;
+ Status = FindVariableEx (VariableName, VendorGuid, PtrTrack);
+ if (!EFI_ERROR (Status)) {
+ return Status;
}
}
- PtrTrack->CurrPtr = NULL;
return EFI_NOT_FOUND;
}
@@ -1222,7 +1234,7 @@ AutoUpdateLangVariable(
// Update Lang if PlatformLang is already set
// Update PlatformLang if Lang is already set
//
- Status = FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *) mVariableModuleGlobal);
+ Status = FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);
if (!EFI_ERROR (Status)) {
//
// Update Lang
@@ -1231,7 +1243,7 @@ AutoUpdateLangVariable(
Data = GetVariableDataPtr (Variable.CurrPtr);
DataSize = Variable.CurrPtr->DataSize;
} else {
- Status = FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *) mVariableModuleGlobal);
+ Status = FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);
if (!EFI_ERROR (Status)) {
//
// Update PlatformLang
@@ -1310,7 +1322,7 @@ AutoUpdateLangVariable(
//
// Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.
//
- FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);
+ FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);
Status = UpdateVariable (L"PlatformLang", &gEfiGlobalVariableGuid, BestPlatformLang,
AsciiStrSize (BestPlatformLang), Attributes, &Variable);
@@ -1839,9 +1851,12 @@ VariableServiceGetNextVariableName (
IN OUT EFI_GUID *VendorGuid
)
{
+ VARIABLE_STORE_TYPE Type;
VARIABLE_POINTER_TRACK Variable;
+ VARIABLE_POINTER_TRACK VariableInHob;
UINTN VarNameSize;
EFI_STATUS Status;
+ VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];
if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {
return EFI_INVALID_PARAMETER;
@@ -1861,45 +1876,85 @@ VariableServiceGetNextVariableName (
Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
}
+ //
+ // 0: Volatile, 1: HOB, 2: Non-Volatile.
+ // The index and attributes mapping must be kept in this order as FindVariable
+ // makes use of this mapping to implement search algorithm.
+ //
+ VariableStoreHeader[VariableStoreTypeVolatile] = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase;
+ VariableStoreHeader[VariableStoreTypeHob] = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;
+ VariableStoreHeader[VariableStoreTypeNv] = mNvVariableCache;
+
while (TRUE) {
//
- // If both volatile and non-volatile variable store are parsed,
- // return not found.
+ // Switch from Volatile to HOB, to Non-Volatile.
//
- if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) {
- Variable.Volatile = (BOOLEAN) (Variable.Volatile ^ ((BOOLEAN) 0x1));
- if (!Variable.Volatile) {
- Variable.StartPtr = GetStartPointer ((VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);
- Variable.EndPtr = GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase));
- } else {
+ 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) {
Status = EFI_NOT_FOUND;
goto Done;
}
-
- Variable.CurrPtr = Variable.StartPtr;
- if (!IsValidVariableHeader (Variable.CurrPtr)) {
- continue;
- }
+ Variable.StartPtr = GetStartPointer (VariableStoreHeader[Type]);
+ Variable.EndPtr = GetEndPointer (VariableStoreHeader[Type]);
+ Variable.CurrPtr = Variable.StartPtr;
}
+
//
// Variable is found
//
- if (IsValidVariableHeader (Variable.CurrPtr) && Variable.CurrPtr->State == VAR_ADDED) {
+ if (Variable.CurrPtr->State == VAR_ADDED) {
if ((AtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) == 0) {
+
+ //
+ // Don't return NV variable when HOB overrides it
+ //
+ if ((VariableStoreHeader[VariableStoreTypeHob] != NULL) && (VariableStoreHeader[VariableStoreTypeNv] != NULL) &&
+ (Variable.StartPtr == GetStartPointer (VariableStoreHeader[VariableStoreTypeNv]))
+ ) {
+ VariableInHob.StartPtr = GetStartPointer (VariableStoreHeader[VariableStoreTypeHob]);
+ VariableInHob.EndPtr = GetEndPointer (VariableStoreHeader[VariableStoreTypeHob]);
+ Status = FindVariableEx (
+ GetVariableNamePtr (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,
- GetVariableNamePtr (Variable.CurrPtr),
- VarNameSize
- );
- CopyMem (
- VendorGuid,
- &Variable.CurrPtr->VendorGuid,
- sizeof (EFI_GUID)
- );
+ CopyMem (VariableName, GetVariableNamePtr (Variable.CurrPtr), VarNameSize);
+ CopyMem (VendorGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));
Status = EFI_SUCCESS;
} else {
Status = EFI_BUFFER_TOO_SMALL;
@@ -2261,16 +2316,16 @@ VariableWriteServiceInitialize (
UINTN Index;
UINT8 Data;
EFI_PHYSICAL_ADDRESS VariableStoreBase;
- UINT64 VariableStoreLength;
+ VARIABLE_HEADER *Variable;
+ VOID *VariableData;
VariableStoreBase = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;
- VariableStoreLength = VariableStoreHeader->Size;
-
+
//
// Check if the free area is really free.
//
- for (Index = mVariableModuleGlobal->NonVolatileLastVariableOffset; Index < VariableStoreLength; Index++) {
+ for (Index = mVariableModuleGlobal->NonVolatileLastVariableOffset; Index < VariableStoreHeader->Size; Index++) {
Data = ((UINT8 *) mNvVariableCache)[Index];
if (Data != 0xff) {
//
@@ -2289,6 +2344,33 @@ VariableWriteServiceInitialize (
}
}
+ //
+ // Flush the HOB variable to flash and invalidate HOB variable.
+ //
+ if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
+ //
+ // Clear the HobVariableBase to avoid SetVariable() updating the variable in HOB
+ //
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;
+ mVariableModuleGlobal->VariableGlobal.HobVariableBase = 0;
+
+ for ( Variable = GetStartPointer (VariableStoreHeader)
+ ; (Variable < GetEndPointer (VariableStoreHeader) && IsValidVariableHeader (Variable))
+ ; Variable = GetNextVariablePtr (Variable)
+ ) {
+ ASSERT (Variable->State == VAR_ADDED);
+ ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0);
+ VariableData = GetVariableDataPtr (Variable);
+ Status = VariableServiceSetVariable (
+ GetVariableNamePtr (Variable),
+ &Variable->VendorGuid,
+ Variable->Attributes,
+ Variable->DataSize,
+ VariableData
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
return EFI_SUCCESS;
}
@@ -2314,6 +2396,7 @@ VariableCommonInitialize (
UINT64 VariableStoreLength;
UINTN ScratchSize;
UINTN VariableSize;
+ EFI_HOB_GUID_TYPE *GuidHob;
//
// Allocate runtime memory for variable driver global structure.
@@ -2334,6 +2417,14 @@ VariableCommonInitialize (
ASSERT (PcdGet32 (PcdHwErrStorageSize) <= PcdGet32 (PcdFlashNvStorageVariableSize));
//
+ // Get HOB variable store.
+ //
+ GuidHob = GetFirstGuidHob (&gEfiVariableGuid);
+ if (GuidHob != NULL) {
+ mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) GET_GUID_HOB_DATA (GuidHob);
+ }
+
+ //
// Allocate memory for volatile variable store, note that there is a scratch space to store scratch data.
//
ScratchSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
index 7cc039dea..22aa5004c 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
@@ -23,6 +23,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/FirmwareVolumeBlock.h>
#include <Protocol/Variable.h>
#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/DxeServicesTableLib.h>
#include <Library/UefiRuntimeLib.h>
@@ -44,6 +45,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
///
#define ISO_639_2_ENTRY_SIZE 3
+typedef enum {
+ VariableStoreTypeVolatile,
+ VariableStoreTypeHob,
+ VariableStoreTypeNv,
+ VariableStoreTypeMax
+} VARIABLE_STORE_TYPE;
+
typedef struct {
VARIABLE_HEADER *CurrPtr;
VARIABLE_HEADER *EndPtr;
@@ -52,6 +60,7 @@ typedef struct {
} VARIABLE_POINTER_TRACK;
typedef struct {
+ EFI_PHYSICAL_ADDRESS HobVariableBase;
EFI_PHYSICAL_ADDRESS VolatileVariableBase;
EFI_PHYSICAL_ADDRESS NonVolatileVariableBase;
EFI_LOCK VariableServicesLock;
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
index 15e000e69..582baf570 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
@@ -52,6 +52,7 @@
DxeServicesTableLib
UefiDriverEntryPoint
PcdLib
+ HobLib
[Protocols]
gEfiFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
index 20481768a..8ea7f2bc8 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
@@ -56,6 +56,7 @@
BaseMemoryLib
DebugLib
DxeServicesTableLib
+ HobLib
[Protocols]
gEfiSmmFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES
@@ -82,4 +83,4 @@
[Depex]
TRUE
- \ No newline at end of file
+