MdeModulePkg/Variable: Add RT GetNextVariableName() cache support

https://bugzilla.tianocore.org/show_bug.cgi?id=2220

This change implements the Runtime Service GetNextVariableName()
using the runtime cache in VariableSmmRuntimeDxe. Runtime Service
calls to GetNextVariableName() will no longer trigger a SW SMI
when gEfiMdeModulePkgTokenSpaceGuid.PcdEnableVariableRuntimeCache
is set to TRUE (default value).

Overall system performance and stability will be improved by
eliminating an SMI for these calls as they typically result in a
relatively large number of invocations to retrieve all variable
names in all variable stores present.

Cc: Dandan Bi <dandan.bi@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Signed-off-by: Michael Kubacki <michael.a.kubacki@intel.com>
Reviewed-by: Jian J Wang <jian.j.wang@intel.com>
Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
This commit is contained in:
Michael Kubacki 2019-09-23 18:49:37 -07:00
parent aab3b9b9a1
commit 6f9838f32f
1 changed files with 128 additions and 9 deletions

View File

@ -823,7 +823,7 @@ RuntimeServiceGetVariable (
} }
/** /**
This code Finds the Next available variable. Finds the next available variable in a runtime cache variable store.
@param[in, out] VariableNameSize Size of the variable name. @param[in, out] VariableNameSize Size of the variable name.
@param[in, out] VariableName Pointer to variable name. @param[in, out] VariableName Pointer to variable name.
@ -836,8 +836,81 @@ RuntimeServiceGetVariable (
**/ **/
EFI_STATUS EFI_STATUS
EFIAPI GetNextVariableNameInRuntimeCache (
RuntimeServiceGetNextVariableName ( IN OUT UINTN *VariableNameSize,
IN OUT CHAR16 *VariableName,
IN OUT EFI_GUID *VendorGuid
)
{
EFI_STATUS Status;
UINTN VarNameSize;
VARIABLE_HEADER *VariablePtr;
VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];
Status = EFI_NOT_FOUND;
//
// The UEFI specification restricts Runtime Services callers from invoking the same or certain other Runtime Service
// functions prior to completion and return from a previous Runtime Service call. These restrictions prevent
// a GetVariable () or GetNextVariable () call from being issued until a prior call has returned. The runtime
// cache read lock should always be free when entering this function.
//
ASSERT (!mVariableRuntimeCacheReadLock);
CheckForRuntimeCacheSync ();
mVariableRuntimeCacheReadLock = TRUE;
if (!mVariableRuntimeCachePendingUpdate) {
//
// 0: Volatile, 1: HOB, 2: Non-Volatile.
// The index and attributes mapping must be kept in this order as FindVariable
// makes use of this mapping to implement search algorithm.
//
VariableStoreHeader[VariableStoreTypeVolatile] = mVariableRuntimeVolatileCacheBuffer;
VariableStoreHeader[VariableStoreTypeHob] = mVariableRuntimeHobCacheBuffer;
VariableStoreHeader[VariableStoreTypeNv] = mVariableRuntimeNvCacheBuffer;
Status = VariableServiceGetNextVariableInternal (
VariableName,
VendorGuid,
VariableStoreHeader,
&VariablePtr,
mVariableAuthFormat
);
if (!EFI_ERROR (Status)) {
VarNameSize = NameSizeOfVariable (VariablePtr, mVariableAuthFormat);
ASSERT (VarNameSize != 0);
if (VarNameSize <= *VariableNameSize) {
CopyMem (VariableName, GetVariableNamePtr (VariablePtr, mVariableAuthFormat), VarNameSize);
CopyMem (VendorGuid, GetVendorGuidPtr (VariablePtr, mVariableAuthFormat), sizeof (EFI_GUID));
Status = EFI_SUCCESS;
} else {
Status = EFI_BUFFER_TOO_SMALL;
}
*VariableNameSize = VarNameSize;
}
}
mVariableRuntimeCacheReadLock = FALSE;
return Status;
}
/**
Finds the next available variable in a SMM variable store.
@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
GetNextVariableNameInSmm (
IN OUT UINTN *VariableNameSize, IN OUT UINTN *VariableNameSize,
IN OUT CHAR16 *VariableName, IN OUT CHAR16 *VariableName,
IN OUT EFI_GUID *VendorGuid IN OUT EFI_GUID *VendorGuid
@ -849,10 +922,6 @@ RuntimeServiceGetNextVariableName (
UINTN OutVariableNameSize; UINTN OutVariableNameSize;
UINTN InVariableNameSize; UINTN InVariableNameSize;
if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {
return EFI_INVALID_PARAMETER;
}
OutVariableNameSize = *VariableNameSize; OutVariableNameSize = *VariableNameSize;
InVariableNameSize = StrSize (VariableName); InVariableNameSize = StrSize (VariableName);
SmmGetNextVariableName = NULL; SmmGetNextVariableName = NULL;
@ -864,8 +933,6 @@ RuntimeServiceGetNextVariableName (
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
AcquireLockOnlyAtBootTime(&mVariableServicesLock);
// //
// Init the communicate buffer. The buffer data size is: // Init the communicate buffer. The buffer data size is:
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize. // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
@ -924,7 +991,59 @@ RuntimeServiceGetNextVariableName (
CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize); CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize);
Done: Done:
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 MaxLen;
Status = EFI_NOT_FOUND;
if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Calculate the possible maximum length of name string, including the Null terminator.
//
MaxLen = *VariableNameSize / sizeof (CHAR16);
if ((MaxLen == 0) || (StrnLenS (VariableName, MaxLen) == MaxLen)) {
//
// Null-terminator is not found in the first VariableNameSize bytes of the input VariableName buffer,
// follow spec to return EFI_INVALID_PARAMETER.
//
return EFI_INVALID_PARAMETER;
}
AcquireLockOnlyAtBootTime (&mVariableServicesLock);
if (FeaturePcdGet (PcdEnableVariableRuntimeCache)) {
Status = GetNextVariableNameInRuntimeCache (VariableNameSize, VariableName, VendorGuid);
} else {
Status = GetNextVariableNameInSmm (VariableNameSize, VariableName, VendorGuid);
}
ReleaseLockOnlyAtBootTime (&mVariableServicesLock); ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
return Status; return Status;
} }