summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Platform/Intel/MinPlatformPkg/Include/Dsc/CoreCommonLib.dsc3
-rw-r--r--Platform/Intel/MinPlatformPkg/Include/Library/LargeVariableReadLib.h61
-rw-r--r--Platform/Intel/MinPlatformPkg/Library/BaseLargeVariableLib/BaseLargeVariableReadLib.inf51
-rw-r--r--Platform/Intel/MinPlatformPkg/Library/BaseLargeVariableLib/LargeVariableCommon.h47
-rw-r--r--Platform/Intel/MinPlatformPkg/Library/BaseLargeVariableLib/LargeVariableReadLib.c176
-rw-r--r--Platform/Intel/MinPlatformPkg/MinPlatformPkg.dec1
6 files changed, 338 insertions, 1 deletions
diff --git a/Platform/Intel/MinPlatformPkg/Include/Dsc/CoreCommonLib.dsc b/Platform/Intel/MinPlatformPkg/Include/Dsc/CoreCommonLib.dsc
index 61d47109..2b207a94 100644
--- a/Platform/Intel/MinPlatformPkg/Include/Dsc/CoreCommonLib.dsc
+++ b/Platform/Intel/MinPlatformPkg/Include/Dsc/CoreCommonLib.dsc
@@ -136,13 +136,14 @@
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
-
+
!if gMinPlatformPkgTokenSpaceGuid.PcdUefiSecureBootEnable == TRUE
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
!endif
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
+ LargeVariableReadLib|MinPlatformPkg/Library/BaseLargeVariableLib/BaseLargeVariableReadLib.inf
#
# CryptLib
diff --git a/Platform/Intel/MinPlatformPkg/Include/Library/LargeVariableReadLib.h b/Platform/Intel/MinPlatformPkg/Include/Library/LargeVariableReadLib.h
new file mode 100644
index 00000000..df5020b9
--- /dev/null
+++ b/Platform/Intel/MinPlatformPkg/Include/Library/LargeVariableReadLib.h
@@ -0,0 +1,61 @@
+/** @file
+ Large Variable Read Lib
+
+ This library is used to retrieve large data sets using the UEFI Variable
+ Services. At time of writing, most UEFI Variable Services implementations do
+ not allow more than 64KB of data to be stored in a single UEFI variable. This
+ library will split data sets across multiple variables as needed.
+
+ In the case where more than one variable is needed to store the data, an
+ integer number will be added to the end of the variable name. This number
+ will be incremented for each variable as needed to retrieve the entire data
+ set.
+
+ The primary use for this library is to create binary compatible drivers
+ and OpROMs which need to work both with TianoCore and other UEFI PI
+ implementations. When customizing and recompiling the platform firmware image
+ is possible, adjusting the value of PcdMaxVariableSize may provide a simpler
+ solution to this problem.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _LARGE_VARIABLE_READ_LIB_H_
+#define _LARGE_VARIABLE_READ_LIB_H_
+
+#include <Uefi/UefiBaseType.h>
+
+/**
+ Returns the value of a large variable.
+
+ @param[in] VariableName A Null-terminated string that is the name of the vendor's
+ variable.
+ @param[in] VendorGuid A unique identifier for the vendor.
+ @param[in, out] DataSize On input, the size in bytes of the return Data buffer.
+ On output the size of data returned in Data.
+ @param[out] Data The buffer to return the contents of the variable. May be NULL
+ with a zero DataSize in order to determine the size buffer needed.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_NOT_FOUND The variable was not found.
+ @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result.
+ @retval EFI_INVALID_PARAMETER VariableName is NULL.
+ @retval EFI_INVALID_PARAMETER VendorGuid is NULL.
+ @retval EFI_INVALID_PARAMETER DataSize is NULL.
+ @retval EFI_INVALID_PARAMETER The DataSize is not too small and Data is NULL.
+ @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error.
+ @retval EFI_SECURITY_VIOLATION The variable could not be retrieved due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+GetLargeVariable (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN OUT UINTN *DataSize,
+ OUT VOID *Data OPTIONAL
+ );
+
+#endif // _LARGE_VARIABLE_READ_LIB_H_
diff --git a/Platform/Intel/MinPlatformPkg/Library/BaseLargeVariableLib/BaseLargeVariableReadLib.inf b/Platform/Intel/MinPlatformPkg/Library/BaseLargeVariableLib/BaseLargeVariableReadLib.inf
new file mode 100644
index 00000000..3cd94e00
--- /dev/null
+++ b/Platform/Intel/MinPlatformPkg/Library/BaseLargeVariableLib/BaseLargeVariableReadLib.inf
@@ -0,0 +1,51 @@
+## @file
+# Component description file for Large Variable Read Library
+#
+# This library is used to retrieve large data sets using the UEFI Variable
+# Services. At time of writing, most UEFI Variable Services implementations do
+# not allow more than 64KB of data to be stored in a single UEFI variable. This
+# library will split data sets across multiple variables as needed.
+#
+# In the case where more than one variable is needed to store the data, an
+# integer number will be added to the end of the variable name. This number
+# will be incremented for each variable as needed to retrieve the entire data
+# set.
+#
+# The primary use for this library is to create binary compatible drivers
+# and OpROMs which need to work both with TianoCore and other UEFI PI
+# implementations. When customizing and recompiling the platform firmware image
+# is possible, adjusting the value of PcdMaxVariableSize may provide a simpler
+# solution to this problem.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseLargeVariableReadLib
+ FILE_GUID = 4E9D7D31-A7A0-4004-AE93-D12F1AB08730
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = LargeVariableReadLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ LargeVariableReadLib.c
+ LargeVariableCommon.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MinPlatformPkg/MinPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+ VariableReadLib
diff --git a/Platform/Intel/MinPlatformPkg/Library/BaseLargeVariableLib/LargeVariableCommon.h b/Platform/Intel/MinPlatformPkg/Library/BaseLargeVariableLib/LargeVariableCommon.h
new file mode 100644
index 00000000..b6554764
--- /dev/null
+++ b/Platform/Intel/MinPlatformPkg/Library/BaseLargeVariableLib/LargeVariableCommon.h
@@ -0,0 +1,47 @@
+/** @file
+ Large Variable Lib Common Header
+
+ These libraries is used to store large data sets using the UEFI Variable
+ Services. At time of writing, most UEFI Variable Services implementations do
+ not allow more than 64KB of data to be stored in a single UEFI variable. This
+ library will split data sets across multiple variables as needed.
+
+ In the case where more than one variable is needed to store the data, an
+ integer number will be added to the end of the variable name. This number
+ will be incremented for each variable as needed to retrieve the entire data
+ set.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _LARGE_VARIABLE_COMMON_H_
+#define _LARGE_VARIABLE_COMMON_H_
+
+//
+// 1024 was choosen because this is the size of the SMM communication buffer
+// used by VariableDxeSmm to transfer the VariableName from DXE to SMM. Choosing
+// the same size will prevent this library from limiting variable names any
+// more than the MdeModulePkg implementation of UEFI Variable Services does.
+//
+#define MAX_VARIABLE_NAME_SIZE 1024
+
+//
+// The 2012 Windows Hardware Requirements specified a minimum variable size of
+// 32KB. By setting the maximum allowed number of variables to 0x20000, this
+// allows up to 4GB of data to be stored on most UEFI implementations in
+// existence. Older UEFI implementations were known to only provide 8KB per
+// variable. In this case, up to 1GB can be stored. Since 1GB vastly exceeds the
+// size of any known NvStorage FV, choosing this number should effectively
+// enable all available NvStorage space to be used to store the given data.
+//
+#define MAX_VARIABLE_SPLIT 131072 // 0x20000
+
+//
+// There are 6 digits in the number 131072, which means the length of the string
+// representation of this number will be at most 6 characters long.
+//
+#define MAX_VARIABLE_SPLIT_DIGITS 6
+
+#endif // _LARGE_VARIABLE_COMMON_H_
diff --git a/Platform/Intel/MinPlatformPkg/Library/BaseLargeVariableLib/LargeVariableReadLib.c b/Platform/Intel/MinPlatformPkg/Library/BaseLargeVariableLib/LargeVariableReadLib.c
new file mode 100644
index 00000000..08690d1f
--- /dev/null
+++ b/Platform/Intel/MinPlatformPkg/Library/BaseLargeVariableLib/LargeVariableReadLib.c
@@ -0,0 +1,176 @@
+/** @file
+ Large Variable Read Lib
+
+ This library is used to retrieve large data sets using the UEFI Variable
+ Services. At time of writing, most UEFI Variable Services implementations do
+ not allow more than 64KB of data to be stored in a single UEFI variable. This
+ library will split data sets across multiple variables as needed.
+
+ In the case where more than one variable is needed to store the data, an
+ integer number will be added to the end of the variable name. This number
+ will be incremented for each variable as needed to retrieve the entire data
+ set.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PrintLib.h>
+#include <Library/VariableReadLib.h>
+
+#include "LargeVariableCommon.h"
+
+/**
+ Returns the value of a large variable.
+
+ @param[in] VariableName A Null-terminated string that is the name of the vendor's
+ variable.
+ @param[in] VendorGuid A unique identifier for the vendor.
+ @param[in, out] DataSize On input, the size in bytes of the return Data buffer.
+ On output the size of data returned in Data.
+ @param[out] Data The buffer to return the contents of the variable. May be NULL
+ with a zero DataSize in order to determine the size buffer needed.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_NOT_FOUND The variable was not found.
+ @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result.
+ @retval EFI_INVALID_PARAMETER VariableName is NULL.
+ @retval EFI_INVALID_PARAMETER VendorGuid is NULL.
+ @retval EFI_INVALID_PARAMETER DataSize is NULL.
+ @retval EFI_INVALID_PARAMETER The DataSize is not too small and Data is NULL.
+ @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error.
+ @retval EFI_SECURITY_VIOLATION The variable could not be retrieved due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+GetLargeVariable (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN OUT UINTN *DataSize,
+ OUT VOID *Data OPTIONAL
+ )
+{
+ CHAR16 TempVariableName[MAX_VARIABLE_NAME_SIZE];
+ EFI_STATUS Status;
+ UINTN TotalSize;
+ UINTN VarDataSize;
+ UINTN Index;
+ UINTN VariableSize;
+ UINTN BytesRemaining;
+ UINT8 *OffsetPtr;
+
+ VarDataSize = 0;
+
+ //
+ // First check if a variable with the given name exists
+ //
+ Status = VarLibGetVariable (VariableName, VendorGuid, NULL, &VarDataSize, NULL);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ if (*DataSize >= VarDataSize) {
+ if (Data == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+ DEBUG ((DEBUG_VERBOSE, "GetLargeVariable: Single Variable Found\n"));
+ Status = VarLibGetVariable (VariableName, VendorGuid, NULL, DataSize, Data);
+ goto Done;
+ } else {
+ *DataSize = VarDataSize;
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ } else if (Status == EFI_NOT_FOUND) {
+ //
+ // Check if the first variable of a multi-variable set exists
+ //
+ if (StrLen (VariableName) >= (MAX_VARIABLE_NAME_SIZE - MAX_VARIABLE_SPLIT_DIGITS)) {
+ DEBUG ((DEBUG_ERROR, "GetLargeVariable: Variable name too long\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ VarDataSize = 0;
+ Index = 0;
+ ZeroMem (TempVariableName, MAX_VARIABLE_NAME_SIZE);
+ UnicodeSPrint (TempVariableName, MAX_VARIABLE_NAME_SIZE, L"%s%d", VariableName, Index);
+ Status = VarLibGetVariable (TempVariableName, VendorGuid, NULL, &VarDataSize, NULL);
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // The first variable exists. Calculate the total size of all the variables.
+ //
+ DEBUG ((DEBUG_VERBOSE, "GetLargeVariable: Multiple Variables Found\n"));
+ TotalSize = 0;
+ for (Index = 0; Index < MAX_VARIABLE_SPLIT; Index++) {
+ VarDataSize = 0;
+ ZeroMem (TempVariableName, MAX_VARIABLE_NAME_SIZE);
+ UnicodeSPrint (TempVariableName, MAX_VARIABLE_NAME_SIZE, L"%s%d", VariableName, Index);
+ Status = VarLibGetVariable (TempVariableName, VendorGuid, NULL, &VarDataSize, NULL);
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ break;
+ }
+ TotalSize += VarDataSize;
+ }
+ DEBUG ((DEBUG_VERBOSE, "TotalSize = %d, NumVariables = %d\n", TotalSize, Index));
+
+ //
+ // Check if the user provided a large enough buffer
+ //
+ if (*DataSize >= TotalSize) {
+ if (Data == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Read the data from all variables
+ //
+ OffsetPtr = (UINT8 *) Data;
+ BytesRemaining = *DataSize;
+ for (Index = 0; Index < MAX_VARIABLE_SPLIT; Index++) {
+ VarDataSize = 0;
+ ZeroMem (TempVariableName, MAX_VARIABLE_NAME_SIZE);
+ UnicodeSPrint (TempVariableName, MAX_VARIABLE_NAME_SIZE, L"%s%d", VariableName, Index);
+ VariableSize = BytesRemaining;
+ DEBUG ((DEBUG_INFO, "Reading %s, Guid = %g,", TempVariableName, VendorGuid));
+ Status = VarLibGetVariable (TempVariableName, VendorGuid, NULL, &VariableSize, (VOID *) OffsetPtr);
+ DEBUG ((DEBUG_INFO, " Size %d\n", VariableSize));
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((DEBUG_VERBOSE, "No more variables found\n"));
+ Status = EFI_SUCCESS; // The end has been reached
+ }
+ goto Done;
+ }
+
+ if (VariableSize < BytesRemaining) {
+ BytesRemaining -= VariableSize;
+ OffsetPtr += VariableSize;
+ } else {
+ DEBUG ((DEBUG_VERBOSE, "All data has been read\n"));
+ BytesRemaining = 0;
+ break;
+ }
+ } //End of for loop
+
+ goto Done;
+ } else {
+ *DataSize = TotalSize;
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+ } else {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+
+Done:
+ DEBUG ((DEBUG_ERROR, "GetLargeVariable: Status = %r\n", Status));
+ return Status;
+}
diff --git a/Platform/Intel/MinPlatformPkg/MinPlatformPkg.dec b/Platform/Intel/MinPlatformPkg/MinPlatformPkg.dec
index 0811b479..91970a62 100644
--- a/Platform/Intel/MinPlatformPkg/MinPlatformPkg.dec
+++ b/Platform/Intel/MinPlatformPkg/MinPlatformPkg.dec
@@ -85,6 +85,7 @@
VariableReadLib|Include/Library/VariableReadLib.h
VariableWriteLib|Include/Library/VariableWriteLib.h
+ LargeVariableReadLib|Include/Library/LargeVariableReadLib.h
[PcdsFixedAtBuild, PcdsPatchableInModule]