391 lines
11 KiB
C
391 lines
11 KiB
C
/** @file
|
|
Common variable supports functions for user can extract whole variables
|
|
(including variable header) from variable store.
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2012 - 2019, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
|
|
#include <Library/VariableSupportLib.h>
|
|
#include <Library/PcdLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/BaseLib.h>
|
|
|
|
#include <Pi/PiFirmwareVolume.h>
|
|
|
|
/**
|
|
This code gets the current status of Variable Store.
|
|
|
|
@param[in] 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.
|
|
**/
|
|
VARIABLE_STORE_STATUS
|
|
GetVariableStoreStatus (
|
|
IN CONST VARIABLE_STORE_HEADER *VarStoreHeader
|
|
)
|
|
{
|
|
ECP_VARIABLE_STORE_HEADER *EcpVarStoreHeader;
|
|
|
|
if (PcdGetBool (PcdUseEcpVariableStoreHeader)) {
|
|
EcpVarStoreHeader = (ECP_VARIABLE_STORE_HEADER *) VarStoreHeader;
|
|
if (EcpVarStoreHeader->Signature == ECP_VARIABLE_STORE_SIGNATURE &&
|
|
EcpVarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
|
|
EcpVarStoreHeader->State == VARIABLE_STORE_HEALTHY
|
|
) {
|
|
|
|
return EfiValid;
|
|
}
|
|
|
|
if (EcpVarStoreHeader->Signature == 0xffffffff &&
|
|
EcpVarStoreHeader->Size == 0xffffffff &&
|
|
EcpVarStoreHeader->Format == 0xff &&
|
|
EcpVarStoreHeader->State == 0xff
|
|
) {
|
|
|
|
return EfiRaw;
|
|
} else {
|
|
|
|
return EfiInvalid;
|
|
}
|
|
} else {
|
|
if ((CompareGuid (&VarStoreHeader->Signature, &gEfiAuthenticatedVariableGuid) ||
|
|
CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid)) &&
|
|
VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
|
|
VarStoreHeader->State == VARIABLE_STORE_HEALTHY
|
|
) {
|
|
|
|
return EfiValid;
|
|
}
|
|
|
|
if (((UINT32 *)(&VarStoreHeader->Signature))[0] == 0xffffffff &&
|
|
((UINT32 *)(&VarStoreHeader->Signature))[1] == 0xffffffff &&
|
|
((UINT32 *)(&VarStoreHeader->Signature))[2] == 0xffffffff &&
|
|
((UINT32 *)(&VarStoreHeader->Signature))[3] == 0xffffffff &&
|
|
VarStoreHeader->Size == 0xffffffff &&
|
|
VarStoreHeader->Format == 0xff &&
|
|
VarStoreHeader->State == 0xff
|
|
) {
|
|
|
|
return EfiRaw;
|
|
} else {
|
|
return EfiInvalid;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
This code checks if variable header is valid or not.
|
|
|
|
@param[in] Variable Pointer to the Variable Header.
|
|
|
|
@retval TRUE Variable header is valid.
|
|
@retval FALSE Variable header is not valid.
|
|
**/
|
|
BOOLEAN
|
|
IsValidVariableHeader (
|
|
IN CONST VARIABLE_HEADER *Variable
|
|
)
|
|
{
|
|
if (Variable == NULL || Variable->StartId != VARIABLE_DATA) {
|
|
return FALSE;
|
|
}
|
|
|
|
if ((GetVariableStoreHeaderSize () + Variable->NameSize + Variable->DataSize) > MAX_VARIABLE_SIZE) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
This code gets the size of name of variable.
|
|
|
|
@param[in] Variable Pointer to the Variable Header.
|
|
|
|
@return UINTN Size of variable in bytes.
|
|
**/
|
|
UINTN
|
|
NameSizeOfVariable (
|
|
IN CONST VARIABLE_HEADER *Variable
|
|
)
|
|
{
|
|
if (Variable->State == (UINT8) (-1) ||
|
|
Variable->DataSize == (UINT32) (-1) ||
|
|
Variable->NameSize == (UINT32) (-1) ||
|
|
Variable->Attributes == (UINT32) (-1)) {
|
|
return 0;
|
|
}
|
|
return (UINTN) Variable->NameSize;
|
|
}
|
|
|
|
/**
|
|
This code gets the pointer to the variable data.
|
|
|
|
@param[in] Variable Pointer to the Variable Header.
|
|
|
|
@retval NULL Variable start id is incorrect.
|
|
@return UINT8* Pointer to Variable Data.
|
|
**/
|
|
UINT8 *
|
|
GetVariableDataPtr (
|
|
IN CONST VARIABLE_HEADER *Variable
|
|
)
|
|
{
|
|
CHAR16 *VariableName;
|
|
|
|
if (Variable->StartId != VARIABLE_DATA) {
|
|
return NULL;
|
|
}
|
|
//
|
|
// Be careful about pad size for alignment
|
|
//
|
|
VariableName = GET_VARIABLE_NAME_PTR (Variable);
|
|
return (UINT8 *) ((UINTN) VariableName + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize));
|
|
}
|
|
|
|
/**
|
|
This code gets the pointer to the next variable header.
|
|
|
|
@param[in] Variable Pointer to the Variable Header.
|
|
|
|
@return VARIABLE_HEADER* Pointer to next variable header.
|
|
**/
|
|
VARIABLE_HEADER *
|
|
GetNextVariablePtr (
|
|
IN CONST VARIABLE_HEADER *Variable
|
|
)
|
|
{
|
|
UINTN Value;
|
|
|
|
if (!IsValidVariableHeader (Variable)) {
|
|
return NULL;
|
|
}
|
|
//
|
|
// Be careful about pad size for alignment
|
|
//
|
|
Value = (UINTN) GetVariableDataPtr (Variable);
|
|
Value += Variable->DataSize;
|
|
Value += GET_PAD_SIZE (Variable->DataSize);
|
|
|
|
//
|
|
// Be careful about pad size for alignment.
|
|
//
|
|
return (VARIABLE_HEADER *) HEADER_ALIGN (Value);
|
|
}
|
|
|
|
/**
|
|
Gets the pointer to the first variable header in given variable store area.
|
|
|
|
@param[in] VarStoreHeader Pointer to the Variable Store Header.
|
|
|
|
@return VARIABLE_HEADER* Pointer to the first variable header.
|
|
**/
|
|
VARIABLE_HEADER *
|
|
GetStartPointer (
|
|
IN CONST VARIABLE_STORE_HEADER *VarStoreHeader
|
|
)
|
|
{
|
|
return (VARIABLE_HEADER *) HEADER_ALIGN (((UINT8 *) VarStoreHeader) + GetVariableStoreHeaderSize ());
|
|
}
|
|
|
|
/**
|
|
Gets the pointer to the end of the variable storage area.
|
|
|
|
This function gets pointer to the end of the variable storage
|
|
area, according to the input variable store header.
|
|
|
|
@param[in] VarStoreHeader Pointer to the Variable Store Header.
|
|
|
|
@return VARIABLE_HEADER* Pointer to the end of the variable storage area.
|
|
**/
|
|
VARIABLE_HEADER *
|
|
GetEndPointer (
|
|
IN CONST VARIABLE_STORE_HEADER *VarStoreHeader
|
|
)
|
|
{
|
|
return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + GetVariableStoreSize (VarStoreHeader));
|
|
|
|
}
|
|
|
|
/**
|
|
This code gets the size of variable data.
|
|
|
|
@param[in] Variable Pointer to the Variable Header.
|
|
|
|
@return UINTN Size of variable in bytes.
|
|
**/
|
|
UINTN
|
|
DataSizeOfVariable (
|
|
IN CONST VARIABLE_HEADER *Variable
|
|
)
|
|
{
|
|
if (Variable->State == (UINT8) (-1) ||
|
|
Variable->DataSize == (UINT32) (-1) ||
|
|
Variable->NameSize == (UINT32) (-1) ||
|
|
Variable->Attributes == (UINT32) (-1)) {
|
|
return 0;
|
|
}
|
|
return (UINTN) Variable->DataSize;
|
|
}
|
|
|
|
/**
|
|
This code gets the size of variable store.
|
|
|
|
@param[in] VarStoreHeader Pointer to the Variable Store Header.
|
|
|
|
@return UINT32 Total size of variable store.
|
|
**/
|
|
UINT32
|
|
GetVariableStoreSize (
|
|
IN CONST VARIABLE_STORE_HEADER *VariableStoreHeader
|
|
)
|
|
{
|
|
if (PcdGetBool (PcdUseEcpVariableStoreHeader)) {
|
|
return ((ECP_VARIABLE_STORE_HEADER *) VariableStoreHeader)->Size;
|
|
} else {
|
|
return VariableStoreHeader->Size;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Gets the size of variable store header.
|
|
|
|
@return UINTN size by byte of variable store header.
|
|
**/
|
|
UINTN
|
|
GetVariableStoreHeaderSize (
|
|
VOID
|
|
)
|
|
{
|
|
return PcdGetBool (PcdUseEcpVariableStoreHeader) ? sizeof (ECP_VARIABLE_STORE_HEADER) : sizeof (VARIABLE_STORE_HEADER);
|
|
}
|
|
|
|
/**
|
|
This code gets the Size of extension variable store header.
|
|
|
|
@param[in] VarStoreHeader Pointer to the Variable Store Header.
|
|
|
|
@return UINT16 Size of extension variable store header.
|
|
**/
|
|
UINT16
|
|
GetExtVariableHeaderSize (
|
|
IN CONST VARIABLE_STORE_HEADER *VariableStoreHeader
|
|
)
|
|
{
|
|
if (PcdGetBool (PcdUseEcpVariableStoreHeader)) {
|
|
return ((ECP_VARIABLE_STORE_HEADER *) VariableStoreHeader)->ExtHeaderSize;
|
|
} else {
|
|
return VariableStoreHeader->ExtHeaderSize;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Helper function to get the Board ID from variable store header.
|
|
|
|
@param[in] VarStoreHeader Pointer to the Variable Store Header.
|
|
|
|
@return the board ID in this variable store.
|
|
|
|
**/
|
|
STATIC
|
|
H2O_BOARD_ID
|
|
GetBoardIdFromVariableStoreHeader (
|
|
IN CONST VARIABLE_STORE_HEADER *VariableStoreHeader
|
|
)
|
|
{
|
|
if (PcdGetBool (PcdUseEcpVariableStoreHeader)) {
|
|
return (UINT64)((ECP_VARIABLE_STORE_HEADER *) VariableStoreHeader)->BoardId;
|
|
} else {
|
|
return (UINT64)VariableStoreHeader->BoardId;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Helper function to get the Board ID from variable store.
|
|
|
|
Get SKUID from EXT variable store header or variable store Header if EXT
|
|
variable store header doesn't exist.
|
|
|
|
@param[in] Buffer Pointer to variable store header.
|
|
|
|
@return the board ID in this variable store.
|
|
**/
|
|
H2O_BOARD_ID
|
|
GetBoardIdFromVariableStore (
|
|
IN CONST VARIABLE_STORE_HEADER *VariableStoreHeader
|
|
)
|
|
{
|
|
UINT32 Size;
|
|
UINT16 ExtHeaderSize;
|
|
EXT_VARIABLE_STORE_HEADER *ExtHeader;
|
|
|
|
ExtHeaderSize = GetExtVariableHeaderSize (VariableStoreHeader);
|
|
Size = GetVariableStoreSize (VariableStoreHeader);
|
|
|
|
if (ExtHeaderSize == 0 || Size < ExtHeaderSize) {
|
|
return GetBoardIdFromVariableStoreHeader (VariableStoreHeader);
|
|
}
|
|
ExtHeader = (EXT_VARIABLE_STORE_HEADER *)((UINT8 *)VariableStoreHeader + (Size - ExtHeaderSize));
|
|
return ExtHeader->BoardId;
|
|
}
|
|
|
|
/**
|
|
According to variable name and GUID to find this variable is whether in input buffer.
|
|
|
|
@param[in] VariableName Name of Variable to be found.
|
|
@param[in] VendorGuid Variable vendor GUID.
|
|
@param[in] Buffer Pointer to variable buffer.
|
|
@param[in] BufferSize the size in bytes of the buffer
|
|
|
|
@retval TRUE The function completed successfully.
|
|
@retval FALSE The function could not complete successfully.
|
|
**/
|
|
BOOLEAN
|
|
DoesVariableExist (
|
|
IN CONST CHAR16 *VariableName,
|
|
IN CONST EFI_GUID *VendorGuid,
|
|
IN CONST UINT8 *Buffer,
|
|
IN UINTN BufferSize
|
|
)
|
|
{
|
|
UINTN HeaderSize;
|
|
UINTN CurrentSearchedSize;
|
|
VARIABLE_HEADER *VariableHeader;
|
|
VARIABLE_HEADER *NexVariable;
|
|
BOOLEAN VariableFound;
|
|
|
|
VariableFound = FALSE;
|
|
if (VariableName == NULL || VendorGuid == NULL || Buffer == NULL) {
|
|
return VariableFound;
|
|
}
|
|
|
|
HeaderSize = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY) + GetVariableStoreHeaderSize ();
|
|
if (BufferSize < HeaderSize) {
|
|
return VariableFound;
|
|
}
|
|
|
|
VariableHeader = (VARIABLE_HEADER *) (Buffer + HeaderSize);
|
|
CurrentSearchedSize = HeaderSize;
|
|
while (IsValidVariableHeader (VariableHeader) && CurrentSearchedSize < BufferSize) {
|
|
NexVariable = GetNextVariablePtr (VariableHeader);
|
|
if (VariableHeader->State == VAR_ADDED && StrCmp (VariableName, GET_VARIABLE_NAME_PTR (VariableHeader)) == 0 &&
|
|
CompareGuid (VendorGuid, &VariableHeader->VendorGuid)) {
|
|
VariableFound = TRUE;
|
|
break;
|
|
}
|
|
CurrentSearchedSize += ((UINTN) NexVariable - (UINTN) VariableHeader);
|
|
VariableHeader = NexVariable;
|
|
}
|
|
|
|
return VariableFound;
|
|
} |