diff options
Diffstat (limited to 'MdeModulePkg/Universal/Variable')
10 files changed, 2600 insertions, 858 deletions
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c index 79962daa64..11bf1a02b6 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c @@ -3,7 +3,7 @@ Handles non-volatile variable store garbage collection, using FTW
(Fault Tolerant Write) protocol.
-Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 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
@@ -14,105 +14,23 @@ 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 Address Address which should be contained
- by returned FVB handle
- @param FvbHandle Pointer to FVB handle for output
-
- @retval EFI_SUCCESS FVB handle successfully returned
- @retval EFI_NOT_FOUND Fail 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;
- EFI_FVB_ATTRIBUTES_2 Attributes;
-
- *FvbHandle = NULL;
- //
- // Locate all handles of Fvb protocol
- //
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiFirmwareVolumeBlockProtocolGuid,
- NULL,
- &HandleCount,
- &HandleBuffer
- );
- if (EFI_ERROR (Status)) {
- return EFI_NOT_FOUND;
- }
- //
- // Get the FVB to access variable store
- //
- for (Index = 0; Index < HandleCount; Index += 1) {
- Status = gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiFirmwareVolumeBlockProtocolGuid,
- (VOID **) &Fvb
- );
- if (EFI_ERROR (Status)) {
- Status = EFI_NOT_FOUND;
- break;
- }
-
- Status = Fvb->GetAttributes (Fvb, &Attributes);
- if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {
- continue;
- }
- //
- // Compare the address and select the right one
- //
- 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
+ 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
+ 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
+ @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
@@ -123,7 +41,6 @@ GetLbaAndOffsetByAddress ( )
{
EFI_STATUS Status;
- EFI_HANDLE FvbHandle;
EFI_PHYSICAL_ADDRESS FvbBaseAddress;
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
@@ -132,25 +49,17 @@ GetLbaAndOffsetByAddress ( *Lba = (EFI_LBA) (-1);
*Offset = 0;
-
+
//
- // Get the proper FVB
+ // Get the proper FVB protocol.
//
- Status = GetFvbHandleByAddress (Address, &FvbHandle);
+ Status = GetFvbInfoByAddress (Address, NULL, &Fvb);
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
+ // Get the Base Address of FV.
//
Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
if (EFI_ERROR (Status)) {
@@ -160,24 +69,22 @@ GetLbaAndOffsetByAddress ( FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
//
- // Get the (LBA, Offset) of Address
+ // 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;
- }
- }
+ 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;
+ }
}
}
@@ -187,17 +94,17 @@ GetLbaAndOffsetByAddress ( /**
Writes a buffer to variable storage space, in the working block.
- This function writes a buffer to variable storage space into firmware
+ 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
+ @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
+ @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
@@ -216,35 +123,31 @@ FtwVariableSpace ( EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
//
- // Locate fault tolerant write protocol
+ // Locate fault tolerant write protocol.
//
- Status = gBS->LocateProtocol (
- &gEfiFaultTolerantWriteProtocolGuid,
- NULL,
- (VOID **) &FtwProtocol
- );
+ Status = GetFtwProtocol((VOID **) &FtwProtocol);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
//
- // Locate Fvb handle by address
+ // Locate Fvb handle by address.
//
- Status = GetFvbHandleByAddress (VariableBase, &FvbHandle);
+ Status = GetFvbInfoByAddress (VariableBase, &FvbHandle, NULL);
if (EFI_ERROR (Status)) {
return Status;
}
//
- // Get LBA and Offset by address
+ // Get LBA and Offset by address.
//
Status = GetLbaAndOffsetByAddress (VariableBase, &VarLba, &VarOffset);
if (EFI_ERROR (Status)) {
return EFI_ABORTED;
}
//
- // Prepare for the variable data
+ // Prepare for the variable data.
//
FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size;
- FtwBuffer = AllocateRuntimePool (FtwBufferSize);
+ FtwBuffer = AllocatePool (FtwBufferSize);
if (FtwBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
@@ -253,17 +156,17 @@ FtwVariableSpace ( CopyMem (FtwBuffer, Buffer, BufferSize);
//
- // FTW write record
+ // FTW write record.
//
Status = FtwProtocol->Write (
- FtwProtocol,
- VarLba, // LBA
- VarOffset, // Offset
- FtwBufferSize, // NumBytes
- NULL, // PrivateData NULL
- FvbHandle, // Fvb Handle
- FtwBuffer // write buffer
- );
+ FtwProtocol,
+ VarLba, // LBA
+ VarOffset, // Offset
+ FtwBufferSize, // NumBytes
+ NULL, // PrivateData NULL
+ FvbHandle, // Fvb Handle
+ FtwBuffer // write buffer
+ );
FreePool (FtwBuffer);
return Status;
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c index dca3e30370..9a2468efb0 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c @@ -1,7 +1,7 @@ /** @file
- Implement all four UEFI Runtime Variable services for the nonvolatile
- and volatile storage space and install variable architecture protocol.
+ The common variable operation routines shared by DXE_RINTIME variable
+ module and DXE_SMM variable module.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
@@ -17,110 +17,16 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "Variable.h"
VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal;
-EFI_EVENT mVirtualAddressChangeEvent = NULL;
-EFI_HANDLE mHandle = NULL;
///
-/// The current Hii implementation accesses this variable many times on every boot.
-/// Other common variables are only accessed once. This is why this cache algorithm
-/// only targets a single variable. Probably to get an performance improvement out of
-/// a Cache you would need a cache that improves the search performance for a variable.
+/// Define a memory cache that improves the search performance for a variable.
///
-VARIABLE_CACHE_ENTRY mVariableCache[] = {
- {
- &gEfiGlobalVariableGuid,
- L"Lang",
- 0x00000000,
- 0x00,
- NULL
- },
- {
- &gEfiGlobalVariableGuid,
- L"PlatformLang",
- 0x00000000,
- 0x00,
- NULL
- }
-};
-
-VARIABLE_INFO_ENTRY *gVariableInfo = NULL;
-EFI_EVENT mFvbRegistration = NULL;
-
-/**
- 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 Attribues of the variable
-
- @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 VARIABLE_POINTER_TRACK *Variable
- );
+VARIABLE_STORE_HEADER *mNvVariableCache = NULL;
-/**
- Acquires lock only at boot time. Simply returns at runtime.
-
- This is a temperary function which 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 (!EfiAtRuntime ()) {
- 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 (!EfiAtRuntime ()) {
- EfiReleaseLock (Lock);
- }
-}
+///
+/// The memory entry used for variable statistics data.
+///
+VARIABLE_INFO_ENTRY *gVariableInfo = NULL;
/**
@@ -134,12 +40,12 @@ ReleaseLockOnlyAtBootTime ( the transaction. Data is allocated by this routine, but never
freed.
- @param[in] VariableName Name of the Variable to track
- @param[in] VendorGuid Guid of the Variable to track
- @param[in] Volatile TRUE if volatile FALSE if non-volatile
- @param[in] Read TRUE if GetVariable() was called
- @param[in] Write TRUE if SetVariable() was called
- @param[in] Delete TRUE if deleted via SetVariable()
+ @param[in] VariableName Name of the Variable to track.
+ @param[in] VendorGuid Guid of the Variable to track.
+ @param[in] Volatile TRUE if volatile FALSE if non-volatile.
+ @param[in] Read TRUE if GetVariable() was called.
+ @param[in] Write TRUE if SetVariable() was called.
+ @param[in] Delete TRUE if deleted via SetVariable().
@param[in] Cache TRUE for a cache hit.
**/
@@ -158,15 +64,15 @@ UpdateVariableInfo ( if (FeaturePcdGet (PcdVariableCollectStatistics)) {
- if (EfiAtRuntime ()) {
- // Don't collect statistics at runtime
+ if (AtRuntime ()) {
+ // Don't collect statistics at runtime.
return;
}
if (gVariableInfo == NULL) {
//
- // on the first call allocate a entry and place a pointer to it in
- // the EFI System Table
+ // On the first call allocate a entry and place a pointer to it in
+ // the EFI System Table.
//
gVariableInfo = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));
ASSERT (gVariableInfo != NULL);
@@ -176,8 +82,6 @@ UpdateVariableInfo ( ASSERT (gVariableInfo->Name != NULL);
StrCpy (gVariableInfo->Name, VariableName);
gVariableInfo->Volatile = Volatile;
-
- gBS->InstallConfigurationTable (&gEfiVariableGuid, gVariableInfo);
}
@@ -204,7 +108,7 @@ UpdateVariableInfo ( if (Entry->Next == NULL) {
//
// If the entry is not in the table add it.
- // Next iteration of the loop will fill in the data
+ // Next iteration of the loop will fill in the data.
//
Entry->Next = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));
ASSERT (Entry->Next != NULL);
@@ -249,18 +153,18 @@ IsValidVariableHeader ( This function writes data to the FWH at the correct LBA even if the LBAs
are fragmented.
- @param Global Pointer to VARAIBLE_GLOBAL structure
- @param Volatile Point out the Variable is Volatile or Non-Volatile
- @param SetByIndex TRUE if target pointer is given as index
- FALSE if target pointer is absolute
- @param Fvb Pointer to the writable FVB protocol
+ @param Global Pointer to VARAIBLE_GLOBAL structure.
+ @param Volatile Point out the Variable is Volatile or Non-Volatile.
+ @param SetByIndex TRUE if target pointer is given as index.
+ FALSE if target pointer is absolute.
+ @param Fvb Pointer to the writable FVB protocol.
@param DataPtrIndex Pointer to the Data from the end of VARIABLE_STORE_HEADER
- structure
- @param DataSize Size of data to be written
- @param Buffer Pointer to the buffer from which data is written
+ structure.
+ @param DataSize Size of data to be written.
+ @param Buffer Pointer to the buffer from which data is written.
- @retval EFI_INVALID_PARAMETER Parameters not valid
- @retval EFI_SUCCESS Variable store successfully updated
+ @retval EFI_INVALID_PARAMETER Parameters not valid.
+ @retval EFI_SUCCESS Variable store successfully updated.
**/
EFI_STATUS
@@ -292,7 +196,7 @@ UpdateVariableStore ( DataPtr = DataPtrIndex;
//
- // Check if the Data is Volatile
+ // Check if the Data is Volatile.
//
if (!Volatile) {
Status = Fvb->GetPhysicalAddress(Fvb, &FvVolHdr);
@@ -301,7 +205,7 @@ UpdateVariableStore ( FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvVolHdr);
//
// Data Pointer should point to the actual Address where data is to be
- // written
+ // written.
//
if (SetByIndex) {
DataPtr += mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
@@ -313,7 +217,7 @@ UpdateVariableStore ( } else {
//
// Data Pointer should point to the actual Address where data is to be
- // written
+ // written.
//
VolatileBase = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);
if (SetByIndex) {
@@ -332,7 +236,7 @@ UpdateVariableStore ( }
//
- // If we are here we are dealing with Non-Volatile Variables
+ // If we are here we are dealing with Non-Volatile Variables.
//
LinearOffset = (UINTN) FwVolHeader;
CurrWritePtr = (UINTN) DataPtr;
@@ -394,9 +298,9 @@ UpdateVariableStore ( @param VarStoreHeader Pointer to the Variable Store Header.
- @retval EfiRaw Variable store status is raw
- @retval EfiValid Variable store status is valid
- @retval EfiInvalid Variable store status is invalid
+ @retval EfiRaw Variable store status is raw.
+ @retval EfiValid Variable store status is valid.
+ @retval EfiInvalid Variable store status is invalid.
**/
VARIABLE_STORE_STATUS
@@ -430,9 +334,9 @@ GetVariableStoreStatus ( This code gets the size of name of variable.
- @param Variable Pointer to the Variable Header
+ @param Variable Pointer to the Variable Header.
- @return UINTN Size of variable in bytes
+ @return UINTN Size of variable in bytes.
**/
UINTN
@@ -453,9 +357,9 @@ NameSizeOfVariable ( This code gets the size of variable data.
- @param Variable Pointer to the Variable Header
+ @param Variable Pointer to the Variable Header.
- @return Size of variable in bytes
+ @return Size of variable in bytes.
**/
UINTN
@@ -476,9 +380,9 @@ DataSizeOfVariable ( This code gets the pointer to the variable name.
- @param Variable Pointer to the Variable Header
+ @param Variable Pointer to the Variable Header.
- @return Pointer to Variable Name which is Unicode encoding
+ @return Pointer to Variable Name which is Unicode encoding.
**/
CHAR16 *
@@ -494,9 +398,9 @@ GetVariableNamePtr ( This code gets the pointer to the variable data.
- @param Variable Pointer to the Variable Header
+ @param Variable Pointer to the Variable Header.
- @return Pointer to Variable Data
+ @return Pointer to Variable Data.
**/
UINT8 *
@@ -507,7 +411,7 @@ GetVariableDataPtr ( UINTN Value;
//
- // Be careful about pad size for alignment
+ // Be careful about pad size for alignment.
//
Value = (UINTN) GetVariableNamePtr (Variable);
Value += NameSizeOfVariable (Variable);
@@ -521,9 +425,9 @@ GetVariableDataPtr ( This code gets the pointer to the next variable header.
- @param Variable Pointer to the Variable Header
+ @param Variable Pointer to the Variable Header.
- @return Pointer to next variable header
+ @return Pointer to next variable header.
**/
VARIABLE_HEADER *
@@ -542,7 +446,7 @@ GetNextVariablePtr ( Value += GET_PAD_SIZE (DataSizeOfVariable (Variable));
//
- // Be careful about pad size for alignment
+ // Be careful about pad size for alignment.
//
return (VARIABLE_HEADER *) HEADER_ALIGN (Value);
}
@@ -553,7 +457,7 @@ GetNextVariablePtr ( @param VarStoreHeader Pointer to the Variable Store Header.
- @return Pointer to the first variable header
+ @return Pointer to the first variable header.
**/
VARIABLE_HEADER *
@@ -562,7 +466,7 @@ GetStartPointer ( )
{
//
- // The end of variable store
+ // The end of variable store.
//
return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);
}
@@ -574,9 +478,9 @@ GetStartPointer ( This function gets pointer to the end of the variable storage
area, according to the input variable store header.
- @param VarStoreHeader Pointer to the Variable Store Header
+ @param VarStoreHeader Pointer to the Variable Store Header.
- @return Pointer to the end of the variable storage area
+ @return Pointer to the end of the variable storage area.
**/
VARIABLE_HEADER *
@@ -595,11 +499,11 @@ GetEndPointer ( Variable store garbage collection and reclaim operation.
- @param VariableBase Base address of variable store
- @param LastVariableOffset Offset of last variable
- @param IsVolatile The variable store is volatile or not,
- if it is non-volatile, need FTW
- @param UpdatingVariable Pointer to updateing variable.
+ @param VariableBase Base address of variable store.
+ @param LastVariableOffset Offset of last variable.
+ @param IsVolatile The variable store is volatile or not;
+ if it is non-volatile, need FTW.
+ @param UpdatingVariable Pointer to updating variable.
@return EFI_OUT_OF_RESOURCES
@return EFI_SUCCESS
@@ -635,7 +539,7 @@ Reclaim ( VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);
//
- // recaluate the total size of Common/HwErr type variables in non-volatile area.
+ // Recalculate the total size of Common/HwErr type variables in non-volatile area.
//
if (!IsVolatile) {
mVariableModuleGlobal->CommonVariableTotalSize = 0;
@@ -673,13 +577,13 @@ Reclaim ( SetMem (ValidBuffer, MaximumBufferSize, 0xff);
//
- // Copy variable store header
+ // Copy variable store header.
//
CopyMem (ValidBuffer, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));
CurrPtr = (UINT8 *) GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);
//
- // Reinstall all ADDED variables as long as they are not identical to Updating Variable
+ // Reinstall all ADDED variables as long as they are not identical to Updating Variable.
//
Variable = GetStartPointer (VariableStoreHeader);
while (IsValidVariableHeader (Variable)) {
@@ -716,7 +620,7 @@ Reclaim ( }
//
- // Reinstall the variable being updated if it is not NULL
+ // Reinstall the variable being updated if it is not NULL.
//
if (UpdatingVariable != NULL) {
VariableSize = (UINTN)(GetNextVariablePtr (UpdatingVariable)) - (UINTN)UpdatingVariable;
@@ -730,7 +634,7 @@ Reclaim ( }
//
- // Reinstall all in delete transition variables
+ // Reinstall all in delete transition variables.
//
Variable = GetStartPointer (VariableStoreHeader);
while (IsValidVariableHeader (Variable)) {
@@ -762,7 +666,7 @@ Reclaim ( }
if (!FoundAdded) {
//
- // Promote VAR_IN_DELETED_TRANSITION to VAR_ADDED
+ // Promote VAR_IN_DELETED_TRANSITION to VAR_ADDED.
//
VariableSize = (UINTN) NextVariable - (UINTN) Variable;
CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
@@ -781,11 +685,11 @@ Reclaim ( if (IsVolatile) {
//
- // If volatile variable store, just copy valid buffer
+ // If volatile variable store, just copy valid buffer.
//
SetMem ((UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size, 0xff);
CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) (CurrPtr - (UINT8 *) ValidBuffer));
- Status = EFI_SUCCESS;
+ Status = EFI_SUCCESS;
} else {
//
// If non-volatile variable store, perform FTW here.
@@ -795,6 +699,7 @@ Reclaim ( ValidBuffer,
(UINTN) (CurrPtr - (UINT8 *) ValidBuffer)
);
+ CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableBase, VariableStoreHeader->Size);
}
if (!EFI_ERROR (Status)) {
*LastVariableOffset = (UINTN) (CurrPtr - (UINT8 *) ValidBuffer);
@@ -809,126 +714,6 @@ Reclaim ( /**
- Update the Cache 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] Attributes Attribues of the variable
- @param[in] DataSize Size of data. 0 means delete
- @param[in] Data Variable data
-
-**/
-VOID
-UpdateVariableCache (
- IN CHAR16 *VariableName,
- IN EFI_GUID *VendorGuid,
- IN UINT32 Attributes,
- IN UINTN DataSize,
- IN VOID *Data
- )
-{
- VARIABLE_CACHE_ENTRY *Entry;
- UINTN Index;
-
- if (EfiAtRuntime ()) {
- //
- // Don't use the cache at runtime
- //
- return;
- }
-
- for (Index = 0, Entry = mVariableCache; Index < sizeof (mVariableCache)/sizeof (VARIABLE_CACHE_ENTRY); Index++, Entry++) {
- if (CompareGuid (VendorGuid, Entry->Guid)) {
- if (StrCmp (VariableName, Entry->Name) == 0) {
- Entry->Attributes = Attributes;
- if (DataSize == 0) {
- //
- // Delete Case
- //
- if (Entry->DataSize != 0) {
- FreePool (Entry->Data);
- }
- Entry->DataSize = DataSize;
- } else if (DataSize == Entry->DataSize) {
- CopyMem (Entry->Data, Data, DataSize);
- } else {
- Entry->Data = AllocatePool (DataSize);
- ASSERT (Entry->Data != NULL);
-
- Entry->DataSize = DataSize;
- CopyMem (Entry->Data, Data, DataSize);
- }
- }
- }
- }
-}
-
-
-/**
- Search the cache to check if the variable is in it.
-
- This function searches the variable cache. If the variable to find exists, return its data
- and attributes.
-
- @param VariableName A Null-terminated Unicode string that is the name of the vendor's
- variable. Each VariableName is unique for each
- VendorGuid.
- @param VendorGuid A unique identifier for the vendor
- @param Attributes Pointer to the attributes bitmask of the variable for output.
- @param DataSize On input, size of the buffer of Data.
- On output, size of the variable's data.
- @param Data Pointer to the data buffer for output.
-
- @retval EFI_SUCCESS VariableGuid & VariableName data was returned.
- @retval EFI_NOT_FOUND No matching variable found in cache.
- @retval EFI_BUFFER_TOO_SMALL *DataSize is smaller than size of the variable's data to return.
-
-**/
-EFI_STATUS
-FindVariableInCache (
- IN CHAR16 *VariableName,
- IN EFI_GUID *VendorGuid,
- OUT UINT32 *Attributes OPTIONAL,
- IN OUT UINTN *DataSize,
- OUT VOID *Data
- )
-{
- VARIABLE_CACHE_ENTRY *Entry;
- UINTN Index;
-
- if (EfiAtRuntime ()) {
- // Don't use the cache at runtime
- return EFI_NOT_FOUND;
- }
-
- for (Index = 0, Entry = mVariableCache; Index < sizeof (mVariableCache)/sizeof (VARIABLE_CACHE_ENTRY); Index++, Entry++) {
- if (CompareGuid (VendorGuid, Entry->Guid)) {
- if (StrCmp (VariableName, Entry->Name) == 0) {
- if (Entry->DataSize == 0) {
- // Variable was deleted so return not found
- return EFI_NOT_FOUND;
- } else if (Entry->DataSize > *DataSize) {
- // If the buffer is too small return correct size
- *DataSize = Entry->DataSize;
- return EFI_BUFFER_TOO_SMALL;
- } else {
- *DataSize = Entry->DataSize;
- // Return the data
- CopyMem (Data, Entry->Data, Entry->DataSize);
- if (Attributes != NULL) {
- *Attributes = Entry->Attributes;
- }
- return EFI_SUCCESS;
- }
- }
- }
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
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.
@@ -936,7 +721,7 @@ FindVariableInCache ( qualified variable without comparing VariableName and VendorGuid.
Otherwise, VariableName and VendorGuid are compared.
- @param VariableName Name of the variable to be found
+ @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.
@@ -945,8 +730,8 @@ FindVariableInCache ( 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
+ VendorGuid is NULL.
+ @retval EFI_SUCCESS Variable successfully found.
@retval EFI_NOT_FOUND Variable not found
**/
@@ -966,12 +751,12 @@ FindVariable ( VOID *Point;
//
- // 0: Volatile, 1: Non-Volatile
+ // 0: Volatile, 1: Non-Volatile.
// The index and attributes mapping must be kept in this order as RuntimeServiceGetNextVariableName
- // make use of this mapping to implement search algorithme.
+ // make use of this mapping to implement search algorithm.
//
VariableStoreHeader[0] = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);
- VariableStoreHeader[1] = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);
+ VariableStoreHeader[1] = mNvVariableCache;
//
// Start Pointers for the variable.
@@ -985,7 +770,7 @@ FindVariable ( }
//
- // Find the variable by walk through volatile and then non-volatile variable store
+ // Find the variable by walk through volatile and then non-volatile variable store.
//
InDeletedVariable = NULL;
InDeletedStorageIndex = 0;
@@ -994,7 +779,7 @@ FindVariable ( if (Variable[Index]->State == VAR_ADDED ||
Variable[Index]->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)
) {
- if (!EfiAtRuntime () || ((Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {
+ 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];
@@ -1067,7 +852,7 @@ FindVariable ( @param Lang Configured language.
@param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC4646.
- @retval the index of language in the language codes.
+ @retval The index of language in the language codes.
**/
UINTN
@@ -1127,7 +912,7 @@ GetIndexFromSupportedLangCodes( /**
Get language string from supported language codes according to index.
- This code is used to get corresponding language string in supported language codes. It can handle
+ This code is used to get corresponding language strings in supported language codes. It can handle
RFC4646 and ISO639 language tags.
In ISO639 language tags, take 3-characters as a delimitation. Find language string according to the index.
In RFC4646 language tags, take semicolon as a delimitation. Find language string according to the index.
@@ -1144,10 +929,10 @@ GetIndexFromSupportedLangCodes( The return value is "fr".
@param SupportedLang Platform supported language codes.
- @param Index the index in supported language codes.
+ @param Index The index in supported language codes.
@param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC4646.
- @retval the language string in the language codes.
+ @retval The language string in the language codes.
**/
CHAR8 *
@@ -1165,18 +950,18 @@ GetLangFromSupportedLangCodes ( Supported = SupportedLang;
if (Iso639Language) {
//
- // according to the index of Lang string in SupportedLang string to get the language.
- // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.
+ // According to the index of Lang string in SupportedLang string to get the language.
+ // This code will be invoked in RUNTIME, therefore there is not a memory allocate/free operation.
// In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.
//
CompareLength = ISO_639_2_ENTRY_SIZE;
mVariableModuleGlobal->Lang[CompareLength] = '\0';
return CopyMem (mVariableModuleGlobal->Lang, SupportedLang + Index * CompareLength, CompareLength);
-
+
} else {
while (TRUE) {
//
- // take semicolon as delimitation, sequentially traverse supported language codes.
+ // Take semicolon as delimitation, sequentially traverse supported language codes.
//
for (CompareLength = 0; *Supported != ';' && *Supported != '\0'; CompareLength++) {
Supported++;
@@ -1191,7 +976,7 @@ GetLangFromSupportedLangCodes ( }
if (SubIndex == Index) {
//
- // according to the index of Lang string in SupportedLang string to get the language.
+ // According to the index of Lang string in SupportedLang string to get the language.
// As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.
// In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.
//
@@ -1199,7 +984,7 @@ GetLangFromSupportedLangCodes ( return CopyMem (mVariableModuleGlobal->PlatformLang, Supported - CompareLength, CompareLength);
}
SubIndex++;
-
+
//
// Skip ';' characters in Supported
//
@@ -1347,11 +1132,11 @@ VariableGetBestLanguage ( According to UEFI spec, PlatformLangCodes/LangCodes are only set once in firmware initialization,
and are read-only. Therefore, in variable driver, only store the original value for other use.
- @param[in] VariableName Name of variable
+ @param[in] VariableName Name of variable.
- @param[in] Data Variable data
+ @param[in] Data Variable data.
- @param[in] DataSize Size of data. 0 means delete
+ @param[in] DataSize Size of data. 0 means delete.
**/
VOID
@@ -1382,7 +1167,7 @@ AutoUpdateLangVariable( //
// PlatformLangCodes is a volatile variable, so it can not be updated at runtime.
//
- if (EfiAtRuntime ()) {
+ if (AtRuntime ()) {
return;
}
@@ -1412,7 +1197,7 @@ AutoUpdateLangVariable( //
// LangCodes is a volatile variable, so it can not be updated at runtime.
//
- if (EfiAtRuntime ()) {
+ if (AtRuntime ()) {
return;
}
@@ -1492,7 +1277,8 @@ AutoUpdateLangVariable( //
FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);
- Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang, ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);
+ Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang,
+ ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);
DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang));
@@ -1539,32 +1325,25 @@ AutoUpdateLangVariable( 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 Attribues of the variable
-
- @param[in] Variable The variable information which is used to keep track of variable usage.
-
+ @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 Attribues of the variable.
+ @param[in] CacheVariable 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 VARIABLE_POINTER_TRACK *Variable
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN VOID *Data,
+ IN UINTN DataSize,
+ IN UINT32 Attributes OPTIONAL,
+ IN VARIABLE_POINTER_TRACK *CacheVariable
)
{
EFI_STATUS Status;
@@ -1579,19 +1358,47 @@ UpdateVariable ( EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
UINT8 State;
BOOLEAN Reclaimed;
+ VARIABLE_POINTER_TRACK *Variable;
+ VARIABLE_POINTER_TRACK NvVariable;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ UINTN CacheOffset;
+ if (CacheVariable->Volatile) {
+ Variable = CacheVariable;
+ } else {
+ if (mVariableModuleGlobal->FvbInstance == NULL) {
+ //
+ // Trying to update NV variable prior to the installation of EFI_VARIABLE_WRITE_ARCH_PROTOCOL
+ //
+ return EFI_NOT_AVAILABLE_YET;
+ }
+
+ //
+ // CacheVariable points to the variable in the memory copy of Flash area
+ // Now let Variable points to the same variable in Flash area.
+ //
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);
+ Variable = &NvVariable;
+ Variable->StartPtr = GetStartPointer (VariableStoreHeader);
+ Variable->EndPtr = GetEndPointer (VariableStoreHeader);
+ if (CacheVariable->CurrPtr == NULL) {
+ Variable->CurrPtr = NULL;
+ } else {
+ Variable->CurrPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->CurrPtr - (UINTN)CacheVariable->StartPtr));
+ }
+ Variable->Volatile = FALSE;
+ }
+
Fvb = mVariableModuleGlobal->FvbInstance;
Reclaimed = FALSE;
if (Variable->CurrPtr != NULL) {
//
- // Update/Delete existing variable
+ // Update/Delete existing variable.
//
- Volatile = Variable->Volatile;
-
- if (EfiAtRuntime ()) {
+ if (AtRuntime ()) {
//
- // If EfiAtRuntime and the variable is Volatile and Runtime Access,
+ // If AtRuntime and the variable is Volatile and Runtime Access,
// the volatile is ReadOnly, and SetVariable should be aborted and
// return EFI_WRITE_PROTECTED.
//
@@ -1600,16 +1407,17 @@ UpdateVariable ( goto Done;
}
//
- // Only variable have NV attribute can be updated/deleted in Runtime
+ // Only variable that have NV attributes can be updated/deleted in Runtime.
//
if ((Variable->CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
Status = EFI_INVALID_PARAMETER;
goto Done;
}
}
+
//
// Setting a data variable with no access, or zero DataSize attributes
- // specified causes it to be deleted.
+ // causes it to be deleted.
//
if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {
State = Variable->CurrPtr->State;
@@ -1625,26 +1433,28 @@ UpdateVariable ( &State
);
if (!EFI_ERROR (Status)) {
- UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, FALSE, TRUE, FALSE);
- UpdateVariableCache (VariableName, VendorGuid, Attributes, DataSize, Data);
+ UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE);
+ if (!Variable->Volatile) {
+ CacheVariable->CurrPtr->State = State;
+ }
}
goto Done;
}
//
- // If the variable is marked valid and the same data has been passed in
+ // If the variable is marked valid, and the same data has been passed in,
// then return to the caller immediately.
//
if (DataSizeOfVariable (Variable->CurrPtr) == DataSize &&
(CompareMem (Data, GetVariableDataPtr (Variable->CurrPtr), DataSize) == 0)) {
- UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE);
+ UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE);
Status = EFI_SUCCESS;
goto Done;
} else if ((Variable->CurrPtr->State == VAR_ADDED) ||
(Variable->CurrPtr->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) {
//
- // Mark the old variable as in delete transition
+ // Mark the old variable as in delete transition.
//
State = Variable->CurrPtr->State;
State &= VAR_IN_DELETED_TRANSITION;
@@ -1661,15 +1471,18 @@ UpdateVariable ( if (EFI_ERROR (Status)) {
goto Done;
}
+ if (!Variable->Volatile) {
+ CacheVariable->CurrPtr->State = State;
+ }
}
} else {
//
- // Not found existing variable. Create a new variable
+ // Not found existing variable. Create a new variable.
//
//
// Make sure we are trying to create a new variable.
- // Setting a data variable with no access, or zero DataSize attributes means to delete it.
+ // Setting a data variable with zero DataSize or no access attributes means to delete it.
//
if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {
Status = EFI_NOT_FOUND;
@@ -1677,9 +1490,9 @@ UpdateVariable ( }
//
- // Only variable have NV|RT attribute can be created in Runtime
+ // Only variable have NV|RT attribute can be created in Runtime.
//
- if (EfiAtRuntime () &&
+ if (AtRuntime () &&
(((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) || ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0))) {
Status = EFI_INVALID_PARAMETER;
goto Done;
@@ -1689,6 +1502,7 @@ UpdateVariable ( //
// Function part - create a new variable and copy the data.
// Both update a variable and create a variable will come here.
+
//
// Tricky part: Use scratch data area at the end of volatile variable store
// as a temporary storage.
@@ -1703,9 +1517,9 @@ UpdateVariable ( //
// NextVariable->State = VAR_ADDED;
//
- NextVariable->Reserved = 0;
- VarNameOffset = sizeof (VARIABLE_HEADER);
- VarNameSize = StrSize (VariableName);
+ NextVariable->Reserved = 0;
+ VarNameOffset = sizeof (VARIABLE_HEADER);
+ VarNameSize = StrSize (VariableName);
CopyMem (
(UINT8 *) ((UINTN) NextVariable + VarNameOffset),
VariableName,
@@ -1721,7 +1535,7 @@ UpdateVariable ( //
// There will be pad bytes after Data, the NextVariable->NameSize and
// NextVariable->DataSize should not include pad size so that variable
- // service can get actual size in GetVariable
+ // service can get actual size in GetVariable.
//
NextVariable->NameSize = (UINT32)VarNameSize;
NextVariable->DataSize = (UINT32)DataSize;
@@ -1733,7 +1547,7 @@ UpdateVariable ( VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);
if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {
//
- // Create a nonvolatile variable
+ // Create a nonvolatile variable.
//
Volatile = FALSE;
NonVolatileVarableStoreSize = ((VARIABLE_STORE_HEADER *)(UINTN)(mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase))->Size;
@@ -1741,12 +1555,12 @@ UpdateVariable ( && ((VarSize + mVariableModuleGlobal->HwErrVariableTotalSize) > PcdGet32 (PcdHwErrStorageSize)))
|| (((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == 0)
&& ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > NonVolatileVarableStoreSize - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize)))) {
- if (EfiAtRuntime ()) {
+ if (AtRuntime ()) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
//
- // Perform garbage collection & reclaim operation
+ // Perform garbage collection & reclaim operation.
//
Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
&mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable->CurrPtr);
@@ -1754,7 +1568,7 @@ UpdateVariable ( goto Done;
}
//
- // If still no enough space, return out of resources
+ // If still no enough space, return out of resources.
//
if ((((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0)
&& ((VarSize + mVariableModuleGlobal->HwErrVariableTotalSize) > PcdGet32 (PcdHwErrStorageSize)))
@@ -1766,7 +1580,7 @@ UpdateVariable ( Reclaimed = TRUE;
}
//
- // Three steps
+ // Four steps
// 1. Write variable header
// 2. Set variable state to header valid
// 3. Write variable data
@@ -1775,6 +1589,7 @@ UpdateVariable ( //
// Step 1:
//
+ CacheOffset = mVariableModuleGlobal->NonVolatileLastVariableOffset;
Status = UpdateVariableStore (
&mVariableModuleGlobal->VariableGlobal,
FALSE,
@@ -1798,9 +1613,9 @@ UpdateVariable ( FALSE,
TRUE,
Fvb,
- mVariableModuleGlobal->NonVolatileLastVariableOffset,
- sizeof (VARIABLE_HEADER),
- (UINT8 *) NextVariable
+ mVariableModuleGlobal->NonVolatileLastVariableOffset + OFFSET_OF (VARIABLE_HEADER, State),
+ sizeof (UINT8),
+ &NextVariable->State
);
if (EFI_ERROR (Status)) {
@@ -1831,9 +1646,9 @@ UpdateVariable ( FALSE,
TRUE,
Fvb,
- mVariableModuleGlobal->NonVolatileLastVariableOffset,
- sizeof (VARIABLE_HEADER),
- (UINT8 *) NextVariable
+ mVariableModuleGlobal->NonVolatileLastVariableOffset + OFFSET_OF (VARIABLE_HEADER, State),
+ sizeof (UINT8),
+ &NextVariable->State
);
if (EFI_ERROR (Status)) {
@@ -1847,16 +1662,20 @@ UpdateVariable ( } else {
mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VarSize);
}
+ //
+ // update the memory copy of Flash region.
+ //
+ CopyMem ((UINT8 *)mNvVariableCache + CacheOffset, (UINT8 *)NextVariable, VarSize);
} else {
//
- // Create a volatile variable
+ // Create a volatile variable.
//
Volatile = TRUE;
if ((UINT32) (VarSize + mVariableModuleGlobal->VolatileLastVariableOffset) >
((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size) {
//
- // Perform garbage collection & reclaim operation
+ // Perform garbage collection & reclaim operation.
//
Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase,
&mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable->CurrPtr);
@@ -1864,7 +1683,7 @@ UpdateVariable ( goto Done;
}
//
- // If still no enough space, return out of resources
+ // If still no enough space, return out of resources.
//
if ((UINT32) (VarSize + mVariableModuleGlobal->VolatileLastVariableOffset) >
((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size
@@ -1894,7 +1713,7 @@ UpdateVariable ( }
//
- // Mark the old variable as deleted
+ // Mark the old variable as deleted.
//
if (!Reclaimed && !EFI_ERROR (Status) && Variable->CurrPtr != NULL) {
State = Variable->CurrPtr->State;
@@ -1909,11 +1728,13 @@ UpdateVariable ( sizeof (UINT8),
&State
);
+ if (!EFI_ERROR (Status) && !Variable->Volatile) {
+ CacheVariable->CurrPtr->State = State;
+ }
}
if (!EFI_ERROR (Status)) {
UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE);
- UpdateVariableCache (VariableName, VendorGuid, Attributes, DataSize, Data);
}
Done:
@@ -1931,15 +1752,15 @@ Done: 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
+ @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
-RuntimeServiceGetVariable (
+VariableServiceGetVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT UINT32 *Attributes OPTIONAL,
@@ -1956,16 +1777,6 @@ RuntimeServiceGetVariable ( }
AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
-
- //
- // Find existing variable
- //
- Status = FindVariableInCache (VariableName, VendorGuid, Attributes, DataSize, Data);
- if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_SUCCESS)){
- // Hit in the Cache
- UpdateVariableInfo (VariableName, VendorGuid, FALSE, TRUE, FALSE, FALSE, TRUE);
- goto Done;
- }
Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);
if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {
@@ -1991,7 +1802,6 @@ RuntimeServiceGetVariable ( *DataSize = VarDataSize;
UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, TRUE, FALSE, FALSE, FALSE);
- UpdateVariableCache (VariableName, VendorGuid, Variable.CurrPtr->Attributes, VarDataSize, Data);
Status = EFI_SUCCESS;
goto Done;
@@ -2012,19 +1822,19 @@ Done: 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
+ @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
+ @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
-RuntimeServiceGetNextVariableName (
+VariableServiceGetNextVariableName (
IN OUT UINTN *VariableNameSize,
IN OUT CHAR16 *VariableName,
IN OUT EFI_GUID *VendorGuid
@@ -2047,7 +1857,7 @@ RuntimeServiceGetNextVariableName ( if (VariableName[0] != 0) {
//
- // If variable name is not NULL, get next variable
+ // If variable name is not NULL, get next variable.
//
Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
}
@@ -2055,7 +1865,7 @@ RuntimeServiceGetNextVariableName ( while (TRUE) {
//
// If both volatile and non-volatile variable store are parsed,
- // return not found
+ // return not found.
//
if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) {
Variable.Volatile = (BOOLEAN) (Variable.Volatile ^ ((BOOLEAN) 0x1));
@@ -2076,7 +1886,7 @@ RuntimeServiceGetNextVariableName ( // Variable is found
//
if (IsValidVariableHeader (Variable.CurrPtr) && Variable.CurrPtr->State == VAR_ADDED) {
- if ((EfiAtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) == 0) {
+ if ((AtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) == 0) {
VarNameSize = NameSizeOfVariable (Variable.CurrPtr);
ASSERT (VarNameSize != 0);
@@ -2113,23 +1923,23 @@ Done: 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 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
+ @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
+ @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
-RuntimeServiceSetVariable (
+VariableServiceSetVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
@@ -2143,11 +1953,11 @@ RuntimeServiceSetVariable ( EFI_PHYSICAL_ADDRESS Point;
//
- // Check input parameters
+ // Check input parameters.
//
if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
return EFI_INVALID_PARAMETER;
- }
+ }
if (DataSize != 0 && Data == NULL) {
return EFI_INVALID_PARAMETER;
@@ -2161,7 +1971,7 @@ RuntimeServiceSetVariable ( }
//
- // Make sure if runtime bit is set, boot service bit is set also
+ // Make sure if runtime bit is set, boot service bit is set also.
//
if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
return EFI_INVALID_PARAMETER;
@@ -2178,7 +1988,7 @@ RuntimeServiceSetVariable ( return EFI_INVALID_PARAMETER;
}
//
- // According to UEFI spec, HARDWARE_ERROR_RECORD variable name convention should be L"HwErrRecXXXX"
+ // According to UEFI spec, HARDWARE_ERROR_RECORD variable name convention should be L"HwErrRecXXXX".
//
if (StrnCmp(VariableName, L"HwErrRec", StrLen(L"HwErrRec")) != 0) {
return EFI_INVALID_PARAMETER;
@@ -2197,12 +2007,12 @@ RuntimeServiceSetVariable ( AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
//
- // Consider reentrant in MCA/INIT/NMI. It needs be reupdated;
+ // Consider reentrant in MCA/INIT/NMI. It needs be reupdated.
//
if (1 < InterlockedIncrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState)) {
- Point = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;;
+ Point = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
//
- // Parse non-volatile variable data and get last variable offset
+ // Parse non-volatile variable data and get last variable offset.
//
NextVariable = GetStartPointer ((VARIABLE_STORE_HEADER *) (UINTN) Point);
while ((NextVariable < GetEndPointer ((VARIABLE_STORE_HEADER *) (UINTN) Point))
@@ -2213,12 +2023,12 @@ RuntimeServiceSetVariable ( }
//
- // Check whether the input variable is already existed
+ // Check whether the input variable is already existed.
//
FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);
//
- // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang
+ // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang.
//
AutoUpdateLangVariable (VariableName, Data, DataSize);
@@ -2250,7 +2060,7 @@ RuntimeServiceSetVariable ( **/
EFI_STATUS
EFIAPI
-RuntimeServiceQueryVariableInfo (
+VariableServiceQueryVariableInfo (
IN UINT32 Attributes,
OUT UINT64 *MaximumVariableStorageSize,
OUT UINT64 *RemainingVariableStorageSize,
@@ -2281,7 +2091,7 @@ RuntimeServiceQueryVariableInfo ( // Make sure if runtime bit is set, boot service bit is set also.
//
return EFI_INVALID_PARAMETER;
- } else if (EfiAtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {
+ } else if (AtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {
//
// Make sure RT Attribute is set if we are in Runtime phase.
//
@@ -2309,7 +2119,7 @@ RuntimeServiceQueryVariableInfo ( //
// Query is Non-Volatile related.
//
- VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);
+ VariableStoreHeader = mNvVariableCache;
}
//
@@ -2348,9 +2158,9 @@ RuntimeServiceQueryVariableInfo ( NextVariable = GetNextVariablePtr (Variable);
VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;
- if (EfiAtRuntime ()) {
+ if (AtRuntime ()) {
//
- // we don't take the state of the variables in mind
+ // We don't take the state of the variables in mind
// when calculating RemainingVariableStorageSize,
// since the space occupied by variables not marked with
// VAR_ADDED is not allowed to be reclaimed in Runtime.
@@ -2362,7 +2172,7 @@ RuntimeServiceQueryVariableInfo ( }
} else {
//
- // Only care about Variables with State VAR_ADDED,because
+ // Only care about Variables with State VAR_ADDED, because
// the space not marked as VAR_ADDED is reclaimable now.
//
if (Variable->State == VAR_ADDED) {
@@ -2375,7 +2185,7 @@ RuntimeServiceQueryVariableInfo ( }
//
- // Go to the next one
+ // Go to the next one.
//
Variable = NextVariable;
}
@@ -2398,21 +2208,12 @@ RuntimeServiceQueryVariableInfo ( /**
- 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
-
+ This function reclaims variable storage if free size is below the threshold.
+
**/
VOID
-EFIAPI
ReclaimForOS(
- EFI_EVENT Event,
- VOID *Context
+ VOID
)
{
EFI_STATUS Status;
@@ -2443,10 +2244,81 @@ ReclaimForOS( }
}
+
/**
- Initializes variable store area for non-volatile and volatile variable.
+ Initializes variable write service after FVB was ready.
- @param FvbProtocol Pointer to an instance of EFI Firmware Volume Block Protocol.
+ @retval EFI_SUCCESS Function successfully executed.
+ @retval Others Fail to initialize the variable service.
+
+**/
+EFI_STATUS
+VariableWriteServiceInitialize (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ UINTN Index;
+ UINT8 Data;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 Length;
+ EFI_PHYSICAL_ADDRESS VariableStoreBase;
+ UINT64 VariableStoreLength;
+
+ 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++) {
+ Data = ((UINT8 *) mNvVariableCache)[Index];
+ if (Data != 0xff) {
+ //
+ // There must be something wrong in variable store, do reclaim operation.
+ //
+ Status = Reclaim (
+ mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
+ &mVariableModuleGlobal->NonVolatileLastVariableOffset,
+ FALSE,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ break;
+ }
+ }
+
+ //
+ // Mark the variable storage region of the FLASH as RUNTIME.
+ //
+ 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"));
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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.
@@ -2454,7 +2326,7 @@ ReclaimForOS( **/
EFI_STATUS
VariableCommonInitialize (
- IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol
+ VOID
)
{
EFI_STATUS Status;
@@ -2462,18 +2334,11 @@ VariableCommonInitialize ( VARIABLE_STORE_HEADER *VariableStoreHeader;
VARIABLE_HEADER *NextVariable;
EFI_PHYSICAL_ADDRESS TempVariableStoreHeader;
- EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
- EFI_PHYSICAL_ADDRESS BaseAddress;
- UINT64 Length;
- UINTN Index;
- UINT8 Data;
EFI_PHYSICAL_ADDRESS VariableStoreBase;
UINT64 VariableStoreLength;
- EFI_EVENT ReadyToBootEvent;
UINTN ScratchSize;
UINTN VariableSize;
- Status = EFI_SUCCESS;
//
// Allocate runtime memory for variable driver global structure.
//
@@ -2482,7 +2347,7 @@ VariableCommonInitialize ( return EFI_OUT_OF_RESOURCES;
}
- EfiInitializeLock(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock, TPL_NOTIFY);
+ InitializeLock (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock, TPL_NOTIFY);
//
// Note that in EdkII variable driver implementation, Hardware Error Record type variable
@@ -2505,139 +2370,69 @@ VariableCommonInitialize ( SetMem (VolatileVariableStore, PcdGet32 (PcdVariableStoreSize) + ScratchSize, 0xff);
//
- // Variable Specific Data
+ // Initialize Variable Specific Data.
//
mVariableModuleGlobal->VariableGlobal.VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore;
mVariableModuleGlobal->VolatileLastVariableOffset = (UINTN) GetStartPointer (VolatileVariableStore) - (UINTN) VolatileVariableStore;
- mVariableModuleGlobal->FvbInstance = FvbProtocol;
+ mVariableModuleGlobal->FvbInstance = NULL;
CopyGuid (&VolatileVariableStore->Signature, &gEfiVariableGuid);
- VolatileVariableStore->Size = PcdGet32 (PcdVariableStoreSize);
- VolatileVariableStore->Format = VARIABLE_STORE_FORMATTED;
- VolatileVariableStore->State = VARIABLE_STORE_HEALTHY;
- VolatileVariableStore->Reserved = 0;
- VolatileVariableStore->Reserved1 = 0;
+ VolatileVariableStore->Size = PcdGet32 (PcdVariableStoreSize);
+ VolatileVariableStore->Format = VARIABLE_STORE_FORMATTED;
+ VolatileVariableStore->State = VARIABLE_STORE_HEALTHY;
+ VolatileVariableStore->Reserved = 0;
+ VolatileVariableStore->Reserved1 = 0;
//
- // Get non volatile varaible store
+ // Get non-volatile varaible store.
//
TempVariableStoreHeader = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
if (TempVariableStoreHeader == 0) {
TempVariableStoreHeader = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
}
-
- VariableStoreBase = TempVariableStoreHeader + \
+ VariableStoreBase = TempVariableStoreHeader + \
+ (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength);
+ VariableStoreLength = (UINT64) PcdGet32 (PcdFlashNvStorageVariableSize) - \
(((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength);
- VariableStoreLength = (UINT64) PcdGet32 (PcdFlashNvStorageVariableSize) - \
- (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength);
- //
- // Mark the variable storage region of the FLASH as RUNTIME
- //
- 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)) {
- goto Done;
- }
- Status = gDS->SetMemorySpaceAttributes (
- BaseAddress,
- Length,
- GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME
- );
- if (EFI_ERROR (Status)) {
+ mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;
+ if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {
+ Status = EFI_VOLUME_CORRUPTED;
+ DEBUG((EFI_D_INFO, "Variable Store header is corrupted\n"));
goto Done;
- }
+ }
+ ASSERT(VariableStoreHeader->Size == VariableStoreLength);
+
//
- // Get address of non volatile variable store base
+ // Parse non-volatile variable data and get last variable offset.
//
- mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;
- VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;
- if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {
- if (~VariableStoreHeader->Size == 0) {
- Status = UpdateVariableStore (
- &mVariableModuleGlobal->VariableGlobal,
- FALSE,
- FALSE,
- mVariableModuleGlobal->FvbInstance,
- (UINTN) &VariableStoreHeader->Size,
- sizeof (UINT32),
- (UINT8 *) &VariableStoreLength
- );
- //
- // As Variables are stored in NV storage, which are slow devices,such as flash.
- // Variable operation may skip checking variable program result to improve performance,
- // We can assume Variable program is OK through some check point.
- // Variable Store Size Setting should be the first Variable write operation,
- // We can assume all Read/Write is OK if we can set Variable store size successfully.
- // If write fail, we will assert here
- //
- ASSERT(VariableStoreHeader->Size == VariableStoreLength);
-
- if (EFI_ERROR (Status)) {
- goto Done;
- }
- }
-
- //
- // Parse non-volatile variable data and get last variable offset
- //
- NextVariable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase);
- Status = EFI_SUCCESS;
-
- while (IsValidVariableHeader (NextVariable)) {
- VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);
- if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
- mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);
- } else {
- mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);
- }
-
- NextVariable = GetNextVariablePtr (NextVariable);
+ NextVariable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase);
+ while (IsValidVariableHeader (NextVariable)) {
+ VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);
+ if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);
+ } else {
+ mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);
}
- mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) VariableStoreBase;
-
- //
- // Check if the free area is really free.
- //
- for (Index = mVariableModuleGlobal->NonVolatileLastVariableOffset; Index < VariableStoreHeader->Size; Index++) {
- Data = ((UINT8 *) (UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase)[Index];
- if (Data != 0xff) {
- //
- // There must be something wrong in variable store, do reclaim operation.
- //
- Status = Reclaim (
- mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
- &mVariableModuleGlobal->NonVolatileLastVariableOffset,
- FALSE,
- NULL
- );
-
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- break;
- }
- }
+ NextVariable = GetNextVariablePtr (NextVariable);
+ }
- //
- // Register the event handling function to reclaim variable for OS usage.
- //
- Status = EfiCreateEventReadyToBootEx (
- TPL_NOTIFY,
- ReclaimForOS,
- NULL,
- &ReadyToBootEvent
- );
- } else {
- Status = EFI_VOLUME_CORRUPTED;
- DEBUG((EFI_D_INFO, "Variable Store header is corrupted\n"));
+ mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) VariableStoreBase;
+
+ //
+ // Allocate runtime memory used for a memory copy of the FLASH region.
+ // Keep the memory and the FLASH in sync as updates occur
+ //
+ mNvVariableCache = AllocateRuntimeZeroPool ((UINTN)VariableStoreLength);
+ if (mNvVariableCache == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
}
+ CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableStoreBase, (UINTN)VariableStoreLength);
+ Status = EFI_SUCCESS;
Done:
if (EFI_ERROR (Status)) {
@@ -2648,97 +2443,45 @@ Done: 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);
-}
/**
- Firmware Volume Block Protocol notification event handler.
+ Get the proper fvb handle and/or fvb protocol by the given Flash address.
- Discover NV Variable Store and install Variable Arch Protocol.
+ @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.
- @param[in] Event Event whose notification function is being invoked.
- @param[in] Context Pointer to the notification function's context.
**/
-VOID
-EFIAPI
-FvbNotificationEvent (
- IN EFI_EVENT Event,
- IN VOID *Context
+EFI_STATUS
+GetFvbInfoByAddress (
+ IN EFI_PHYSICAL_ADDRESS Address,
+ OUT EFI_HANDLE *FvbHandle OPTIONAL,
+ OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvbProtocol OPTIONAL
)
{
- 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;
- EFI_FVB_ATTRIBUTES_2 Attributes;
- EFI_SYSTEM_TABLE *SystemTable;
- EFI_PHYSICAL_ADDRESS NvStorageVariableBase;
-
- SystemTable = (EFI_SYSTEM_TABLE *)Context;
- Fvb = NULL;
-
+ 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;
+ EFI_FVB_ATTRIBUTES_2 Attributes;
+
//
- // Locate all handles of Fvb protocol
+ // Get all FVB handles.
//
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiFirmwareVolumeBlockProtocolGuid,
- NULL,
- &HandleCount,
- &HandleBuffer
- );
+ Status = GetFvbCountAndBuffer (&HandleCount, &HandleBuffer);
if (EFI_ERROR (Status)) {
- return ;
+ return EFI_NOT_FOUND;
}
-
+
//
- // Get the FVB to access variable store
+ // Get the FVB to access variable store.
//
+ Fvb = NULL;
for (Index = 0; Index < HandleCount; Index += 1, Status = EFI_NOT_FOUND, Fvb = NULL) {
- Status = gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiFirmwareVolumeBlockProtocolGuid,
- (VOID **) &Fvb
- );
+ Status = GetFvbByHandle (HandleBuffer[Index], &Fvb);
if (EFI_ERROR (Status)) {
Status = EFI_NOT_FOUND;
break;
@@ -2751,8 +2494,9 @@ FvbNotificationEvent ( if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {
continue;
}
+
//
- // Compare the address and select the right one
+ // Compare the address and select the right one.
//
Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
if (EFI_ERROR (Status)) {
@@ -2760,87 +2504,23 @@ FvbNotificationEvent ( }
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
- NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
- if (NvStorageVariableBase == 0) {
- NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
- }
-
- if ((NvStorageVariableBase >= FvbBaseAddress) && (NvStorageVariableBase < (FvbBaseAddress + FwVolHeader->FvLength))) {
- Status = EFI_SUCCESS;
+ if ((Address >= FvbBaseAddress) && (Address < (FvbBaseAddress + FwVolHeader->FvLength))) {
+ if (FvbHandle != NULL) {
+ *FvbHandle = HandleBuffer[Index];
+ }
+ if (FvbProtocol != NULL) {
+ *FvbProtocol = Fvb;
+ }
+ Status = EFI_SUCCESS;
break;
}
}
-
FreePool (HandleBuffer);
- if (!EFI_ERROR (Status) && Fvb != NULL) {
- //
- // Close the notify event to avoid install gEfiVariableArchProtocolGuid & gEfiVariableWriteArchProtocolGuid again.
- //
- Status = gBS->CloseEvent (Event);
- ASSERT_EFI_ERROR (Status);
- Status = VariableCommonInitialize (Fvb);
- ASSERT_EFI_ERROR (Status);
-
- SystemTable->RuntimeServices->GetVariable = RuntimeServiceGetVariable;
- SystemTable->RuntimeServices->GetNextVariableName = RuntimeServiceGetNextVariableName;
- SystemTable->RuntimeServices->SetVariable = RuntimeServiceSetVariable;
- SystemTable->RuntimeServices->QueryVariableInfo = RuntimeServiceQueryVariableInfo;
-
- //
- // Now install the Variable Runtime Architectural Protocol on a new handle
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &mHandle,
- &gEfiVariableArchProtocolGuid, NULL,
- &gEfiVariableWriteArchProtocolGuid, NULL,
- NULL
- );
- ASSERT_EFI_ERROR (Status);
-
- Status = gBS->CreateEventEx (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- VariableClassAddressChangeEvent,
- NULL,
- &gEfiEventVirtualAddressChangeGuid,
- &mVirtualAddressChangeEvent
- );
- ASSERT_EFI_ERROR (Status);
+ if (Fvb == NULL) {
+ Status = EFI_NOT_FOUND;
}
-
-}
-
-/**
- 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 availible. It also registers
- notification function for 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
- )
-{
- //
- // Register FvbNotificationEvent () notify function.
- //
- EfiCreateProtocolNotifyEvent (
- &gEfiFirmwareVolumeBlockProtocolGuid,
- TPL_CALLBACK,
- FvbNotificationEvent,
- (VOID *)SystemTable,
- &mFvbRegistration
- );
-
- return EFI_SUCCESS;
+ return Status;
}
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h index 91fdf9dbfd..7cc039dea8 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h @@ -1,7 +1,7 @@ /** @file
The internal header file includes the common header files, defines
- internal structure and functions used by RuntimeVariable module.
+ internal structure and functions used by Variable modules.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
@@ -82,17 +82,17 @@ typedef struct { /**
Writes a buffer to variable storage space, in the working block.
- This function writes a buffer to variable storage space into firmware
- volume block device. The destination is specified by parameter
+ 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 variable to write
- @param Buffer Point to the data buffer
- @param BufferSize The number of bytes of the data Buffer
+ @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
+ @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
@@ -103,4 +103,329 @@ FtwVariableSpace ( );
+/**
+ 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 Attribues of the variable.
+
+ @param[in] Variable The variable information that 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, 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 VARIABLE_POINTER_TRACK *Variable
+ );
+
+
+/**
+ 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
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c new file mode 100644 index 0000000000..f9f20bdf6d --- /dev/null +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c @@ -0,0 +1,402 @@ +/** @file
+
+ Implement all four UEFI Runtime Variable services for the nonvolatile
+ and volatile storage space and install variable architecture protocol.
+
+Copyright (c) 2006 - 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"
+
+extern VARIABLE_STORE_HEADER *mNvVariableCache;
+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 **) &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 ();
+}
+
+
+/**
+ 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;
+
+ //
+ // Ensure FTW protocol is installed.
+ //
+ Status = GetFtwProtocol (&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;
+
+ 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 availible. 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
+ );
+
+ if (FeaturePcdGet (PcdVariableCollectStatistics)) {
+ gBS->InstallConfigurationTable (&gEfiVariableGuid, gVariableInfo);
+ }
+ return EFI_SUCCESS;
+}
+
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf index bde1d04386..15e000e69b 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf @@ -33,6 +33,7 @@ [Sources]
Reclaim.c
Variable.c
+ VariableDxe.c
Variable.h
[Packages]
@@ -76,7 +77,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## SOMETIME_CONSUMES (statistic the information of variable.)
[Depex]
- gEfiFirmwareVolumeBlockProtocolGuid AND gEfiFaultTolerantWriteProtocolGuid
+ TRUE
# [Event]
# ##
@@ -84,4 +85,5 @@ # #
# EVENT_TYPE_NOTIFY_SIGNAL ## PRODUCES
#
-#
\ No newline at end of file +#
+
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c new file mode 100644 index 0000000000..75a5163cb9 --- /dev/null +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c @@ -0,0 +1,585 @@ +/** @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, 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/SmmFaultTolerantWrite.h>
+#include <Library/SmmServicesTableLib.h>
+
+#include "Variable.h"
+#include "VariableSmmCommon.h"
+
+extern SMM_VARIABLE_COMMUNICATE_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_GUID mSmmVariableWriteGuid = EFI_SMM_VARIABLE_WRITE_GUID;
+
+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 SMM_VARIABLE_COMMUNICATE_VARIABLE_INFO_ENTRY *InfoEntry,
+ IN OUT UINTN *InfoSize
+ )
+{
+ SMM_VARIABLE_COMMUNICATE_VARIABLE_INFO_ENTRY *VariableInfo;
+ UINTN NameLength;
+ UINTN StatisticsInfoSize;
+ CHAR16 *InfoName;
+
+ ASSERT (InfoEntry != NULL);
+ VariableInfo = gVariableInfo;
+ if (VariableInfo == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ StatisticsInfoSize = sizeof (SMM_VARIABLE_COMMUNICATE_VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name);
+ if (*InfoSize < sizeof (SMM_VARIABLE_COMMUNICATE_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 (SMM_VARIABLE_COMMUNICATE_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 (SMM_VARIABLE_COMMUNICATE_VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name);
+ if (*InfoSize < StatisticsInfoSize) {
+ *InfoSize = StatisticsInfoSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ CopyMem (InfoEntry, VariableInfo, sizeof (SMM_VARIABLE_COMMUNICATE_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;
+ SMM_VARIABLE_COMMUNICATE_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 = (SMM_VARIABLE_COMMUNICATE_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 (&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,
+ &mSmmVariableWriteGuid,
+ 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 availible. 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;
+}
+
+
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf new file mode 100644 index 0000000000..6a52c6f490 --- /dev/null +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf @@ -0,0 +1,86 @@ +## @file +# Component description file for SMM 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, 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 = 23A089B3-EED5-4ac5-B2AB-43E3298C2343 + 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 + Variable.h + VariableSmmCommon.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + MemoryAllocationLib + BaseLib + SynchronizationLib + UefiLib + SmmLib + SmmServicesTableLib + BaseMemoryLib + DebugLib + DxeServicesTableLib + +[Protocols] + gEfiSmmFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES + gEfiSmmVariableProtocolGuid ## ALWAYS_PRODUCES + gEfiSmmFaultTolerantWriteProtocolGuid ## SOMETIMES_CONSUMES + +[Guids] + gEfiVariableGuid ## PRODUCES ## Configuration Table Guid + gEfiGlobalVariableGuid ## PRODUCES ## Variable Guid + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize + gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize + +[FeaturePcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## SOMETIME_CONSUMES (statistic the information of variable.) + +[Depex] + TRUE + +
\ No newline at end of file diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmCommon.h b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmCommon.h new file mode 100644 index 0000000000..06541ecb0f --- /dev/null +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmCommon.h @@ -0,0 +1,40 @@ +/** @file
+
+ The internal header file includes the common header files shared
+ by VariableSmm module and VariableSmmRuntimeDxe module.
+
+Copyright (c) 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.
+
+**/
+
+#ifndef _VARIABLE_SMM_COMMON_H_
+#define _VARIABLE_SMM_COMMON_H_
+
+#include <PiDxe.h>
+
+#include <Protocol/SmmVariable.h>
+#include <Protocol/SmmFirmwareVolumeBlock.h>
+#include <Guid/VariableFormat.h>
+
+#define EFI_SMM_VARIABLE_WRITE_GUID \
+ { 0x93ba1826, 0xdffb, 0x45dd, { 0x82, 0xa7, 0xe7, 0xdc, 0xaa, 0x3b, 0xbd, 0xf3 } }
+
+///
+/// Size of SMM communicate header, without including the payload.
+///
+#define SMM_COMMUNICATE_HEADER_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data))
+
+///
+/// Size of SMM variable communicate header, without including the payload.
+///
+#define SMM_VARIABLE_COMMUNICATE_HEADER_SIZE (OFFSET_OF (SMM_VARIABLE_COMMUNICATE_HEADER, Data))
+
+
+#endif
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c new file mode 100644 index 0000000000..ac8b96c766 --- /dev/null +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c @@ -0,0 +1,650 @@ +/** @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, 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/VariableWrite.h>
+#include <Protocol/Variable.h>
+#include <Protocol/SmmCommunication.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 "VariableSmmCommon.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;
+EFI_GUID mSmmVariableWriteGuid = EFI_SMM_VARIABLE_WRITE_GUID;
+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 (&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 (&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 (&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_VARIABLE_INFO_ENTRY);
+ Status = InitCommunicateBuffer (&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 (&mSmmVariableWriteGuid, 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 availible. 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 (
+ &mSmmVariableWriteGuid,
+ 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;
+}
+
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf new file mode 100644 index 0000000000..9f1a6ff7e1 --- /dev/null +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf @@ -0,0 +1,69 @@ +## @file
+# Component description file for 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, 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 = 9F7DCADE-11EA-448a-A46F-76E003657DD1
+ 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
+ VariableSmmCommon.h
+
+[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
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
+
+[Depex]
+ gEfiSmmCommunicationProtocolGuid
|