914 lines
29 KiB
C
914 lines
29 KiB
C
/** @file
|
|
Multi Config Base library implementation code.
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2013 - 2020, Insyde Software Corporation. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
|
|
*/
|
|
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/PrintLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/FlashRegionLib.h>
|
|
#include <Library/MultiConfigBaseLib.h>
|
|
|
|
//
|
|
// Multi Config Region Base
|
|
//
|
|
#define FLASH_REGION_MULTI_CONFIG_BASE FdmGetNAtAddr(&gH2OFlashMapRegionMultiConfigGuid, 1)
|
|
|
|
//
|
|
// Multi Config Region Size
|
|
//
|
|
#define FLASH_REGION_MULTI_CONFIG_SIZE FdmGetNAtSize(&gH2OFlashMapRegionMultiConfigGuid, 1)
|
|
|
|
/**
|
|
Calculate Hash value with string.
|
|
|
|
@param[in] str The string that is used to generate hash value.
|
|
@param[in] mix set 'mix' to some value other than zero if you want a tagged hash.
|
|
|
|
@return Hash value.
|
|
**/
|
|
STATIC
|
|
UINT64
|
|
QuickHash64 (
|
|
IN CONST CHAR8 *str,
|
|
IN UINT64 mix
|
|
)
|
|
{
|
|
CONST UINT64 mulp = 2654435789ull;
|
|
|
|
mix ^= 104395301;
|
|
|
|
while(*str) {
|
|
mix += MultU64x32(mulp, (UINT32)*str) ^ RShiftU64 (mix, 23);
|
|
str++;
|
|
}
|
|
|
|
return mix ^ LShiftU64 (mix, 37);
|
|
}
|
|
|
|
/**
|
|
Get HashData with Variable Name And Guid.
|
|
|
|
@param[in] VariableName Variable Name.
|
|
@param[in] VendorGuid Vendor Guid.
|
|
@param[out] HashData a hash value that is generated with Variable Name And Guid.
|
|
|
|
@retval EFI_SUCCESS Generating hash value success.
|
|
@retval EFI_INVALID_PARAMETER VariableName, VendorGuid or HashData is NULL.
|
|
@retval EFI_OUT_OF_RESOURCES Allocate memory fail.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
GetHashDataByVarNameAndGuid (
|
|
IN CONST CHAR16 *VariableName,
|
|
IN CONST EFI_GUID *VendorGuid,
|
|
OUT UINT64 *HashData
|
|
)
|
|
{
|
|
CHAR8 *HashStr;
|
|
UINTN BufferSize;
|
|
UINT16 Index;
|
|
UINT64 HashValue;
|
|
|
|
if ((VariableName == NULL) || (VendorGuid == NULL) || (HashData == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
HashStr = NULL;
|
|
BufferSize = 0;
|
|
HashValue = 0;
|
|
|
|
BufferSize = 32 + 4 + StrLen (VariableName) + 1;
|
|
HashStr = AllocateZeroPool (BufferSize);
|
|
if (HashStr == NULL) {
|
|
ASSERT (HashStr != NULL);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
AsciiSPrint (HashStr, BufferSize, "%g", VendorGuid);
|
|
for (Index = 0; VariableName[Index]; Index++) {
|
|
HashStr[32 + 4 + Index] = (UINT8)VariableName[Index];
|
|
}
|
|
HashStr[32 + 4 + Index] = 0;
|
|
|
|
HashValue = QuickHash64 (HashStr, 0);
|
|
|
|
*HashData = HashValue;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Set SCU variable Data by Multi-Config data
|
|
|
|
@param[in] VariableName Variable Name.
|
|
@param[in] VendorGuid Vendor Guid.
|
|
@param[in] MultiConfigData The config data for setting to Variable data.
|
|
@param[in] MultiConfigDataSize The config data size.
|
|
@param[in,out] SCUData Variable data.
|
|
@param[in] SCUDataSize Variable data size.
|
|
|
|
@retval EFI_SUCCESS Set SCU variable Data by Multi-Config data success.
|
|
@retval EFI_INVALID_PARAMETER VariableName, VendorGuid, MultiConfigData or SCUData is NULL, or MultiConfigDataSize or SCUDataSize is zero.
|
|
@retval EFI_UNSUPPORTED Doesn't have setting with specified variable in Multi-Config.
|
|
@retval EFI_OUT_OF_RESOURCES Allocate memory fail.
|
|
*/
|
|
STATIC
|
|
EFI_STATUS
|
|
SetSCUData (
|
|
IN CONST CHAR16 *VariableName,
|
|
IN CONST EFI_GUID *VendorGuid,
|
|
IN CONST VOID *MultiConfigData,
|
|
IN UINTN MultiConfigDataSize,
|
|
IN OUT VOID *SCUData,
|
|
IN UINTN SCUDataSize
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT16 SCUSettingBlockCount;
|
|
MC_SCU_SETTING_HEADER *MCSCUSettingHdr;
|
|
MC_SCU_SETTING *MCDefSetting;
|
|
UINT16 SettingBlockIdx;
|
|
UINT16 SettingIdx;
|
|
UINT64 HashData;
|
|
|
|
if ((MultiConfigData == NULL) || (MultiConfigDataSize == 0) || (SCUData == NULL) || (SCUDataSize == 0)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
SCUSettingBlockCount = *(UINT16 *)MultiConfigData;
|
|
if (SCUSettingBlockCount == 0) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
Status = GetHashDataByVarNameAndGuid (VariableName, VendorGuid, &HashData);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
MCSCUSettingHdr = (MC_SCU_SETTING_HEADER *)((UINTN)MultiConfigData + sizeof (UINT16));
|
|
|
|
for (SettingBlockIdx = 0; SettingBlockIdx < SCUSettingBlockCount; SettingBlockIdx++) {
|
|
|
|
if (HashData == MCSCUSettingHdr->NameGuidHash) {
|
|
break;
|
|
}
|
|
|
|
if (((UINTN)MCSCUSettingHdr + sizeof (MC_SCU_SETTING_HEADER) + MCSCUSettingHdr->SettingSize) >= ((UINTN)MultiConfigData + MultiConfigDataSize)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
MCSCUSettingHdr = (MC_SCU_SETTING_HEADER *)((UINTN)MCSCUSettingHdr + sizeof (MC_SCU_SETTING_HEADER) + MCSCUSettingHdr->SettingSize);
|
|
}
|
|
|
|
if (SettingBlockIdx >= SCUSettingBlockCount) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
//
|
|
// set settings
|
|
//
|
|
MCDefSetting = (MC_SCU_SETTING *)((UINTN)MCSCUSettingHdr + sizeof (MC_SCU_SETTING_HEADER));
|
|
for (SettingIdx = 0; SettingIdx < MCSCUSettingHdr->SettingCount; SettingIdx++) {
|
|
ASSERT (MCDefSetting->Offset < SCUDataSize);
|
|
if (MCDefSetting->Offset < SCUDataSize) {
|
|
CopyMem ((VOID *)((UINTN)SCUData + MCDefSetting->Offset), MCDefSetting + 1, MCDefSetting->Width);
|
|
}
|
|
|
|
if (((UINTN)MCDefSetting + sizeof (MC_SCU_SETTING) + MCDefSetting->Width) >= ((UINTN)MCSCUSettingHdr + sizeof (MC_SCU_SETTING_HEADER) + MCSCUSettingHdr->SettingSize)) {
|
|
break;
|
|
}
|
|
|
|
MCDefSetting = (MC_SCU_SETTING *)((UINTN)MCDefSetting + sizeof (MC_SCU_SETTING) + MCDefSetting->Width);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
This internal function reverses bits for 32bit data.
|
|
|
|
@param Value The data to be reversed.
|
|
|
|
@return Data reversed.
|
|
**/
|
|
UINT32
|
|
ReverseBits (
|
|
IN UINT32 Value
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINT32 NewValue;
|
|
|
|
NewValue = 0;
|
|
for (Index = 0; Index < 32; Index++) {
|
|
if ((Value & (1 << Index)) != 0) {
|
|
NewValue = NewValue | (1 << (31 - Index));
|
|
}
|
|
}
|
|
|
|
return NewValue;
|
|
}
|
|
|
|
|
|
/**
|
|
Initialize CRC32 table.
|
|
|
|
@param none
|
|
|
|
@retval none
|
|
**/
|
|
VOID
|
|
InitializeCrc32Table (
|
|
OUT UINT32 *CrcTable
|
|
)
|
|
{
|
|
UINTN TableEntry;
|
|
UINTN Index;
|
|
UINT32 Value;
|
|
|
|
for (TableEntry = 0; TableEntry < 256; TableEntry++) {
|
|
Value = ReverseBits ((UINT32) TableEntry);
|
|
for (Index = 0; Index < 8; Index++) {
|
|
if ((Value & 0x80000000) != 0) {
|
|
Value = (Value << 1) ^ 0x04c11db7;
|
|
} else {
|
|
Value = Value << 1;
|
|
}
|
|
}
|
|
|
|
CrcTable[TableEntry] = ReverseBits (Value);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
Returns the length of Header (including MULTI_CONFIG_REGION_HEADER and all CONFIG_HEADERs).
|
|
|
|
@param[in] Binary Pointer to Multi Config Region Raw Data.
|
|
|
|
@return The length of Header.
|
|
*/
|
|
UINTN
|
|
GetHeaderLenghth (
|
|
IN VOID *Binary
|
|
)
|
|
{
|
|
MULTI_CONFIG_REGION_HEADER *MultiConfigHdr;
|
|
|
|
MultiConfigHdr = (MULTI_CONFIG_REGION_HEADER*)Binary;
|
|
|
|
return (sizeof (MULTI_CONFIG_REGION_HEADER) + (sizeof (CONFIG_HEADER) * MultiConfigHdr->ConfigCount));
|
|
}
|
|
|
|
|
|
/**
|
|
Returns the CONFIG_HEADER point of ranking order.
|
|
|
|
@param[in] Order Pointer to a UINT16 value indicate specific Config Order.
|
|
|
|
@return The CONFIG_HEADER point of ranking order.
|
|
*/
|
|
CONFIG_HEADER*
|
|
GetConfigHeaderByOrder (
|
|
IN UINT16 Order
|
|
)
|
|
{
|
|
VOID *MultiConfigRegionBase;
|
|
|
|
MultiConfigRegionBase = (VOID*)(UINTN)FLASH_REGION_MULTI_CONFIG_BASE;
|
|
|
|
return (CONFIG_HEADER*)((UINT8*)MultiConfigRegionBase + (sizeof (MULTI_CONFIG_REGION_HEADER) + sizeof (CONFIG_HEADER) * Order));
|
|
}
|
|
|
|
|
|
/**
|
|
Returns the Config Data point of ranking order.
|
|
|
|
@param[in] Order Pointer to a UINT16 value indicate specific Config Order.
|
|
@param[in] Binary Pointer to Multi Config Region Raw Data.
|
|
|
|
@return The Config Data point of ranking order.
|
|
*/
|
|
VOID*
|
|
GetConfigDataByOrder (
|
|
IN UINT16 Order,
|
|
IN VOID *Binary
|
|
)
|
|
{
|
|
UINTN HeaderLenght;
|
|
UINTN DataOffset;
|
|
CONFIG_HEADER *ConfigHeader;
|
|
UINT16 Index;
|
|
|
|
HeaderLenght = GetHeaderLenghth (Binary);
|
|
|
|
ConfigHeader = (CONFIG_HEADER *)((MULTI_CONFIG_REGION_HEADER *)Binary + 1);
|
|
|
|
DataOffset = 0;
|
|
|
|
for (Index = 0; Index < Order; Index++) {
|
|
DataOffset += ConfigHeader->ConfigDataSize;
|
|
ConfigHeader += 1;
|
|
}
|
|
|
|
return (VOID*)((UINT8*)Binary + (HeaderLenght + DataOffset));
|
|
}
|
|
|
|
|
|
/**
|
|
Returns the Config Count.
|
|
|
|
@return The Config Count.
|
|
*/
|
|
UINT16
|
|
GetConfigCount (
|
|
VOID
|
|
)
|
|
{
|
|
VOID *MultiConfigRegionBase;
|
|
|
|
MultiConfigRegionBase = (VOID*)(UINTN)FLASH_REGION_MULTI_CONFIG_BASE;
|
|
if (MultiConfigRegionBase == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
return (UINT16)((MULTI_CONFIG_REGION_HEADER*)(MultiConfigRegionBase))->ConfigCount;
|
|
}
|
|
|
|
|
|
/**
|
|
Get the specific Config Header and Order, order number is 0, 1, 2, 3,......
|
|
|
|
@param[in] Type Config Data Type.
|
|
@param[in] ConfigId Config Data Identity Number.
|
|
@param[in] Binary Pointer to Multi Config Region Raw Data.
|
|
@param[out] ConfigHeader Pointer to specific Config Header search by Type & ID.
|
|
@param[out] Order Pointer to a UINT16 value indicate specific Config Order.
|
|
|
|
@retval EFI_SUCCESS Configuration header found.
|
|
@retval EFI_NOT_FOUND Can't Find the specific Config Header.
|
|
@retval EFI_INVALID_PARAMETER Binary is NULL.
|
|
*/
|
|
EFI_STATUS
|
|
GetConfigHeaderOrder (
|
|
IN UINT8 Type,
|
|
IN UINT8 ConfigId,
|
|
IN VOID *Binary,
|
|
OUT CONFIG_HEADER **ConfigHeader OPTIONAL,
|
|
OUT UINT16 *ConfigOrder OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
CONFIG_HEADER *TempConfigHeader;
|
|
UINT16 ConfigCount;
|
|
UINT16 Index;
|
|
|
|
if (Binary == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
TempConfigHeader = GetConfigHeaderByOrder (0);
|
|
ConfigCount = GetConfigCount ();
|
|
|
|
Status = EFI_NOT_FOUND;
|
|
|
|
for (Index = 0; Index < ConfigCount; Index++) {
|
|
if ((TempConfigHeader->Type == Type) && (TempConfigHeader->ConfigId == ConfigId)) {
|
|
Status = EFI_SUCCESS;
|
|
if (ConfigHeader != NULL) {
|
|
*ConfigHeader = TempConfigHeader;
|
|
}
|
|
if (ConfigOrder != NULL) {
|
|
*ConfigOrder = Index;
|
|
}
|
|
break;
|
|
}
|
|
TempConfigHeader += 1;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Check CRC32 for Multi Config Header.
|
|
|
|
@param[in] Binary Pointer to Multi Config Region Raw Data.
|
|
|
|
@retval EFI_SUCCESS Check CRC32 correct.
|
|
@retval EFI_CRC_ERROR Check CRC32 error.
|
|
*/
|
|
EFI_STATUS
|
|
CheckMultiConfigHeaderCrc32 (
|
|
IN VOID *Binary
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
MULTI_CONFIG_REGION_HEADER *MultiConfigHeader;
|
|
UINT32 TempCrc32;
|
|
|
|
MultiConfigHeader = (MULTI_CONFIG_REGION_HEADER*)Binary;
|
|
|
|
//
|
|
// Save the original HeaderCrc32 value.
|
|
//
|
|
TempCrc32 = MultiConfigHeader->HeaderCrc32;
|
|
MultiConfigHeader->HeaderCrc32 = 0;
|
|
|
|
MultiConfigHeader->HeaderCrc32= CalculateCrc32 (MultiConfigHeader, MultiConfigHeader->HeaderLength);
|
|
if (MultiConfigHeader->HeaderCrc32 == TempCrc32) {
|
|
Status = EFI_SUCCESS;
|
|
} else {
|
|
Status = EFI_CRC_ERROR;
|
|
//
|
|
// Recovery the original HeaderCrc32 value.
|
|
//
|
|
MultiConfigHeader->HeaderCrc32 = TempCrc32;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Check CRC32 for Multi Config Data.
|
|
|
|
@param[in] Binary Pointer to Multi Config Region Raw Data.
|
|
|
|
@retval EFI_SUCCESS Check CRC32 correct.
|
|
@retval EFI_CRC_ERROR Check CRC32 error.
|
|
*/
|
|
EFI_STATUS
|
|
CheckMultiConfigDataCrc32 (
|
|
IN UINT32 Crc32,
|
|
IN UINT16 ConfigDataSize,
|
|
IN VOID *ConfigData
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT32 TempCrc32;
|
|
|
|
TempCrc32 = CalculateCrc32 (ConfigData, ConfigDataSize);
|
|
if (TempCrc32 == Crc32) {
|
|
Status = EFI_SUCCESS;
|
|
} else {
|
|
Status = EFI_CRC_ERROR;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Check Signature & Header CRC32 for Multi Config Region.
|
|
|
|
@param[in] MultiConfigRegion Pointer to Multi Config Region Raw Data.
|
|
|
|
@retval EFI_SUCCESS Check Signature & Header CRC32 success.
|
|
@retval EFI_NOT_FOUND Verify the signature error.
|
|
@retval EFI_CRC_ERROR Check Multi config Header CRC32 error.
|
|
*/
|
|
EFI_STATUS
|
|
CheckSignatureAndHeaderCrc (
|
|
VOID *MultiConfigRegion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT64 Signature;
|
|
MULTI_CONFIG_REGION_HEADER *RegionHeader;
|
|
VOID *TempRegionHeader;
|
|
|
|
//
|
|
// Verify Signature
|
|
//
|
|
Signature = MULTI_CONFIG_SIGNATURE;
|
|
if (CompareMem (&Signature, MultiConfigRegion, sizeof (UINT64)) != 0) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
RegionHeader = (MULTI_CONFIG_REGION_HEADER*)MultiConfigRegion;
|
|
|
|
TempRegionHeader = AllocateZeroPool (RegionHeader->HeaderLength);
|
|
if (TempRegionHeader == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
CopyMem (TempRegionHeader, MultiConfigRegion, RegionHeader->HeaderLength);
|
|
|
|
//
|
|
// Check CRC32 for Multi Config Header
|
|
//
|
|
Status = CheckMultiConfigHeaderCrc32 (TempRegionHeader);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_CRC_ERROR;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Find the specific Config Header and Order, order number is 0, 1, 2, 3,......
|
|
This specific Config Data is Setup setting use for BIOS POST or Load Default.
|
|
|
|
@param[in] Type The type of config data.
|
|
@param[in] RequireKind Find Setup Setting for (1: BIOS POST) or (2: Load Default).
|
|
@param[in,out] ConfigOrder Pointer to a UINT16 value indicate specific Config Order.
|
|
@param[in] Binary Pointer to Multi Config Region Raw Data.
|
|
@param[out] ConfigHeader Point to specific Config Header.
|
|
|
|
@retval EFI_SUCCESS Get the specific Config Header and Order success.
|
|
@retval EFI_NOT_FOUND Can't Find the specific Config Header.
|
|
@retval EFI_INVALID_PARAMETER Binary or ConfigHeader is NULL.
|
|
*/
|
|
EFI_STATUS
|
|
FindConfigSetting (
|
|
IN UINT8 Type,
|
|
IN CONST UINT8 RequireKind,
|
|
IN OUT UINT16 *ConfigOrder,
|
|
IN VOID *Binary,
|
|
OUT CONFIG_HEADER **ConfigHeader
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
CONFIG_HEADER *TempConfigHeader;
|
|
UINT16 ConfigCount;
|
|
UINT16 Index;
|
|
|
|
if (Binary == NULL || ConfigHeader == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
TempConfigHeader = GetConfigHeaderByOrder (*ConfigOrder);
|
|
ConfigCount = GetConfigCount ();
|
|
|
|
Status = EFI_NOT_FOUND;
|
|
|
|
for (Index = *ConfigOrder; Index < ConfigCount; Index++) {
|
|
//
|
|
// Config Type is Full Setup Setting & Attribute is VALID
|
|
//
|
|
if ((TempConfigHeader->Type == Type) && \
|
|
((TempConfigHeader->Attribute & MULTI_CONFIG_ATTRIBUTE_VALID) == MULTI_CONFIG_ATTRIBUTE_VALID)) {
|
|
//
|
|
// Full Setup Setting for BIOS POST or Load Default
|
|
//
|
|
if (RequireKind == SETUP_FOR_BIOS_POST) {
|
|
//
|
|
// Config attribute is ACTIVE | BIOS_POST (The attribute Only support on SCU setting currently)
|
|
//
|
|
if ((TempConfigHeader->Attribute & 0x40000000) == 0x00000000) {
|
|
Status = EFI_SUCCESS;
|
|
*ConfigHeader = TempConfigHeader;
|
|
*ConfigOrder = Index;
|
|
break;
|
|
}
|
|
} else {
|
|
//
|
|
// Config attribute is ACTIVE | DEFAULT
|
|
//
|
|
if ((TempConfigHeader->Attribute & 0x20000000) == 0x20000000) {
|
|
Status = EFI_SUCCESS;
|
|
*ConfigHeader = TempConfigHeader;
|
|
*ConfigOrder = Index;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
TempConfigHeader += 1;
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Get the Active or Default Full Setup Setting Config Data, identify by Config Type & Attribute.
|
|
|
|
@param[in] RequireKind Find Setup Setting for SETUP_FOR_BIOS_POST or SETUP_FOR_LOAD_DEFAULT.
|
|
@param[in,out] ConfigOrder Pointer to a UINT16 value indicate specific Config Order.
|
|
@param[in] DataBufferSize Full Setup setting data size.
|
|
@param[out] DataBuffer Buffer to store the data.
|
|
@param[out] ConfigId Pointer to UINT8 for carrying Config Identity Number.
|
|
@param[out] Attribute Pointer to UINT32 for carrying Config Attribute.
|
|
|
|
@retval EFI_SUCCESS Get the specific Config Data success.
|
|
@retval EFI_INVALID_PARAMETER DataBuffer is NULL.
|
|
@retval EFI_NOT_FOUND Verify the signature error or can't find the specific Config Data.
|
|
@retval EFI_UNSUPPORTED The flash device is not supported.
|
|
@retval EFI_CRC_ERROR Check Multi Config Header or Data CRC32 error.
|
|
*/
|
|
EFI_STATUS
|
|
GetFullSetupSetting (
|
|
IN CONST UINT8 RequireKind,
|
|
IN OUT UINT16 *ConfigOrder,
|
|
IN UINTN DataBufferSize,
|
|
OUT VOID **DataBuffer,
|
|
OUT UINT8 *ConfigId OPTIONAL,
|
|
OUT UINT32 *Attribute OPTIONAL
|
|
)
|
|
{
|
|
return EFI_UNSUPPORTED;
|
|
// EFI_STATUS Status;
|
|
// VOID *MultiConfigRegionBase;
|
|
// CONFIG_HEADER *TempHeader;
|
|
// VOID *TempConfigData;
|
|
//
|
|
// if (DataBuffer == NULL) {
|
|
// return EFI_INVALID_PARAMETER;
|
|
// }
|
|
//
|
|
// MultiConfigRegionBase = (VOID*)(UINTN)FLASH_REGION_MULTI_CONFIG_BASE;
|
|
//
|
|
// //
|
|
// // Check Signature & Header CRC32 for Multi Config Region.
|
|
// //
|
|
// Status = CheckSignatureAndHeaderCrc (MultiConfigRegionBase);
|
|
// if (EFI_ERROR (Status)) {
|
|
// return Status;
|
|
// }
|
|
//
|
|
// //
|
|
// // Search the specific Config Header
|
|
// //
|
|
// TempHeader = NULL;
|
|
// Status = FindConfigSetting (MULTI_CONFIG_TYPE_FULL_SETUP_SETTING_VALUE, RequireKind, ConfigOrder, MultiConfigRegionBase, &TempHeader);
|
|
// if (EFI_ERROR (Status)) {
|
|
// return EFI_NOT_FOUND;
|
|
// }
|
|
//
|
|
// //
|
|
// // Check CRC32 for Multi Config Data
|
|
// // Direct get Config Data by Config Data Offset
|
|
// //
|
|
// TempConfigData = (UINT8*)MultiConfigRegionBase + TempHeader->ConfigDataOffset;
|
|
// Status = CheckMultiConfigDataCrc32 (TempHeader->Crc32, TempHeader->ConfigDataSize, TempConfigData);
|
|
// if (EFI_ERROR (Status)) {
|
|
// //
|
|
// // Get Config Data by Config Order
|
|
// //
|
|
// TempConfigData = GetConfigDataByOrder (*ConfigOrder, MultiConfigRegionBase);
|
|
// Status = CheckMultiConfigDataCrc32 (TempHeader->Crc32, TempHeader->ConfigDataSize, TempConfigData);
|
|
// if (EFI_ERROR (Status)) {
|
|
// return EFI_CRC_ERROR;
|
|
// }
|
|
// }
|
|
//
|
|
// *DataBuffer = TempConfigData;
|
|
//
|
|
// if (ConfigId != NULL) {
|
|
// *ConfigId = TempHeader->ConfigId;
|
|
// }
|
|
// if (Attribute != NULL) {
|
|
// *Attribute = TempHeader->Attribute;
|
|
// }
|
|
//
|
|
// return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Get the Active or Default SCU Setting Config Data, identify by Config Type & Attribute.
|
|
|
|
@param[in] RequireKind Find Setup Setting for SETUP_FOR_BIOS_POST or SETUP_FOR_LOAD_DEFAULT.
|
|
@param[in,out] ConfigOrder Pointer to a UINT16 value indicate specific Config Order.
|
|
@param[out] DataBuffer Buffer to store the data.
|
|
@param[in] DataBufferSize Full Setup setting data size.
|
|
@param[out] ConfigId Pointer to UINT8 for carrying Config Identity Number.
|
|
@param[out] Attribute Pointer to UINT32 for carrying Config Attribute.
|
|
|
|
@retval EFI_SUCCESS Get the specific Config Data success.
|
|
@retval EFI_INVALID_PARAMETER DataBuffer is NULL.
|
|
@retval EFI_NOT_FOUND Verify the signature error or can't find the specific Config Data.
|
|
@retval EFI_CRC_ERROR Check Multi Config Header or Data CRC32 error.
|
|
*/
|
|
EFI_STATUS
|
|
GetSCUSetting (
|
|
IN CONST UINT8 RequireKind,
|
|
IN OUT UINT16 *ConfigOrder,
|
|
OUT VOID **DataBuffer,
|
|
IN UINTN *DataBufferSize OPTIONAL,
|
|
OUT UINT8 *ConfigId OPTIONAL,
|
|
OUT UINT32 *Attribute OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
VOID *MultiConfigRegionBase;
|
|
CONFIG_HEADER *TempHeader;
|
|
VOID *TempConfigData;
|
|
|
|
if (DataBuffer == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
MultiConfigRegionBase = (VOID*)(UINTN)FLASH_REGION_MULTI_CONFIG_BASE;
|
|
|
|
//
|
|
// Check Signature & Header CRC32 for Multi Config Region.
|
|
//
|
|
Status = CheckSignatureAndHeaderCrc (MultiConfigRegionBase);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Search the specific Config Header
|
|
//
|
|
TempHeader = NULL;
|
|
Status = FindConfigSetting (MULTI_CONFIG_TYPE_SCU_SETTING_PARTIAL_VALUE, RequireKind, ConfigOrder, MultiConfigRegionBase, &TempHeader);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Check CRC32 for Multi Config Data
|
|
// Direct get Config Data by Config Data Offset
|
|
//
|
|
TempConfigData = (UINT8*)MultiConfigRegionBase + TempHeader->ConfigDataOffset;
|
|
Status = CheckMultiConfigDataCrc32 (TempHeader->Crc32, TempHeader->ConfigDataSize, TempConfigData);
|
|
if (EFI_ERROR (Status)) {
|
|
//
|
|
// Get Config Data by Config Order
|
|
//
|
|
TempConfigData = GetConfigDataByOrder (*ConfigOrder, MultiConfigRegionBase);
|
|
Status = CheckMultiConfigDataCrc32 (TempHeader->Crc32, TempHeader->ConfigDataSize, TempConfigData);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_CRC_ERROR;
|
|
}
|
|
}
|
|
|
|
*DataBuffer = TempConfigData;
|
|
|
|
if (DataBufferSize != NULL) {
|
|
*DataBufferSize = TempHeader->ConfigDataSize;
|
|
}
|
|
|
|
if (ConfigId != NULL) {
|
|
*ConfigId = TempHeader->ConfigId;
|
|
}
|
|
if (Attribute != NULL) {
|
|
*Attribute = TempHeader->Attribute;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Set SCU setting with specified SCU config data.
|
|
|
|
@param[in] VariableName Variable Name.
|
|
@param[in] VendorGuid Vendor Guid.
|
|
@param[in] RequireKind Find Setup Setting for SETUP_FOR_BIOS_POST or SETUP_FOR_LOAD_DEFAULT.
|
|
@param[out] SCUData Variable data.
|
|
@param[in] SCUDataSize Variable data size.
|
|
|
|
@retval EFI_SUCCESS Set SCU setting with specified SCU config data success.
|
|
@retval EFI_INVALID_PARAMETER Argument is NULL.
|
|
@retval EFI_NOT_FOUND Verify the signature error or can't find the specific Config Data.
|
|
@retval EFI_UNSUPPORTED Doesn't have setting with specified variable in Multi-Config.
|
|
@retval EFI_OUT_OF_RESOURCES Allocate memory fail.
|
|
*/
|
|
EFI_STATUS
|
|
SetSCUDataFromMC (
|
|
IN CONST CHAR16 *VariableName,
|
|
IN CONST EFI_GUID *VendorGuid,
|
|
IN CONST UINT8 RequireKind,
|
|
IN OUT VOID *SCUData,
|
|
IN UINTN SCUDataSize
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT16 ConfigCount;
|
|
UINT16 Index;
|
|
UINTN MultiConfigDataSize;
|
|
VOID *MultiConfigData;
|
|
|
|
Index = 0;
|
|
MultiConfigDataSize = 0;
|
|
ConfigCount = GetConfigCount();
|
|
|
|
for ( ; Index < ConfigCount; Index ++) {
|
|
//
|
|
// Get Active (Attribute: ACTIVE & LOAD_DEFAULT) Config Data from Multi Config Region
|
|
//
|
|
Status = GetSCUSetting (
|
|
RequireKind,
|
|
&Index,
|
|
&MultiConfigData,
|
|
&MultiConfigDataSize,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
//
|
|
// set MultiConfigData to MyIfrNVData
|
|
//
|
|
return SetSCUData (VariableName, VendorGuid, MultiConfigData, MultiConfigDataSize, SCUData, SCUDataSize);
|
|
}
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
Compare SCU variable Data With Multi-Config data
|
|
|
|
@param[in] VariableName Variable Name.
|
|
@param[in] VendorGuid Vendor Guid.
|
|
@param[in] MultiConfigData The config data for comparing with Variable data.
|
|
@param[in] MultiConfigDataSize The config data size.
|
|
@param[in] SCUData Variable data.
|
|
@param[in] SCUDataSize Variable data size.
|
|
@param[out] IsSame The result of comparing is same or not.
|
|
|
|
@retval EFI_SUCCESS Compare with Config Data success.
|
|
@retval EFI_INVALID_PARAMETER VariableName, VendorGuid, MultiConfigData or SCUData is NULL, or MultiConfigDataSize or SCUDataSize is zero.
|
|
@retval EFI_UNSUPPORTED Doesn't have setting with specified variable in Multi-Config.
|
|
@retval EFI_OUT_OF_RESOURCES Allocate memory fail.
|
|
*/
|
|
EFI_STATUS
|
|
CompareSCUDataWithMC (
|
|
IN CONST CHAR16 *VariableName,
|
|
IN CONST EFI_GUID *VendorGuid,
|
|
IN CONST VOID *MultiConfigData,
|
|
IN UINTN MultiConfigDataSize,
|
|
IN VOID *SCUData,
|
|
IN UINTN SCUDataSize,
|
|
OUT BOOLEAN *IsSame
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT16 SCUSettingBlockCount;
|
|
MC_SCU_SETTING_HEADER *MCSCUSettingHdr;
|
|
MC_SCU_SETTING *MCDefSetting;
|
|
UINT16 SettingBlockIdx;
|
|
UINT16 SettingIdx;
|
|
UINT64 HashData;
|
|
|
|
if ((MultiConfigData == NULL) || (MultiConfigDataSize == 0) || (SCUData == NULL) || (SCUDataSize == 0)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
*IsSame = TRUE;
|
|
|
|
SCUSettingBlockCount = *(UINT16 *)MultiConfigData;
|
|
if (SCUSettingBlockCount == 0) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
Status = GetHashDataByVarNameAndGuid (VariableName, VendorGuid, &HashData);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
MCSCUSettingHdr = (MC_SCU_SETTING_HEADER *)((UINTN)MultiConfigData + sizeof (UINT16));
|
|
|
|
for (SettingBlockIdx = 0; SettingBlockIdx < SCUSettingBlockCount; SettingBlockIdx++) {
|
|
|
|
if (HashData == MCSCUSettingHdr->NameGuidHash) {
|
|
break;
|
|
}
|
|
|
|
if (((UINTN)MCSCUSettingHdr + sizeof (MC_SCU_SETTING_HEADER) + MCSCUSettingHdr->SettingSize) >= ((UINTN)MultiConfigData + MultiConfigDataSize)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
MCSCUSettingHdr = (MC_SCU_SETTING_HEADER *)((UINTN)MCSCUSettingHdr + sizeof (MC_SCU_SETTING_HEADER) + MCSCUSettingHdr->SettingSize);
|
|
}
|
|
|
|
if (SettingBlockIdx >= SCUSettingBlockCount) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
//
|
|
// set settings
|
|
//
|
|
MCDefSetting = (MC_SCU_SETTING *)((UINTN)MCSCUSettingHdr + sizeof (MC_SCU_SETTING_HEADER));
|
|
for (SettingIdx = 0; SettingIdx < MCSCUSettingHdr->SettingCount; SettingIdx++) {
|
|
ASSERT (MCDefSetting->Offset < SCUDataSize);
|
|
if (MCDefSetting->Offset < SCUDataSize) {
|
|
if (CompareMem ((VOID *)((UINTN)SCUData + MCDefSetting->Offset), MCDefSetting + 1, MCDefSetting->Width) != 0) {
|
|
*IsSame = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (((UINTN)MCDefSetting + sizeof (MC_SCU_SETTING) + MCDefSetting->Width) >= ((UINTN)MCSCUSettingHdr + sizeof (MC_SCU_SETTING_HEADER) + MCSCUSettingHdr->SettingSize)) {
|
|
break;
|
|
}
|
|
|
|
MCDefSetting = (MC_SCU_SETTING *)((UINTN)MCDefSetting + sizeof (MC_SCU_SETTING) + MCDefSetting->Width);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|