mirror of https://github.com/acidanthera/audk.git
BaseTools/FCE: Add a tool FCE
FCE is a tool to retrieve and change HII configuration data in Firmware Device(*.fd) files. https://bugzilla.tianocore.org/show_bug.cgi?id=1848 Cc: Bob Feng <bob.c.feng@intel.com> Cc: Liming Gao <liming.gao@intel.com> Signed-off-by: Shenglei Zhang <shenglei.zhang@intel.com> Reviewed-by: Bob Feng <bob.c.feng@intel.com>
This commit is contained in:
parent
dc7b0dc8d6
commit
3c59d94637
|
@ -0,0 +1,29 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
|
||||
dir=$(dirname "$full_cmd")
|
||||
cmd=${full_cmd##*/}
|
||||
|
||||
if [ -n "$WORKSPACE" ] && [ -e "$WORKSPACE/Conf/BaseToolsCBinaries" ]
|
||||
then
|
||||
exec "$WORKSPACE/Conf/BaseToolsCBinaries/$cmd"
|
||||
elif [ -n "$WORKSPACE" ] && [ -e "$EDK_TOOLS_PATH/Source/C" ]
|
||||
then
|
||||
if [ ! -e "$EDK_TOOLS_PATH/Source/C/bin/$cmd" ]
|
||||
then
|
||||
echo "BaseTools C Tool binary was not found ($cmd)"
|
||||
echo "You may need to run:"
|
||||
echo " make -C $EDK_TOOLS_PATH/Source/C"
|
||||
else
|
||||
exec "$EDK_TOOLS_PATH/Source/C/bin/$cmd" "$@"
|
||||
fi
|
||||
elif [ -e "$dir/../../Source/C/bin/$cmd" ]
|
||||
then
|
||||
exec "$dir/../../Source/C/bin/$cmd" "$@"
|
||||
else
|
||||
echo "Unable to find the real '$cmd' to run"
|
||||
echo "This message was printed by"
|
||||
echo " $0"
|
||||
exit 127
|
||||
fi
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
/** @file
|
||||
|
||||
The API to create the binary.
|
||||
|
||||
Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "BinaryCreate.h"
|
||||
#ifndef __GNUC__
|
||||
#define GENSEC_RAW "GenSec -s %s \"%s\" -o \"%s\" > NUL"
|
||||
#else
|
||||
#define GENSEC_RAW "GenSec -s %s \"%s\" -o \"%s\" > /dev/null"
|
||||
#endif
|
||||
|
||||
//
|
||||
// The guid is to for FFS of BFV.
|
||||
//
|
||||
EFI_GUID gEfiFfsBfvForMultiPlatformGuid = EFI_FFS_BFV_FOR_MULTIPLATFORM_GUID;
|
||||
EFI_GUID gEfiFfsBfvForMultiPlatformGuid2 = EFI_FFS_BFV_FOR_MULTIPLATFORM_GUID2;
|
||||
|
||||
/**
|
||||
Convert a GUID to a string.
|
||||
|
||||
@param[in] Guid Pointer to GUID to print.
|
||||
|
||||
@return The string after convert.
|
||||
**/
|
||||
static
|
||||
CHAR8 *
|
||||
LibBfmGuidToStr (
|
||||
IN EFI_GUID *Guid
|
||||
)
|
||||
{
|
||||
CHAR8 * Buffer;
|
||||
|
||||
Buffer = NULL;
|
||||
|
||||
if (Guid == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Buffer = (CHAR8 *) malloc (36 + 1);
|
||||
|
||||
if (Buffer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memset (Buffer, '\0', 36 + 1);
|
||||
|
||||
sprintf (
|
||||
Buffer,
|
||||
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||
Guid->Data1,
|
||||
Guid->Data2,
|
||||
Guid->Data3,
|
||||
Guid->Data4[0],
|
||||
Guid->Data4[1],
|
||||
Guid->Data4[2],
|
||||
Guid->Data4[3],
|
||||
Guid->Data4[4],
|
||||
Guid->Data4[5],
|
||||
Guid->Data4[6],
|
||||
Guid->Data4[7]
|
||||
);
|
||||
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
Create the Ras section in FFS
|
||||
|
||||
@param[in] InputFilePath .efi file, it's optional unless process PE/TE section.
|
||||
@param[in] OutputFilePath .te or .pe file
|
||||
|
||||
@retval EFI_SUCCESS
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
CreateRawSection (
|
||||
IN CHAR8* InputFilePath,
|
||||
IN CHAR8* OutputFilePath
|
||||
)
|
||||
{
|
||||
INT32 ReturnValue;
|
||||
CHAR8* SystemCommand;
|
||||
|
||||
SystemCommand = NULL;
|
||||
SystemCommand = malloc (
|
||||
strlen (GENSEC_RAW) +
|
||||
strlen ("EFI_SECTION_RAW") +
|
||||
strlen (InputFilePath) +
|
||||
strlen (OutputFilePath) +
|
||||
1
|
||||
);
|
||||
if (NULL == SystemCommand) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
sprintf (
|
||||
SystemCommand,
|
||||
GENSEC_RAW,
|
||||
"EFI_SECTION_RAW",
|
||||
InputFilePath,
|
||||
OutputFilePath
|
||||
);
|
||||
ReturnValue = system (SystemCommand);
|
||||
free(SystemCommand);
|
||||
|
||||
if (ReturnValue != 0) {
|
||||
printf ("Error. Call GenSec failed.\n");
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Create the Ras type of FFS
|
||||
|
||||
@param[in] InputFilePath .efi file, it's optional unless process PE/TE section.
|
||||
@param[in] OutputFilePath .te or .pe file
|
||||
|
||||
@retval EFI_SUCCESS
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
CreateRawFfs (
|
||||
IN CHAR8** InputFilePaths,
|
||||
IN CHAR8* OutputFilePath,
|
||||
IN BOOLEAN SizeOptimized
|
||||
)
|
||||
{
|
||||
INT32 ReturnValue;
|
||||
CHAR8* SystemCommandFormatString;
|
||||
CHAR8* SystemCommand;
|
||||
CHAR8* GuidStr;
|
||||
CHAR8* FilePathFormatStr;
|
||||
CHAR8* FilePathStr;
|
||||
UINT32 Index;
|
||||
UINT32 StrLen;
|
||||
UINT32 Size;
|
||||
|
||||
SystemCommand = NULL;
|
||||
GuidStr = NULL;
|
||||
FilePathStr = NULL;
|
||||
StrLen = 0;
|
||||
|
||||
FilePathFormatStr = " -i \"";
|
||||
|
||||
for (Index = 0; InputFilePaths[Index] != NULL; Index++) {
|
||||
Size = strlen (FilePathFormatStr) + strlen (InputFilePaths[Index]) + 2; // 2 menas "" "
|
||||
if (FilePathStr == NULL) {
|
||||
FilePathStr = malloc (Size);
|
||||
if (NULL == FilePathStr) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
} else {
|
||||
FilePathStr = realloc (FilePathStr, StrLen + Size);
|
||||
if (NULL == FilePathStr) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
}
|
||||
memset (FilePathStr + StrLen, ' ', Size);
|
||||
memcpy (FilePathStr + StrLen, FilePathFormatStr, strlen(FilePathFormatStr));
|
||||
memcpy(FilePathStr + StrLen + strlen(FilePathFormatStr), InputFilePaths[Index], strlen(InputFilePaths[Index]));
|
||||
StrLen += Size;
|
||||
*(FilePathStr + StrLen - 2) = '\"';
|
||||
}
|
||||
if (FilePathStr == NULL) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
*(FilePathStr + StrLen - 1)= '\0';
|
||||
|
||||
|
||||
if (SizeOptimized) {
|
||||
GuidStr = LibBfmGuidToStr(&gEfiFfsBfvForMultiPlatformGuid2);
|
||||
} else {
|
||||
GuidStr = LibBfmGuidToStr(&gEfiFfsBfvForMultiPlatformGuid);
|
||||
}
|
||||
if (NULL == GuidStr) {
|
||||
free (FilePathStr);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
SystemCommandFormatString = "GenFfs -t %s %s -g %s -o \"%s\"";
|
||||
SystemCommand = malloc (
|
||||
strlen (SystemCommandFormatString) +
|
||||
strlen ("EFI_FV_FILETYPE_FREEFORM") +
|
||||
strlen (FilePathStr) +
|
||||
strlen (GuidStr) +
|
||||
strlen (OutputFilePath) +
|
||||
1
|
||||
);
|
||||
if (NULL == SystemCommand) {
|
||||
free (GuidStr);
|
||||
free (FilePathStr);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
sprintf (
|
||||
SystemCommand,
|
||||
"GenFfs -t %s %s -g %s -o \"%s\"",
|
||||
"EFI_FV_FILETYPE_FREEFORM",// -t
|
||||
FilePathStr, // -i
|
||||
GuidStr, // -g
|
||||
OutputFilePath // -o
|
||||
);
|
||||
ReturnValue = system (SystemCommand);
|
||||
free(SystemCommand);
|
||||
free (FilePathStr);
|
||||
free (GuidStr);
|
||||
|
||||
if (ReturnValue != 0) {
|
||||
printf ("Error. Call GenFfs failed.\n");
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
/** @file
|
||||
|
||||
The API to create the binary.
|
||||
|
||||
Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _BINARY_CREATE_H_
|
||||
#define _BINARY_CREATE_H_ 1
|
||||
|
||||
#include <FvLib.h>
|
||||
#include "Compress.h"
|
||||
#include "Decompress.h"
|
||||
#include "CommonLib.h"
|
||||
#include "EfiUtilityMsgs.h"
|
||||
#include "FirmwareVolumeBufferLib.h"
|
||||
#include "OsPath.h"
|
||||
#include "ParseGuidedSectionTools.h"
|
||||
#include "StringFuncs.h"
|
||||
#include "ParseInf.h"
|
||||
#include <Common/UefiBaseTypes.h>
|
||||
#include <Common/UefiInternalFormRepresentation.h>
|
||||
#include <Common/UefiCapsule.h>
|
||||
#include <Common/PiFirmwareFile.h>
|
||||
#include <Common/PiFirmwareVolume.h>
|
||||
#include <Guid/PiFirmwareFileSystem.h>
|
||||
#include <IndustryStandard/PeImage.h>
|
||||
#include <Protocol/GuidedSectionExtraction.h>
|
||||
|
||||
//1AE42876-008F-4161-B2B7-1C0D15C5EF43
|
||||
#define EFI_FFS_BFV_FOR_MULTIPLATFORM_GUID \
|
||||
{ 0x1ae42876, 0x008f, 0x4161, { 0xb2, 0xb7, 0x1c, 0xd, 0x15, 0xc5, 0xef, 0x43 }}
|
||||
|
||||
extern EFI_GUID gEfiFfsBfvForMultiPlatformGuid;
|
||||
|
||||
// {003E7B41-98A2-4BE2-B27A-6C30C7655225}
|
||||
#define EFI_FFS_BFV_FOR_MULTIPLATFORM_GUID2 \
|
||||
{ 0x3e7b41, 0x98a2, 0x4be2, { 0xb2, 0x7a, 0x6c, 0x30, 0xc7, 0x65, 0x52, 0x25 }}
|
||||
|
||||
extern EFI_GUID gEfiFfsBfvForMultiPlatformGuid2;
|
||||
|
||||
typedef UINT64 SKU_ID;
|
||||
|
||||
typedef struct {
|
||||
UINT32 Offset:24;
|
||||
UINT32 Value:8;
|
||||
} PCD_DATA_DELTA;
|
||||
|
||||
typedef struct {
|
||||
SKU_ID SkuId;
|
||||
UINT16 DefaultId;
|
||||
UINT8 Reserved[6];
|
||||
} PCD_DEFAULT_INFO;
|
||||
|
||||
typedef struct {
|
||||
//
|
||||
// Full size, it must be at 8 byte alignment.
|
||||
//
|
||||
UINT32 DataSize;
|
||||
//
|
||||
// HeaderSize includes HeaderSize fields and DefaultInfo arrays
|
||||
//
|
||||
UINT32 HeaderSize;
|
||||
//
|
||||
// DefaultInfo arrays those have the same default setting.
|
||||
//
|
||||
PCD_DEFAULT_INFO DefaultInfo[1];
|
||||
//
|
||||
// Default data is stored as variable storage or the array of DATA_DELTA.
|
||||
//
|
||||
} PCD_DEFAULT_DATA;
|
||||
|
||||
#define PCD_NV_STORE_DEFAULT_BUFFER_SIGNATURE SIGNATURE_32('N', 'S', 'D', 'B')
|
||||
|
||||
typedef struct {
|
||||
//
|
||||
// PCD_NV_STORE_DEFAULT_BUFFER_SIGNATURE
|
||||
//
|
||||
UINT32 Signature;
|
||||
//
|
||||
// Length of the taken default buffer
|
||||
//
|
||||
UINT32 Length;
|
||||
//
|
||||
// Length of the total reserved buffer
|
||||
//
|
||||
UINT32 MaxLength;
|
||||
//
|
||||
// Reserved for 8 byte alignment
|
||||
//
|
||||
UINT32 Reserved;
|
||||
// one or more PCD_DEFAULT_DATA
|
||||
} PCD_NV_STORE_DEFAULT_BUFFER_HEADER;
|
||||
|
||||
//
|
||||
// NvStoreDefaultValueBuffer layout:
|
||||
// +-------------------------------------+
|
||||
// | PCD_NV_STORE_DEFAULT_BUFFER_HEADER |
|
||||
// +-------------------------------------+
|
||||
// | PCD_DEFAULT_DATA (DEFAULT, Standard)|
|
||||
// +-------------------------------------+
|
||||
// | PCD_DATA_DELTA (DEFAULT, Standard)|
|
||||
// +-------------------------------------+
|
||||
// | ...... |
|
||||
// +-------------------------------------+
|
||||
// | PCD_DEFAULT_DATA (SKU A, Standard) |
|
||||
// +-------------------------------------+
|
||||
// | PCD_DATA_DELTA (SKU A, Standard) |
|
||||
// +-------------------------------------+
|
||||
// | ...... |
|
||||
// +-------------------------------------+
|
||||
//
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct {
|
||||
UINT16 Offset;
|
||||
UINT8 Value;
|
||||
} DATA_DELTA;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
/**
|
||||
Create the Ras section in FFS
|
||||
|
||||
@param[in] InputFilePath The input file path and name.
|
||||
@param[in] OutputFilePath The output file path and name.
|
||||
|
||||
@retval EFI_SUCCESS
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
CreateRawSection (
|
||||
IN CHAR8* InputFilePath,
|
||||
IN CHAR8* OutputFilePath
|
||||
);
|
||||
|
||||
/**
|
||||
Create the Ras type of FFS
|
||||
|
||||
@param[in] InputFilePath .efi file, it's optional unless process PE/TE section.
|
||||
@param[in] OutputFilePath .te or .pe file
|
||||
|
||||
@retval EFI_SUCCESS
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
CreateRawFfs (
|
||||
IN CHAR8** InputFilePaths,
|
||||
IN CHAR8* OutputFilePath,
|
||||
IN BOOLEAN SizeOptimized
|
||||
);
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,187 @@
|
|||
/** @file
|
||||
|
||||
The API to parse the binary.
|
||||
|
||||
Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
#ifndef _BINARY_PARSE_H_
|
||||
#define _BINARY_PARSE_H_ 1
|
||||
|
||||
#include <FvLib.h>
|
||||
#include "Compress.h"
|
||||
#include "Decompress.h"
|
||||
#include "CommonLib.h"
|
||||
#include "EfiUtilityMsgs.h"
|
||||
#include "FirmwareVolumeBufferLib.h"
|
||||
#include "OsPath.h"
|
||||
#include "ParseGuidedSectionTools.h"
|
||||
#include "StringFuncs.h"
|
||||
#include "ParseInf.h"
|
||||
#include <Common/UefiBaseTypes.h>
|
||||
#include <Common/UefiInternalFormRepresentation.h>
|
||||
#include <Common/UefiCapsule.h>
|
||||
#include <Common/PiFirmwareFile.h>
|
||||
#include <Common/PiFirmwareVolume.h>
|
||||
#include <Guid/PiFirmwareFileSystem.h>
|
||||
#include <IndustryStandard/PeImage.h>
|
||||
#include <Protocol/GuidedSectionExtraction.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define OS_SEP '/'
|
||||
#define OS_SEP_STR "/"
|
||||
#else
|
||||
#define OS_SEP '\\'
|
||||
#define OS_SEP_STR "\\"
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#define TEMP_DIR_NAME "Temp"
|
||||
#define MAX_FILENAME_LEN 200
|
||||
#define MAX_MATCH_GUID_NUM 100
|
||||
#define MAX_EFI_IN_FFS_NUM 100
|
||||
|
||||
typedef struct {
|
||||
VOID *Fd;
|
||||
UINT32 FdSize;
|
||||
UINTN EfiVariableAddr;
|
||||
UINTN Length[MAX_EFI_IN_FFS_NUM];
|
||||
VOID *FfsArray[MAX_EFI_IN_FFS_NUM];
|
||||
VOID *StorageFfsInBfv;
|
||||
VOID *NvStoreDatabase;
|
||||
BOOLEAN ExistNvStoreDatabase;
|
||||
} G_EFI_FD_INFO;
|
||||
|
||||
///
|
||||
///Define the structure for th sections
|
||||
///
|
||||
typedef struct {
|
||||
UINTN BufferBase;
|
||||
UINTN UncompressedBuffer[MAX_EFI_IN_FFS_NUM];
|
||||
UINTN Length;
|
||||
UINT8 UnCompressIndex;
|
||||
} EFI_SECTION_STRUCT;
|
||||
|
||||
// {d0bc7cb4-6a47-495f-aa11-710746da06a2}
|
||||
#define EFI_VFR_ATTRACT_GUID \
|
||||
{ 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } }
|
||||
|
||||
// {8913C5E0-33F6-4d86-9BF1-43EF89FC0666}
|
||||
#define EFI_UNI_STR_ATTRACT_GUID \
|
||||
{ 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
|
||||
|
||||
// {FFF12B8D-7696-4C8B-A985-2747075B4F50}
|
||||
#define EFI_SYSTEM_NVDATA_FV_GUID \
|
||||
{ 0xFFF12B8D, 0x7696, 0x4C8B, { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }}
|
||||
|
||||
/**
|
||||
Parses FFS Sections, and remove the FFS headers. Tis function olny handle one efi in this FFS.
|
||||
|
||||
@param SectionBuffer The section base address
|
||||
@param BufferLength The length of FFS.
|
||||
@param EfiBufferHeader The structure dual pointer to the efi informations
|
||||
|
||||
@retval EFI_SUCCESS The application exited normally.
|
||||
@retval EFI_ABORTED An error occurred.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
ParseSection (
|
||||
IN BOOLEAN IsFfsOrEfi,
|
||||
IN OUT UINT8 *SectionBuffer,
|
||||
IN UINT32 BufferLength,
|
||||
IN OUT EFI_SECTION_STRUCT **EfiBufferHeader
|
||||
);
|
||||
|
||||
/**
|
||||
Search the VfrBin Base address.
|
||||
|
||||
According the known GUID gVfrArrayAttractGuid to get the base address from FFS.
|
||||
|
||||
@param Fv the Pointer to the FFS
|
||||
@param EfiAddr the Pointer to the EFI in FFS
|
||||
@param Length the length of Fv
|
||||
@param Offset the Pointer to the Addr (Offset)
|
||||
@param NumOfMachingOffset the number of Addr (Offset)
|
||||
|
||||
@retval EFI_SUCCESS Get the address successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
SearchVfrBinInFFS (
|
||||
IN VOID *Fv,
|
||||
IN VOID *EfiAddr,
|
||||
IN UINTN Length,
|
||||
OUT UINTN **Offset,
|
||||
OUT UINT8 *NumOfMachingOffset
|
||||
);
|
||||
|
||||
/**
|
||||
Search the UniBin Base address.
|
||||
|
||||
According the known GUID gUniStrArrayAttractGuid to get the base address from FFS.
|
||||
|
||||
@param Fv the Pointer to the FFS
|
||||
@param EfiAddr the Pointer to the EFI in FFS
|
||||
@param Length the length of Fv
|
||||
@param Offset the Pointer to the Addr (Offset)
|
||||
|
||||
@retval Base address Get the address successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
SearchUniBinInFFS (
|
||||
IN VOID *Fv,
|
||||
IN VOID *EfiAddr,
|
||||
IN UINTN Length,
|
||||
OUT UINTN **Offset
|
||||
);
|
||||
|
||||
/**
|
||||
Read the file to memory.
|
||||
|
||||
@param InputFile The file that contains the FV image.
|
||||
@param Size The size of the file.
|
||||
|
||||
@retval The pointer to the begining position of memory.
|
||||
**/
|
||||
VOID *
|
||||
ReadFileToMemory (
|
||||
IN CHAR8 *FileName,
|
||||
OUT UINT32 *Size
|
||||
);
|
||||
|
||||
/**
|
||||
Search the EFI variables address in Fd.
|
||||
|
||||
Open and read the *.fd to the memory, initialize the global structure.
|
||||
Update the EFI variables addr and the begining position of memory.
|
||||
|
||||
@retval EFI_SUCCESS Get the address successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetEfiVariablesAddr (
|
||||
BOOLEAN UqiIsSet
|
||||
);
|
||||
|
||||
/**
|
||||
Pick up the FFS which includes IFR section.
|
||||
|
||||
Parse all FFS extracted by BfmLib, and save all which includes IFR
|
||||
Binary to gEfiFdInfo structure.
|
||||
|
||||
@retval EFI_SUCCESS Get the address successfully.
|
||||
@retval EFI_BUFFER_TOO_SMALL Memory can't be allocated.
|
||||
@retval EFI_ABORTED Read FFS Failed.
|
||||
**/
|
||||
EFI_STATUS
|
||||
FindFileInFolder (
|
||||
IN CHAR8 *FolderName,
|
||||
OUT BOOLEAN *ExistStorageInBfv,
|
||||
OUT BOOLEAN *SizeOptimized
|
||||
);
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,999 @@
|
|||
/** @file
|
||||
|
||||
Common library.
|
||||
|
||||
Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
#ifndef _COMMON_LIB_H_
|
||||
#define _COMMON_LIB_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef __GNUC__
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include "CommonLib.h"
|
||||
#include <Common/UefiBaseTypes.h>
|
||||
|
||||
#define MAX_QUI_PARAM_LEN 2000
|
||||
#define ERROR_INFO_LENGTH 400
|
||||
#define MAX_STR_LEN_FOR_PICK_UQI 200
|
||||
#define MAX_PLATFORM_DEFAULT_ID_NUM 1000
|
||||
#define _MAX_BUILD_VERSION 100
|
||||
#define _MAXIMUM_SECTION_FILE_NUM 1000
|
||||
|
||||
#ifndef _MAX_PATH
|
||||
#define _MAX_PATH 500
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Variable attributes.
|
||||
///
|
||||
#define EFI_VARIABLE_NON_VOLATILE 0x00000001
|
||||
#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
|
||||
#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
|
||||
|
||||
///
|
||||
/// This attribute is identified by the mnemonic 'HR'
|
||||
/// elsewhere in this specification.
|
||||
///
|
||||
#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010
|
||||
|
||||
#define VARSTORE_LIST_TYPE 0x0000000000000001ULL
|
||||
#define EFI_VARSTORE_LIST_TYPE 0x0000000000000002ULL
|
||||
#define PLATFORM_DEFAULT_ID_TYPE 0x0000000000000004ULL
|
||||
#define UQI_LIST_TYPE 0x0000000000000008ULL
|
||||
#define HII_OBJ_LIST_TYPE 0x0000000000000010ULL
|
||||
|
||||
///
|
||||
/// LIST_ENTRY structure definition.
|
||||
///
|
||||
typedef struct _LIST_ENTRY {
|
||||
struct _LIST_ENTRY *ForwardLink;
|
||||
struct _LIST_ENTRY *BackLink;
|
||||
} LIST_ENTRY;
|
||||
|
||||
#define CR(Record, TYPE, Field, TestSignature) ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))
|
||||
#define AllocateZeroPool(a) calloc(a, sizeof (CHAR8))
|
||||
#define FreePool(a) free(a)
|
||||
#define CopyMem(a, b, c) memcpy(a, b, c)
|
||||
#define ZeroMem(a, b) memset(a, 0, b)
|
||||
#define CompareMem(a, b, c) memcmp(a, b, c)
|
||||
#define AllocatePool(a) malloc(a)
|
||||
|
||||
/**
|
||||
Returns a 16-bit signature built from 2 ASCII characters.
|
||||
|
||||
This macro returns a 16-bit value built from the two ASCII characters specified
|
||||
by A and B.
|
||||
|
||||
@param A The first ASCII character.
|
||||
@param B The second ASCII character.
|
||||
|
||||
@return A 16-bit value built from the two ASCII characters specified by A and B.
|
||||
|
||||
**/
|
||||
#define SIGNATURE_16(A, B) ((A) | (B << 8))
|
||||
|
||||
/**
|
||||
Returns a 32-bit signature built from 4 ASCII characters.
|
||||
|
||||
This macro returns a 32-bit value built from the four ASCII characters specified
|
||||
by A, B, C, and D.
|
||||
|
||||
@param A The first ASCII character.
|
||||
@param B The second ASCII character.
|
||||
@param C The third ASCII character.
|
||||
@param D The fourth ASCII character.
|
||||
|
||||
@return A 32-bit value built from the two ASCII characters specified by A, B,
|
||||
C and D.
|
||||
|
||||
**/
|
||||
#define SIGNATURE_32(A, B, C, D) (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16))
|
||||
|
||||
#define ASSERT_UNICODE_BUFFER(Buffer) ASSERT ((((UINTN) (Buffer)) & 0x01) == 0)
|
||||
|
||||
/**
|
||||
Returns an argument of a specified type from a variable argument list and updates
|
||||
the pointer to the variable argument list to point to the next argument.
|
||||
|
||||
This function returns an argument of the type specified by TYPE from the beginning
|
||||
of the variable argument list specified by Marker. Marker is then updated to point
|
||||
to the next argument in the variable argument list. The method for computing the
|
||||
pointer to the next argument in the argument list is CPU specific following the EFIAPI ABI.
|
||||
|
||||
@param Marker The pointer to the beginning of a variable argument list.
|
||||
@param TYPE The type of argument to retrieve from the beginning
|
||||
of the variable argument list.
|
||||
|
||||
@return An argument of the type specified by TYPE.
|
||||
|
||||
**/
|
||||
#define BASE_ARG(Marker, TYPE) (*(TYPE *) ((Marker += _BASE_INT_SIZE_OF (TYPE)) - _BASE_INT_SIZE_OF (TYPE)))
|
||||
|
||||
///
|
||||
/// Define the maximum number of characters that are required to
|
||||
/// encode with a NULL terminator a decimal, hexadecimal, GUID,
|
||||
/// or TIME value.
|
||||
///
|
||||
/// Maximum Length Decimal String = 28
|
||||
/// "-9,223,372,036,854,775,808"
|
||||
/// Maximum Length Hexadecimal String = 17
|
||||
/// "FFFFFFFFFFFFFFFF"
|
||||
/// Maximum Length GUID = 37
|
||||
/// "00000000-0000-0000-0000-000000000000"
|
||||
/// Maximum Length TIME = 18
|
||||
/// "12/12/2006 12:12"
|
||||
///
|
||||
#define MAXIMUM_VALUE_CHARACTERS 38
|
||||
|
||||
///
|
||||
/// Pointer to the start of a variable argument list stored in a memory buffer. Same as UINT8 *.
|
||||
///
|
||||
typedef UINTN *BASE_LIST;
|
||||
|
||||
/**
|
||||
Returns the size of a data type in sizeof(UINTN) units rounded up to the nearest UINTN boundary.
|
||||
|
||||
@param TYPE The date type to determine the size of.
|
||||
|
||||
@return The size of TYPE in sizeof (UINTN) units rounded up to the nearest UINTN boundary.
|
||||
**/
|
||||
#define _BASE_INT_SIZE_OF(TYPE) ((sizeof (TYPE) + sizeof (UINTN) - 1) / sizeof (UINTN))
|
||||
|
||||
//
|
||||
// Print primitives
|
||||
//
|
||||
#define PREFIX_SIGN BIT1
|
||||
#define PREFIX_BLANK BIT2
|
||||
#define LONG_TYPE BIT4
|
||||
#define OUTPUT_UNICODE BIT6
|
||||
#define FORMAT_UNICODE BIT8
|
||||
#define PAD_TO_WIDTH BIT9
|
||||
#define ARGUMENT_UNICODE BIT10
|
||||
#define PRECISION BIT11
|
||||
#define ARGUMENT_REVERSED BIT12
|
||||
#define COUNT_ONLY_NO_PRINT BIT13
|
||||
|
||||
///
|
||||
/// Flags bitmask values use in UnicodeValueToString() and
|
||||
/// AsciiValueToString()
|
||||
///
|
||||
#define LEFT_JUSTIFY 0x01
|
||||
#define COMMA_TYPE 0x08
|
||||
#define PREFIX_ZERO 0x20
|
||||
#define RADIX_HEX 0x80
|
||||
|
||||
//
|
||||
// Record date and time information
|
||||
//
|
||||
typedef struct {
|
||||
UINT16 Year;
|
||||
UINT8 Month;
|
||||
UINT8 Day;
|
||||
UINT8 Hour;
|
||||
UINT8 Minute;
|
||||
UINT8 Second;
|
||||
UINT8 Pad1;
|
||||
UINT32 Nanosecond;
|
||||
INT16 TimeZone;
|
||||
UINT8 Daylight;
|
||||
UINT8 Pad2;
|
||||
} TIME;
|
||||
|
||||
|
||||
/**
|
||||
Copies one Null-terminated Unicode string to another Null-terminated Unicode
|
||||
string and returns the new Unicode string.
|
||||
|
||||
This function copies the contents of the Unicode string Source to the Unicode
|
||||
string Destination, and returns Destination. If Source and Destination
|
||||
overlap, then the results are undefined.
|
||||
|
||||
If Destination is NULL, then return NULL.
|
||||
If Destination is not aligned on a 16-bit boundary, then return NULL.
|
||||
|
||||
@param Destination A pointer to a Null-terminated Unicode string.
|
||||
@param Source A pointer to a Null-terminated Unicode string.
|
||||
|
||||
@return Destination.
|
||||
|
||||
**/
|
||||
CHAR16 *
|
||||
StrCpy (
|
||||
OUT CHAR16 *Destination,
|
||||
IN CONST CHAR16 *Source
|
||||
);
|
||||
|
||||
/**
|
||||
Returns the length of a Null-terminated Unicode string.
|
||||
|
||||
This function returns the number of Unicode characters in the Null-terminated
|
||||
Unicode string specified by String.
|
||||
|
||||
If String is NULL, then return 0.
|
||||
|
||||
@param String A pointer to a Null-terminated Unicode string.
|
||||
|
||||
@return The length of String.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
FceStrLen (
|
||||
IN CONST CHAR16 *String
|
||||
);
|
||||
|
||||
/**
|
||||
Returns the size of a Null-terminated Unicode string in bytes, including the
|
||||
Null terminator.
|
||||
|
||||
This function returns the size, in bytes, of the Null-terminated Unicode string
|
||||
specified by String.
|
||||
|
||||
If String is NULL, then ASSERT().
|
||||
If String is not aligned on a 16-bit boundary, then ASSERT().
|
||||
If PcdMaximumUnicodeStringLength is not zero, and String contains more than
|
||||
PcdMaximumUnicodeStringLength Unicode characters, not including the
|
||||
Null-terminator, then ASSERT().
|
||||
|
||||
@param String A pointer to a Null-terminated Unicode string.
|
||||
|
||||
@return The size of String.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
FceStrSize (
|
||||
IN CONST CHAR16 *String
|
||||
);
|
||||
|
||||
/**
|
||||
Compares two Null-terminated Unicode strings, and returns the difference
|
||||
between the first mismatched Unicode characters.
|
||||
|
||||
This function compares the Null-terminated Unicode string FirstString to the
|
||||
Null-terminated Unicode string SecondString. If FirstString is identical to
|
||||
SecondString, then 0 is returned. Otherwise, the value returned is the first
|
||||
mismatched Unicode character in SecondString subtracted from the first
|
||||
mismatched Unicode character in FirstString.
|
||||
|
||||
@param FirstString A pointer to a Null-terminated Unicode string.
|
||||
@param SecondString A pointer to a Null-terminated Unicode string.
|
||||
|
||||
@retval 0 FirstString is identical to SecondString.
|
||||
@return others FirstString is not identical to SecondString.
|
||||
|
||||
**/
|
||||
INTN
|
||||
FceStrCmp (
|
||||
IN CONST CHAR16 *FirstString,
|
||||
IN CONST CHAR16 *SecondString
|
||||
);
|
||||
|
||||
/**
|
||||
Concatenates one Null-terminated Unicode string to another Null-terminated
|
||||
Unicode string, and returns the concatenated Unicode string.
|
||||
|
||||
This function concatenates two Null-terminated Unicode strings. The contents
|
||||
of Null-terminated Unicode string Source are concatenated to the end of
|
||||
Null-terminated Unicode string Destination. The Null-terminated concatenated
|
||||
Unicode String is returned. If Source and Destination overlap, then the
|
||||
results are undefined.
|
||||
|
||||
If Destination is NULL, then ASSERT().
|
||||
If Destination is not aligned on a 16-bit boundary, then ASSERT().
|
||||
If Source is NULL, then ASSERT().
|
||||
If Source is not aligned on a 16-bit boundary, then ASSERT().
|
||||
If Source and Destination overlap, then ASSERT().
|
||||
If PcdMaximumUnicodeStringLength is not zero, and Destination contains more
|
||||
than PcdMaximumUnicodeStringLength Unicode characters, not including the
|
||||
Null-terminator, then ASSERT().
|
||||
If PcdMaximumUnicodeStringLength is not zero, and Source contains more than
|
||||
PcdMaximumUnicodeStringLength Unicode characters, not including the
|
||||
Null-terminator, then ASSERT().
|
||||
If PcdMaximumUnicodeStringLength is not zero, and concatenating Destination
|
||||
and Source results in a Unicode string with more than
|
||||
PcdMaximumUnicodeStringLength Unicode characters, not including the
|
||||
Null-terminator, then ASSERT().
|
||||
|
||||
@param Destination A pointer to a Null-terminated Unicode string.
|
||||
@param Source A pointer to a Null-terminated Unicode string.
|
||||
|
||||
@return Destination.
|
||||
|
||||
**/
|
||||
CHAR16 *
|
||||
StrCat (
|
||||
IN OUT CHAR16 *Destination,
|
||||
IN CONST CHAR16 *Source
|
||||
);
|
||||
|
||||
/**
|
||||
Returns the first occurrence of a Null-terminated Unicode sub-string
|
||||
in a Null-terminated Unicode string.
|
||||
|
||||
This function scans the contents of the Null-terminated Unicode string
|
||||
specified by String and returns the first occurrence of SearchString.
|
||||
If SearchString is not found in String, then NULL is returned. If
|
||||
the length of SearchString is zero, then String is
|
||||
returned.
|
||||
|
||||
If String is NULL, then ASSERT().
|
||||
If String is not aligned on a 16-bit boundary, then ASSERT().
|
||||
If SearchString is NULL, then ASSERT().
|
||||
If SearchString is not aligned on a 16-bit boundary, then ASSERT().
|
||||
|
||||
If PcdMaximumUnicodeStringLength is not zero, and SearchString
|
||||
or String contains more than PcdMaximumUnicodeStringLength Unicode
|
||||
characters, not including the Null-terminator, then ASSERT().
|
||||
|
||||
@param String A pointer to a Null-terminated Unicode string.
|
||||
@param SearchString A pointer to a Null-terminated Unicode string to search for.
|
||||
|
||||
@retval NULL If the SearchString does not appear in String.
|
||||
@return others If there is a match.
|
||||
|
||||
**/
|
||||
CHAR16 *
|
||||
StrStr (
|
||||
IN CONST CHAR16 *String,
|
||||
IN CONST CHAR16 *SearchString
|
||||
);
|
||||
|
||||
/**
|
||||
Convert a Null-terminated Unicode decimal string to a value of
|
||||
type UINT64.
|
||||
|
||||
This function returns a value of type UINT64 by interpreting the contents
|
||||
of the Unicode string specified by String as a decimal number. The format
|
||||
of the input Unicode string String is:
|
||||
|
||||
[spaces] [decimal digits].
|
||||
|
||||
The valid decimal digit character is in the range [0-9]. The
|
||||
function will ignore the pad space, which includes spaces or
|
||||
tab characters, before [decimal digits]. The running zero in the
|
||||
beginning of [decimal digits] will be ignored. Then, the function
|
||||
stops at the first character that is a not a valid decimal character
|
||||
or a Null-terminator, whichever one comes first.
|
||||
|
||||
If String is NULL, then ASSERT().
|
||||
If String is not aligned in a 16-bit boundary, then ASSERT().
|
||||
If String has only pad spaces, then 0 is returned.
|
||||
If String has no pad spaces or valid decimal digits,
|
||||
then 0 is returned.
|
||||
If the number represented by String overflows according
|
||||
to the range defined by UINT64, then ASSERT().
|
||||
|
||||
If PcdMaximumUnicodeStringLength is not zero, and String contains
|
||||
more than PcdMaximumUnicodeStringLength Unicode characters, not including
|
||||
the Null-terminator, then ASSERT().
|
||||
|
||||
@param String A pointer to a Null-terminated Unicode string.
|
||||
|
||||
@retval Value translated from String.
|
||||
|
||||
**/
|
||||
UINT64
|
||||
FceStrDecimalToUint64 (
|
||||
IN CONST CHAR16 *String
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Convert one Null-terminated ASCII string to a Null-terminated
|
||||
Unicode string and returns the Unicode string.
|
||||
|
||||
This function converts the contents of the ASCII string Source to the Unicode
|
||||
string Destination, and returns Destination. The function terminates the
|
||||
Unicode string Destination by appending a Null-terminator character at the end.
|
||||
The caller is responsible to make sure Destination points to a buffer with size
|
||||
equal or greater than ((AsciiStrLen (Source) + 1) * sizeof (CHAR16)) in bytes.
|
||||
|
||||
@param Source A pointer to a Null-terminated ASCII string.
|
||||
@param Destination A pointer to a Null-terminated Unicode string.
|
||||
|
||||
@return Destination.
|
||||
@return NULL If Destination or Source is NULL, return NULL.
|
||||
|
||||
**/
|
||||
CHAR16 *
|
||||
AsciiStrToUnicodeStr (
|
||||
IN CONST CHAR8 *Source,
|
||||
OUT CHAR16 *Destination
|
||||
);
|
||||
|
||||
/**
|
||||
Worker function that produces a Null-terminated string in an output buffer
|
||||
based on a Null-terminated format string and variable argument list.
|
||||
|
||||
VSPrint function to process format and place the results in Buffer. Since a
|
||||
VA_LIST is used this routine allows the nesting of Vararg routines. Thus
|
||||
this is the main print working routine
|
||||
|
||||
@param StartOfBuffer The character buffer to print the results of the parsing
|
||||
of Format into.
|
||||
@param BufferSize The maximum number of characters to put into buffer.
|
||||
Zero means no limit.
|
||||
@param Flags Initial flags value.
|
||||
Can only have FORMAT_UNICODE and OUTPUT_UNICODE set
|
||||
@param FormatString A Null-terminated format string.
|
||||
@param ... The variable argument list.
|
||||
|
||||
@return The number of characters printed.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
BasePrintLibSPrint (
|
||||
OUT CHAR8 *StartOfBuffer,
|
||||
IN UINTN BufferSize,
|
||||
IN UINTN Flags,
|
||||
IN CONST CHAR8 *FormatString,
|
||||
...
|
||||
);
|
||||
|
||||
/**
|
||||
Produces a Null-terminated Unicode string in an output buffer based on a Null-terminated
|
||||
Unicode format string and variable argument list.
|
||||
|
||||
Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer
|
||||
and BufferSize.
|
||||
The Unicode string is produced by parsing the format string specified by FormatString.
|
||||
Arguments are pulled from the variable argument list based on the contents of the format string.
|
||||
The number of Unicode characters in the produced output buffer is returned not including
|
||||
the Null-terminator.
|
||||
If BufferSize is 0 or 1, then no output buffer is produced and 0 is returned.
|
||||
|
||||
If BufferSize > 1 and StartOfBuffer is NULL, then ASSERT().
|
||||
If BufferSize > 1 and StartOfBuffer is not aligned on a 16-bit boundary, then ASSERT().
|
||||
If BufferSize > 1 and FormatString is NULL, then ASSERT().
|
||||
If BufferSize > 1 and FormatString is not aligned on a 16-bit boundary, then ASSERT().
|
||||
If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than
|
||||
PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, then
|
||||
ASSERT().
|
||||
If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string
|
||||
contains more than PcdMaximumUnicodeStringLength Unicode characters not including the
|
||||
Null-terminator, then ASSERT().
|
||||
|
||||
@param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
|
||||
Unicode string.
|
||||
@param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
|
||||
@param FormatString A Null-terminated Unicode format string.
|
||||
@param ... Variable argument list whose contents are accessed based on the
|
||||
format string specified by FormatString.
|
||||
|
||||
@return The number of Unicode characters in the produced output buffer not including the
|
||||
Null-terminator.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
UnicodeSPrint (
|
||||
OUT CHAR16 *StartOfBuffer,
|
||||
IN UINTN BufferSize,
|
||||
IN CONST CHAR16 *FormatString,
|
||||
...
|
||||
);
|
||||
|
||||
/**
|
||||
Convert a Null-terminated Unicode string to a Null-terminated
|
||||
ASCII string and returns the ASCII string.
|
||||
|
||||
This function converts the content of the Unicode string Source
|
||||
to the ASCII string Destination by copying the lower 8 bits of
|
||||
each Unicode character. It returns Destination. The function terminates
|
||||
the ASCII string Destination by appending a Null-terminator character
|
||||
at the end. The caller is responsible to make sure Destination points
|
||||
to a buffer with size equal or greater than (FceStrLen (Source) + 1) in bytes.
|
||||
|
||||
If Destination is NULL, then ASSERT().
|
||||
If Source is NULL, then ASSERT().
|
||||
If Source is not aligned on a 16-bit boundary, then ASSERT().
|
||||
If Source and Destination overlap, then ASSERT().
|
||||
|
||||
If any Unicode characters in Source contain non-zero value in
|
||||
the upper 8 bits, then ASSERT().
|
||||
|
||||
@param Source Pointer to a Null-terminated Unicode string.
|
||||
@param Destination Pointer to a Null-terminated ASCII string.
|
||||
|
||||
@reture Destination
|
||||
|
||||
**/
|
||||
CHAR8 *
|
||||
UnicodeStrToAsciiStr (
|
||||
IN CONST CHAR16 *Source,
|
||||
OUT CHAR8 *Destination
|
||||
);
|
||||
|
||||
/**
|
||||
Allocate new memory and then copy the Unicode string Source to Destination.
|
||||
|
||||
@param Dest Location to copy string
|
||||
@param Src String to copy
|
||||
|
||||
**/
|
||||
VOID
|
||||
NewStringCpy (
|
||||
IN OUT CHAR16 **Dest,
|
||||
IN CHAR16 *Src
|
||||
);
|
||||
|
||||
/**
|
||||
Convert a Null-terminated Unicode hexadecimal string to a value of type UINT64.
|
||||
|
||||
This function returns a value of type UINT64 by interpreting the contents
|
||||
of the Unicode string specified by String as a hexadecimal number.
|
||||
The format of the input Unicode string String is
|
||||
|
||||
[spaces][zeros][x][hexadecimal digits].
|
||||
|
||||
The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].
|
||||
The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.
|
||||
If "x" appears in the input string, it must be prefixed with at least one 0.
|
||||
The function will ignore the pad space, which includes spaces or tab characters,
|
||||
before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or
|
||||
[hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the
|
||||
first valid hexadecimal digit. Then, the function stops at the first character that is
|
||||
a not a valid hexadecimal character or NULL, whichever one comes first.
|
||||
|
||||
If String is NULL, then ASSERT().
|
||||
If String is not aligned in a 16-bit boundary, then ASSERT().
|
||||
If String has only pad spaces, then zero is returned.
|
||||
If String has no leading pad spaces, leading zeros or valid hexadecimal digits,
|
||||
then zero is returned.
|
||||
If the number represented by String overflows according to the range defined by
|
||||
UINT64, then ASSERT().
|
||||
|
||||
If PcdMaximumUnicodeStringLength is not zero, and String contains more than
|
||||
PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,
|
||||
then ASSERT().
|
||||
|
||||
@param String A pointer to a Null-terminated Unicode string.
|
||||
|
||||
@retval Value translated from String.
|
||||
|
||||
**/
|
||||
UINT64
|
||||
FceStrHexToUint64 (
|
||||
IN CONST CHAR16 *String
|
||||
);
|
||||
|
||||
|
||||
CHAR16
|
||||
ToUpper (
|
||||
CHAR16 a
|
||||
);
|
||||
|
||||
CHAR16
|
||||
ToLower (
|
||||
CHAR16 a
|
||||
);
|
||||
|
||||
/**
|
||||
Performs a case-insensitive comparison between a Null-terminated
|
||||
Unicode pattern string and a Null-terminated Unicode string.
|
||||
|
||||
@param String - A pointer to a Null-terminated Unicode string.
|
||||
@param Pattern - A pointer to a Null-terminated Unicode pattern string.
|
||||
|
||||
|
||||
@retval TRUE - Pattern was found in String.
|
||||
@retval FALSE - Pattern was not found in String.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
MetaiMatch (
|
||||
IN CHAR16 *String,
|
||||
IN CHAR16 *Pattern
|
||||
);
|
||||
|
||||
/**
|
||||
Multiplies a 64-bit unsigned integer by a 32-bit unsigned integer and
|
||||
generates a 64-bit unsigned result.
|
||||
|
||||
This function multiplies the 64-bit unsigned value Multiplicand by the 32-bit
|
||||
unsigned value Multiplier and generates a 64-bit unsigned result. This 64-
|
||||
bit unsigned result is returned.
|
||||
|
||||
@param Multiplicand A 64-bit unsigned value.
|
||||
@param Multiplier A 32-bit unsigned value.
|
||||
|
||||
@return Multiplicand * Multiplier.
|
||||
|
||||
**/
|
||||
UINT64
|
||||
MultU64x32 (
|
||||
IN UINT64 Multiplicand,
|
||||
IN UINT32 Multiplier
|
||||
);
|
||||
|
||||
/**
|
||||
Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates
|
||||
a 64-bit unsigned result.
|
||||
|
||||
This function divides the 64-bit unsigned value Dividend by the 32-bit
|
||||
unsigned value Divisor and generates a 64-bit unsigned quotient. This
|
||||
function returns the 64-bit unsigned quotient.
|
||||
|
||||
If Divisor is 0, then ASSERT().
|
||||
|
||||
@param Dividend A 64-bit unsigned value.
|
||||
@param Divisor A 32-bit unsigned value.
|
||||
|
||||
@return Dividend / Divisor
|
||||
|
||||
**/
|
||||
UINT64
|
||||
DivU64x32 (
|
||||
IN UINT64 Dividend,
|
||||
IN UINT32 Divisor
|
||||
);
|
||||
|
||||
/**
|
||||
Shifts a 64-bit integer left between 0 and 63 bits. The low bits are filled
|
||||
with zeros. The shifted value is returned.
|
||||
|
||||
This function shifts the 64-bit value Operand to the left by Count bits. The
|
||||
low Count bits are set to zero. The shifted value is returned.
|
||||
|
||||
If Count is greater than 63, then ASSERT().
|
||||
|
||||
@param Operand The 64-bit operand to shift left.
|
||||
@param Count The number of bits to shift left.
|
||||
|
||||
@return Operand << Count.
|
||||
|
||||
**/
|
||||
UINT64
|
||||
LShiftU64 (
|
||||
IN UINT64 Operand,
|
||||
IN UINTN Count
|
||||
);
|
||||
|
||||
/**
|
||||
Shifts a 64-bit integer right between 0 and 63 bits. This high bits are
|
||||
filled with zeros. The shifted value is returned.
|
||||
|
||||
This function shifts the 64-bit value Operand to the right by Count bits. The
|
||||
high Count bits are set to zero. The shifted value is returned.
|
||||
|
||||
If Count is greater than 63, then ASSERT().
|
||||
|
||||
@param Operand The 64-bit operand to shift right.
|
||||
@param Count The number of bits to shift right.
|
||||
|
||||
@return Operand >> Count.
|
||||
|
||||
**/
|
||||
UINT64
|
||||
RShiftU64 (
|
||||
IN UINT64 Operand,
|
||||
IN UINTN Count
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates
|
||||
a 64-bit unsigned result and an optional 32-bit unsigned remainder.
|
||||
|
||||
This function divides the 64-bit unsigned value Dividend by the 32-bit
|
||||
unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder
|
||||
is not NULL, then the 32-bit unsigned remainder is returned in Remainder.
|
||||
This function returns the 64-bit unsigned quotient.
|
||||
|
||||
If Divisor is 0, then ASSERT().
|
||||
|
||||
@param Dividend A 64-bit unsigned value.
|
||||
@param Divisor A 32-bit unsigned value.
|
||||
@param Remainder A pointer to a 32-bit unsigned value. This parameter is
|
||||
optional and may be NULL.
|
||||
|
||||
@return Dividend / Divisor
|
||||
|
||||
**/
|
||||
UINT64
|
||||
DivU64x32Remainder (
|
||||
IN UINT64 Dividend,
|
||||
IN UINT32 Divisor,
|
||||
OUT UINT32 *Remainder
|
||||
);
|
||||
|
||||
/**
|
||||
Copies a buffer to an allocated buffer.
|
||||
|
||||
Allocates the number bytes specified by AllocationSize, copies allocationSize bytes
|
||||
from Buffer to the newly allocated buffer, and returns a pointer to the allocated
|
||||
buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
|
||||
is not enough memory remaining to satisfy the request, then NULL is returned.
|
||||
|
||||
If Buffer is NULL, then ASSERT().
|
||||
|
||||
@param AllocationSize The number of bytes to allocate and zero.
|
||||
@param Buffer The buffer to copy to the allocated buffer.
|
||||
|
||||
@return A pointer to the allocated buffer or NULL if allocation fails.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
FceAllocateCopyPool (
|
||||
IN UINTN AllocationSize,
|
||||
IN CONST VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Initializes the head node of a doubly-linked list, and returns the pointer to
|
||||
the head node of the doubly-linked list.
|
||||
|
||||
Initializes the forward and backward links of a new linked list. After
|
||||
initializing a linked list with this function, the other linked list
|
||||
functions may be used to add and remove nodes from the linked list. It is up
|
||||
to the caller of this function to allocate the memory for ListHead.
|
||||
|
||||
If ListHead is NULL, then ASSERT().
|
||||
|
||||
@param ListHead A pointer to the head node of a new doubly-linked list.
|
||||
|
||||
@return ListHead
|
||||
|
||||
**/
|
||||
LIST_ENTRY *
|
||||
InitializeListHead (
|
||||
IN OUT LIST_ENTRY *ListHead
|
||||
);
|
||||
|
||||
/**
|
||||
Adds a node to the beginning of a doubly-linked list, and returns the pointer
|
||||
to the head node of the doubly-linked list.
|
||||
|
||||
Adds the node Entry at the beginning of the doubly-linked list denoted by
|
||||
ListHead, and returns ListHead.
|
||||
|
||||
If ListHead is NULL, then ASSERT().
|
||||
If Entry is NULL, then ASSERT().
|
||||
If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or
|
||||
InitializeListHead(), then ASSERT().
|
||||
If PcdMaximumLinkedListLenth is not zero, and prior to insertion the number
|
||||
of nodes in ListHead, including the ListHead node, is greater than or
|
||||
equal to PcdMaximumLinkedListLength, then ASSERT().
|
||||
|
||||
@param ListHead A pointer to the head node of a doubly-linked list.
|
||||
@param Entry A pointer to a node that is to be inserted at the beginning
|
||||
of a doubly-linked list.
|
||||
|
||||
@return ListHead
|
||||
|
||||
**/
|
||||
LIST_ENTRY *
|
||||
InsertHeadList (
|
||||
IN OUT LIST_ENTRY *ListHead,
|
||||
IN OUT LIST_ENTRY *Entry
|
||||
);
|
||||
|
||||
/**
|
||||
Adds a node to the end of a doubly-linked list, and returns the pointer to
|
||||
the head node of the doubly-linked list.
|
||||
|
||||
Adds the node Entry to the end of the doubly-linked list denoted by ListHead,
|
||||
and returns ListHead.
|
||||
|
||||
If ListHead is NULL, then ASSERT().
|
||||
If Entry is NULL, then ASSERT().
|
||||
If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or
|
||||
InitializeListHead(), then ASSERT().
|
||||
If PcdMaximumLinkedListLenth is not zero, and prior to insertion the number
|
||||
of nodes in ListHead, including the ListHead node, is greater than or
|
||||
equal to PcdMaximumLinkedListLength, then ASSERT().
|
||||
|
||||
@param ListHead A pointer to the head node of a doubly-linked list.
|
||||
@param Entry A pointer to a node that is to be added at the end of the
|
||||
doubly-linked list.
|
||||
|
||||
@return ListHead
|
||||
|
||||
**/
|
||||
LIST_ENTRY *
|
||||
InsertTailList (
|
||||
IN OUT LIST_ENTRY *ListHead,
|
||||
IN OUT LIST_ENTRY *Entry
|
||||
);
|
||||
|
||||
/**
|
||||
Retrieves the first node of a doubly-linked list.
|
||||
|
||||
Returns the first node of a doubly-linked list. List must have been
|
||||
initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead().
|
||||
If List is empty, then List is returned.
|
||||
|
||||
If List is NULL, then ASSERT().
|
||||
If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or
|
||||
InitializeListHead(), then ASSERT().
|
||||
If PcdMaximumLinkedListLenth is not zero, and the number of nodes
|
||||
in List, including the List node, is greater than or equal to
|
||||
PcdMaximumLinkedListLength, then ASSERT().
|
||||
|
||||
@param List A pointer to the head node of a doubly-linked list.
|
||||
|
||||
@return The first node of a doubly-linked list.
|
||||
@retval NULL The list is empty.
|
||||
|
||||
**/
|
||||
LIST_ENTRY *
|
||||
GetFirstNode (
|
||||
IN CONST LIST_ENTRY *List
|
||||
);
|
||||
|
||||
/**
|
||||
Retrieves the next node of a doubly-linked list.
|
||||
|
||||
Returns the node of a doubly-linked list that follows Node.
|
||||
List must have been initialized with INTIALIZE_LIST_HEAD_VARIABLE()
|
||||
or InitializeListHead(). If List is empty, then List is returned.
|
||||
|
||||
If List is NULL, then ASSERT().
|
||||
If Node is NULL, then ASSERT().
|
||||
If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or
|
||||
InitializeListHead(), then ASSERT().
|
||||
If PcdMaximumLinkedListLenth is not zero, and List contains more than
|
||||
PcdMaximumLinkedListLenth nodes, then ASSERT().
|
||||
If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT().
|
||||
|
||||
@param List A pointer to the head node of a doubly-linked list.
|
||||
@param Node A pointer to a node in the doubly-linked list.
|
||||
|
||||
@return A pointer to the next node if one exists. Otherwise List is returned.
|
||||
|
||||
**/
|
||||
LIST_ENTRY *
|
||||
GetNextNode (
|
||||
IN CONST LIST_ENTRY *List,
|
||||
IN CONST LIST_ENTRY *Node
|
||||
);
|
||||
|
||||
/**
|
||||
Retrieves the previous node of a doubly-linked list.
|
||||
|
||||
Returns the node of a doubly-linked list that precedes Node.
|
||||
List must have been initialized with INTIALIZE_LIST_HEAD_VARIABLE()
|
||||
or InitializeListHead(). If List is empty, then List is returned.
|
||||
|
||||
If List is NULL, then ASSERT().
|
||||
If Node is NULL, then ASSERT().
|
||||
If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or
|
||||
InitializeListHead(), then ASSERT().
|
||||
If PcdMaximumLinkedListLenth is not zero, and List contains more than
|
||||
PcdMaximumLinkedListLenth nodes, then ASSERT().
|
||||
If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT().
|
||||
|
||||
@param List A pointer to the head node of a doubly-linked list.
|
||||
@param Node A pointer to a node in the doubly-linked list.
|
||||
|
||||
@return A pointer to the previous node if one exists. Otherwise List is returned.
|
||||
|
||||
**/
|
||||
LIST_ENTRY *
|
||||
GetPreviousNode (
|
||||
IN CONST LIST_ENTRY *List,
|
||||
IN CONST LIST_ENTRY *Node
|
||||
);
|
||||
|
||||
/**
|
||||
Checks to see if a doubly-linked list is empty or not.
|
||||
|
||||
Checks to see if the doubly-linked list is empty. If the linked list contains
|
||||
zero nodes, this function returns TRUE. Otherwise, it returns FALSE.
|
||||
|
||||
If ListHead is NULL, then ASSERT().
|
||||
If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or
|
||||
InitializeListHead(), then ASSERT().
|
||||
If PcdMaximumLinkedListLenth is not zero, and the number of nodes
|
||||
in List, including the List node, is greater than or equal to
|
||||
PcdMaximumLinkedListLength, then ASSERT().
|
||||
|
||||
@param ListHead A pointer to the head node of a doubly-linked list.
|
||||
|
||||
@retval TRUE The linked list is empty.
|
||||
@retval FALSE The linked list is not empty.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsListEmpty (
|
||||
IN CONST LIST_ENTRY *ListHead
|
||||
);
|
||||
|
||||
/**
|
||||
Determines if a node in a doubly-linked list is the head node of a the same
|
||||
doubly-linked list. This function is typically used to terminate a loop that
|
||||
traverses all the nodes in a doubly-linked list starting with the head node.
|
||||
|
||||
Returns TRUE if Node is equal to List. Returns FALSE if Node is one of the
|
||||
nodes in the doubly-linked list specified by List. List must have been
|
||||
initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead().
|
||||
|
||||
If List is NULL, then ASSERT().
|
||||
If Node is NULL, then ASSERT().
|
||||
If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(),
|
||||
then ASSERT().
|
||||
If PcdMaximumLinkedListLenth is not zero, and the number of nodes
|
||||
in List, including the List node, is greater than or equal to
|
||||
PcdMaximumLinkedListLength, then ASSERT().
|
||||
If PcdVerifyNodeInList is TRUE and Node is not a node in List and Node is not
|
||||
equal to List, then ASSERT().
|
||||
|
||||
@param List A pointer to the head node of a doubly-linked list.
|
||||
@param Node A pointer to a node in the doubly-linked list.
|
||||
|
||||
@retval TRUE Node is the head of the doubly-linked list pointed by List.
|
||||
@retval FALSE Node is not the head of the doubly-linked list pointed by List.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsNull (
|
||||
IN CONST LIST_ENTRY *List,
|
||||
IN CONST LIST_ENTRY *Node
|
||||
);
|
||||
|
||||
/**
|
||||
Determines if a node the last node in a doubly-linked list.
|
||||
|
||||
Returns TRUE if Node is the last node in the doubly-linked list specified by
|
||||
List. Otherwise, FALSE is returned. List must have been initialized with
|
||||
INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead().
|
||||
|
||||
If List is NULL, then ASSERT().
|
||||
If Node is NULL, then ASSERT().
|
||||
If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or
|
||||
InitializeListHead(), then ASSERT().
|
||||
If PcdMaximumLinkedListLenth is not zero, and the number of nodes
|
||||
in List, including the List node, is greater than or equal to
|
||||
PcdMaximumLinkedListLength, then ASSERT().
|
||||
If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT().
|
||||
|
||||
@param List A pointer to the head node of a doubly-linked list.
|
||||
@param Node A pointer to a node in the doubly-linked list.
|
||||
|
||||
@retval TRUE Node is the last node in the linked list.
|
||||
@retval FALSE Node is not the last node in the linked list.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsNodeAtEnd (
|
||||
IN CONST LIST_ENTRY *List,
|
||||
IN CONST LIST_ENTRY *Node
|
||||
);
|
||||
|
||||
/**
|
||||
Removes a node from a doubly-linked list, and returns the node that follows
|
||||
the removed node.
|
||||
|
||||
Removes the node Entry from a doubly-linked list. It is up to the caller of
|
||||
this function to release the memory used by this node if that is required. On
|
||||
exit, the node following Entry in the doubly-linked list is returned. If
|
||||
Entry is the only node in the linked list, then the head node of the linked
|
||||
list is returned.
|
||||
|
||||
If Entry is NULL, then ASSERT().
|
||||
If Entry is the head node of an empty list, then ASSERT().
|
||||
If PcdMaximumLinkedListLength is not zero, and the number of nodes in the
|
||||
linked list containing Entry, including the Entry node, is greater than
|
||||
or equal to PcdMaximumLinkedListLength, then ASSERT().
|
||||
|
||||
@param Entry A pointer to a node in a linked list.
|
||||
|
||||
@return Entry.
|
||||
|
||||
**/
|
||||
LIST_ENTRY *
|
||||
RemoveEntryList (
|
||||
IN CONST LIST_ENTRY *Entry
|
||||
);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,447 @@
|
|||
/** @file
|
||||
|
||||
FCE is a tool which enables developers to retrieve and change HII configuration ("Setup")
|
||||
data in Firmware Device files (".fd" files).
|
||||
|
||||
Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _FCE_H_
|
||||
#define _FCE_H_ 1
|
||||
|
||||
//#define NDEBUG
|
||||
|
||||
#include "Common.h"
|
||||
#include "IfrParse.h"
|
||||
#include "VariableCommon.h"
|
||||
#include "BinaryParse.h"
|
||||
#include "BinaryCreate.h"
|
||||
///
|
||||
/// Utility global variables
|
||||
///
|
||||
#define UTILITY_MAJOR_VERSION 0
|
||||
#define UTILITY_MINOR_VERSION 34
|
||||
|
||||
#define UTILITY_NAME "FCE"
|
||||
|
||||
#define SUCCESS 0
|
||||
#define FAIL 1
|
||||
#define VR_FAIL 2
|
||||
#define MAX_INPUT_ALLOCATE_SIZE 256
|
||||
|
||||
///
|
||||
/// The type of file input and operations
|
||||
///
|
||||
typedef enum {
|
||||
INFD,
|
||||
OUTFD,
|
||||
OUTTXT,
|
||||
SETUPTXT
|
||||
} FILETYPE;
|
||||
|
||||
typedef enum {
|
||||
NONE,
|
||||
READ,
|
||||
UPDATE,
|
||||
UPDATE_REMOVE,
|
||||
UPDATE_IGNORE,
|
||||
VERIFY,
|
||||
UPDATEQ
|
||||
} OPERATION_TYPE;
|
||||
|
||||
typedef struct _GUID_SEC_TOOL_ENTRY {
|
||||
EFI_GUID Guid;
|
||||
CHAR8* Name;
|
||||
CHAR8* Path;
|
||||
struct _GUID_SEC_TOOL_ENTRY *Next;
|
||||
} GUID_SEC_TOOL_ENTRY;
|
||||
|
||||
///
|
||||
/// The tag for use in identifying UNICODE files.
|
||||
/// If the file is UNICODE, the first 16 bits of the file will equal this value.
|
||||
///
|
||||
enum {
|
||||
BigUnicodeFileTag = 0xFEFF,
|
||||
LittleUnicodeFileTag = 0xFFFE
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
ASCII,
|
||||
BIG_UCS2,
|
||||
LITTLE_UCS2
|
||||
} FILE_TYPE;
|
||||
|
||||
/**
|
||||
Exchange the data between Efi variable and the data of VarList when the
|
||||
variable use the authenticated variable header
|
||||
|
||||
If VarToList is TRUE, copy the efi variable data to the VarList; Otherwise,
|
||||
update the data from varlist to efi variable.
|
||||
|
||||
@param VarToList The flag to control the direction of exchange.
|
||||
@param StorageListHead Decide which variale list be updated
|
||||
|
||||
@retval EFI_SUCCESS Get the address successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES No available in the EFI variable zone.
|
||||
@retval EFI_INVALID_PARAMETER Invalid variable name.
|
||||
**/
|
||||
EFI_STATUS
|
||||
SynAuthEfiVariable (
|
||||
IN BOOLEAN VarToList,
|
||||
IN LIST_ENTRY *StorageListHead
|
||||
);
|
||||
|
||||
/**
|
||||
Remove the variable from Efi variable
|
||||
|
||||
Found the variable with the same name in StorageListHead and remove it.
|
||||
|
||||
@param StorageListHead Decide which variale list be removed.
|
||||
|
||||
@retval EFI_SUCCESS Remove the variables successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
RemoveAuthEfiVariable (
|
||||
IN LIST_ENTRY *StorageListHead
|
||||
);
|
||||
|
||||
/**
|
||||
Exchange the data between Efi variable and the data of VarList when the
|
||||
variable use the time stamp authenticated variable header
|
||||
|
||||
If VarToList is TRUE, copy the efi variable data to the VarList; Otherwise,
|
||||
update the data from varlist to efi variable.
|
||||
|
||||
@param VarToList The flag to control the direction of exchange.
|
||||
@param StorageListHead Decide which variale list be updated
|
||||
|
||||
@retval EFI_SUCCESS Get the address successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES No available in the EFI variable zone.
|
||||
@retval EFI_INVALID_PARAMETER Invalid variable name.
|
||||
**/
|
||||
|
||||
EFI_STATUS
|
||||
SynAuthEfiVariableBasedTime (
|
||||
IN BOOLEAN VarToList,
|
||||
IN LIST_ENTRY *StorageListHead
|
||||
);
|
||||
|
||||
/**
|
||||
Remove the variable from Efi variable
|
||||
|
||||
Found the variable with the same name in StorageListHead and remove it.
|
||||
|
||||
@param StorageListHead Decide which variale list be removed.
|
||||
|
||||
@retval EFI_SUCCESS Remove the variables successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
RemoveAuthEfiVariableBasedTime (
|
||||
IN LIST_ENTRY *StorageListHead
|
||||
);
|
||||
|
||||
/**
|
||||
Exchange the data between Efi variable and the data of VarList when the
|
||||
variable use the authenticated variable header
|
||||
|
||||
If VarToList is TRUE, copy the efi variable data to the VarList; Otherwise,
|
||||
update the data from varlist to efi variable.
|
||||
|
||||
@param VarToList The flag to control the direction of exchange.
|
||||
@param StorageListHead Decide which variale list be updated
|
||||
|
||||
@retval EFI_SUCCESS Get the address successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES No available in the EFI variable zone.
|
||||
**/
|
||||
|
||||
EFI_STATUS
|
||||
SynEfiVariable (
|
||||
IN BOOLEAN VarToList,
|
||||
IN LIST_ENTRY *StorageListHead
|
||||
);
|
||||
|
||||
/**
|
||||
Remove the variable from Efi variable
|
||||
|
||||
Found the variable with the same name in StorageListHead and remove it.
|
||||
|
||||
@param StorageListHead Decide which variale list be removed.
|
||||
|
||||
@retval EFI_SUCCESS Remove the variables successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
RemoveNormalEfiVariable (
|
||||
IN LIST_ENTRY *StorageListHead
|
||||
);
|
||||
|
||||
/**
|
||||
Read all defaultId and platformId from binary.
|
||||
|
||||
@param Binary The pointer to the bianry
|
||||
@param Storage The pointer to the Storage
|
||||
**/
|
||||
VOID
|
||||
ReadDefaultAndPlatformIdFromBfv (
|
||||
IN UINT8 *Binary,
|
||||
IN FORMSET_STORAGE *Storage
|
||||
);
|
||||
|
||||
/**
|
||||
Store all defaultId and platformId to binary.
|
||||
|
||||
@param Binary The pointer to the bianry
|
||||
@param Storage The pointer to the Storage
|
||||
|
||||
@retval Length Return the length of the header
|
||||
**/
|
||||
|
||||
UINT32
|
||||
WriteDefaultAndPlatformId (
|
||||
IN UINT8 *Binary,
|
||||
IN FORMSET_STORAGE *Storage
|
||||
);
|
||||
|
||||
/**
|
||||
Store all defaultId and platformId to binary.
|
||||
|
||||
@param Binary The pointer to the bianry
|
||||
@param Storage The pointer to the Storage
|
||||
|
||||
@retval Length Return the length of the header
|
||||
**/
|
||||
UINT32
|
||||
WriteNvStoreDefaultAndPlatformId (
|
||||
IN UINT8 *Binary,
|
||||
IN FORMSET_STORAGE *Storage
|
||||
);
|
||||
|
||||
/**
|
||||
Copy variable to binary in multi-platform mode
|
||||
|
||||
@param Storage The pointer to a storage in storage list.
|
||||
@param StorageBeginning The pointer to the beginning of storage under specifed platformId and defaultId
|
||||
@param Index The number of the storage. If the Index is 0, record the variable header to
|
||||
the binary. Or else, only record the storage.
|
||||
|
||||
@return length The length of storage
|
||||
**/
|
||||
UINT32
|
||||
CopyVariableToBinary (
|
||||
IN FORMSET_STORAGE *Storage,
|
||||
IN OUT UINT8 *StorageBeginning,
|
||||
IN UINT32 Index
|
||||
);
|
||||
|
||||
/**
|
||||
Copy variable to binary in multi-platform mode
|
||||
|
||||
@param Storage The pointer to a storage in storage list.
|
||||
@param StorageBeginning The pointer to the beginning of storage under specifed platformId and defaultId
|
||||
@param Index The number of the storage. If the Index is 0, record the variable header to
|
||||
the binary. Or else, only record the storage.
|
||||
|
||||
@return length The length of storage
|
||||
**/
|
||||
UINT32
|
||||
CopyVariableToNvStoreBinary (
|
||||
IN FORMSET_STORAGE *Storage,
|
||||
IN OUT UINT8 *StorageBeginning,
|
||||
IN UINT32 Index
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Read variable to storage list in multi-platform mode
|
||||
|
||||
@param Binary The pointer to the header of storage under specifed platformId and defaultId
|
||||
@param StorageListEntry The pointer to the storage list.
|
||||
|
||||
@return length The length of storage
|
||||
**/
|
||||
|
||||
UINT32
|
||||
ReadNvStoreVariableToList (
|
||||
IN UINT8 *Binary,
|
||||
IN LIST_ENTRY *StorageListEntry
|
||||
);
|
||||
|
||||
/**
|
||||
Read variable to storage list in multi-platform mode
|
||||
|
||||
@param Binary The pointer to the header of storage under specifed platformId and defaultId
|
||||
@param StorageListEntry The pointer to the storage list.
|
||||
|
||||
@return length The length of storage
|
||||
**/
|
||||
UINT32
|
||||
ReadVariableToList (
|
||||
IN UINT8 *Binary,
|
||||
IN LIST_ENTRY *StorageListEntry
|
||||
);
|
||||
|
||||
/**
|
||||
Check whether exists the valid normal variables in NvStorage or not.
|
||||
|
||||
@retval TRUE If existed, return TRUE.
|
||||
@retval FALSE Others
|
||||
**/
|
||||
BOOLEAN
|
||||
ExistNormalEfiVarOrNot (
|
||||
IN LIST_ENTRY *StorageListHead
|
||||
);
|
||||
|
||||
/**
|
||||
Fix the size of variable header.
|
||||
|
||||
@param Binary The pointer to the header of storage under specifed platformId and defaultId
|
||||
@param Length The length of binary.
|
||||
|
||||
**/
|
||||
VOID
|
||||
FixVariableHeaderSize (
|
||||
IN UINT8 *BinaryBeginning,
|
||||
IN UINT32 Length
|
||||
);
|
||||
|
||||
/**
|
||||
Fix the size of variable header.
|
||||
|
||||
@param Binary The pointer to the header of storage under specifed platformId and defaultId
|
||||
@param Length The length of binary.
|
||||
|
||||
**/
|
||||
|
||||
VOID
|
||||
FixNvStoreVariableHeaderSize (
|
||||
IN UINT8 *BinaryBeginning,
|
||||
IN UINT32 Length
|
||||
);
|
||||
/**
|
||||
Copy time-based authenticated variable to binary in multi-platform mode
|
||||
|
||||
@param Storage The pointer to a storage in storage list.
|
||||
@param StorageBeginning The pointer to the beginning of storage under specifed platformId and defaultId
|
||||
@param Index The number of the storage. If the Index is 0, record the variable header to
|
||||
the binary. Or else, only record the storage.
|
||||
@return length The length of storage
|
||||
**/
|
||||
UINT32
|
||||
CopyTimeBasedVariableToBinary (
|
||||
IN FORMSET_STORAGE *Storage,
|
||||
IN OUT UINT8 *StorageBeginning,
|
||||
IN UINT32 Index
|
||||
);
|
||||
|
||||
/**
|
||||
Read time-based authenticated variable to storage list in multi-platform mode
|
||||
|
||||
@param Binary The pointer to the header of storage under specifed platformId and defaultId
|
||||
@param StorageListEntry The pointer to the storage list.
|
||||
|
||||
@return length The length of storage
|
||||
**/
|
||||
UINT32
|
||||
ReadTimeBasedVariableToList (
|
||||
IN UINT8 *Binary,
|
||||
IN LIST_ENTRY *StorageListEntry
|
||||
);
|
||||
|
||||
/**
|
||||
Check whether exists the valid time-based variables in NvStorage or not.
|
||||
|
||||
@retval TRUE If existed, return TRUE.
|
||||
@retval FALSE Others
|
||||
**/
|
||||
BOOLEAN
|
||||
ExistTimeBasedEfiVarOrNot (
|
||||
IN LIST_ENTRY *StorageListHead
|
||||
);
|
||||
|
||||
/**
|
||||
Fix the size of time-based variable header.
|
||||
|
||||
@param Binary The pointer to the header of storage under specifed platformId and defaultId
|
||||
@param Length The length of binary.
|
||||
|
||||
**/
|
||||
VOID
|
||||
FixBasedTimeVariableHeaderSize (
|
||||
IN UINT8 *BinaryBeginning,
|
||||
IN UINT32 Length
|
||||
);
|
||||
|
||||
/**
|
||||
Copy Monotonic-Based authenticated variable to binary in multi-platform mode
|
||||
|
||||
@param Storage The pointer to a storage in storage list.
|
||||
@param StorageBeginning The pointer to the beginning of storage under specifed platformId and defaultId
|
||||
@param Index The number of the storage. If the Index is 0, record the variable header to
|
||||
the binary. Or else, only record the storage.
|
||||
|
||||
@return length The length of storage
|
||||
**/
|
||||
UINT32
|
||||
CopyMonotonicBasedVariableToBinary (
|
||||
IN FORMSET_STORAGE *Storage,
|
||||
IN OUT UINT8 *StorageBeginning,
|
||||
IN UINT32 Index
|
||||
);
|
||||
|
||||
/**
|
||||
Read Monotonic-based authenticated variable to storage list in multi-platform mode
|
||||
|
||||
@param Binary The pointer to the header of storage under specifed platformId and defaultId
|
||||
@param StorageListEntry The pointer to the storage list.
|
||||
|
||||
@return length The length of storage
|
||||
**/
|
||||
UINT32
|
||||
ReadMonotonicBasedVariableToList (
|
||||
IN UINT8 *Binary,
|
||||
IN LIST_ENTRY *StorageListEntry
|
||||
);
|
||||
|
||||
/**
|
||||
Check whether exists the valid MonotonicBased variables in NvStorage or not.
|
||||
|
||||
@retval TRUE If existed, return TRUE.
|
||||
@retval FALSE Others
|
||||
**/
|
||||
BOOLEAN
|
||||
ExistMonotonicBasedEfiVarOrNot (
|
||||
IN LIST_ENTRY *StorageListHead
|
||||
);
|
||||
|
||||
/**
|
||||
Fix the size of montonic variable header.
|
||||
|
||||
@param Binary The pointer to the header of storage under specifed platformId and defaultId
|
||||
@param Length The length of binary.
|
||||
|
||||
**/
|
||||
VOID
|
||||
FixMontonicVariableHeaderSize (
|
||||
IN UINT8 *BinaryBeginning,
|
||||
IN UINT32 Length
|
||||
);
|
||||
|
||||
/**
|
||||
FCE application entry point
|
||||
|
||||
@param argc The number of input parameters.
|
||||
@param *argv[] The array pointer to the parameters.
|
||||
|
||||
@retval 0 The application exited normally.
|
||||
@retval 1 An error occurred.
|
||||
@retval 2 An error about check occurred.
|
||||
|
||||
**/
|
||||
int
|
||||
main (
|
||||
int argc,
|
||||
char *argv[]
|
||||
);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,55 @@
|
|||
## @file GNUmakefile
|
||||
#
|
||||
# GNU makefile for 'FCE' module build.
|
||||
#
|
||||
# Copyright (c) 2007 - 2018, 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 ARCH
|
||||
#
|
||||
# If ARCH is not defined, then we use 'uname -m' to attempt
|
||||
# try to figure out the appropriate ARCH.
|
||||
#
|
||||
uname_m = $(shell uname -m)
|
||||
$(info Attempting to detect ARCH from 'uname -m': $(uname_m))
|
||||
ifneq (,$(strip $(filter $(uname_m), x86_64 amd64)))
|
||||
ARCH=X64
|
||||
endif
|
||||
ifeq ($(patsubst i%86,IA32,$(uname_m)),IA32)
|
||||
ARCH=IA32
|
||||
endif
|
||||
ifneq (,$(findstring aarch64,$(uname_m)))
|
||||
ARCH=AARCH64
|
||||
endif
|
||||
ifneq (,$(findstring arm,$(uname_m)))
|
||||
ARCH=ARM
|
||||
endif
|
||||
ifndef ARCH
|
||||
$(info Could not detected ARCH from uname results)
|
||||
$(error ARCH is not defined!)
|
||||
endif
|
||||
$(info Detected ARCH of $(ARCH) using uname.)
|
||||
endif
|
||||
|
||||
export ARCH
|
||||
export HOST_ARCH=$(ARCH)
|
||||
|
||||
MAKEROOT ?= $(EDK_TOOLS_PATH)/Source/C
|
||||
|
||||
APPNAME = FCE
|
||||
|
||||
OBJECTS = Fce.o Variable.o TimeBasedVariable.o MonotonicBasedVariable.o IfrParse.o Common.o BinaryParse.o BinaryCreate.o Expression.o
|
||||
|
||||
include $(MAKEROOT)/Makefiles/app.makefile
|
||||
|
||||
LIBS = -lCommon -lm
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,789 @@
|
|||
/** @file
|
||||
|
||||
Parser for IFR binary encoding.
|
||||
|
||||
Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _IFR_PARSE_H_
|
||||
#define _IFR_PARSE_H_
|
||||
|
||||
#include "Common.h"
|
||||
#include <Common/UefiInternalFormRepresentation.h>
|
||||
#include <Common/MdeModuleHii.h>
|
||||
|
||||
//
|
||||
// Scope for Browser action. It may be Form, FormSet or System level.
|
||||
//
|
||||
typedef enum {
|
||||
FormLevel,
|
||||
FormSetLevel,
|
||||
SystemLevel,
|
||||
MaxLevel
|
||||
} BROWSER_SETTING_SCOPE;
|
||||
|
||||
///
|
||||
///Old EFI_IFR_VARSTORE_EFI structure to complible with UEFI 2.3
|
||||
///
|
||||
typedef struct _EFI_IFR_VARSTORE_EFI_OLD {
|
||||
EFI_IFR_OP_HEADER Header;
|
||||
EFI_VARSTORE_ID VarStoreId;
|
||||
EFI_GUID Guid;
|
||||
UINT32 Attributes;
|
||||
} EFI_IFR_VARSTORE_EFI_OLD;
|
||||
|
||||
///
|
||||
/// The languages used in HII DB
|
||||
///
|
||||
typedef enum {
|
||||
UQI,
|
||||
EN_US,
|
||||
ENG
|
||||
} LANGUAGE;
|
||||
|
||||
///
|
||||
/// Define the structure for the parameters of Uqi and Uqi List
|
||||
///
|
||||
typedef struct _FORM_BROWSER_STATEMENT FORM_BROWSER_STATEMENT;
|
||||
|
||||
typedef enum {
|
||||
ONE_OF,
|
||||
NUMERIC,
|
||||
CHECKBOX,
|
||||
STRING,
|
||||
ORDERED_LIST
|
||||
} QUEST_TYPE;
|
||||
|
||||
typedef struct {
|
||||
UINT16 *DefaultId;
|
||||
UINT64 *PlatformId;
|
||||
UINT32 IdNum;
|
||||
UINT32 HexNum;
|
||||
QUEST_TYPE Type;
|
||||
CHAR16 *Data;
|
||||
UINT8 *Value;
|
||||
UINT8 *DiffValue;
|
||||
UINT32 ScriptsLine;
|
||||
FORM_BROWSER_STATEMENT *Question;
|
||||
} UQI_HEADER;
|
||||
|
||||
typedef struct _UQI_PARAM_LIST {
|
||||
struct _UQI_PARAM_LIST *Next;
|
||||
UQI_HEADER Header;
|
||||
BOOLEAN ParseOrNot;
|
||||
BOOLEAN SameOrNot;
|
||||
BOOLEAN ErrorOrNot;
|
||||
CHAR8 *Error;
|
||||
} UQI_PARAM_LIST;
|
||||
|
||||
//
|
||||
// Incremental size of stack for expression
|
||||
//
|
||||
#define EXPRESSION_STACK_SIZE_INCREMENT 0x100
|
||||
|
||||
//
|
||||
// IFR relative definition
|
||||
//
|
||||
#define EFI_HII_EXPRESSION_INCONSISTENT_IF 0
|
||||
#define EFI_HII_EXPRESSION_NO_SUBMIT_IF 1
|
||||
#define EFI_HII_EXPRESSION_GRAY_OUT_IF 2
|
||||
#define EFI_HII_EXPRESSION_SUPPRESS_IF 3
|
||||
#define EFI_HII_EXPRESSION_DISABLE_IF 4
|
||||
#define EFI_HII_EXPRESSION_VALUE 5
|
||||
#define EFI_HII_EXPRESSION_RULE 6
|
||||
#define EFI_HII_EXPRESSION_READ 7
|
||||
#define EFI_HII_EXPRESSION_WRITE 8
|
||||
#define EFI_HII_EXPRESSION_WARNING_IF 9
|
||||
|
||||
#define EFI_HII_VARSTORE_BUFFER 0
|
||||
#define EFI_HII_VARSTORE_NAME_VALUE 1
|
||||
#define EFI_HII_VARSTORE_EFI_VARIABLE 2
|
||||
#define EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER 3
|
||||
|
||||
#define FORM_INCONSISTENT_VALIDATION 0
|
||||
#define FORM_NO_SUBMIT_VALIDATION 1
|
||||
|
||||
typedef struct {
|
||||
//
|
||||
// HII Data Type
|
||||
//
|
||||
UINT8 Type;
|
||||
//
|
||||
// Buffer Data and Length if Type is EFI_IFR_TYPE_BUFFER or EFI_IFR_TYPE_STRING
|
||||
//
|
||||
UINT8 *Buffer;
|
||||
UINT16 BufferLen;
|
||||
EFI_IFR_TYPE_VALUE Value;
|
||||
} EFI_HII_VALUE;
|
||||
|
||||
#define NAME_VALUE_NODE_SIGNATURE SIGNATURE_32 ('N', 'V', 'S', 'T')
|
||||
|
||||
typedef struct {
|
||||
UINTN Signature;
|
||||
LIST_ENTRY Link;
|
||||
CHAR16 *Name;
|
||||
CHAR16 *Value;
|
||||
CHAR16 *EditValue;
|
||||
} NAME_VALUE_NODE;
|
||||
|
||||
#define NAME_VALUE_NODE_FROM_LINK(a) CR (a, NAME_VALUE_NODE, Link, NAME_VALUE_NODE_SIGNATURE)
|
||||
|
||||
#define FORMSET_STORAGE_SIGNATURE SIGNATURE_32 ('F', 'S', 'T', 'G')
|
||||
|
||||
typedef struct {
|
||||
UINTN Signature;
|
||||
LIST_ENTRY Link;
|
||||
|
||||
UINT16 DefaultId[MAX_PLATFORM_DEFAULT_ID_NUM];
|
||||
UINT64 PlatformId[MAX_PLATFORM_DEFAULT_ID_NUM];
|
||||
UINT32 DefaultPlatformIdNum;
|
||||
UINT32 FormSetOrder;
|
||||
|
||||
BOOLEAN NewEfiVarstore; //EfiVarStore for UEFI 2.31 or not
|
||||
BOOLEAN Skip; //Flag for sorting out the variables
|
||||
|
||||
UINT8 Type; // Storage type
|
||||
|
||||
UINT16 VarStoreId;
|
||||
EFI_GUID Guid;
|
||||
|
||||
CHAR16 *Name; // For EFI_IFR_VARSTORE
|
||||
UINT16 Size;
|
||||
UINT8 *Buffer;
|
||||
|
||||
LIST_ENTRY NameValueListHead; // List of NAME_VALUE_NODE
|
||||
|
||||
UINT32 Attributes; // For EFI_IFR_VARSTORE_EFI: EFI Variable attribute
|
||||
} FORMSET_STORAGE;
|
||||
|
||||
#define FORMSET_STORAGE_FROM_LINK(a) CR (a, FORMSET_STORAGE, Link, FORMSET_STORAGE_SIGNATURE)
|
||||
|
||||
typedef union {
|
||||
EFI_STRING_ID VarName;
|
||||
UINT16 VarOffset;
|
||||
} VAR_STORE_INFO;
|
||||
|
||||
#define EXPRESSION_OPCODE_SIGNATURE SIGNATURE_32 ('E', 'X', 'O', 'P')
|
||||
|
||||
typedef struct {
|
||||
UINTN Signature;
|
||||
LIST_ENTRY Link;
|
||||
|
||||
UINT8 Operand;
|
||||
|
||||
UINT8 Format; // For EFI_IFR_TO_STRING, EFI_IFR_FIND
|
||||
UINT8 Flags; // For EFI_IFR_SPAN
|
||||
UINT8 RuleId; // For EFI_IFR_RULE_REF
|
||||
|
||||
EFI_HII_VALUE Value; // For EFI_IFR_EQ_ID_VAL, EFI_IFR_UINT64, EFI_IFR_UINT32, EFI_IFR_UINT16, EFI_IFR_UINT8, EFI_IFR_STRING_REF1
|
||||
|
||||
EFI_QUESTION_ID QuestionId; // For EFI_IFR_EQ_ID_ID, EFI_IFR_EQ_ID_VAL_LIST, EFI_IFR_QUESTION_REF1
|
||||
EFI_QUESTION_ID QuestionId2;
|
||||
|
||||
UINT16 ListLength; // For EFI_IFR_EQ_ID_VAL_LIST
|
||||
UINT16 *ValueList;
|
||||
|
||||
EFI_STRING_ID DevicePath; // For EFI_IFR_QUESTION_REF3_2, EFI_IFR_QUESTION_REF3_3
|
||||
EFI_GUID Guid;
|
||||
|
||||
FORMSET_STORAGE *VarStorage; // For EFI_IFR_SET, EFI_IFR_GET
|
||||
VAR_STORE_INFO VarStoreInfo;// For EFI_IFR_SET, EFI_IFR_GET
|
||||
UINT8 ValueType; // For EFI_IFR_SET, EFI_IFR_GET
|
||||
UINT8 ValueWidth; // For EFI_IFR_SET, EFI_IFR_GET
|
||||
CHAR16 *ValueName; // For EFI_IFR_SET, EFI_IFR_GET
|
||||
LIST_ENTRY MapExpressionList; // nested expressions inside of Map opcode.
|
||||
} EXPRESSION_OPCODE;
|
||||
|
||||
#define EXPRESSION_OPCODE_FROM_LINK(a) CR (a, EXPRESSION_OPCODE, Link, EXPRESSION_OPCODE_SIGNATURE)
|
||||
|
||||
#define FORM_EXPRESSION_SIGNATURE SIGNATURE_32 ('F', 'E', 'X', 'P')
|
||||
|
||||
typedef struct {
|
||||
UINTN Signature;
|
||||
LIST_ENTRY Link;
|
||||
|
||||
UINT8 Type; // Type for this expression
|
||||
|
||||
UINT8 RuleId; // For EFI_IFR_RULE only
|
||||
EFI_STRING_ID Error; // For EFI_IFR_NO_SUBMIT_IF, EFI_IFR_INCONSISTENT_IF only
|
||||
|
||||
EFI_HII_VALUE Result; // Expression evaluation result
|
||||
UINT8 TimeOut; // For EFI_IFR_WARNING_IF
|
||||
|
||||
LIST_ENTRY OpCodeListHead; // OpCodes consist of this expression (EXPRESSION_OPCODE)
|
||||
} FORM_EXPRESSION;
|
||||
|
||||
#define FORM_EXPRESSION_FROM_LINK(a) CR (a, FORM_EXPRESSION, Link, FORM_EXPRESSION_SIGNATURE)
|
||||
|
||||
#define QUESTION_DEFAULT_SIGNATURE SIGNATURE_32 ('Q', 'D', 'F', 'T')
|
||||
|
||||
typedef struct {
|
||||
UINTN Signature;
|
||||
LIST_ENTRY Link;
|
||||
|
||||
UINT16 DefaultId;
|
||||
EFI_HII_VALUE Value; // Default value
|
||||
|
||||
FORM_EXPRESSION *ValueExpression; // Not-NULL indicates default value is provided by EFI_IFR_VALUE
|
||||
} QUESTION_DEFAULT;
|
||||
|
||||
#define QUESTION_DEFAULT_FROM_LINK(a) CR (a, QUESTION_DEFAULT, Link, QUESTION_DEFAULT_SIGNATURE)
|
||||
|
||||
#define QUESTION_OPTION_SIGNATURE SIGNATURE_32 ('Q', 'O', 'P', 'T')
|
||||
|
||||
typedef struct {
|
||||
UINTN Signature;
|
||||
LIST_ENTRY Link;
|
||||
|
||||
EFI_STRING_ID Text;
|
||||
UINT8 Flags;
|
||||
EFI_HII_VALUE Value;
|
||||
|
||||
FORM_EXPRESSION *SuppressExpression; // Non-NULL indicates nested inside of SuppressIf
|
||||
} QUESTION_OPTION;
|
||||
|
||||
#define QUESTION_OPTION_FROM_LINK(a) CR (a, QUESTION_OPTION, Link, QUESTION_OPTION_SIGNATURE)
|
||||
|
||||
#define FORM_BROWSER_STATEMENT_SIGNATURE SIGNATURE_32 ('F', 'S', 'T', 'A')
|
||||
|
||||
struct _FORM_BROWSER_STATEMENT {
|
||||
UINTN Signature;
|
||||
LIST_ENTRY Link;
|
||||
UINT8 Operand; // The operand (first byte) of this Statement or Question
|
||||
|
||||
UQI_HEADER Uqi;
|
||||
UINT32 FormSetOrder;
|
||||
EFI_GUID Guid;
|
||||
UINT8 Type; // Storage type
|
||||
BOOLEAN NewEfiVarstore; //EfiVarStore for UEFI 2.31 or not
|
||||
UINT32 Attributes; // For EFI_IFR_VARSTORE_EFI: EFI Variable attribute
|
||||
BOOLEAN QuestionReferToBitField;// Whether the question is stored in a bit field.
|
||||
//
|
||||
// Statement Header
|
||||
//
|
||||
EFI_STRING_ID Prompt;
|
||||
EFI_STRING_ID Help;
|
||||
EFI_STRING_ID TextTwo; // For EFI_IFR_TEXT
|
||||
|
||||
//
|
||||
// Question Header
|
||||
//
|
||||
EFI_QUESTION_ID QuestionId; // The value of zero is reserved
|
||||
EFI_VARSTORE_ID VarStoreId; // A value of zero indicates no variable storage
|
||||
FORMSET_STORAGE *Storage;
|
||||
VAR_STORE_INFO VarStoreInfo;
|
||||
UINT16 StorageWidth;
|
||||
UINT16 BitStorageWidth;
|
||||
UINT16 BitVarOffset;
|
||||
UINT8 QuestionFlags;
|
||||
CHAR16 *VariableName; // Name/Value or EFI Variable name
|
||||
|
||||
EFI_HII_VALUE HiiValue; // Edit copy for checkbox, numberic, oneof
|
||||
UINT8 *BufferValue; // Edit copy for string, password, orderedlist
|
||||
UINT8 ValueType; // Data type for orderedlist value array
|
||||
|
||||
//
|
||||
// OpCode specific members
|
||||
//
|
||||
UINT8 Flags; // for EFI_IFR_CHECKBOX, EFI_IFR_DATE, EFI_IFR_NUMERIC, EFI_IFR_ONE_OF,
|
||||
// EFI_IFR_ORDERED_LIST, EFI_IFR_STRING,EFI_IFR_SUBTITLE,EFI_IFR_TIME, EFI_IFR_BANNER
|
||||
UINT8 MaxContainers; // for EFI_IFR_ORDERED_LIST
|
||||
|
||||
UINT16 BannerLineNumber; // for EFI_IFR_BANNER, 1-based line number
|
||||
|
||||
UINT64 Minimum; // for EFI_IFR_ONE_OF/EFI_IFR_NUMERIC, it's Min/Max value
|
||||
UINT64 Maximum; // for EFI_IFR_STRING/EFI_IFR_PASSWORD, it's Min/Max length
|
||||
UINT64 Step;
|
||||
|
||||
EFI_DEFAULT_ID DefaultId; // for EFI_IFR_RESET_BUTTON
|
||||
EFI_GUID RefreshGuid; // for EFI_IFR_REFRESH_ID
|
||||
|
||||
//
|
||||
// Get from IFR parsing
|
||||
//
|
||||
FORM_EXPRESSION *ValueExpression; // nested EFI_IFR_VALUE, provide Question value and indicate Question is ReadOnly
|
||||
LIST_ENTRY DefaultListHead; // nested EFI_IFR_DEFAULT list (QUESTION_DEFAULT), provide default values
|
||||
LIST_ENTRY OptionListHead; // nested EFI_IFR_ONE_OF_OPTION list (QUESTION_OPTION)
|
||||
|
||||
EFI_IMAGE_ID ImageId; // nested EFI_IFR_IMAGE
|
||||
UINT8 RefreshInterval; // nested EFI_IFR_REFRESH, refresh interval(in seconds) for Question value, 0 means no refresh
|
||||
BOOLEAN InSubtitle; // nesting inside of EFI_IFR_SUBTITLE
|
||||
|
||||
LIST_ENTRY InconsistentListHead;// nested inconsistent expression list (FORM_EXPRESSION)
|
||||
LIST_ENTRY NoSubmitListHead; // nested nosubmit expression list (FORM_EXPRESSION)
|
||||
LIST_ENTRY WarningListHead; // nested warning expression list (FORM_EXPRESSION)
|
||||
FORM_EXPRESSION *GrayOutExpression; // nesting inside of GrayOutIf
|
||||
FORM_EXPRESSION *SuppressExpression; // nesting inside of SuppressIf
|
||||
FORM_EXPRESSION *DisableExpression; // nesting inside of DisableIf
|
||||
|
||||
FORM_EXPRESSION *ReadExpression; // nested EFI_IFR_READ, provide this question value by read expression.
|
||||
FORM_EXPRESSION *WriteExpression; // nested EFI_IFR_WRITE, evaluate write expression after this question value is set.
|
||||
};
|
||||
|
||||
#define FORM_BROWSER_STATEMENT_FROM_LINK(a) CR (a, FORM_BROWSER_STATEMENT, Link, FORM_BROWSER_STATEMENT_SIGNATURE)
|
||||
|
||||
#define FORM_BROWSER_FORM_SIGNATURE SIGNATURE_32 ('F', 'F', 'R', 'M')
|
||||
#define STANDARD_MAP_FORM_TYPE 0x01
|
||||
|
||||
typedef struct {
|
||||
UINTN Signature;
|
||||
LIST_ENTRY Link;
|
||||
|
||||
UINT16 FormId; // FormId of normal form or formmap form.
|
||||
EFI_STRING_ID FormTitle; // FormTile of normal form, or FormMapMethod title of formmap form.
|
||||
UINT16 FormType; // Specific form type for the different form.
|
||||
|
||||
BOOLEAN ModalForm; // Whether this is a modal form.
|
||||
LIST_ENTRY ExpressionListHead; // List of Expressions (FORM_EXPRESSION)
|
||||
LIST_ENTRY StatementListHead; // List of Statements and Questions (FORM_BROWSER_STATEMENT)
|
||||
FORM_EXPRESSION *SuppressExpression; // nesting inside of SuppressIf
|
||||
} FORM_BROWSER_FORM;
|
||||
|
||||
#define FORM_BROWSER_FORM_FROM_LINK(a) CR (a, FORM_BROWSER_FORM, Link, FORM_BROWSER_FORM_SIGNATURE)
|
||||
|
||||
#define FORMSET_DEFAULTSTORE_SIGNATURE SIGNATURE_32 ('F', 'D', 'F', 'S')
|
||||
|
||||
typedef struct {
|
||||
UINTN Signature;
|
||||
LIST_ENTRY Link;
|
||||
|
||||
UINT16 DefaultId;
|
||||
EFI_STRING_ID DefaultName;
|
||||
} FORMSET_DEFAULTSTORE;
|
||||
|
||||
#define STRING_NUMBER 100
|
||||
|
||||
typedef struct {
|
||||
EFI_STRING_ID StringId;
|
||||
CHAR16 *String;
|
||||
} STRING_INFO;
|
||||
|
||||
typedef struct {
|
||||
EFI_STRING_ID CachedIdNum;
|
||||
EFI_STRING_ID MaxIdNum;
|
||||
STRING_INFO *StringInfoList;
|
||||
} FORMSET_STRING_LIST;
|
||||
|
||||
#define FORMSET_DEFAULTSTORE_FROM_LINK(a) CR (a, FORMSET_DEFAULTSTORE, Link, FORMSET_DEFAULTSTORE_SIGNATURE)
|
||||
|
||||
#define FORM_BROWSER_FORMSET_SIGNATURE SIGNATURE_32 ('F', 'B', 'F', 'S')
|
||||
|
||||
typedef struct {
|
||||
UINTN Signature;
|
||||
LIST_ENTRY Link;
|
||||
|
||||
UINT32 FormSetOrder;
|
||||
|
||||
UINTN IfrBinaryLength;
|
||||
UINT8 *IfrBinaryData;
|
||||
UINT8 *UnicodeBinary;
|
||||
|
||||
EFI_GUID Guid;
|
||||
EFI_STRING_ID FormSetTitle;
|
||||
EFI_STRING_ID Help;
|
||||
UINT8 NumberOfClassGuid;
|
||||
EFI_GUID ClassGuid[3]; // Up to three ClassGuid
|
||||
UINT16 Class; // Tiano extended Class code
|
||||
UINT16 SubClass; // Tiano extended Subclass code
|
||||
|
||||
FORM_BROWSER_STATEMENT *StatementBuffer; // Buffer for all Statements and Questions
|
||||
EXPRESSION_OPCODE *ExpressionBuffer; // Buffer for all Expression OpCode
|
||||
|
||||
LIST_ENTRY *StorageListHead; // Storage list (FORMSET_STORAGE)
|
||||
LIST_ENTRY DefaultStoreListHead; // DefaultStore list (FORMSET_DEFAULTSTORE)
|
||||
LIST_ENTRY FormListHead; // Form list (FORM_BROWSER_FORM)
|
||||
LIST_ENTRY ExpressionListHead; // List of Expressions (FORM_EXPRESSION)
|
||||
FORMSET_STRING_LIST EnUsStringList; // Cache EN_US English list
|
||||
FORMSET_STRING_LIST UqiStringList; // Cache EN_US English list
|
||||
} FORM_BROWSER_FORMSET;
|
||||
|
||||
#define FORM_BROWSER_FORMSET_FROM_LINK(a) CR (a, FORM_BROWSER_FORMSET, Link, FORM_BROWSER_FORMSET_SIGNATURE)
|
||||
|
||||
///
|
||||
/// Structure for multi-platform support
|
||||
///
|
||||
typedef struct {
|
||||
UINT16 DefaultId[MAX_PLATFORM_DEFAULT_ID_NUM];
|
||||
UINT16 DefaultIdNum;
|
||||
UINT64 PlatformId[MAX_PLATFORM_DEFAULT_ID_NUM];
|
||||
UINT16 PlatformIdNum;
|
||||
UINT16 KeyDefaultId[MAX_PLATFORM_DEFAULT_ID_NUM];
|
||||
UINT64 KeyPlatformId[MAX_PLATFORM_DEFAULT_ID_NUM];
|
||||
UINT16 KeyIdNum;
|
||||
FORM_BROWSER_STATEMENT PlatformIdQuestion;
|
||||
FORM_BROWSER_STATEMENT *Question;
|
||||
UINT16 PlatformIdWidth;
|
||||
UQI_HEADER Uqi;
|
||||
BOOLEAN MultiPlatformOrNot;
|
||||
BOOLEAN ExistStorageFfsInBfv;
|
||||
BOOLEAN SizeOptimized;
|
||||
BOOLEAN SizeOptimizedParam;
|
||||
} MULTI_PLATFORM_PARAMETERS;
|
||||
|
||||
/**
|
||||
Search the variable list according to the variable Guid and name, and return the pointer
|
||||
of that Node.
|
||||
|
||||
@param HiiObjList The pointer to the Question
|
||||
@param VarName The EFI variable name need to be updated to VarList
|
||||
@param Offset The offset of the variable
|
||||
@param StorageListHead The pointer to the LIST_ENTRY of Storage
|
||||
@param Vaue The value in that value offset of the variable
|
||||
@param VarList The dual pointer of Varlist
|
||||
|
||||
@return EFI_SUCCESS
|
||||
**/
|
||||
EFI_STATUS
|
||||
SearchVarStorage (
|
||||
IN FORM_BROWSER_STATEMENT *Question,
|
||||
IN CHAR16* VarName,
|
||||
IN UINT32 Offset,
|
||||
IN LIST_ENTRY *StorageListHead,
|
||||
IN OUT CHAR8 **Value,
|
||||
IN OUT FORMSET_STORAGE **VarList
|
||||
);
|
||||
|
||||
/**
|
||||
Get the string based on the StringId and HII Package List Handle.
|
||||
|
||||
@param Token The String's ID.
|
||||
@param HiiHandle The package list in the HII database to search for
|
||||
the specified string.
|
||||
|
||||
@return The output string.
|
||||
|
||||
**/
|
||||
CHAR16 *
|
||||
GetToken (
|
||||
IN EFI_STRING_ID Token,
|
||||
IN UINT8 *UniPackge
|
||||
);
|
||||
|
||||
/**
|
||||
Free resources allocated for all Storage in an LIST_ENTRY.
|
||||
|
||||
@param FormSet Pointer of the FormSet
|
||||
|
||||
**/
|
||||
VOID
|
||||
DestroyAllStorage (
|
||||
IN LIST_ENTRY *StorageEntryListHead
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Free resources allocated for a FormSet.
|
||||
|
||||
@param FormSet Pointer of the FormSet
|
||||
|
||||
**/
|
||||
VOID
|
||||
DestroyFormSet (
|
||||
IN FORM_BROWSER_FORMSET *FormSet
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Free resources allocated for all FormSet in an LIST_ENTRY.
|
||||
|
||||
@param FormSet Pointer of the FormSet
|
||||
|
||||
**/
|
||||
VOID
|
||||
DestroyAllFormSet (
|
||||
IN LIST_ENTRY *FormSetEntryListHead
|
||||
);
|
||||
|
||||
/**
|
||||
Parse opcodes in the formset IFR binary.
|
||||
|
||||
@param FormSet Pointer of the FormSet data structure.
|
||||
|
||||
@retval EFI_SUCCESS Opcode parse success.
|
||||
@retval Other Opcode parse fail.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
ParseOpCodes (
|
||||
IN FORM_BROWSER_FORMSET *FormSet
|
||||
);
|
||||
|
||||
/**
|
||||
Set the value to the variable of platformId question.
|
||||
|
||||
@param PlatformId The form set.
|
||||
|
||||
@retval EFI_SUCCESS Set successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
AssignThePlatformId (
|
||||
IN UINT64 PlatformId
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Reset Questions to their default value in a Form, Formset or System.
|
||||
|
||||
@param FormSet FormSet data structure.
|
||||
@param Form Form data structure.
|
||||
@param DefaultId The default Id
|
||||
@param PlatformId The platform Id
|
||||
@param SettingScope Setting Scope for Default action.
|
||||
|
||||
@retval EFI_SUCCESS The function completed successfully.
|
||||
@retval EFI_UNSUPPORTED Unsupport SettingScope.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
ExtractDefault (
|
||||
IN FORM_BROWSER_FORMSET *FormSet,
|
||||
IN FORM_BROWSER_FORM *Form,
|
||||
IN UINT16 DefaultId,
|
||||
IN UINT64 PlatformId,
|
||||
IN BROWSER_SETTING_SCOPE SettingScope
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Reset stack pointer to begin of the stack.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ResetCurrentExpressionStack (
|
||||
VOID
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Push current expression onto the Stack
|
||||
|
||||
@param Pointer Pointer to current expression.
|
||||
|
||||
@retval EFI_SUCCESS The value was pushed onto the stack.
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PushCurrentExpression (
|
||||
IN VOID *Pointer
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Pop current expression from the Stack
|
||||
|
||||
@param Pointer Pointer to current expression to be pop.
|
||||
|
||||
@retval EFI_SUCCESS The value was pushed onto the stack.
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PopCurrentExpression (
|
||||
OUT VOID **Pointer
|
||||
);
|
||||
|
||||
/**
|
||||
Reset stack pointer to begin of the stack.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ResetMapExpressionListStack (
|
||||
VOID
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Push the list of map expression onto the Stack
|
||||
|
||||
@param Pointer Pointer to the list of map expression to be pushed.
|
||||
|
||||
@retval EFI_SUCCESS The value was pushed onto the stack.
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PushMapExpressionList (
|
||||
IN VOID *Pointer
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Pop the list of map expression from the Stack
|
||||
|
||||
@param Pointer Pointer to the list of map expression to be pop.
|
||||
|
||||
@retval EFI_SUCCESS The value was pushed onto the stack.
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PopMapExpressionList (
|
||||
OUT VOID **Pointer
|
||||
);
|
||||
|
||||
/**
|
||||
Reset stack pointer to begin of the stack.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ResetScopeStack (
|
||||
VOID
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Push an Operand onto the Stack
|
||||
|
||||
@param Operand Operand to push.
|
||||
|
||||
@retval EFI_SUCCESS The value was pushed onto the stack.
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
|
||||
stack.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PushScope (
|
||||
IN UINT8 Operand
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Pop an Operand from the Stack
|
||||
|
||||
@param Operand Operand to pop.
|
||||
|
||||
@retval EFI_SUCCESS The value was pushed onto the stack.
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
|
||||
stack.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PopScope (
|
||||
OUT UINT8 *Operand
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Zero extend integer/boolean/date/time to UINT64 for comparing.
|
||||
|
||||
@param Value HII Value to be converted.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ExtendValueToU64 (
|
||||
IN EFI_HII_VALUE *Value
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Compare two Hii value.
|
||||
|
||||
@param Value1 Expression value to compare on left-hand.
|
||||
@param Value2 Expression value to compare on right-hand.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Could not perform compare on two values.
|
||||
@retval 0 Two operators equal.
|
||||
@return Positive value if Value1 is greater than Value2.
|
||||
@retval Negative value if Value1 is less than Value2.
|
||||
|
||||
**/
|
||||
INTN
|
||||
CompareHiiValue (
|
||||
IN EFI_HII_VALUE *Value1,
|
||||
IN EFI_HII_VALUE *Value2,
|
||||
IN FORM_BROWSER_FORMSET *FormSet
|
||||
);
|
||||
|
||||
/**
|
||||
Evaluate the result of a HII expression.
|
||||
|
||||
If Expression is NULL, then ASSERT.
|
||||
|
||||
@param FormSet FormSet associated with this expression.
|
||||
@param Form Form associated with this expression.
|
||||
@param Expression Expression to be evaluated.
|
||||
@param ConstantExpression The pointer to the flag of constant expression. If constant, will return TRUE.
|
||||
|
||||
@retval EFI_SUCCESS The expression evaluated successfuly
|
||||
@retval EFI_NOT_FOUND The Question which referenced by a QuestionId
|
||||
could not be found.
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
|
||||
stack.
|
||||
@retval EFI_ACCESS_DENIED The pop operation underflowed the stack
|
||||
@retval EFI_INVALID_PARAMETER Syntax error with the Expression
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EvaluateExpression (
|
||||
IN FORM_BROWSER_FORMSET *FormSet,
|
||||
IN FORM_BROWSER_FORM *Form,
|
||||
IN OUT FORM_EXPRESSION *Expression,
|
||||
IN OUT BOOLEAN *ConstantExpression
|
||||
);
|
||||
|
||||
/**
|
||||
Compare two Uqi parameters
|
||||
|
||||
@param UqiParm1 The pointer to the first Uqi parameter.
|
||||
@param UqiParm2 The pointer to the second Uqi parameter.
|
||||
|
||||
@retval TRUE If these two Uqi parameters are the same, return TRUE;
|
||||
@return FALSE Otherwise, return FALSE;
|
||||
**/
|
||||
BOOLEAN
|
||||
CompareUqiHeader (
|
||||
IN CONST UQI_HEADER *UqiParm1,
|
||||
IN CONST UQI_HEADER *UqiParm2
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Print all ONE_OF ORDER_LIST NUMERIC STRING and CHECKBOX in all fromsets.
|
||||
|
||||
@param Formset The pointer to the entry of the fromset list
|
||||
@param Formset The pointer to the entry of the storage list
|
||||
|
||||
@retval EFI_SUCCESS It was complete successfully
|
||||
@return EFI_ABORTED An error occurred
|
||||
**/
|
||||
EFI_STATUS
|
||||
PrintInfoInAllFormset (
|
||||
IN LIST_ENTRY *FormSetEntryListHead,
|
||||
IN LIST_ENTRY *StorageEntryListHead
|
||||
);
|
||||
|
||||
/**
|
||||
Get the question value with bit field from the buffer.
|
||||
|
||||
@param Question The question refer to bit field.
|
||||
@param Buffer The buffer which the question value get from.
|
||||
@param Value Retun the value.
|
||||
|
||||
**/
|
||||
VOID
|
||||
GetBitsQuestionValue(
|
||||
IN FORM_BROWSER_STATEMENT *Question,
|
||||
IN UINT8 *Buffer,
|
||||
OUT UINT32 *Value
|
||||
);
|
||||
|
||||
/**
|
||||
Set the question value with bit field to the buffer.
|
||||
|
||||
@param Question The question refer to bit field.
|
||||
@param Buffer The buffer which the question value set to.
|
||||
@param Value The value need to set.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SetBitsQuestionValue (
|
||||
IN FORM_BROWSER_STATEMENT *Question,
|
||||
IN UINT8 *Buffer,
|
||||
IN UINT32 Value
|
||||
);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,19 @@
|
|||
## @file
|
||||
#
|
||||
# Windows makefile for 'FCE' module build.
|
||||
#
|
||||
#Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
|
||||
#SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
##
|
||||
|
||||
!INCLUDE $(EDK_TOOLS_PATH)\Source\C\Makefiles\ms.common
|
||||
|
||||
APPNAME = FCE
|
||||
|
||||
LIBS = $(LIB_PATH)\Common.lib
|
||||
|
||||
OBJECTS = Fce.obj Variable.obj TimeBasedVariable.obj MonotonicBasedVariable.obj IfrParse.obj Common.obj BinaryParse.obj BinaryCreate.obj Expression.obj
|
||||
|
||||
!INCLUDE $(EDK_TOOLS_PATH)\Source\C\Makefiles\ms.app
|
||||
|
|
@ -0,0 +1,874 @@
|
|||
/** @file
|
||||
|
||||
Read and edit the authenticated variables.
|
||||
|
||||
Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Fce.h"
|
||||
#include "MonotonicBasedVariable.h"
|
||||
|
||||
extern LIST_ENTRY mAllVarListEntry;
|
||||
extern MULTI_PLATFORM_PARAMETERS mMultiPlatformParam;
|
||||
extern G_EFI_FD_INFO gEfiFdInfo;
|
||||
EFI_GUID gEfiAuthenticatedVariableGuid = EFI_AUTHENTICATED_VARIABLE_GUID;
|
||||
/**
|
||||
|
||||
Gets the pointer to the first variable header in given variable store area.
|
||||
|
||||
@param VarStoreHeader Pointer to the Variable Store Header.
|
||||
|
||||
@return Pointer to the first variable header.
|
||||
|
||||
**/
|
||||
static
|
||||
VARIABLE_HEADER *
|
||||
GetStartPointer (
|
||||
IN VARIABLE_STORE_HEADER *VarStoreHeader
|
||||
)
|
||||
{
|
||||
//
|
||||
// The end of variable store.
|
||||
//
|
||||
return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
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 VarStoreHeader Pointer to the Variable Store Header.
|
||||
|
||||
@return Pointer to the end of the variable storage area.
|
||||
|
||||
**/
|
||||
static
|
||||
VARIABLE_HEADER *
|
||||
GetEndPointer (
|
||||
IN VARIABLE_STORE_HEADER *VarStoreHeader
|
||||
)
|
||||
{
|
||||
//
|
||||
// The end of variable store
|
||||
//
|
||||
return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
This code checks if variable header is valid or not.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@retval TRUE Variable header is valid.
|
||||
@retval FALSE Variable header is not valid.
|
||||
|
||||
**/
|
||||
static
|
||||
BOOLEAN
|
||||
IsValidVariableHeader (
|
||||
IN VARIABLE_HEADER *Variable
|
||||
)
|
||||
{
|
||||
if ((Variable == NULL) || (Variable->StartId != VARIABLE_DATA)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
This code gets the size of name of variable.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@return UINTN Size of variable in bytes.
|
||||
|
||||
**/
|
||||
static
|
||||
UINTN
|
||||
NameSizeOfVariable (
|
||||
IN 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 size of variable data.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@return Size of variable in bytes.
|
||||
|
||||
**/
|
||||
static
|
||||
UINTN
|
||||
DataSizeOfVariable (
|
||||
IN 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 pointer to the variable name.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@return Pointer to Variable Name which is Unicode encoding.
|
||||
|
||||
**/
|
||||
static
|
||||
CHAR16 *
|
||||
GetVariableNamePtr (
|
||||
IN VARIABLE_HEADER *Variable
|
||||
)
|
||||
{
|
||||
return (CHAR16 *) (Variable + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
This code gets the pointer to the variable data.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@return Pointer to Variable Data.
|
||||
|
||||
**/
|
||||
static
|
||||
UINT8 *
|
||||
GetVariableDataPtr (
|
||||
IN VARIABLE_HEADER *Variable
|
||||
)
|
||||
{
|
||||
UINTN Value;
|
||||
|
||||
//
|
||||
// Be careful about pad size for alignment.
|
||||
//
|
||||
Value = (UINTN) GetVariableNamePtr (Variable);
|
||||
Value += NameSizeOfVariable (Variable);
|
||||
Value += GET_PAD_SIZE (NameSizeOfVariable (Variable));
|
||||
|
||||
return (UINT8 *) Value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
This code gets the pointer to the next variable header.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@return Pointer to next variable header.
|
||||
|
||||
**/
|
||||
static
|
||||
VARIABLE_HEADER *
|
||||
GetNextVariablePtr (
|
||||
IN VARIABLE_HEADER *Variable
|
||||
)
|
||||
{
|
||||
UINTN Value;
|
||||
|
||||
if (!IsValidVariableHeader (Variable)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Value = (UINTN) GetVariableDataPtr (Variable);
|
||||
Value += DataSizeOfVariable (Variable);
|
||||
Value += GET_PAD_SIZE (DataSizeOfVariable (Variable));
|
||||
|
||||
//
|
||||
// Be careful about pad size for alignment.
|
||||
//
|
||||
return (VARIABLE_HEADER *) HEADER_ALIGN (Value);
|
||||
}
|
||||
|
||||
/**
|
||||
Search and get a free space in the EFI variable zone
|
||||
|
||||
@param VariableStoreHeader The start of a EFI variable zone.
|
||||
@param VarListSize The size of a variables needs to be allocated.
|
||||
@param FreeBeginVar The dual pointer to the free NV space.
|
||||
|
||||
@retval EFI_SUCCESS Return the beginning of a free variable space.
|
||||
@retval RETURN_BUFFER_TOO_SMALL Failed.
|
||||
**/
|
||||
static
|
||||
EFI_STATUS
|
||||
GetVariableVar (
|
||||
IN VARIABLE_STORE_HEADER *VariableStoreHeader,
|
||||
IN UINT32 VarListSize,
|
||||
IN OUT CHAR8 **FreeBeginVar
|
||||
)
|
||||
{
|
||||
BOOLEAN Flag;
|
||||
VARIABLE_HEADER *Variable;
|
||||
VARIABLE_HEADER *EndOfVariable;
|
||||
CHAR8 *BeginVar;
|
||||
|
||||
BeginVar = NULL;
|
||||
Flag = FALSE;
|
||||
Variable = NULL;
|
||||
EndOfVariable = NULL;
|
||||
*FreeBeginVar = NULL;
|
||||
|
||||
if (VariableStoreHeader == NULL) {
|
||||
*FreeBeginVar = NULL;
|
||||
return RETURN_INVALID_PARAMETER;
|
||||
}
|
||||
Variable = GetStartPointer (VariableStoreHeader);
|
||||
EndOfVariable = GetEndPointer(VariableStoreHeader);
|
||||
//
|
||||
//Search the beginning of free NV
|
||||
//
|
||||
while (Variable != EndOfVariable) {
|
||||
BeginVar = (CHAR8 *)Variable;
|
||||
Variable = GetNextVariablePtr (Variable);
|
||||
if (Variable == NULL) {
|
||||
Flag = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Check whether the free space is more than what we want
|
||||
//
|
||||
if ((CHAR8 *)BeginVar + VarListSize > (CHAR8 *)EndOfVariable) {
|
||||
return RETURN_BUFFER_TOO_SMALL;
|
||||
}
|
||||
//
|
||||
// If not find the available space, return NULL
|
||||
//
|
||||
if (!Flag) {
|
||||
return RETURN_BUFFER_TOO_SMALL;
|
||||
}
|
||||
*FreeBeginVar = BeginVar;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Search whether the variable in VarList has existed in current NV.
|
||||
|
||||
Parse the FFS or Fd image, and find the valid variable pointer.
|
||||
|
||||
@param VariableStoreHeader The start of a EFI variable zone.
|
||||
@param VarList The pointer to the VarList
|
||||
|
||||
@retval address If the variable existed in current NV, return address
|
||||
@return NULL Otherwise, return NULL
|
||||
**/
|
||||
static
|
||||
VARIABLE_HEADER *
|
||||
FindVariableInNv (
|
||||
IN VARIABLE_STORE_HEADER *VariableStoreHeader,
|
||||
IN FORMSET_STORAGE *Storage
|
||||
)
|
||||
{
|
||||
BOOLEAN Flag;
|
||||
VARIABLE_HEADER *Variable;
|
||||
VARIABLE_HEADER *EndOfVariable;
|
||||
CHAR16 *VariableName;
|
||||
|
||||
Flag = FALSE;
|
||||
Variable = NULL;
|
||||
EndOfVariable = NULL;
|
||||
VariableName = NULL;
|
||||
|
||||
if ((VariableStoreHeader == NULL) || (Storage == NULL) || (Storage->Name == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
Variable = GetStartPointer (VariableStoreHeader);
|
||||
EndOfVariable = GetEndPointer(VariableStoreHeader);
|
||||
//
|
||||
// Parse and compare the variable in the NV space one by one
|
||||
//
|
||||
while ((Variable != EndOfVariable) && (Variable != NULL)) {
|
||||
VariableName = (CHAR16 *)((CHAR8 *)Variable + sizeof (VARIABLE_HEADER));
|
||||
if (!CompareGuid (&Variable->VendorGuid, &Storage->Guid) \
|
||||
&& !FceStrCmp (Storage->Name, VariableName) \
|
||||
&& (Variable->State == VAR_ADDED)) {
|
||||
Flag = TRUE;
|
||||
break;
|
||||
}
|
||||
Variable = GetNextVariablePtr (Variable);
|
||||
}
|
||||
if (!Flag) {
|
||||
return NULL;
|
||||
}
|
||||
return Variable;
|
||||
}
|
||||
|
||||
/**
|
||||
Exchange the data between Efi variable and the data of VarList when the
|
||||
variable use the authenticated variable header
|
||||
|
||||
If VarToList is TRUE, copy the efi variable data to the VarList; Otherwise,
|
||||
update the data from varlist to efi variable.
|
||||
|
||||
@param VarToList The flag to control the direction of exchange.
|
||||
@param StorageListHead Decide which variale list be updated
|
||||
|
||||
@retval EFI_SUCCESS Get the address successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES No available in the EFI variable zone.
|
||||
@retval EFI_INVALID_PARAMETER Invalid variable name.
|
||||
**/
|
||||
EFI_STATUS
|
||||
SynAuthEfiVariable (
|
||||
IN BOOLEAN VarToList,
|
||||
IN LIST_ENTRY *StorageListHead
|
||||
)
|
||||
{
|
||||
EFI_FIRMWARE_VOLUME_HEADER *VarAddr;
|
||||
LIST_ENTRY *StorageLink;
|
||||
FORMSET_STORAGE *Storage;
|
||||
EFI_STATUS Status;
|
||||
CHAR8 *NewAvailableAddr;
|
||||
CHAR8 *DataBase;
|
||||
VARIABLE_HEADER *VariableHeader;
|
||||
VARIABLE_STORE_HEADER *VariableStoreHeader;
|
||||
UINTN VarNameSize;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
DataBase = NULL;
|
||||
NewAvailableAddr = NULL;
|
||||
VarNameSize = 0;
|
||||
VariableHeader = NULL;
|
||||
VarAddr = (EFI_FIRMWARE_VOLUME_HEADER *) gEfiFdInfo.EfiVariableAddr;
|
||||
VariableStoreHeader = (VARIABLE_STORE_HEADER *)((CHAR8 *)VarAddr + VarAddr->HeaderLength);
|
||||
//
|
||||
//Parse the variable range, and check whether there is some existed ones.
|
||||
//
|
||||
StorageLink = GetFirstNode (StorageListHead);
|
||||
while (!IsNull (StorageListHead, StorageLink)) {
|
||||
Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
|
||||
//
|
||||
// Ignore the invalid varlist node
|
||||
//
|
||||
if (Storage->Buffer == NULL) {
|
||||
StorageLink = GetNextNode (StorageListHead, StorageLink);
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// Report error, if the variable name is invalid.
|
||||
//
|
||||
if ((Storage->Name == NULL) || (FceStrLen(Storage->Name) == 0)) {
|
||||
printf ("Error. One variable name is NULL. Its GUID is: ");
|
||||
PrintGuid(&(Storage->Guid));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
VariableHeader = FindVariableInNv (
|
||||
VariableStoreHeader,
|
||||
Storage
|
||||
);
|
||||
|
||||
if (VarToList) {
|
||||
//
|
||||
//Copy the data from NV to the VarList.
|
||||
//
|
||||
if (VariableHeader != NULL) {
|
||||
if (Storage->Buffer == NULL) {
|
||||
Storage->Buffer = calloc (Storage->Size, sizeof (CHAR8));
|
||||
ASSERT (Storage->Buffer != NULL);
|
||||
}
|
||||
//
|
||||
// The variable in VarList is CHAR8, but in the EFI variable is CHAR16.
|
||||
//
|
||||
DataBase = (CHAR8 *)GetVariableDataPtr (VariableHeader);
|
||||
memcpy (
|
||||
Storage->Buffer,
|
||||
(VOID *) DataBase,
|
||||
Storage->Size
|
||||
);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
//If existed, copy the List data to the variable in NV directly. If not found, create a new one.
|
||||
//
|
||||
VarNameSize = 2 * (FceStrLen (Storage->Name) + 1);
|
||||
//
|
||||
//If this variable has existed in current FD, the data in VarList has
|
||||
// been updated, and this variable is not authenticated type, then
|
||||
// update it from VarList to the FD.
|
||||
//
|
||||
if ((VariableHeader != NULL) \
|
||||
&& (Storage->Buffer != NULL)
|
||||
) {
|
||||
if (!(VariableHeader->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)) {
|
||||
DataBase = (CHAR8 *)GetVariableDataPtr (VariableHeader);
|
||||
memcpy (
|
||||
(VOID *) DataBase,
|
||||
Storage->Buffer,
|
||||
Storage->Size
|
||||
);
|
||||
} else {
|
||||
printf ("Error. Not support to update authenticated variables.\n");
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
} else if ((VariableHeader == NULL) && (Storage->Buffer != NULL)){
|
||||
//
|
||||
//If EfiVarstore is not EFI_VARIABLE_NON_VOLATILE, only skip it.
|
||||
//
|
||||
if (Storage->NewEfiVarstore
|
||||
&& ((Storage->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0)
|
||||
) {
|
||||
StorageLink = GetNextNode (StorageListHead, StorageLink);
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// Try to get the available zone from the efi variables
|
||||
//
|
||||
Status = GetVariableVar (
|
||||
VariableStoreHeader,
|
||||
Storage->Size + sizeof (VARIABLE_HEADER),
|
||||
&NewAvailableAddr
|
||||
);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// Create the authenticated variable header
|
||||
//
|
||||
VariableHeader = (VARIABLE_HEADER *) NewAvailableAddr;
|
||||
VariableHeader->StartId = VARIABLE_DATA;
|
||||
VariableHeader->State = VAR_ADDED;
|
||||
VariableHeader->Reserved = 0x0;
|
||||
VariableHeader->MonotonicCount = 0x0;
|
||||
VariableHeader->PubKeyIndex = 0x0;
|
||||
if (Storage->NewEfiVarstore) {
|
||||
VariableHeader->Attributes = Storage->Attributes;
|
||||
} else {
|
||||
VariableHeader->Attributes = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
|
||||
}
|
||||
VariableHeader->NameSize = VarNameSize;
|
||||
VariableHeader->DataSize = Storage->Size;
|
||||
//
|
||||
//Copy the Guid, variable name, and data in sequence.
|
||||
//
|
||||
memcpy (
|
||||
(VOID *)&(VariableHeader->VendorGuid),
|
||||
&(Storage->Guid),
|
||||
sizeof (EFI_GUID)
|
||||
);
|
||||
NewAvailableAddr = NewAvailableAddr + sizeof (VARIABLE_HEADER);
|
||||
memcpy (
|
||||
(VOID *) NewAvailableAddr,
|
||||
Storage->Name,
|
||||
VarNameSize
|
||||
);
|
||||
|
||||
NewAvailableAddr = NewAvailableAddr + VarNameSize + GET_PAD_SIZE (VarNameSize);
|
||||
memcpy (
|
||||
(VOID *) NewAvailableAddr,
|
||||
Storage->Buffer,
|
||||
Storage->Size * sizeof (CHAR8)
|
||||
);
|
||||
} else {
|
||||
printf ("Error. No available space in NV ram.\n");
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
}
|
||||
}
|
||||
StorageLink = GetNextNode (StorageListHead, StorageLink);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Remove the variable from Efi variable
|
||||
|
||||
Found the variable with the same name in StorageListHead and remove it.
|
||||
|
||||
@param StorageListHead Decide which variale list be removed.
|
||||
|
||||
@retval EFI_SUCCESS Remove the variables successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
RemoveAuthEfiVariable (
|
||||
IN LIST_ENTRY *StorageListHead
|
||||
)
|
||||
{
|
||||
EFI_FIRMWARE_VOLUME_HEADER *VarAddr;
|
||||
LIST_ENTRY *StorageLink;
|
||||
FORMSET_STORAGE *Storage;
|
||||
VARIABLE_HEADER *VariableHeader;
|
||||
VARIABLE_STORE_HEADER *VariableStoreHeader;
|
||||
|
||||
VariableHeader = NULL;
|
||||
VarAddr = (EFI_FIRMWARE_VOLUME_HEADER *) gEfiFdInfo.EfiVariableAddr;
|
||||
VariableStoreHeader = (VARIABLE_STORE_HEADER *)((CHAR8 *)VarAddr + VarAddr->HeaderLength);
|
||||
//
|
||||
//Parse the variable range, and check whether there is some existed ones.
|
||||
//
|
||||
StorageLink = GetFirstNode (StorageListHead);
|
||||
while (!IsNull (StorageListHead, StorageLink)) {
|
||||
Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
|
||||
//
|
||||
// Ignore the invalid varlist node
|
||||
//
|
||||
if (Storage->Buffer == NULL) {
|
||||
StorageLink = GetNextNode (StorageListHead, StorageLink);
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// Report error, if the variable name is invalid.
|
||||
//
|
||||
if ((Storage->Name == NULL) || (FceStrLen(Storage->Name) == 0)) {
|
||||
printf ("Error. One variable name is NULL. Its GUID is: ");
|
||||
PrintGuid(&(Storage->Guid));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
VariableHeader = FindVariableInNv (
|
||||
VariableStoreHeader,
|
||||
Storage
|
||||
);
|
||||
if (VariableHeader != NULL) {
|
||||
VariableHeader->State = VAR_DELETED;
|
||||
}
|
||||
StorageLink = GetNextNode (StorageListHead, StorageLink);
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Check the store variable is Monotonic based authenticated or not
|
||||
|
||||
@param VarToList The pointer to the header of Variable Store.
|
||||
|
||||
@retval TRUE If authenticated, return TRUE.
|
||||
@retval FALSE Otherwise, return FALSE.
|
||||
**/
|
||||
|
||||
BOOLEAN
|
||||
CheckMonotonicBasedVarStore (
|
||||
IN VOID *VariableStoreHeader
|
||||
)
|
||||
{
|
||||
if (!CompareGuid (
|
||||
&gEfiAuthenticatedVariableGuid,
|
||||
&((VARIABLE_STORE_HEADER *)VariableStoreHeader)->Signature)
|
||||
) {
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Copy Monotonic-Based authenticated variable to binary in multi-platform mode
|
||||
|
||||
@param Storage The pointer to a storage in storage list.
|
||||
@param StorageBeginning The pointer to the beginning of storage under specifed platformId and defaultId
|
||||
@param Index The number of the storage. If the Index is 0, record the variable header to
|
||||
the binary. Or else, only record the storage.
|
||||
|
||||
@return length The length of storage
|
||||
**/
|
||||
UINT32
|
||||
CopyMonotonicBasedVariableToBinary (
|
||||
IN FORMSET_STORAGE *Storage,
|
||||
IN OUT UINT8 *StorageBeginning,
|
||||
IN UINT32 Index
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
CHAR8 *NewAvailableAddr;
|
||||
VARIABLE_HEADER *VariableHeader;
|
||||
VARIABLE_STORE_HEADER *VariableStoreHeader;
|
||||
UINTN VarNameSize;
|
||||
UINT32 HeaderLength;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
NewAvailableAddr = NULL;
|
||||
VarNameSize = 0;
|
||||
HeaderLength = 0;
|
||||
VariableHeader = NULL;
|
||||
VariableStoreHeader = NULL;
|
||||
|
||||
if ((Storage->Name == NULL) || (FceStrLen(Storage->Name) == 0)) {
|
||||
printf ("Error. One variable name is NULL. Its GUID is: ");
|
||||
PrintGuid(&(Storage->Guid));
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// If the first storage under one specified platformId and defaultId, create the variable header
|
||||
//
|
||||
if (Index == 0) {
|
||||
HeaderLength = WriteDefaultAndPlatformId (StorageBeginning, Storage);
|
||||
VariableStoreHeader = (VARIABLE_STORE_HEADER *) (StorageBeginning + HeaderLength);
|
||||
//
|
||||
//Create the Variable Storage header
|
||||
//
|
||||
memcpy (&(VariableStoreHeader->Signature), &gEfiAuthenticatedVariableGuid, sizeof (EFI_GUID));
|
||||
VariableStoreHeader->Format = 0x5A;
|
||||
VariableStoreHeader->State = 0xFE;
|
||||
//
|
||||
//Assign a big size here. It will be fixed after the storage under a specifed platformId and defaultId are all written.
|
||||
//
|
||||
VariableStoreHeader->Size = gEfiFdInfo.FdSize;
|
||||
}
|
||||
VariableStoreHeader = (VARIABLE_STORE_HEADER *) (StorageBeginning + *(UINT16 *)StorageBeginning);
|
||||
|
||||
Status = GetVariableVar (
|
||||
VariableStoreHeader,
|
||||
Storage->Size + sizeof (VARIABLE_HEADER),
|
||||
&NewAvailableAddr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return FAIL;
|
||||
}
|
||||
//
|
||||
// Create the variable header
|
||||
//
|
||||
VarNameSize = 2 * (FceStrLen (Storage->Name) + 1);
|
||||
VariableHeader = (VARIABLE_HEADER *) NewAvailableAddr;
|
||||
VariableHeader->StartId = VARIABLE_DATA;
|
||||
VariableHeader->State = VAR_ADDED;
|
||||
VariableHeader->Reserved = 0x0;
|
||||
VariableHeader->MonotonicCount = 0x0;
|
||||
VariableHeader->PubKeyIndex = 0x0;
|
||||
|
||||
if (Storage->NewEfiVarstore) {
|
||||
VariableHeader->Attributes = Storage->Attributes;
|
||||
} else {
|
||||
VariableHeader->Attributes = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
|
||||
}
|
||||
VariableHeader->NameSize = VarNameSize;
|
||||
VariableHeader->DataSize = Storage->Size;
|
||||
//
|
||||
//Copy the Guid, variable name, and data in sequence.
|
||||
//
|
||||
memcpy (
|
||||
(VOID *)&(VariableHeader->VendorGuid),
|
||||
&(Storage->Guid),
|
||||
sizeof (EFI_GUID)
|
||||
);
|
||||
NewAvailableAddr = NewAvailableAddr + sizeof (VARIABLE_HEADER);
|
||||
memcpy (
|
||||
(VOID *) NewAvailableAddr,
|
||||
Storage->Name,
|
||||
VarNameSize
|
||||
);
|
||||
|
||||
NewAvailableAddr = NewAvailableAddr + VarNameSize + GET_PAD_SIZE (VarNameSize);
|
||||
memcpy (
|
||||
(VOID *) NewAvailableAddr,
|
||||
Storage->Buffer,
|
||||
Storage->Size * sizeof (CHAR8)
|
||||
);
|
||||
|
||||
|
||||
//
|
||||
// Return the length which is from the beginning of Binary
|
||||
//
|
||||
return ((UINT32) ((UINT8*)NewAvailableAddr - StorageBeginning) + Storage->Size);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Read Monotonic-based authenticated variable to storage list in multi-platform mode
|
||||
|
||||
@param Binary The pointer to the header of storage under specifed platformId and defaultId
|
||||
@param StorageListEntry The pointer to the storage list.
|
||||
|
||||
@return length The length of storage
|
||||
**/
|
||||
UINT32
|
||||
ReadMonotonicBasedVariableToList (
|
||||
IN UINT8 *Binary,
|
||||
IN LIST_ENTRY *StorageListEntry
|
||||
)
|
||||
{
|
||||
VARIABLE_HEADER *EndOfVariable;
|
||||
VARIABLE_HEADER *Variable;
|
||||
VARIABLE_STORE_HEADER *VariableStoreHeader;
|
||||
FORMSET_STORAGE *Storage;
|
||||
BOOLEAN ReadIdHeaderFlag;
|
||||
UINT32 Length;
|
||||
EFI_COMMON_SECTION_HEADER *SectionHeader;
|
||||
UINT8 *DataBase;
|
||||
static UINT16 PreDefaultId[MAX_PLATFORM_DEFAULT_ID_NUM];
|
||||
static UINT64 PrePlatformId[MAX_PLATFORM_DEFAULT_ID_NUM];
|
||||
|
||||
VariableStoreHeader = NULL;
|
||||
Variable = NULL;
|
||||
ReadIdHeaderFlag = TRUE;
|
||||
Length = 0;
|
||||
SectionHeader = (EFI_COMMON_SECTION_HEADER *)Binary;
|
||||
DataBase = Binary + sizeof (EFI_COMMON_SECTION_HEADER);
|
||||
VariableStoreHeader = (VARIABLE_STORE_HEADER *) (DataBase + *(UINT16 *)DataBase);
|
||||
EndOfVariable = GetEndPointer(VariableStoreHeader);
|
||||
|
||||
for (Variable = GetStartPointer (VariableStoreHeader);
|
||||
Length < VariableStoreHeader->Size;
|
||||
Length += sizeof (VARIABLE_HEADER) + Variable->NameSize + Variable->DataSize
|
||||
) {
|
||||
//
|
||||
// Create the storage
|
||||
//
|
||||
Storage = NULL;
|
||||
Storage = calloc (sizeof (FORMSET_STORAGE), sizeof (CHAR8));
|
||||
if (Storage == NULL) {
|
||||
printf ("Allocate memory failed.\n");
|
||||
return FAIL;
|
||||
}
|
||||
//
|
||||
// If access the first storage, read the platformId and defaultId
|
||||
//
|
||||
if (ReadIdHeaderFlag) {
|
||||
ReadDefaultAndPlatformIdFromBfv (DataBase, Storage);
|
||||
Length += sizeof (VARIABLE_HEADER) + Variable->NameSize + Variable->DataSize;
|
||||
ReadIdHeaderFlag = FALSE;
|
||||
memcpy (PreDefaultId, Storage->DefaultId, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT16));
|
||||
memcpy (PrePlatformId, Storage->PlatformId, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT64));
|
||||
} else {
|
||||
//
|
||||
// Store the DefaultId and PlatformId collected from the header to Storage.
|
||||
//
|
||||
memcpy (Storage->DefaultId, PreDefaultId, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT16));
|
||||
memcpy (Storage->PlatformId, PrePlatformId, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT64));
|
||||
}
|
||||
Storage->Attributes = Variable->Attributes;
|
||||
Storage->Size = (UINT16)Variable->DataSize;
|
||||
Storage->Name = calloc (Variable->NameSize, sizeof (UINT8));
|
||||
ASSERT (Storage->Name != NULL);
|
||||
Storage->Buffer = calloc (Variable->DataSize, sizeof (UINT8));
|
||||
ASSERT (Storage->Buffer != NULL);
|
||||
memcpy (
|
||||
&(Storage->Guid),
|
||||
&(Variable->VendorGuid),
|
||||
sizeof (EFI_GUID)
|
||||
);
|
||||
memcpy (
|
||||
Storage->Name,
|
||||
(UINT8 *)Variable + sizeof (VARIABLE_HEADER),
|
||||
Variable->NameSize
|
||||
);
|
||||
memcpy (
|
||||
Storage->Buffer,
|
||||
(UINT8 *)Variable + sizeof (VARIABLE_HEADER) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize),
|
||||
Storage->Size * sizeof (CHAR8)
|
||||
);
|
||||
//
|
||||
// Assigned the value for comparison in verify mode
|
||||
//
|
||||
Storage->Type = EFI_IFR_VARSTORE_EFI_OP;
|
||||
Storage->NewEfiVarstore = TRUE;
|
||||
InitializeListHead (&Storage->NameValueListHead);
|
||||
|
||||
InsertTailList(StorageListEntry, &Storage->Link);
|
||||
//
|
||||
// If the last variable, exit.
|
||||
//
|
||||
if (Variable == EndOfVariable) {
|
||||
break;
|
||||
}
|
||||
|
||||
Variable = GetNextVariablePtr (Variable);
|
||||
assert (Variable != NULL);
|
||||
}
|
||||
//
|
||||
// Return the length which is from the beginning of Binary
|
||||
//
|
||||
Length = FvBufExpand3ByteSize (SectionHeader->Size);
|
||||
|
||||
return Length;
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether exists the valid MonotonicBased variables in NvStorage or not.
|
||||
|
||||
@retval TRUE If existed, return TRUE.
|
||||
@retval FALSE Others
|
||||
**/
|
||||
BOOLEAN
|
||||
ExistMonotonicBasedEfiVarOrNot (
|
||||
IN LIST_ENTRY *StorageListHead
|
||||
)
|
||||
{
|
||||
EFI_FIRMWARE_VOLUME_HEADER *VarAddr;
|
||||
LIST_ENTRY *StorageLink;
|
||||
FORMSET_STORAGE *Storage;
|
||||
VARIABLE_HEADER *VariableHeader;
|
||||
VARIABLE_STORE_HEADER *VariableStoreHeader;
|
||||
|
||||
VariableHeader = NULL;
|
||||
VarAddr = (EFI_FIRMWARE_VOLUME_HEADER *) gEfiFdInfo.EfiVariableAddr;
|
||||
VariableStoreHeader = (VARIABLE_STORE_HEADER *)((CHAR8 *)VarAddr + VarAddr->HeaderLength);
|
||||
//
|
||||
//Parse the variable range, and check whether there is some existed ones.
|
||||
//
|
||||
StorageLink = GetFirstNode (StorageListHead);
|
||||
while (!IsNull (StorageListHead, StorageLink)) {
|
||||
Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
|
||||
//
|
||||
// Ignore the invalid varlist node
|
||||
//
|
||||
if ((Storage->Buffer == NULL)
|
||||
|| (Storage->Name == NULL)
|
||||
|| (FceStrLen(Storage->Name) == 0)
|
||||
) {
|
||||
StorageLink = GetNextNode (StorageListHead, StorageLink);
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// Report error, if the variable name is invalid.
|
||||
//
|
||||
if ((Storage->Name == NULL) || (FceStrLen(Storage->Name) == 0)) {
|
||||
StorageLink = GetNextNode (StorageListHead, StorageLink);
|
||||
continue;
|
||||
}
|
||||
VariableHeader = FindVariableInNv (
|
||||
VariableStoreHeader,
|
||||
Storage
|
||||
);
|
||||
|
||||
if ((VariableHeader != NULL)) {
|
||||
return TRUE;
|
||||
}
|
||||
StorageLink = GetNextNode (StorageListHead, StorageLink);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
/**
|
||||
Fix the size of montonic variable header.
|
||||
|
||||
@param Binary The pointer to the header of storage under specifed platformId and defaultId
|
||||
@param Length The length of binary.
|
||||
|
||||
**/
|
||||
VOID
|
||||
FixMontonicVariableHeaderSize (
|
||||
IN UINT8 *BinaryBeginning,
|
||||
IN UINT32 Length
|
||||
)
|
||||
{
|
||||
VARIABLE_STORE_HEADER *VariableStoreHeader;
|
||||
|
||||
VariableStoreHeader = (VARIABLE_STORE_HEADER *) (BinaryBeginning + *(UINT16 *)BinaryBeginning);
|
||||
VariableStoreHeader->Size = Length - *(UINT16 *)BinaryBeginning;
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
/** @file
|
||||
|
||||
The header of MonotonicBasedVariable.c.
|
||||
|
||||
Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __AUTHENTICATED_VARIABLE_FORMAT_H__
|
||||
#define __AUTHENTICATED_VARIABLE_FORMAT_H__
|
||||
|
||||
#define EFI_AUTHENTICATED_VARIABLE_GUID \
|
||||
{ 0x515fa686, 0xb06e, 0x4550, { 0x91, 0x12, 0x38, 0x2b, 0xf1, 0x6, 0x7b, 0xfb }}
|
||||
|
||||
extern EFI_GUID gEfiAuthenticatedVariableGuid;
|
||||
|
||||
///
|
||||
/// Alignment of variable name and data, according to the architecture:
|
||||
/// * For IA-32 and Intel(R) 64 architectures: 1
|
||||
/// * For IA-64 architecture: 8
|
||||
///
|
||||
#if defined (MDE_CPU_IPF)
|
||||
#define ALIGNMENT 8
|
||||
#else
|
||||
#define ALIGNMENT 1
|
||||
#endif
|
||||
|
||||
///
|
||||
/// GET_PAD_SIZE calculates the miminal pad bytes needed to make the current pad size satisfy the alignment requirement.
|
||||
///
|
||||
#if (ALIGNMENT == 1)
|
||||
#define GET_PAD_SIZE(a) (0)
|
||||
#else
|
||||
#define GET_PAD_SIZE(a) (((~a) + 1) & (ALIGNMENT - 1))
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Alignment of Variable Data Header in Variable Store region
|
||||
///
|
||||
#define HEADER_ALIGNMENT 4
|
||||
#define HEADER_ALIGN(Header) (((UINTN) (Header) + HEADER_ALIGNMENT - 1) & (~(HEADER_ALIGNMENT - 1)))
|
||||
|
||||
///
|
||||
/// Status of Variable Store Region
|
||||
///
|
||||
typedef enum {
|
||||
EfiRaw,
|
||||
EfiValid,
|
||||
EfiInvalid,
|
||||
EfiUnknown
|
||||
} VARIABLE_STORE_STATUS;
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
#define VARIABLE_STORE_SIGNATURE EFI_VARIABLE_GUID
|
||||
|
||||
///
|
||||
/// Variable Store Header Format and State
|
||||
///
|
||||
#define VARIABLE_STORE_FORMATTED 0x5a
|
||||
#define VARIABLE_STORE_HEALTHY 0xfe
|
||||
|
||||
///
|
||||
/// Variable Store region header
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// Variable store region signature.
|
||||
///
|
||||
EFI_GUID Signature;
|
||||
///
|
||||
/// Size of entire variable store,
|
||||
/// including size of variable store header but not including the size of FvHeader.
|
||||
///
|
||||
UINT32 Size;
|
||||
///
|
||||
/// Variable region format state.
|
||||
///
|
||||
UINT8 Format;
|
||||
///
|
||||
/// Variable region healthy state.
|
||||
///
|
||||
UINT8 State;
|
||||
UINT16 Reserved;
|
||||
UINT32 Reserved1;
|
||||
} VARIABLE_STORE_HEADER;
|
||||
|
||||
///
|
||||
/// Variable data start flag.
|
||||
///
|
||||
#define VARIABLE_DATA 0x55AA
|
||||
|
||||
///
|
||||
/// Variable State flags
|
||||
///
|
||||
#define VAR_IN_DELETED_TRANSITION 0xfe ///< Variable is in obsolete transition
|
||||
#define VAR_DELETED 0xfd ///< Variable is obsolete
|
||||
#define VAR_HEADER_VALID_ONLY 0x7f ///< Variable header has been valid
|
||||
#define VAR_ADDED 0x3f ///< Variable has been completely added
|
||||
|
||||
///
|
||||
/// Single Variable Data Header Structure.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// Variable Data Start Flag.
|
||||
///
|
||||
UINT16 StartId;
|
||||
///
|
||||
/// Variable State defined above.
|
||||
///
|
||||
UINT8 State;
|
||||
UINT8 Reserved;
|
||||
///
|
||||
/// Attributes of variable defined in UEFI spec
|
||||
///
|
||||
UINT32 Attributes;
|
||||
///
|
||||
/// Associated monotonic count value against replay attack.
|
||||
///
|
||||
UINT64 MonotonicCount;
|
||||
///
|
||||
/// Index of associated public key in database.
|
||||
///
|
||||
UINT32 PubKeyIndex;
|
||||
///
|
||||
/// Size of variable null-terminated Unicode string name.
|
||||
///
|
||||
UINT32 NameSize;
|
||||
///
|
||||
/// Size of the variable data without this header.
|
||||
///
|
||||
UINT32 DataSize;
|
||||
///
|
||||
/// A unique identifier for the vendor that produces and consumes this varaible.
|
||||
///
|
||||
EFI_GUID VendorGuid;
|
||||
} VARIABLE_HEADER;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
typedef struct _VARIABLE_INFO_ENTRY VARIABLE_INFO_ENTRY;
|
||||
|
||||
///
|
||||
/// This structure contains the variable list that is put in EFI system table.
|
||||
/// The variable driver collects all variables that were used at boot service time and produces this list.
|
||||
/// This is an optional feature to dump all used variables in shell environment.
|
||||
///
|
||||
struct _VARIABLE_INFO_ENTRY {
|
||||
VARIABLE_INFO_ENTRY *Next; ///< Pointer to next entry.
|
||||
EFI_GUID VendorGuid; ///< Guid of Variable.
|
||||
CHAR16 *Name; ///< Name of Variable.
|
||||
UINT32 Attributes; ///< Attributes of variable defined in UEFI spec.
|
||||
UINT32 ReadCount; ///< Number of times to read this variable.
|
||||
UINT32 WriteCount; ///< Number of times to write this variable.
|
||||
UINT32 DeleteCount; ///< Number of times to delete this variable.
|
||||
UINT32 CacheCount; ///< Number of times that cache hits this variable.
|
||||
BOOLEAN Volatile; ///< TRUE if volatile, FALSE if non-volatile.
|
||||
};
|
||||
|
||||
#endif // _EFI_VARIABLE_H_
|
|
@ -0,0 +1,878 @@
|
|||
/** @file
|
||||
|
||||
Read and edit the time-base authenticated variables.
|
||||
|
||||
Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Fce.h"
|
||||
#include "TimeBasedVariable.h"
|
||||
|
||||
extern LIST_ENTRY mAllVarListEntry;
|
||||
extern MULTI_PLATFORM_PARAMETERS mMultiPlatformParam;
|
||||
extern G_EFI_FD_INFO gEfiFdInfo;
|
||||
|
||||
EFI_GUID gEfiAuthenticatedVariableBasedTimeGuid = EFI_AUTHENTICATED_VARIABLE_BASED_TIME_GUID;
|
||||
/**
|
||||
|
||||
Gets the pointer to the first variable header in given variable store area.
|
||||
|
||||
@param VarStoreHeader Pointer to the Variable Store Header.
|
||||
|
||||
@return Pointer to the first variable header.
|
||||
|
||||
**/
|
||||
static
|
||||
VARIABLE_HEADER *
|
||||
GetStartPointer (
|
||||
IN VARIABLE_STORE_HEADER *VarStoreHeader
|
||||
)
|
||||
{
|
||||
//
|
||||
// The end of variable store.
|
||||
//
|
||||
return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
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 VarStoreHeader Pointer to the Variable Store Header.
|
||||
|
||||
@return Pointer to the end of the variable storage area.
|
||||
|
||||
**/
|
||||
static
|
||||
VARIABLE_HEADER *
|
||||
GetEndPointer (
|
||||
IN VARIABLE_STORE_HEADER *VarStoreHeader
|
||||
)
|
||||
{
|
||||
//
|
||||
// The end of variable store
|
||||
//
|
||||
return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
This code checks if variable header is valid or not.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@retval TRUE Variable header is valid.
|
||||
@retval FALSE Variable header is not valid.
|
||||
|
||||
**/
|
||||
static
|
||||
BOOLEAN
|
||||
IsValidVariableHeader (
|
||||
IN VARIABLE_HEADER *Variable
|
||||
)
|
||||
{
|
||||
if ((Variable == NULL) || (Variable->StartId != VARIABLE_DATA)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
This code gets the size of name of variable.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@return UINTN Size of variable in bytes.
|
||||
|
||||
**/
|
||||
static
|
||||
UINTN
|
||||
NameSizeOfVariable (
|
||||
IN 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 size of variable data.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@return Size of variable in bytes.
|
||||
|
||||
**/
|
||||
static
|
||||
UINTN
|
||||
DataSizeOfVariable (
|
||||
IN 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 pointer to the variable name.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@return Pointer to Variable Name which is Unicode encoding.
|
||||
|
||||
**/
|
||||
static
|
||||
CHAR16 *
|
||||
GetVariableNamePtr (
|
||||
IN VARIABLE_HEADER *Variable
|
||||
)
|
||||
{
|
||||
return (CHAR16 *) (Variable + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
This code gets the pointer to the variable data.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@return Pointer to Variable Data.
|
||||
|
||||
**/
|
||||
static
|
||||
UINT8 *
|
||||
GetVariableDataPtr (
|
||||
IN VARIABLE_HEADER *Variable
|
||||
)
|
||||
{
|
||||
UINTN Value;
|
||||
|
||||
//
|
||||
// Be careful about pad size for alignment.
|
||||
//
|
||||
Value = (UINTN) GetVariableNamePtr (Variable);
|
||||
Value += NameSizeOfVariable (Variable);
|
||||
Value += GET_PAD_SIZE (NameSizeOfVariable (Variable));
|
||||
|
||||
return (UINT8 *) Value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
This code gets the pointer to the next variable header.
|
||||
|
||||
@param Variable Pointer to the Variable Header.
|
||||
|
||||
@return Pointer to next variable header.
|
||||
|
||||
**/
|
||||
static
|
||||
VARIABLE_HEADER *
|
||||
GetNextVariablePtr (
|
||||
IN VARIABLE_HEADER *Variable
|
||||
)
|
||||
{
|
||||
UINTN Value;
|
||||
|
||||
if (!IsValidVariableHeader (Variable)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Value = (UINTN) GetVariableDataPtr (Variable);
|
||||
Value += DataSizeOfVariable (Variable);
|
||||
Value += GET_PAD_SIZE (DataSizeOfVariable (Variable));
|
||||
|
||||
//
|
||||
// Be careful about pad size for alignment.
|
||||
//
|
||||
return (VARIABLE_HEADER *) HEADER_ALIGN (Value);
|
||||
}
|
||||
|
||||
/**
|
||||
Search and get a free space in the EFI variable zone
|
||||
|
||||
@param VariableStoreHeader The start of a EFI variable zone.
|
||||
@param VarListSize The size of a variables needs to be allocated.
|
||||
@param FreeBeginVar The dual pointer to the free NV space.
|
||||
|
||||
@retval EFI_SUCCESS Return the beginning of a free variable space.
|
||||
@retval RETURN_BUFFER_TOO_SMALL Failed.
|
||||
**/
|
||||
static
|
||||
EFI_STATUS
|
||||
GetVariableVar (
|
||||
IN VARIABLE_STORE_HEADER *VariableStoreHeader,
|
||||
IN UINT32 VarListSize,
|
||||
IN OUT CHAR8 **FreeBeginVar
|
||||
)
|
||||
{
|
||||
BOOLEAN Flag;
|
||||
VARIABLE_HEADER *Variable;
|
||||
VARIABLE_HEADER *EndOfVariable;
|
||||
CHAR8 *BeginVar;
|
||||
|
||||
BeginVar = NULL;
|
||||
Flag = FALSE;
|
||||
Variable = NULL;
|
||||
EndOfVariable = NULL;
|
||||
*FreeBeginVar = NULL;
|
||||
|
||||
if (VariableStoreHeader == NULL) {
|
||||
*FreeBeginVar = NULL;
|
||||
return RETURN_INVALID_PARAMETER;
|
||||
}
|
||||
Variable = GetStartPointer (VariableStoreHeader);
|
||||
EndOfVariable = GetEndPointer(VariableStoreHeader);
|
||||
//
|
||||
//Search the beginning of free NV
|
||||
//
|
||||
while (Variable != EndOfVariable) {
|
||||
BeginVar = (CHAR8 *)Variable;
|
||||
Variable = GetNextVariablePtr (Variable);
|
||||
if (Variable == NULL) {
|
||||
Flag = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Check whether the free space is more than what we want
|
||||
//
|
||||
if ((CHAR8 *)BeginVar + VarListSize > (CHAR8 *)EndOfVariable) {
|
||||
return RETURN_BUFFER_TOO_SMALL;
|
||||
}
|
||||
//
|
||||
// If not find the available space, return NULL
|
||||
//
|
||||
if (!Flag) {
|
||||
return RETURN_BUFFER_TOO_SMALL;
|
||||
}
|
||||
*FreeBeginVar = BeginVar;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Search whether the variable in VarList has existed in current NV.
|
||||
|
||||
Parse the FFS or Fd image, and find the valid variable pointer.
|
||||
|
||||
@param VariableStoreHeader The start of a EFI variable zone.
|
||||
@param VarList The pointer to the VarList
|
||||
|
||||
@retval address If the variable existed in current NV, return address
|
||||
@return NULL Otherwise, return NULL
|
||||
**/
|
||||
static
|
||||
VARIABLE_HEADER *
|
||||
FindVariableInNv (
|
||||
IN VARIABLE_STORE_HEADER *VariableStoreHeader,
|
||||
IN FORMSET_STORAGE *Storage
|
||||
)
|
||||
{
|
||||
BOOLEAN Flag;
|
||||
VARIABLE_HEADER *Variable;
|
||||
VARIABLE_HEADER *EndOfVariable;
|
||||
CHAR16 *VariableName;
|
||||
|
||||
Flag = FALSE;
|
||||
Variable = NULL;
|
||||
EndOfVariable = NULL;
|
||||
VariableName = NULL;
|
||||
|
||||
if ((VariableStoreHeader == NULL) || (Storage == NULL) || (Storage->Name == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
Variable = GetStartPointer (VariableStoreHeader);
|
||||
EndOfVariable = GetEndPointer(VariableStoreHeader);
|
||||
//
|
||||
// Parse and compare the variable in the NV space one by one
|
||||
//
|
||||
while ((Variable != EndOfVariable) && (Variable != NULL)) {
|
||||
VariableName = (CHAR16 *)((CHAR8 *)Variable + sizeof (VARIABLE_HEADER));
|
||||
if (!CompareGuid (&Variable->VendorGuid, &Storage->Guid) \
|
||||
&& !FceStrCmp (Storage->Name, VariableName) \
|
||||
&& (Variable->State == VAR_ADDED)
|
||||
) {
|
||||
Flag = TRUE;
|
||||
break;
|
||||
}
|
||||
Variable = GetNextVariablePtr (Variable);
|
||||
}
|
||||
if (!Flag) {
|
||||
return NULL;
|
||||
}
|
||||
return Variable;
|
||||
}
|
||||
/**
|
||||
Exchange the data between Efi variable and the data of VarList when the
|
||||
variable use the time stamp authenticated variable header
|
||||
|
||||
If VarToList is TRUE, copy the efi variable data to the VarList; Otherwise,
|
||||
update the data from varlist to efi variable.
|
||||
|
||||
@param VarToList The flag to control the direction of exchange.
|
||||
@param StorageListHead Decide which variale list be updated
|
||||
|
||||
@retval EFI_SUCCESS Get the address successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES No available in the EFI variable zone.
|
||||
@retval EFI_INVALID_PARAMETER Invalid variable name.
|
||||
**/
|
||||
|
||||
EFI_STATUS
|
||||
SynAuthEfiVariableBasedTime (
|
||||
IN BOOLEAN VarToList,
|
||||
IN LIST_ENTRY *StorageListHead
|
||||
)
|
||||
{
|
||||
EFI_FIRMWARE_VOLUME_HEADER *VarAddr;
|
||||
LIST_ENTRY *StorageLink;
|
||||
FORMSET_STORAGE *Storage;
|
||||
EFI_STATUS Status;
|
||||
CHAR8 *NewAvailableAddr;
|
||||
CHAR8 *DataBase;
|
||||
VARIABLE_HEADER *VariableHeader;
|
||||
VARIABLE_STORE_HEADER *VariableStoreHeader;
|
||||
UINTN VarNameSize;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
DataBase = NULL;
|
||||
NewAvailableAddr = NULL;
|
||||
VarNameSize = 0;
|
||||
VariableHeader = NULL;
|
||||
VarAddr = (EFI_FIRMWARE_VOLUME_HEADER *) gEfiFdInfo.EfiVariableAddr;
|
||||
VariableStoreHeader = (VARIABLE_STORE_HEADER *)((CHAR8 *)VarAddr + VarAddr->HeaderLength);
|
||||
//
|
||||
//Parse the variable range, and check whether there is some existed ones.
|
||||
//
|
||||
StorageLink = GetFirstNode (StorageListHead);
|
||||
while (!IsNull (StorageListHead, StorageLink)) {
|
||||
Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
|
||||
//
|
||||
// Ignore the invalid varlist node
|
||||
//
|
||||
if (Storage->Buffer == NULL) {
|
||||
StorageLink = GetNextNode (StorageListHead, StorageLink);
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// Report error, if the variable name is invalid.
|
||||
//
|
||||
if ((Storage->Name == NULL) || (FceStrLen(Storage->Name) == 0)) {
|
||||
printf ("Error. One variable name is NULL. Its GUID is: ");
|
||||
PrintGuid(&(Storage->Guid));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
VariableHeader = FindVariableInNv (
|
||||
VariableStoreHeader,
|
||||
Storage
|
||||
);
|
||||
|
||||
if (VarToList) {
|
||||
//
|
||||
//Copy the data from NV to the VarList.
|
||||
//
|
||||
if (VariableHeader != NULL) {
|
||||
if (Storage->Buffer == NULL) {
|
||||
Storage->Buffer = calloc (Storage->Size, sizeof (CHAR8));
|
||||
ASSERT (Storage->Buffer != NULL);
|
||||
}
|
||||
//
|
||||
// The variable in VarList is CHAR8, but in the EFI variable is CHAR16.
|
||||
//
|
||||
DataBase = (CHAR8 *)GetVariableDataPtr (VariableHeader);
|
||||
memcpy (
|
||||
Storage->Buffer,
|
||||
(VOID *) DataBase,
|
||||
Storage->Size
|
||||
);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
//If existed, copy the List data to the variable in NV directly. If not found, create a new one.
|
||||
//
|
||||
VarNameSize = 2 * (FceStrLen (Storage->Name) + 1);
|
||||
//
|
||||
//If this variable has existed in current FD, the data in VarList has
|
||||
// been updated, and this variable is not authenticated type, then
|
||||
// update it from VarList to the FD.
|
||||
//
|
||||
if ((VariableHeader != NULL) \
|
||||
&& (Storage->Buffer != NULL)
|
||||
) {
|
||||
if (!(VariableHeader->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)) {
|
||||
DataBase = (CHAR8 *)GetVariableDataPtr (VariableHeader);
|
||||
memcpy (
|
||||
(VOID *) DataBase,
|
||||
Storage->Buffer,
|
||||
Storage->Size
|
||||
);
|
||||
} else {
|
||||
printf ("Error. Not support to update authenticated variables.\n");
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
} else if ((VariableHeader == NULL) && (Storage->Buffer != NULL)){
|
||||
//
|
||||
//If EfiVarstore is not EFI_VARIABLE_NON_VOLATILE, only skip it.
|
||||
//
|
||||
if (Storage->NewEfiVarstore
|
||||
&& ((Storage->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0)
|
||||
) {
|
||||
StorageLink = GetNextNode (StorageListHead, StorageLink);
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// Try to get the available zone from the efi variables
|
||||
//
|
||||
Status = GetVariableVar (
|
||||
VariableStoreHeader,
|
||||
Storage->Size + sizeof (VARIABLE_HEADER),
|
||||
&NewAvailableAddr
|
||||
);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// Create the authenticated variable header
|
||||
//
|
||||
VariableHeader = (VARIABLE_HEADER *) NewAvailableAddr;
|
||||
VariableHeader->StartId = VARIABLE_DATA;
|
||||
VariableHeader->State = VAR_ADDED;
|
||||
VariableHeader->Reserved = 0x0;
|
||||
VariableHeader->MonotonicCount = 0x0;
|
||||
memset (&(VariableHeader->TimeStamp), 0, sizeof (EFI_TIME));
|
||||
VariableHeader->PubKeyIndex = 0x0;
|
||||
if (Storage->NewEfiVarstore) {
|
||||
VariableHeader->Attributes = Storage->Attributes;
|
||||
} else {
|
||||
VariableHeader->Attributes = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
|
||||
}
|
||||
VariableHeader->NameSize = VarNameSize;
|
||||
VariableHeader->DataSize = Storage->Size;
|
||||
//
|
||||
//Copy the Guid, variable name, and data in sequence.
|
||||
//
|
||||
memcpy (
|
||||
(VOID *)&(VariableHeader->VendorGuid),
|
||||
&(Storage->Guid),
|
||||
sizeof (EFI_GUID)
|
||||
);
|
||||
NewAvailableAddr = NewAvailableAddr + sizeof (VARIABLE_HEADER);
|
||||
memcpy (
|
||||
(VOID *) NewAvailableAddr,
|
||||
Storage->Name,
|
||||
VarNameSize
|
||||
);
|
||||
|
||||
NewAvailableAddr = NewAvailableAddr + VarNameSize + GET_PAD_SIZE (VarNameSize);
|
||||
memcpy (
|
||||
(VOID *) NewAvailableAddr,
|
||||
Storage->Buffer,
|
||||
Storage->Size * sizeof (CHAR8)
|
||||
);
|
||||
} else {
|
||||
printf ("Error. No available space in NV ram.\n");
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
}
|
||||
}
|
||||
StorageLink = GetNextNode (StorageListHead, StorageLink);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Remove the variable from Efi variable
|
||||
|
||||
Found the variable with the same name in StorageListHead and remove it.
|
||||
|
||||
@param StorageListHead Decide which variale list be removed.
|
||||
|
||||
@retval EFI_SUCCESS Remove the variables successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
RemoveAuthEfiVariableBasedTime (
|
||||
IN LIST_ENTRY *StorageListHead
|
||||
)
|
||||
{
|
||||
EFI_FIRMWARE_VOLUME_HEADER *VarAddr;
|
||||
LIST_ENTRY *StorageLink;
|
||||
FORMSET_STORAGE *Storage;
|
||||
VARIABLE_HEADER *VariableHeader;
|
||||
VARIABLE_STORE_HEADER *VariableStoreHeader;
|
||||
|
||||
VariableHeader = NULL;
|
||||
VarAddr = (EFI_FIRMWARE_VOLUME_HEADER *) gEfiFdInfo.EfiVariableAddr;
|
||||
VariableStoreHeader = (VARIABLE_STORE_HEADER *)((CHAR8 *)VarAddr + VarAddr->HeaderLength);
|
||||
//
|
||||
//Parse the variable range, and check whether there is some existed ones.
|
||||
//
|
||||
StorageLink = GetFirstNode (StorageListHead);
|
||||
while (!IsNull (StorageListHead, StorageLink)) {
|
||||
Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
|
||||
//
|
||||
// Ignore the invalid varlist node
|
||||
//
|
||||
if (Storage->Buffer == NULL) {
|
||||
StorageLink = GetNextNode (StorageListHead, StorageLink);
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// Report error, if the variable name is invalid.
|
||||
//
|
||||
if ((Storage->Name == NULL) || (FceStrLen(Storage->Name) == 0)) {
|
||||
printf ("Error. One variable name is NULL. Its GUID is: ");
|
||||
PrintGuid(&(Storage->Guid));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
VariableHeader = FindVariableInNv (
|
||||
VariableStoreHeader,
|
||||
Storage
|
||||
);
|
||||
if (VariableHeader != NULL) {
|
||||
VariableHeader->State = VAR_DELETED;
|
||||
}
|
||||
StorageLink = GetNextNode (StorageListHead, StorageLink);
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Check the store variable is Time stamp authenticated or not
|
||||
|
||||
@param VarToList The pointer to the header of Variable Store.
|
||||
|
||||
@retval TRUE If authenticated, return TRUE.
|
||||
@retval FALSE Otherwise, return FALSE.
|
||||
**/
|
||||
|
||||
BOOLEAN
|
||||
CheckTimeBasedVarStoreOrNot (
|
||||
IN VOID *VariableStoreHeader
|
||||
)
|
||||
{
|
||||
if (!CompareGuid (
|
||||
&gEfiAuthenticatedVariableBasedTimeGuid,
|
||||
&((VARIABLE_STORE_HEADER *)VariableStoreHeader)->Signature)
|
||||
) {
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Copy time-based authenticated variable to binary in multi-platform mode
|
||||
|
||||
@param Storage The pointer to a storage in storage list.
|
||||
@param StorageBeginning The pointer to the beginning of storage under specifed platformId and defaultId
|
||||
@param Index The number of the storage. If the Index is 0, record the variable header to
|
||||
the binary. Or else, only record the storage.
|
||||
|
||||
@return length The length of storage
|
||||
**/
|
||||
UINT32
|
||||
CopyTimeBasedVariableToBinary (
|
||||
IN FORMSET_STORAGE *Storage,
|
||||
IN OUT UINT8 *StorageBeginning,
|
||||
IN UINT32 Index
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
CHAR8 *NewAvailableAddr;
|
||||
VARIABLE_HEADER *VariableHeader;
|
||||
VARIABLE_STORE_HEADER *VariableStoreHeader;
|
||||
UINTN VarNameSize;
|
||||
UINT32 HeaderLength;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
NewAvailableAddr = NULL;
|
||||
VarNameSize = 0;
|
||||
HeaderLength = 0;
|
||||
VariableHeader = NULL;
|
||||
VariableStoreHeader = NULL;
|
||||
|
||||
if ((Storage->Name == NULL) || (FceStrLen(Storage->Name) == 0)) {
|
||||
printf ("Error. One variable name is NULL. Its GUID is: ");
|
||||
PrintGuid(&(Storage->Guid));
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// If the first storage under one specified platformId and defaultId, create the variable header
|
||||
//
|
||||
if (Index == 0) {
|
||||
HeaderLength = WriteDefaultAndPlatformId (StorageBeginning, Storage);
|
||||
VariableStoreHeader = (VARIABLE_STORE_HEADER *) (StorageBeginning + HeaderLength);
|
||||
//
|
||||
//Create the Variable Storage header
|
||||
//
|
||||
memcpy (&(VariableStoreHeader->Signature), &gEfiAuthenticatedVariableBasedTimeGuid, sizeof (EFI_GUID));
|
||||
VariableStoreHeader->Format = 0x5A;
|
||||
VariableStoreHeader->State = 0xFE;
|
||||
//
|
||||
//Assign a big size here. It will be fixed after the storage under a specifed platformId and defaultId are all written.
|
||||
//
|
||||
VariableStoreHeader->Size = gEfiFdInfo.FdSize;
|
||||
}
|
||||
|
||||
VariableStoreHeader = (VARIABLE_STORE_HEADER *) (StorageBeginning + *(UINT16 *)StorageBeginning);
|
||||
|
||||
Status = GetVariableVar (
|
||||
VariableStoreHeader,
|
||||
Storage->Size + sizeof (VARIABLE_HEADER),
|
||||
&NewAvailableAddr
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return FAIL;
|
||||
}
|
||||
//
|
||||
// Create the variable header
|
||||
//
|
||||
VarNameSize = 2 * (FceStrLen (Storage->Name) + 1);
|
||||
VariableHeader = (VARIABLE_HEADER *) NewAvailableAddr;
|
||||
VariableHeader->StartId = VARIABLE_DATA;
|
||||
VariableHeader->State = VAR_ADDED;
|
||||
VariableHeader->Reserved = 0x0;
|
||||
VariableHeader->MonotonicCount = 0x0;
|
||||
memset (&(VariableHeader->TimeStamp), 0, sizeof (EFI_TIME));
|
||||
VariableHeader->PubKeyIndex = 0x0;
|
||||
|
||||
if (Storage->NewEfiVarstore) {
|
||||
VariableHeader->Attributes = Storage->Attributes;
|
||||
} else {
|
||||
VariableHeader->Attributes = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
|
||||
}
|
||||
VariableHeader->NameSize = VarNameSize;
|
||||
VariableHeader->DataSize = Storage->Size;
|
||||
//
|
||||
//Copy the Guid, variable name, and data in sequence.
|
||||
//
|
||||
memcpy (
|
||||
(VOID *)&(VariableHeader->VendorGuid),
|
||||
&(Storage->Guid),
|
||||
sizeof (EFI_GUID)
|
||||
);
|
||||
NewAvailableAddr = NewAvailableAddr + sizeof (VARIABLE_HEADER);
|
||||
memcpy (
|
||||
(VOID *) NewAvailableAddr,
|
||||
Storage->Name,
|
||||
VarNameSize
|
||||
);
|
||||
|
||||
NewAvailableAddr = NewAvailableAddr + VarNameSize + GET_PAD_SIZE (VarNameSize);
|
||||
memcpy (
|
||||
(VOID *) NewAvailableAddr,
|
||||
Storage->Buffer,
|
||||
Storage->Size * sizeof (CHAR8)
|
||||
);
|
||||
//
|
||||
// Return the length which is from the beginning of Binary
|
||||
//
|
||||
return ((UINT32) ((UINT8*)NewAvailableAddr - StorageBeginning) + Storage->Size);
|
||||
}
|
||||
|
||||
/**
|
||||
Read time-based authenticated variable to storage list in multi-platform mode
|
||||
|
||||
@param Binary The pointer to the header of storage under specifed platformId and defaultId
|
||||
@param StorageListEntry The pointer to the storage list.
|
||||
|
||||
@return length The length of storage
|
||||
**/
|
||||
UINT32
|
||||
ReadTimeBasedVariableToList (
|
||||
IN UINT8 *Binary,
|
||||
IN LIST_ENTRY *StorageListEntry
|
||||
)
|
||||
{
|
||||
VARIABLE_HEADER *EndOfVariable;
|
||||
VARIABLE_HEADER *Variable;
|
||||
VARIABLE_STORE_HEADER *VariableStoreHeader;
|
||||
FORMSET_STORAGE *Storage;
|
||||
BOOLEAN ReadIdHeaderFlag;
|
||||
UINT32 Length;
|
||||
EFI_COMMON_SECTION_HEADER *SectionHeader;
|
||||
UINT8 *DataBase;
|
||||
static UINT16 PreDefaultId[MAX_PLATFORM_DEFAULT_ID_NUM];
|
||||
static UINT64 PrePlatformId[MAX_PLATFORM_DEFAULT_ID_NUM];
|
||||
|
||||
VariableStoreHeader = NULL;
|
||||
Variable = NULL;
|
||||
ReadIdHeaderFlag = TRUE;
|
||||
Length = 0;
|
||||
SectionHeader = (EFI_COMMON_SECTION_HEADER *)Binary;
|
||||
DataBase = Binary + sizeof (EFI_COMMON_SECTION_HEADER);
|
||||
VariableStoreHeader = (VARIABLE_STORE_HEADER *) (DataBase + *(UINT16 *)DataBase);
|
||||
EndOfVariable = GetEndPointer(VariableStoreHeader);
|
||||
|
||||
for (Variable = GetStartPointer (VariableStoreHeader);
|
||||
Length < VariableStoreHeader->Size;
|
||||
Length += sizeof (VARIABLE_HEADER) + Variable->NameSize + Variable->DataSize
|
||||
) {
|
||||
//
|
||||
// Create the storage
|
||||
//
|
||||
Storage = NULL;
|
||||
Storage = calloc (sizeof (FORMSET_STORAGE), sizeof (CHAR8));
|
||||
if (Storage == NULL) {
|
||||
printf ("Allocate memory failed.\n");
|
||||
return FAIL;
|
||||
}
|
||||
//
|
||||
// If access the first storage, read the platformId and defaultId
|
||||
//
|
||||
if (ReadIdHeaderFlag) {
|
||||
ReadDefaultAndPlatformIdFromBfv (DataBase, Storage);
|
||||
Length += sizeof (VARIABLE_HEADER) + Variable->NameSize + Variable->DataSize;
|
||||
ReadIdHeaderFlag = FALSE;
|
||||
memcpy (PreDefaultId, Storage->DefaultId, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT16));
|
||||
memcpy (PrePlatformId, Storage->PlatformId, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT64));
|
||||
} else {
|
||||
//
|
||||
// Store the DefaultId and PlatformId collected from the header to Storage.
|
||||
//
|
||||
memcpy (Storage->DefaultId, PreDefaultId, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT16));
|
||||
memcpy (Storage->PlatformId, PrePlatformId, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT64));
|
||||
}
|
||||
Storage->Attributes = Variable->Attributes;
|
||||
Storage->Size = (UINT16)Variable->DataSize;
|
||||
Storage->Name = calloc (Variable->NameSize, sizeof (UINT8));
|
||||
ASSERT (Storage->Name != NULL);
|
||||
Storage->Buffer = calloc (Variable->DataSize, sizeof (UINT8));
|
||||
ASSERT (Storage->Buffer != NULL);
|
||||
memcpy (
|
||||
&(Storage->Guid),
|
||||
&(Variable->VendorGuid),
|
||||
sizeof (EFI_GUID)
|
||||
);
|
||||
memcpy (
|
||||
Storage->Name,
|
||||
(UINT8 *)Variable + sizeof (VARIABLE_HEADER),
|
||||
Variable->NameSize
|
||||
);
|
||||
memcpy (
|
||||
Storage->Buffer,
|
||||
(UINT8 *)Variable + sizeof (VARIABLE_HEADER) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize),
|
||||
Storage->Size * sizeof (CHAR8)
|
||||
);
|
||||
//
|
||||
// Assigned the value for comparison in verify mode
|
||||
//
|
||||
Storage->Type = EFI_IFR_VARSTORE_EFI_OP;
|
||||
Storage->NewEfiVarstore = TRUE;
|
||||
InitializeListHead (&Storage->NameValueListHead);
|
||||
|
||||
InsertTailList(StorageListEntry, &Storage->Link);
|
||||
//
|
||||
// If the last variable, exit.
|
||||
//
|
||||
if (Variable == EndOfVariable) {
|
||||
break;
|
||||
}
|
||||
|
||||
Variable = GetNextVariablePtr (Variable);
|
||||
assert (Variable != NULL);
|
||||
}
|
||||
//
|
||||
// Return the length which is from the beginning of Binary
|
||||
//
|
||||
Length = FvBufExpand3ByteSize (SectionHeader->Size);
|
||||
|
||||
return Length;
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether exists the valid time-based variables in NvStorage or not.
|
||||
|
||||
@retval TRUE If existed, return TRUE.
|
||||
@retval FALSE Others
|
||||
**/
|
||||
BOOLEAN
|
||||
ExistTimeBasedEfiVarOrNot (
|
||||
IN LIST_ENTRY *StorageListHead
|
||||
)
|
||||
{
|
||||
EFI_FIRMWARE_VOLUME_HEADER *VarAddr;
|
||||
LIST_ENTRY *StorageLink;
|
||||
FORMSET_STORAGE *Storage;
|
||||
VARIABLE_HEADER *VariableHeader;
|
||||
VARIABLE_STORE_HEADER *VariableStoreHeader;
|
||||
|
||||
VariableHeader = NULL;
|
||||
VarAddr = (EFI_FIRMWARE_VOLUME_HEADER *) gEfiFdInfo.EfiVariableAddr;
|
||||
VariableStoreHeader = (VARIABLE_STORE_HEADER *)((CHAR8 *)VarAddr + VarAddr->HeaderLength);
|
||||
//
|
||||
//Parse the variable range, and check whether there is some existed ones.
|
||||
//
|
||||
StorageLink = GetFirstNode (StorageListHead);
|
||||
while (!IsNull (StorageListHead, StorageLink)) {
|
||||
Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
|
||||
//
|
||||
// Ignore the invalid varlist node
|
||||
//
|
||||
if ((Storage->Buffer == NULL)
|
||||
|| (Storage->Name == NULL)
|
||||
|| (FceStrLen(Storage->Name) == 0)
|
||||
) {
|
||||
StorageLink = GetNextNode (StorageListHead, StorageLink);
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// Report error, if the variable name is invalid.
|
||||
//
|
||||
if ((Storage->Name == NULL) || (FceStrLen(Storage->Name) == 0)) {
|
||||
StorageLink = GetNextNode (StorageListHead, StorageLink);
|
||||
continue;
|
||||
}
|
||||
VariableHeader = FindVariableInNv (
|
||||
VariableStoreHeader,
|
||||
Storage
|
||||
);
|
||||
|
||||
if ((VariableHeader != NULL)) {
|
||||
return TRUE;
|
||||
}
|
||||
StorageLink = GetNextNode (StorageListHead, StorageLink);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Fix the size of time-based variable header.
|
||||
|
||||
@param Binary The pointer to the header of storage under specifed platformId and defaultId
|
||||
@param Length The length of binary.
|
||||
|
||||
**/
|
||||
VOID
|
||||
FixBasedTimeVariableHeaderSize (
|
||||
IN UINT8 *BinaryBeginning,
|
||||
IN UINT32 Length
|
||||
)
|
||||
{
|
||||
VARIABLE_STORE_HEADER *VariableStoreHeader;
|
||||
|
||||
VariableStoreHeader = (VARIABLE_STORE_HEADER *) (BinaryBeginning + *(UINT16 *)BinaryBeginning);
|
||||
VariableStoreHeader->Size = Length - *(UINT16 *)BinaryBeginning;
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
/** @file
|
||||
|
||||
The header of TimeBasedVariable.c.
|
||||
|
||||
Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __AUTHENTICATED_VARIABLE_FORMAT_BASED_TIME_H__
|
||||
#define __AUTHENTICATED_VARIABLE_FORMAT_BASED_TIME_H__
|
||||
|
||||
#define EFI_AUTHENTICATED_VARIABLE_BASED_TIME_GUID \
|
||||
{ 0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 } }
|
||||
|
||||
extern EFI_GUID gEfiAuthenticatedVariableBasedTimeGuid;
|
||||
|
||||
///
|
||||
/// Alignment of variable name and data, according to the architecture:
|
||||
/// * For IA-32 and Intel(R) 64 architectures: 1
|
||||
/// * For IA-64 architecture: 8
|
||||
///
|
||||
#if defined (MDE_CPU_IPF)
|
||||
#define ALIGNMENT 8
|
||||
#else
|
||||
#define ALIGNMENT 1
|
||||
#endif
|
||||
|
||||
///
|
||||
/// GET_PAD_SIZE calculates the miminal pad bytes needed to make the current pad size satisfy the alignment requirement.
|
||||
///
|
||||
#if (ALIGNMENT == 1)
|
||||
#define GET_PAD_SIZE(a) (0)
|
||||
#else
|
||||
#define GET_PAD_SIZE(a) (((~a) + 1) & (ALIGNMENT - 1))
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Alignment of Variable Data Header in Variable Store region
|
||||
///
|
||||
#define HEADER_ALIGNMENT 4
|
||||
#define HEADER_ALIGN(Header) (((UINTN) (Header) + HEADER_ALIGNMENT - 1) & (~(HEADER_ALIGNMENT - 1)))
|
||||
|
||||
///
|
||||
/// Status of Variable Store Region
|
||||
///
|
||||
typedef enum {
|
||||
EfiRaw,
|
||||
EfiValid,
|
||||
EfiInvalid,
|
||||
EfiUnknown
|
||||
} VARIABLE_STORE_STATUS;
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
#define VARIABLE_STORE_SIGNATURE EFI_VARIABLE_GUID
|
||||
|
||||
///
|
||||
/// Variable Store Header Format and State
|
||||
///
|
||||
#define VARIABLE_STORE_FORMATTED 0x5a
|
||||
#define VARIABLE_STORE_HEALTHY 0xfe
|
||||
|
||||
///
|
||||
/// Variable Store region header
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// Variable store region signature.
|
||||
///
|
||||
EFI_GUID Signature;
|
||||
///
|
||||
/// Size of entire variable store,
|
||||
/// including size of variable store header but not including the size of FvHeader.
|
||||
///
|
||||
UINT32 Size;
|
||||
///
|
||||
/// Variable region format state.
|
||||
///
|
||||
UINT8 Format;
|
||||
///
|
||||
/// Variable region healthy state.
|
||||
///
|
||||
UINT8 State;
|
||||
UINT16 Reserved;
|
||||
UINT32 Reserved1;
|
||||
} VARIABLE_STORE_HEADER;
|
||||
|
||||
///
|
||||
/// Variable data start flag.
|
||||
///
|
||||
#define VARIABLE_DATA 0x55AA
|
||||
|
||||
///
|
||||
/// Variable State flags
|
||||
///
|
||||
#define VAR_IN_DELETED_TRANSITION 0xfe ///< Variable is in obsolete transition
|
||||
#define VAR_DELETED 0xfd ///< Variable is obsolete
|
||||
#define VAR_HEADER_VALID_ONLY 0x7f ///< Variable header has been valid
|
||||
#define VAR_ADDED 0x3f ///< Variable has been completely added
|
||||
|
||||
///
|
||||
/// Single Variable Data Header Structure.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// Variable Data Start Flag.
|
||||
///
|
||||
UINT16 StartId;
|
||||
///
|
||||
/// Variable State defined above.
|
||||
///
|
||||
UINT8 State;
|
||||
UINT8 Reserved;
|
||||
///
|
||||
/// Attributes of variable defined in UEFI spec
|
||||
///
|
||||
UINT32 Attributes;
|
||||
///
|
||||
/// Associated monotonic count value against replay attack.
|
||||
///
|
||||
UINT64 MonotonicCount;
|
||||
///
|
||||
/// Associated TimeStamp value against replay attack.
|
||||
///
|
||||
EFI_TIME TimeStamp;
|
||||
///
|
||||
/// Index of associated public key in database.
|
||||
///
|
||||
UINT32 PubKeyIndex;
|
||||
///
|
||||
/// Size of variable null-terminated Unicode string name.
|
||||
///
|
||||
UINT32 NameSize;
|
||||
///
|
||||
/// Size of the variable data without this header.
|
||||
///
|
||||
UINT32 DataSize;
|
||||
///
|
||||
/// A unique identifier for the vendor that produces and consumes this varaible.
|
||||
///
|
||||
EFI_GUID VendorGuid;
|
||||
} VARIABLE_HEADER;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
typedef struct _VARIABLE_INFO_ENTRY VARIABLE_INFO_ENTRY;
|
||||
|
||||
///
|
||||
/// This structure contains the variable list that is put in EFI system table.
|
||||
/// The variable driver collects all variables that were used at boot service time and produces this list.
|
||||
/// This is an optional feature to dump all used variables in shell environment.
|
||||
///
|
||||
struct _VARIABLE_INFO_ENTRY {
|
||||
VARIABLE_INFO_ENTRY *Next; ///< Pointer to next entry.
|
||||
EFI_GUID VendorGuid; ///< Guid of Variable.
|
||||
CHAR16 *Name; ///< Name of Variable.
|
||||
UINT32 Attributes; ///< Attributes of variable defined in UEFI spec.
|
||||
UINT32 ReadCount; ///< Number of times to read this variable.
|
||||
UINT32 WriteCount; ///< Number of times to write this variable.
|
||||
UINT32 DeleteCount; ///< Number of times to delete this variable.
|
||||
UINT32 CacheCount; ///< Number of times that cache hits this variable.
|
||||
BOOLEAN Volatile; ///< TRUE if volatile, FALSE if non-volatile.
|
||||
};
|
||||
|
||||
#endif // _EFI_VARIABLE_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,154 @@
|
|||
/** @file
|
||||
|
||||
The header of Variable.c.
|
||||
|
||||
Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __VARIABLE_FORMAT_H__
|
||||
#define __VARIABLE_FORMAT_H__
|
||||
|
||||
#define EFI_VARIABLE_GUID \
|
||||
{ 0xddcf3616, 0x3275, 0x4164, { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d } }
|
||||
|
||||
extern EFI_GUID gEfiVariableGuid;
|
||||
|
||||
///
|
||||
/// Alignment of variable name and data, according to the architecture:
|
||||
/// * For IA-32 and Intel(R) 64 architectures: 1.
|
||||
/// * For IA-64 architecture: 8.
|
||||
///
|
||||
#if defined (MDE_CPU_IPF)
|
||||
#define ALIGNMENT 8
|
||||
#else
|
||||
#define ALIGNMENT 1
|
||||
#endif
|
||||
|
||||
///
|
||||
/// GET_PAD_SIZE calculates the miminal pad bytes needed to make the current pad size satisfy the alignment requirement.
|
||||
///
|
||||
#if (ALIGNMENT == 1)
|
||||
#define GET_PAD_SIZE(a) (0)
|
||||
#else
|
||||
#define GET_PAD_SIZE(a) (((~a) + 1) & (ALIGNMENT - 1))
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Alignment of Variable Data Header in Variable Store region.
|
||||
///
|
||||
#define HEADER_ALIGNMENT 4
|
||||
#define HEADER_ALIGN(Header) (((UINTN) (Header) + HEADER_ALIGNMENT - 1) & (~(HEADER_ALIGNMENT - 1)))
|
||||
|
||||
///
|
||||
/// Status of Variable Store Region.
|
||||
///
|
||||
typedef enum {
|
||||
EfiRaw,
|
||||
EfiValid,
|
||||
EfiInvalid,
|
||||
EfiUnknown
|
||||
} VARIABLE_STORE_STATUS;
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
#define VARIABLE_STORE_SIGNATURE EFI_VARIABLE_GUID
|
||||
|
||||
///
|
||||
/// Variable Store Header Format and State.
|
||||
///
|
||||
#define VARIABLE_STORE_FORMATTED 0x5a
|
||||
#define VARIABLE_STORE_HEALTHY 0xfe
|
||||
|
||||
///
|
||||
/// Variable Store region header.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// Variable store region signature.
|
||||
///
|
||||
EFI_GUID Signature;
|
||||
///
|
||||
/// Size of entire variable store,
|
||||
/// including size of variable store header but not including the size of FvHeader.
|
||||
///
|
||||
UINT32 Size;
|
||||
///
|
||||
/// Variable region format state.
|
||||
///
|
||||
UINT8 Format;
|
||||
///
|
||||
/// Variable region healthy state.
|
||||
///
|
||||
UINT8 State;
|
||||
UINT16 Reserved;
|
||||
UINT32 Reserved1;
|
||||
} VARIABLE_STORE_HEADER;
|
||||
|
||||
///
|
||||
/// Variable data start flag.
|
||||
///
|
||||
#define VARIABLE_DATA 0x55AA
|
||||
|
||||
///
|
||||
/// Variable State flags.
|
||||
///
|
||||
#define VAR_IN_DELETED_TRANSITION 0xfe ///< Variable is in obsolete transition.
|
||||
#define VAR_DELETED 0xfd ///< Variable is obsolete.
|
||||
#define VAR_HEADER_VALID_ONLY 0x7f ///< Variable header has been valid.
|
||||
#define VAR_ADDED 0x3f ///< Variable has been completely added.
|
||||
|
||||
///
|
||||
/// Single Variable Data Header Structure.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// Variable Data Start Flag.
|
||||
///
|
||||
UINT16 StartId;
|
||||
///
|
||||
/// Variable State defined above.
|
||||
///
|
||||
UINT8 State;
|
||||
UINT8 Reserved;
|
||||
///
|
||||
/// Attributes of variable defined in UEFI specification.
|
||||
///
|
||||
UINT32 Attributes;
|
||||
///
|
||||
/// Size of variable null-terminated Unicode string name.
|
||||
///
|
||||
UINT32 NameSize;
|
||||
///
|
||||
/// Size of the variable data without this header.
|
||||
///
|
||||
UINT32 DataSize;
|
||||
///
|
||||
/// A unique identifier for the vendor that produces and consumes this varaible.
|
||||
///
|
||||
EFI_GUID VendorGuid;
|
||||
} VARIABLE_HEADER;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
typedef struct _VARIABLE_INFO_ENTRY VARIABLE_INFO_ENTRY;
|
||||
|
||||
///
|
||||
/// This structure contains the variable list that is put in EFI system table.
|
||||
/// The variable driver collects all variables that were used at boot service time and produces this list.
|
||||
/// This is an optional feature to dump all used variables in shell environment.
|
||||
///
|
||||
struct _VARIABLE_INFO_ENTRY {
|
||||
VARIABLE_INFO_ENTRY *Next; ///< Pointer to next entry.
|
||||
EFI_GUID VendorGuid; ///< Guid of Variable.
|
||||
CHAR16 *Name; ///< Name of Variable.
|
||||
UINT32 Attributes; ///< Attributes of variable defined in UEFI specification.
|
||||
UINT32 ReadCount; ///< Number of times to read this variable.
|
||||
UINT32 WriteCount; ///< Number of times to write this variable.
|
||||
UINT32 DeleteCount; ///< Number of times to delete this variable.
|
||||
UINT32 CacheCount; ///< Number of times that cache hits this variable.
|
||||
BOOLEAN Volatile; ///< TRUE if volatile, FALSE if non-volatile.
|
||||
};
|
||||
|
||||
#endif // _EFI_VARIABLE_H_
|
|
@ -0,0 +1,55 @@
|
|||
/** @file
|
||||
|
||||
The header of common Variable.c TimeBasedVariable.c and MonotonicBasedVariable.c.
|
||||
|
||||
Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __VARIABLE_COMMON_H__
|
||||
#define __VARIABLE_COMMON_H__
|
||||
|
||||
/**
|
||||
Check the store variable is no-authenticated or not
|
||||
|
||||
@param VarToList The pointer to the header of Variable Store.
|
||||
|
||||
@retval TRUE If no-authenticated, return TRUE.
|
||||
@retval FALSE Otherwise, return FALSE.
|
||||
**/
|
||||
|
||||
BOOLEAN
|
||||
CheckNormalVarStoreOrNot (
|
||||
IN VOID *VariableStoreHeader
|
||||
);
|
||||
/**
|
||||
Check the store variable is Monotonic based authenticated or not
|
||||
|
||||
@param VarToList The pointer to the header of Variable Store.
|
||||
|
||||
@retval TRUE If authenticated, return TRUE.
|
||||
@retval FALSE Otherwise, return FALSE.
|
||||
**/
|
||||
|
||||
BOOLEAN
|
||||
CheckMonotonicBasedVarStore (
|
||||
IN VOID *VariableStoreHeader
|
||||
);
|
||||
|
||||
/**
|
||||
Check the store variable is Time stamp authenticated or not
|
||||
|
||||
@param VarToList The pointer to the header of Variable Store.
|
||||
|
||||
@retval TRUE If authenticated, return TRUE.
|
||||
@retval FALSE Otherwise, return FALSE.
|
||||
**/
|
||||
BOOLEAN
|
||||
CheckTimeBasedVarStoreOrNot (
|
||||
IN VOID *VariableStoreHeader
|
||||
);
|
||||
|
||||
|
||||
|
||||
#endif // _EFI_VARIABLE_COMMON_H_
|
|
@ -1,7 +1,7 @@
|
|||
## @file
|
||||
# GNU/Linux makefile for C tools build.
|
||||
#
|
||||
# Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
|
@ -49,6 +49,7 @@ APPLICATIONS = \
|
|||
VfrCompile \
|
||||
BfmLib \
|
||||
EfiRom \
|
||||
FCE \
|
||||
GenFfs \
|
||||
GenFv \
|
||||
GenFw \
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
## @file
|
||||
# Windows makefile for C tools build.
|
||||
#
|
||||
# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
HOST_ARCH = IA32
|
||||
|
@ -14,6 +14,7 @@ APPLICATIONS = \
|
|||
BrotliCompress \
|
||||
BfmLib \
|
||||
EfiRom \
|
||||
FCE \
|
||||
GenCrc32 \
|
||||
GenFfs \
|
||||
GenFv \
|
||||
|
|
Loading…
Reference in New Issue