1444 lines
43 KiB
C
1444 lines
43 KiB
C
/**@file
|
|
|
|
@copyright
|
|
INTEL CONFIDENTIAL
|
|
Copyright 2010 - 2021 Intel Corporation.
|
|
|
|
The source code contained or described herein and all documents related to the
|
|
source code ("Material") are owned by Intel Corporation or its suppliers or
|
|
licensors. Title to the Material remains with Intel Corporation or its suppliers
|
|
and licensors. The Material may contain trade secrets and proprietary and
|
|
confidential information of Intel Corporation and its suppliers and licensors,
|
|
and is protected by worldwide copyright and trade secret laws and treaty
|
|
provisions. No part of the Material may be used, copied, reproduced, modified,
|
|
published, uploaded, posted, transmitted, distributed, or disclosed in any way
|
|
without Intel's prior express written permission.
|
|
|
|
No license under any patent, copyright, trade secret or other intellectual
|
|
property right is granted to or conferred upon you by disclosure or delivery
|
|
of the Materials, either expressly, by implication, inducement, estoppel or
|
|
otherwise. Any license under such intellectual property rights must be
|
|
express and approved by Intel in writing.
|
|
|
|
Unless otherwise agreed by Intel in writing, you may not remove or alter
|
|
this notice or any other notice embedded in Materials by Intel or
|
|
Intel's suppliers or licensors in any way.
|
|
|
|
This file contains a 'Sample Driver' and is licensed as such under the terms
|
|
of your license agreement with Intel or your vendor. This file may be modified
|
|
by the user, subject to the additional terms of the license agreement.
|
|
|
|
@par Specification Reference:
|
|
**/
|
|
|
|
#include <Protocol/HiiDatabase.h>
|
|
#include <Protocol/HiiConfigAccess.h>
|
|
#include <Protocol/HiiConfigRouting.h>
|
|
#include <Protocol/HiiString.h>
|
|
#include <Library/UefiLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
#include <Library/HiiLib.h>
|
|
#include <Guid/GlobalVariable.h>
|
|
#include "SetupPrivate.h"
|
|
#include <InitStringList.h>
|
|
#include <Library/DebugPrintErrorLevelLib.h>
|
|
#include <Library/SerialPortParameterLib.h>
|
|
#include <PlatformBoardId.h>
|
|
#include <Library/BoardConfigLib.h>
|
|
|
|
extern CALLBACK_INFO SetupCallBack[];
|
|
extern BOOLEAN IsFirstBoot;
|
|
extern EFI_HII_CONFIG_ROUTING_PROTOCOL *mConfigRouting;
|
|
|
|
VOID IccExtractConfig (
|
|
VOID
|
|
);
|
|
VOID MeExtractConfig (
|
|
VOID
|
|
);
|
|
VOID IccRouteConfig (
|
|
VOID
|
|
);
|
|
VOID MeRouteConfig (
|
|
VOID
|
|
);
|
|
VOID UpdateSubmenuStrings (
|
|
VOID
|
|
);
|
|
|
|
extern EFI_HII_DATABASE_PROTOCOL *gIfrLibHiiDatabase;
|
|
extern EFI_HII_STRING_PROTOCOL *gIfrLibHiiString;
|
|
|
|
#define EfiStrStr StrStr
|
|
#define GetSupportedLanguages HiiGetSupportedLanguages
|
|
|
|
//
|
|
// Limited buffer size recommended by RFC4646 (4.3. Length Considerations)
|
|
// (42 characters plus a NULL terminator)
|
|
//
|
|
#define RFC_3066_ENTRY_SIZE (42 + 1)
|
|
|
|
//
|
|
// CONTAINING_RECORD - returns a pointer to the structure
|
|
// from one of it's elements.
|
|
//
|
|
#define _CR(Record, TYPE, Field) ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))
|
|
|
|
//InitPciBusStrings, InitSioStrings, NatInitSioStrings, InitSioStrings_WPCN381U, InitCPUStrings, InitSaStrings, InitSBStrings, InitAcpiStrings, InitMeInfo, InitICCStrings, InitOverClockStrings, InitPlatformStrings, InitUSBStrings, InitBoardStrings,
|
|
|
|
//@todo Track down where this is used and correct this. Quick fix for now.
|
|
#ifdef __GNUC__
|
|
#pragma GCC diagnostic warning "-Wunused-variable"
|
|
#endif
|
|
static CHAR16* VarStoreVariableNameList[] = {
|
|
L"SystemAccess",
|
|
L"SetupVolatileData",
|
|
L"SetupCpuFeatures",
|
|
L"UsbMassDevNum",
|
|
L"UsbMassDevValid",
|
|
L"UsbControllerNum",
|
|
L"UsbSupport",
|
|
L"MeSetupStorage",
|
|
L"CpuSetupVolatileData",
|
|
L"TbtSetupVolatileData",
|
|
L"IccAdvancedSetupDataVar",
|
|
L"WheaSetup",
|
|
L"BootTime",
|
|
L"PNP0604_0_VV",
|
|
L"PNP0604_0_NV",
|
|
L"PNP0501_2_VV",
|
|
L"PNP0501_2_NV",
|
|
L"PNP0400_1_VV",
|
|
L"PNP0400_1_NV",
|
|
L"PNP0604_2_VV",
|
|
L"PNP0604_2_NV",
|
|
L"PNP0501_3_VV",
|
|
L"PNP0501_3_NV",
|
|
L"PNP0501_4_VV",
|
|
L"PNP0501_4_NV",
|
|
L"PNP0400_2_VV",
|
|
L"PNP0400_2_NV",
|
|
L"SerialPortsEnabledVar",
|
|
L"TcgSetup",
|
|
L"PasswordStatus",
|
|
L"DebugConfigData",
|
|
L"SetupMeFeatures",
|
|
L"SecureBoot",
|
|
L"TCG2_CONFIGURATION",
|
|
L"OsProfile",
|
|
L"Setup",
|
|
L"SiSetup",
|
|
L"SaSetup",
|
|
L"CpuSetup",
|
|
L"PchSetup",
|
|
L"MeSetup",
|
|
L"DebugSetupVolatileData",
|
|
NULL
|
|
};
|
|
|
|
EFI_HANDLE
|
|
GetCurrentHandle (
|
|
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *CurrentProtocol
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN NumberConfigAccessHandles;
|
|
EFI_HANDLE *ConfigAccessHandles;
|
|
UINTN Index;
|
|
EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
|
|
|
|
|
|
NumberConfigAccessHandles = 0;
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiHiiConfigAccessProtocolGuid,
|
|
NULL,
|
|
&NumberConfigAccessHandles,
|
|
&ConfigAccessHandles
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return NULL;
|
|
}
|
|
|
|
for (Index = 0; Index < NumberConfigAccessHandles; Index++) {
|
|
Status = gBS->HandleProtocol (
|
|
ConfigAccessHandles[Index],
|
|
&gEfiHiiConfigAccessProtocolGuid,
|
|
(VOID **) &ConfigAccess
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
if (ConfigAccess == CurrentProtocol) {
|
|
return ConfigAccessHandles[Index];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Determines if a Unicode character is a hexadecimal digit.
|
|
The test is case insensitive.
|
|
|
|
@param[out] Digit - Pointer to byte that receives the value of the hex character.
|
|
@param[in] Char - Unicode character to test.
|
|
|
|
@return TRUE - If the character is a hexadecimal digit.
|
|
@return FALSE - Otherwise.
|
|
|
|
**/
|
|
BOOLEAN
|
|
IsHexDigit (
|
|
OUT UINT8 *Digit,
|
|
IN CHAR16 Char
|
|
)
|
|
{
|
|
if ((Char >= L'0') && (Char <= L'9')) {
|
|
*Digit = (UINT8) (Char - L'0');
|
|
return TRUE;
|
|
}
|
|
|
|
if ((Char >= L'A') && (Char <= L'F')) {
|
|
*Digit = (UINT8) (Char - L'A' + 0x0A);
|
|
return TRUE;
|
|
}
|
|
|
|
if ((Char >= L'a') && (Char <= L'f')) {
|
|
*Digit = (UINT8) (Char - L'a' + 0x0A);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Converts Unicode string to binary buffer.
|
|
The conversion may be partial.
|
|
The first character in the string that is not hex digit stops the conversion.
|
|
At a minimum, any blob of data could be represented as a hex string.
|
|
|
|
@param[in, out] Buf - Pointer to buffer that receives the data.
|
|
@param[in, out] Len - Length in bytes of the buffer to hold converted data.
|
|
If routine return with EFI_SUCCESS, containing length of converted data.
|
|
If routine return with EFI_BUFFER_TOO_SMALL, containg length of buffer desired.
|
|
@param[in] Str - String to be converted from.
|
|
@param[out] ConvertedStrLen - Length of the Hex String consumed.
|
|
|
|
@return EFI_SUCCESS: Routine Success.
|
|
@return EFI_BUFFER_TOO_SMALL: The buffer is too small to hold converted data.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
HexStringToBuf (
|
|
IN OUT UINT8 *Buf,
|
|
IN OUT UINTN *Len,
|
|
IN CHAR16 *Str,
|
|
OUT UINTN *ConvertedStrLen OPTIONAL
|
|
)
|
|
{
|
|
UINTN HexCnt;
|
|
UINTN Idx;
|
|
UINTN BufferLength;
|
|
UINT8 Digit;
|
|
UINT8 Byte;
|
|
|
|
//
|
|
// Find out how many hex characters the string has.
|
|
//
|
|
for (Idx = 0, HexCnt = 0; IsHexDigit (&Digit, Str[Idx]); Idx++, HexCnt++);
|
|
|
|
if (HexCnt == 0) {
|
|
*Len = 0;
|
|
return EFI_SUCCESS;
|
|
}
|
|
//
|
|
// Two Unicode characters make up 1 buffer byte. Round up.
|
|
//
|
|
BufferLength = (HexCnt + 1) / 2;
|
|
|
|
//
|
|
// Test if buffer is passed enough.
|
|
//
|
|
if (BufferLength > (*Len)) {
|
|
*Len = BufferLength;
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
*Len = BufferLength;
|
|
|
|
for (Idx = 0; Idx < HexCnt; Idx++) {
|
|
|
|
IsHexDigit (&Digit, Str[HexCnt - 1 - Idx]);
|
|
|
|
//
|
|
// For odd charaters, write the lower nibble for each buffer byte,
|
|
// and for even characters, the upper nibble.
|
|
//
|
|
if ((Idx & 1) == 0) {
|
|
Byte = Digit;
|
|
} else {
|
|
Byte = Buf[Idx / 2];
|
|
Byte &= 0x0F;
|
|
Byte |= Digit << 4;
|
|
}
|
|
|
|
Buf[Idx / 2] = Byte;
|
|
}
|
|
|
|
if (ConvertedStrLen != NULL) {
|
|
*ConvertedStrLen = HexCnt;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Swap bytes in the buffer.
|
|
|
|
@param[in, out] Buffer - Binary buffer.
|
|
@param[in] BufferSize - Size of the buffer in bytes.
|
|
|
|
**/
|
|
STATIC
|
|
VOID
|
|
SwapBuffer (
|
|
IN OUT UINT8 *Buffer,
|
|
IN UINTN BufferSize
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINT8 Temp;
|
|
UINTN SwapCount;
|
|
|
|
SwapCount = BufferSize / 2;
|
|
for (Index = 0; Index < SwapCount; Index++) {
|
|
Temp = Buffer[Index];
|
|
Buffer[Index] = Buffer[BufferSize - 1 - Index];
|
|
Buffer[BufferSize - 1 - Index] = Temp;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Converts Hex String to binary buffer in reversed byte order from HexStringToBuf().
|
|
|
|
@param[in, out] Buffer - Pointer to buffer that receives the data.
|
|
@param[in, out] BufferSize - Length in bytes of the buffer to hold converted data.
|
|
If routine return with EFI_SUCCESS, containing length of converted data.
|
|
If routine return with EFI_BUFFER_TOO_SMALL, containg length of buffer desired.
|
|
@param[in] Str - String to be converted from.
|
|
|
|
@return EFI_SUCCESS - The function completed successfully.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
HexStringToBuffer (
|
|
IN OUT UINT8 *Buffer,
|
|
IN OUT UINTN *BufferSize,
|
|
IN CHAR16 *Str
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN ConvertedStrLen;
|
|
|
|
ConvertedStrLen = 0;
|
|
Status = HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen);
|
|
if (!EFI_ERROR (Status)) {
|
|
SwapBuffer (Buffer, (ConvertedStrLen + 1) / 2);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Convert binary representation Config string (e.g. "0041004200430044") to the
|
|
original string (e.g. "ABCD"). Config string appears in <ConfigHdr> (i.e.
|
|
"&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
|
|
|
|
@param[in, out] UnicodeString - Original Unicode string.
|
|
@param[in, out] StrBufferLen - On input: Length in bytes of buffer to hold the Unicode string.
|
|
Includes tailing '\0' character.
|
|
On output:
|
|
If return EFI_SUCCESS, containing length of Unicode string buffer.
|
|
If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
|
|
@param[in] ConfigString - Binary representation of Unicode String, <string> := (<HexCh>4)+
|
|
|
|
@return EFI_SUCCESS - Routine success.
|
|
@return EFI_BUFFER_TOO_SMALL - The string buffer is too small.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
ConfigStringToUnicode (
|
|
IN OUT CHAR16 *UnicodeString,
|
|
IN OUT UINTN *StrBufferLen,
|
|
IN CHAR16 *ConfigString
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINTN Len;
|
|
UINTN BufferSize;
|
|
CHAR16 BackupChar;
|
|
|
|
Len = StrLen (ConfigString) / 4;
|
|
BufferSize = (Len + 1) * sizeof (CHAR16);
|
|
|
|
if (*StrBufferLen < BufferSize) {
|
|
*StrBufferLen = BufferSize;
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
*StrBufferLen = BufferSize;
|
|
|
|
for (Index = 0; Index < Len; Index++) {
|
|
BackupChar = ConfigString[4];
|
|
ConfigString[4] = L'\0';
|
|
|
|
HexStringToBuf ((UINT8 *) UnicodeString, &BufferSize, ConfigString, NULL);
|
|
|
|
ConfigString[4] = BackupChar;
|
|
|
|
ConfigString += 4;
|
|
UnicodeString += 1;
|
|
}
|
|
|
|
//
|
|
// Add tailing '\0' character
|
|
//
|
|
*UnicodeString = L'\0';
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Converts the low nibble of a byte to hex unicode character.
|
|
|
|
@param[in] Nibble - lower nibble of a byte.
|
|
|
|
Hex unicode character.
|
|
|
|
**/
|
|
CHAR16
|
|
NibbleToHexChar (
|
|
IN UINT8 Nibble
|
|
)
|
|
{
|
|
Nibble &= 0x0F;
|
|
if (Nibble <= 0x9) {
|
|
return (CHAR16)(Nibble + L'0');
|
|
}
|
|
|
|
return (CHAR16)(Nibble - 0xA + L'A');
|
|
}
|
|
|
|
/**
|
|
Converts binary buffer to Unicode string.
|
|
At a minimum, any blob of data could be represented as a hex string.
|
|
|
|
@param[in, out] Str - Pointer to the string.
|
|
@param[in, out] HexStringBufferLength - Length in bytes of buffer to hold the hex string. Includes tailing '\0' character.
|
|
If routine return with EFI_SUCCESS, containing length of hex string buffer.
|
|
If routine return with EFI_BUFFER_TOO_SMALL, containg length of hex string buffer desired.
|
|
@param[in] Buf - Buffer to be converted from.
|
|
@param[in] Len - Length in bytes of the buffer to be converted.
|
|
|
|
@return EFI_SUCCESS: Routine success.
|
|
@return EFI_BUFFER_TOO_SMALL: The hex string buffer is too small.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
BufToHexString (
|
|
IN OUT CHAR16 *Str,
|
|
IN OUT UINTN *HexStringBufferLength,
|
|
IN UINT8 *Buf,
|
|
IN UINTN Len
|
|
)
|
|
{
|
|
UINTN Idx;
|
|
UINT8 Byte;
|
|
UINTN StrLen;
|
|
|
|
//
|
|
// Make sure string is either passed or allocate enough.
|
|
// It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer.
|
|
// Plus the Unicode termination character.
|
|
//
|
|
StrLen = Len * 2;
|
|
if (StrLen > ((*HexStringBufferLength) - 1)) {
|
|
*HexStringBufferLength = StrLen + 1;
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
*HexStringBufferLength = StrLen + 1;
|
|
//
|
|
// Ends the string.
|
|
//
|
|
Str[StrLen] = L'\0';
|
|
|
|
for (Idx = 0; Idx < Len; Idx++) {
|
|
|
|
Byte = Buf[Idx];
|
|
Str[StrLen - 1 - Idx * 2] = NibbleToHexChar (Byte);
|
|
Str[StrLen - 2 - Idx * 2] = NibbleToHexChar ((UINT8)(Byte >> 4));
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
BOOLEAN
|
|
IsVariableNameInSupportedList (
|
|
IN CHAR16 *VariableName
|
|
)
|
|
{
|
|
UINTN Index;
|
|
|
|
if (VariableName == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
for (Index = 0; VarStoreVariableNameList[Index] != NULL; Index ++) {
|
|
if (StrCmp (VarStoreVariableNameList[Index], VariableName) == 0) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ExtractGuidNameFromConfigHdr (
|
|
IN CONST EFI_STRING ConfigHdr,
|
|
OUT EFI_GUID *Guid,
|
|
OUT CHAR16 **Name,
|
|
OUT UINTN *Offset
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
CHAR16 *StrPtr;
|
|
UINTN Length;
|
|
CHAR16 *StrName;
|
|
|
|
*Offset = 0;
|
|
//
|
|
// <ConfigHdr> ::=
|
|
// GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
|
|
// | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
|
|
//
|
|
if (StrLen (ConfigHdr) <= (5 + 32 + 6)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// check syntax for guid
|
|
//
|
|
StrPtr = ConfigHdr + 5 + 32;
|
|
if (*StrPtr != L'&') {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
*StrPtr = L'\0';
|
|
|
|
//
|
|
// extract guid
|
|
//
|
|
Length = sizeof (EFI_GUID);
|
|
Status = HexStringToBuffer (
|
|
(UINT8 *) Guid,
|
|
&Length,
|
|
ConfigHdr + 5
|
|
);
|
|
*StrPtr = L'&';
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "HII Config Access: Guid extraction failed\n"));
|
|
*Offset = 5;
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// check syntax for name
|
|
//
|
|
StrPtr = ConfigHdr + 5 + 32 + 6;
|
|
while (*StrPtr != L'\0' && *StrPtr != L'&') {
|
|
StrPtr++;
|
|
}
|
|
if (*StrPtr != L'&') {
|
|
*Offset = 5 + 32 + 6;
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// extract name
|
|
//
|
|
*StrPtr = L'\0';
|
|
Length = StrSize (ConfigHdr + 5 + 32 + 6);
|
|
StrName = AllocatePool (Length);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
Status = ConfigStringToUnicode (
|
|
StrName,
|
|
&Length,
|
|
ConfigHdr + 5 + 32 + 6
|
|
);
|
|
*StrPtr = L'&';
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "HII Config Access: Name extraction failed\n"));
|
|
*Offset = 5 + 32 + 6;
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!IsVariableNameInSupportedList (StrName)) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
*Name = StrName;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Create altcfg string.
|
|
|
|
@param Result The request result string.
|
|
@param ConfigHdr The request head info. <ConfigHdr> format.
|
|
@param ConfigPatchTable The ConfigPatchTable.
|
|
@param ConfigPatchTableSize The TableSize of ConfigPatchTable
|
|
|
|
@return EFI_SUCCESS: Routine success.
|
|
**/
|
|
EFI_STRING
|
|
CreateAltCfgString (
|
|
IN EFI_STRING Result,
|
|
IN EFI_STRING ConfigHdr,
|
|
IN CONFIG_PATCH_TABLE *ConfigPatchTable,
|
|
IN UINTN ConfigPatchTableSize
|
|
)
|
|
{
|
|
EFI_STRING StringPtr;
|
|
EFI_STRING TmpStr;
|
|
UINTN NewLen;
|
|
UINTN TableIndex;
|
|
|
|
NewLen = StrnLenS (Result, MAX_UINT32);
|
|
DEBUG ((DEBUG_INFO, "HiiConfigAccess: In CreateAltCfgString\n"));
|
|
|
|
//
|
|
// String Len = (ConfigResp + (AltConfig * TableSize))*2 + 1("\0")
|
|
//
|
|
NewLen = (NewLen + ((1 + StrLen (ConfigHdr) + 8 + 4) + (8 + 4 + 7 + 4 + 7 + 16) * ConfigPatchTableSize) * 2 + 1) * sizeof (CHAR16);
|
|
StringPtr = AllocateZeroPool (NewLen);
|
|
if (StringPtr == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
TmpStr = StringPtr;
|
|
if (Result != NULL) {
|
|
StrCpyS (StringPtr, NewLen / sizeof (CHAR16), Result);
|
|
StringPtr += StrLen (Result);
|
|
FreePool (Result);
|
|
}
|
|
|
|
UnicodeSPrint (
|
|
StringPtr,
|
|
(1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
|
|
L"&%s&ALTCFG=%04x",
|
|
ConfigHdr,
|
|
EFI_HII_DEFAULT_CLASS_STANDARD
|
|
);
|
|
StringPtr += StrLen (StringPtr);
|
|
|
|
DEBUG ((EFI_D_INFO, "Patch Begin\n"));
|
|
for (TableIndex = 0; TableIndex < ConfigPatchTableSize; TableIndex++) {
|
|
DEBUG ((EFI_D_INFO, "&OFFSET=%04x&WIDTH=%04x&VALUE=%l016x\n", ConfigPatchTable[TableIndex].Offset, ConfigPatchTable[TableIndex].Size, ConfigPatchTable[TableIndex].Data));
|
|
UnicodeSPrint (
|
|
StringPtr,
|
|
(8 + 4 + 7 + 4 + 7 + 16 + 1) * sizeof (CHAR16),
|
|
L"&OFFSET=%04x&WIDTH=%04x&VALUE=%l016x",
|
|
ConfigPatchTable[TableIndex].Offset,
|
|
ConfigPatchTable[TableIndex].Size,
|
|
ConfigPatchTable[TableIndex].Data
|
|
);
|
|
StringPtr += StrLen (StringPtr);
|
|
}
|
|
DEBUG ((EFI_D_INFO, "Patch End\n"));
|
|
|
|
UnicodeSPrint (
|
|
StringPtr,
|
|
(1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
|
|
L"&%s&ALTCFG=%04x",
|
|
ConfigHdr,
|
|
EFI_HII_DEFAULT_CLASS_MANUFACTURING
|
|
);
|
|
StringPtr += StrLen (StringPtr);
|
|
|
|
for (TableIndex = 0; TableIndex < ConfigPatchTableSize ; TableIndex++) {
|
|
UnicodeSPrint (
|
|
StringPtr,
|
|
(8 + 4 + 7 + 4 + 7 + 16 + 1) * sizeof (CHAR16),
|
|
L"&OFFSET=%04x&WIDTH=%04x&VALUE=%l016x",
|
|
ConfigPatchTable[TableIndex].Offset,
|
|
ConfigPatchTable[TableIndex].Size,
|
|
ConfigPatchTable[TableIndex].Data
|
|
);
|
|
StringPtr += StrLen (StringPtr);
|
|
}
|
|
return TmpStr;
|
|
}
|
|
|
|
/**
|
|
Check whether need to add the altcfg string. if need to add, add the altcfg
|
|
string.
|
|
|
|
@param[in, out] RequestResult The request result string.
|
|
@param[in] Name Setup Variable Name
|
|
@param[in] DriverHandle Current driver handle.
|
|
|
|
@return EFI_SUCCESS Routine success.
|
|
@retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
|
|
@retval EFI_INVALID_PARAMETER DriverHandle is NULL.
|
|
**/
|
|
EFI_STATUS
|
|
AppendAltCfgString (
|
|
IN OUT EFI_STRING *RequestResult,
|
|
IN CHAR16 *Name,
|
|
IN EFI_HANDLE DriverHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_STRING ConfigRequest;
|
|
CONFIG_PATCH_TABLE *ConfigPatchTableTemp;
|
|
UINTN ConfigPatchTableSize;
|
|
|
|
Status = EFI_SUCCESS;
|
|
ConfigRequest = NULL;
|
|
|
|
if (DriverHandle == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (StrnCmp (L"Setup", Name, StrLen (Name)) == 0) {
|
|
ConfigPatchTableSize = (UINTN) PcdGet64 (PcdSetupConfigPatchTableSize);
|
|
if (ConfigPatchTableSize) {
|
|
DEBUG ((EFI_D_INFO, "AppendAltCfgString : PcdSetupConfigPatchTableSize %d\n", ConfigPatchTableSize));
|
|
|
|
ConfigPatchTableTemp = (CONFIG_PATCH_TABLE *) (UINT64) PcdGet64 (PcdSetupConfigPatchTable);
|
|
ConfigRequest = HiiConstructConfigHdr (&gSetupVariableGuid, L"Setup", DriverHandle);
|
|
if (ConfigRequest == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
*RequestResult = CreateAltCfgString (*RequestResult, ConfigRequest, ConfigPatchTableTemp, ConfigPatchTableSize);
|
|
}
|
|
} else if (StrnCmp (L"SaSetup", Name, StrLen (Name)) == 0) {
|
|
ConfigPatchTableSize = (UINTN) PcdGet64 (PcdSaSetupConfigPatchTableSize);
|
|
if (ConfigPatchTableSize) {
|
|
DEBUG ((EFI_D_INFO, "AppendAltCfgString : PcdSaSetupConfigPatchTableSize %d\n", ConfigPatchTableSize));
|
|
|
|
ConfigPatchTableTemp = (CONFIG_PATCH_TABLE *) (UINT64) PcdGet64 (PcdSaSetupConfigPatchTable);
|
|
ConfigRequest = HiiConstructConfigHdr (&gSaSetupVariableGuid, L"SaSetup", DriverHandle);
|
|
if (ConfigRequest == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
*RequestResult = CreateAltCfgString (*RequestResult, ConfigRequest, ConfigPatchTableTemp, ConfigPatchTableSize);
|
|
}
|
|
} else if (StrnCmp (L"CpuSetup", Name, StrLen (Name)) == 0) {
|
|
ConfigPatchTableSize = (UINTN) PcdGet64 (PcdCpuSetupConfigPatchTableSize);
|
|
if (ConfigPatchTableSize) {
|
|
DEBUG ((EFI_D_INFO, "AppendAltCfgString : PcdCpuSetupConfigPatchTableSize %d\n", ConfigPatchTableSize));
|
|
|
|
ConfigPatchTableTemp = (CONFIG_PATCH_TABLE *) (UINT64) PcdGet64 (PcdCpuSetupConfigPatchTable);
|
|
ConfigRequest = HiiConstructConfigHdr (&gCpuSetupVariableGuid, L"CpuSetup", DriverHandle);
|
|
if (ConfigRequest == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
*RequestResult = CreateAltCfgString (*RequestResult, ConfigRequest, ConfigPatchTableTemp, ConfigPatchTableSize);
|
|
}
|
|
} else if (StrnCmp (L"PchSetup", Name, StrLen (Name)) == 0) {
|
|
ConfigPatchTableSize = (UINTN) PcdGet64 (PcdPchSetupConfigPatchTableSize);
|
|
if (ConfigPatchTableSize) {
|
|
DEBUG ((EFI_D_INFO, "AppendAltCfgString : PcdPchSetupConfigPatchTableSize %d\n", ConfigPatchTableSize));
|
|
|
|
ConfigPatchTableTemp = (CONFIG_PATCH_TABLE *) (UINT64) PcdGet64 (PcdPchSetupConfigPatchTable);
|
|
ConfigRequest = HiiConstructConfigHdr (&gPchSetupVariableGuid, L"PchSetup", DriverHandle);
|
|
if (ConfigRequest == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
*RequestResult = CreateAltCfgString (*RequestResult, ConfigRequest, ConfigPatchTableTemp, ConfigPatchTableSize);
|
|
}
|
|
} else if (StrnCmp (L"MeSetup", Name, StrLen (Name)) == 0) {
|
|
ConfigPatchTableSize = (UINTN) PcdGet64 (PcdMeSetupConfigPatchTableSize);
|
|
if (ConfigPatchTableSize) {
|
|
DEBUG ((EFI_D_INFO, "AppendAltCfgString : PcdMeSetupConfigPatchTableSize %d\n", ConfigPatchTableSize));
|
|
|
|
ConfigPatchTableTemp = (CONFIG_PATCH_TABLE *) (UINT64) PcdGet64 (PcdMeSetupConfigPatchTable);
|
|
ConfigRequest = HiiConstructConfigHdr (&gMeSetupVariableGuid, L"MeSetup", DriverHandle);
|
|
if (ConfigRequest == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
*RequestResult = CreateAltCfgString (*RequestResult, ConfigRequest, ConfigPatchTableTemp, ConfigPatchTableSize);
|
|
}
|
|
}
|
|
|
|
if (ConfigRequest != NULL) {
|
|
FreePool (ConfigRequest);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
HiiAccessExtractConfig (
|
|
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
|
|
IN CONST EFI_STRING Request,
|
|
OUT EFI_STRING *Progress,
|
|
OUT EFI_STRING *Results
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_STATUS Status2;
|
|
UINTN Length;
|
|
EFI_GUID Guid;
|
|
CHAR16 *Name;
|
|
UINT8 *Var;
|
|
UINTN Offset;
|
|
EFI_HANDLE DriverHandle;
|
|
EFI_HII_HANDLE HiiHandle;
|
|
EFI_STRING StringPtr;
|
|
UINTN HexStringBufferLen;
|
|
EFI_STRING ConfigRequest;
|
|
BOOLEAN AllocatedRequest;
|
|
UINTN MaxLen;
|
|
UINTN NameLength;
|
|
UINTN DevicePathSize;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
EFI_HANDLE CurrentHandle;
|
|
|
|
if (Progress == NULL || Results == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
CurrentHandle = NULL;
|
|
ConfigRequest = Request;
|
|
*Progress = Request;
|
|
AllocatedRequest = FALSE;
|
|
|
|
if (ConfigRequest == NULL) {
|
|
HiiHandle = _CR (This, CALLBACK_INFO, pFormCallback)->HiiHandle;
|
|
if (NULL == gIfrLibHiiDatabase) {
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiHiiDatabaseProtocolGuid,
|
|
NULL,
|
|
(VOID **) &gIfrLibHiiDatabase
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
}
|
|
Status = gIfrLibHiiDatabase->GetPackageListHandle(gIfrLibHiiDatabase, HiiHandle, &DriverHandle);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
CopyMem (&Guid, &gSetupVariableGuid, sizeof (gSetupVariableGuid));
|
|
Length = StrSize (PLATFORM_SETUP_VARSTORE_NAME);
|
|
Name = AllocatePool (Length);
|
|
if (Name == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
StrCpyS (Name, Length / sizeof (CHAR16), PLATFORM_SETUP_VARSTORE_NAME);
|
|
|
|
//
|
|
// Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..."
|
|
//
|
|
ConfigRequest = HiiConstructConfigHdr (&Guid, Name, DriverHandle);
|
|
ASSERT (ConfigRequest != NULL);
|
|
if (ConfigRequest == NULL) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
//
|
|
// Followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
|
|
//
|
|
NameLength = StrLen (Name);
|
|
DevicePath = DevicePathFromHandle (DriverHandle);
|
|
DevicePathSize = GetDevicePathSize (DevicePath);
|
|
MaxLen = 5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1;
|
|
|
|
StringPtr = ConfigRequest + StrLen (ConfigRequest);
|
|
MaxLen = MaxLen - StrLen (ConfigRequest);
|
|
StrCpyS (StringPtr, MaxLen, L"&OFFSET=0");
|
|
StringPtr += 9;
|
|
MaxLen -= 9;
|
|
StrCpyS (StringPtr, MaxLen, L"&WIDTH=");
|
|
StringPtr += 7;
|
|
Length = sizeof (SETUP_DATA);
|
|
HexStringBufferLen = 17;
|
|
BufToHexString (StringPtr, &HexStringBufferLen, (UINT8 *) &Length, sizeof (Length));
|
|
AllocatedRequest = TRUE;
|
|
} else {
|
|
Status = ExtractGuidNameFromConfigHdr (ConfigRequest, &Guid, &Name, &Offset);
|
|
if (EFI_ERROR (Status)) {
|
|
*Progress = ConfigRequest + Offset;
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Check whether Request includes Request Element.
|
|
//
|
|
if (EfiStrStr (ConfigRequest, L"OFFSET") == NULL) {
|
|
//
|
|
// Check Request Element does exist in Reques String
|
|
//
|
|
StringPtr = EfiStrStr (ConfigRequest, L"PATH");
|
|
if (StringPtr == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
if (EfiStrStr (StringPtr, L"&") == NULL) {
|
|
Length = (StrLen (ConfigRequest) + 32 + 1) * sizeof (CHAR16);
|
|
ConfigRequest = AllocatePool (Length);
|
|
if (ConfigRequest == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
|
|
//
|
|
Length = Length / sizeof (CHAR16);
|
|
StrCpyS (ConfigRequest, Length, Request);
|
|
StringPtr = ConfigRequest + StrLen (ConfigRequest);
|
|
Length -= StrLen (ConfigRequest);
|
|
StrCpyS (StringPtr, Length, L"&OFFSET=0");
|
|
StringPtr += 9;
|
|
Length -= 9;
|
|
StrCpyS (StringPtr, Length, L"&WIDTH=");
|
|
StringPtr += 7;
|
|
|
|
if (StrCmp (L"SaSetup", Name) == 0) {
|
|
Length = sizeof (SA_SETUP);
|
|
} else if (StrCmp (L"PchSetup", Name) == 0) {
|
|
Length = sizeof (PCH_SETUP);
|
|
} else if (StrCmp (L"CpuSetup", Name) == 0) {
|
|
Length = sizeof (CPU_SETUP);
|
|
} else if (StrCmp (L"MeSetup", Name) == 0) {
|
|
Length = sizeof (ME_SETUP);
|
|
} else if (StrCmp (L"Setup", Name) == 0) {
|
|
Length = sizeof (SETUP_DATA);
|
|
}
|
|
HexStringBufferLen = 17;
|
|
BufToHexString (StringPtr, &HexStringBufferLen, (UINT8 *) &Length, sizeof (Length));
|
|
AllocatedRequest = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (StrCmp (L"IccAdvancedSetupDataVar", Name) == 0) {
|
|
IccExtractConfig();
|
|
}
|
|
if (StrCmp (L"MeSetupStorage", Name) == 0) {
|
|
MeExtractConfig();
|
|
}
|
|
if (StrCmp (L"Setup", Name) == 0) {
|
|
UpdateSubmenuStrings ();
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "Extract value from Storage %s\n", Name));
|
|
|
|
//
|
|
// get variable by name and guid from nvram
|
|
//
|
|
Length = 0;
|
|
Var = NULL;
|
|
Status = gRT->GetVariable (Name, &Guid, NULL, &Length, Var);
|
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
Var = AllocateZeroPool (Length);
|
|
ASSERT (Var != NULL);
|
|
Status = gRT->GetVariable (Name, &Guid, NULL, &Length, Var);
|
|
}
|
|
if (EFI_ERROR (Status)) {
|
|
if (AllocatedRequest) {
|
|
FreePool (ConfigRequest);
|
|
}
|
|
if (Var != NULL) {
|
|
FreePool (Var);
|
|
}
|
|
*Progress = Request;
|
|
FreePool (Name);
|
|
return Status;
|
|
}
|
|
|
|
Status = mConfigRouting->BlockToConfig (mConfigRouting, ConfigRequest, Var, Length, Results, Progress);
|
|
CurrentHandle = GetCurrentHandle (This);
|
|
if (CurrentHandle == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
Status2 = AppendAltCfgString (Results, Name, CurrentHandle);
|
|
|
|
FreePool (Name);
|
|
FreePool (Var);
|
|
|
|
if (AllocatedRequest) {
|
|
FreePool (ConfigRequest);
|
|
//
|
|
// Set Progress string to the original request string.
|
|
//
|
|
if (Request == NULL) {
|
|
*Progress = NULL;
|
|
} else {
|
|
*Progress = Request + StrLen (Request);
|
|
}
|
|
}
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
} else if (EFI_ERROR (Status2)) {
|
|
return Status2;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
HiiAccessRouteConfig (
|
|
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
|
|
IN CONST EFI_STRING Configuration,
|
|
OUT EFI_STRING *Progress
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Length;
|
|
UINTN VarSize;
|
|
UINTN Offset;
|
|
EFI_GUID Guid;
|
|
CHAR16 *Name;
|
|
UINT8 *Var;
|
|
EFI_HANDLE Handle;
|
|
UINT32 Attributes;
|
|
|
|
if (Progress == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
*Progress = Configuration;
|
|
|
|
if (Configuration == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS;
|
|
|
|
Status = ExtractGuidNameFromConfigHdr (Configuration, &Guid, &Name, &Offset);
|
|
if (EFI_ERROR (Status)) {
|
|
*Progress = Configuration + Offset;
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// get variable by name and guid from nvram
|
|
//
|
|
Var = NULL;
|
|
Length = 0;
|
|
Status = gRT->GetVariable (Name, &Guid, &Attributes, &Length, Var);
|
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
Var = AllocateZeroPool (Length);
|
|
if (Var == NULL) {
|
|
ASSERT (FALSE);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
Status = gRT->GetVariable (Name, &Guid, &Attributes, &Length, Var);
|
|
}
|
|
if (EFI_ERROR (Status)) {
|
|
//
|
|
// requested variable not found
|
|
//
|
|
if (Var != NULL) {
|
|
FreePool (Var);
|
|
}
|
|
Var = NULL;
|
|
Length = 0;
|
|
Status = mConfigRouting->ConfigToBlock (mConfigRouting, Configuration, Var, &Length, Progress);
|
|
if (Status == EFI_INVALID_PARAMETER) {
|
|
Var = AllocateZeroPool (Length);
|
|
if (Var == NULL) {
|
|
ASSERT (FALSE);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
} else {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
VarSize = Length;
|
|
Status = mConfigRouting->ConfigToBlock (mConfigRouting, Configuration, Var, &Length, Progress);
|
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
//
|
|
// block not large enough
|
|
//
|
|
if (Var != NULL) {
|
|
FreePool (Var);
|
|
}
|
|
|
|
VarSize = Length;
|
|
Var = AllocateZeroPool (Length);
|
|
if (Var == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
Status = mConfigRouting->ConfigToBlock (mConfigRouting, Configuration, Var, &Length, Progress);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
FreePool (Var);
|
|
return Status;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "Route value for Storage %s\n", Name));
|
|
|
|
gRT->SetVariable (
|
|
Name,
|
|
&Guid,
|
|
Attributes,
|
|
VarSize,
|
|
Var
|
|
);
|
|
|
|
if (StrCmp (L"IccAdvancedSetupDataVar", Name) == 0) {
|
|
IccRouteConfig();
|
|
}
|
|
|
|
if (StrCmp (L"MeSetupStorage", Name) == 0) {
|
|
MeRouteConfig();
|
|
}
|
|
|
|
FreePool (Var);
|
|
|
|
//
|
|
// Trigger gSetupNvramUpdateGuid event when save value on UI.
|
|
// The code is in Greens Glacier SetupBrowser driver but as we are using Tiano SetupBrowser driver, move
|
|
// the code here.
|
|
//
|
|
Handle = NULL;
|
|
Status = gBS->InstallProtocolInterface (
|
|
&Handle,
|
|
&gSetupNvramUpdateGuid,
|
|
EFI_NATIVE_INTERFACE,
|
|
NULL
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = gBS->UninstallProtocolInterface (
|
|
Handle,
|
|
&gSetupNvramUpdateGuid,
|
|
NULL
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
HiiAccessFormCallback (
|
|
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
|
|
IN EFI_BROWSER_ACTION Action,
|
|
IN EFI_QUESTION_ID QuestionId,
|
|
IN UINT8 Type,
|
|
IN EFI_IFR_TYPE_VALUE *Value,
|
|
OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
|
|
)
|
|
{
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
EFI_HII_CONFIG_ACCESS_PROTOCOL DefaultConfigAccess = {
|
|
HiiAccessExtractConfig,
|
|
HiiAccessRouteConfig,
|
|
HiiAccessFormCallback
|
|
};
|
|
|
|
VOID
|
|
EFIAPI
|
|
UpdateCallBack (
|
|
CALLBACK_INFO *pCallBackFound
|
|
)
|
|
{
|
|
if (pCallBackFound->pFormCallback != NULL) {
|
|
if (pCallBackFound->pFormCallback->ExtractConfig == NULL) {
|
|
pCallBackFound->pFormCallback->ExtractConfig = HiiAccessExtractConfig;
|
|
}
|
|
if (pCallBackFound->pFormCallback->RouteConfig == NULL) {
|
|
pCallBackFound->pFormCallback->RouteConfig = HiiAccessRouteConfig;
|
|
}
|
|
if (pCallBackFound->pFormCallback->Callback == NULL) {
|
|
pCallBackFound->pFormCallback->Callback = HiiAccessFormCallback;
|
|
}
|
|
} else {
|
|
pCallBackFound->pFormCallback = &DefaultConfigAccess;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Returns a pointer to an allocated buffer that contains the best matching language
|
|
from a set of supported languages.
|
|
|
|
This function supports both ISO 639-2 and RFC 4646 language codes, but language
|
|
code types may not be mixed in a single call to this function. The language
|
|
code returned is allocated using AllocatePool(). The caller is responsible for
|
|
freeing the allocated buffer using FreePool(). This function supports a variable
|
|
argument list that allows the caller to pass in a prioritized list of language
|
|
codes to test against all the language codes in SupportedLanguages.
|
|
|
|
If SupportedLanguages is NULL, then ASSERT()..
|
|
|
|
@param[in] SupportedLanguages - A pointer to a Null-terminated ASCII string that
|
|
contains a set of language codes in the format
|
|
specified by Iso639Language.
|
|
@param[in] Iso639Language - If TRUE, then all language codes are assumed to be
|
|
in ISO 639-2 format. If FALSE, then all language
|
|
codes are assumed to be in RFC 4646 language format.
|
|
... - A variable argument list that contains pointers to
|
|
Null-terminated ASCII strings that contain one or more
|
|
language codes in the format specified by Iso639Language.
|
|
The first language code from each of these language
|
|
code lists is used to determine if it is an exact or
|
|
close match to any of the language codes in
|
|
SupportedLanguages. Close matches only apply to RFC 4646
|
|
language codes, and the matching algorithm from RFC 4647
|
|
is used to determine if a close match is present. If
|
|
an exact or close match is found, then the matching
|
|
language code from SupportedLanguages is returned. If
|
|
no matches are found, then the next variable argument
|
|
parameter is evaluated. The variable argument list
|
|
is terminated by a NULL
|
|
|
|
@return NULL - The best matching language could not be found in SupportedLanguages.
|
|
@return NULL - There are not enough resources available to return the best matching
|
|
language.
|
|
@return Other - A pointer to a Null-terminated ASCII string that is the best matching
|
|
language in SupportedLanguages.
|
|
|
|
**/
|
|
CHAR8 *
|
|
EFIAPI
|
|
HiiLibGetBestLanguage (
|
|
IN CHAR8 *SupportedLanguages,
|
|
IN BOOLEAN Iso639Language,
|
|
...
|
|
)
|
|
{
|
|
VA_LIST Args;
|
|
CHAR8 *Language;
|
|
UINTN CompareLength;
|
|
UINTN LanguageLength;
|
|
CHAR8 *Supported;
|
|
CHAR8 *BestLanguage;
|
|
|
|
ASSERT (SupportedLanguages != NULL);
|
|
if (SupportedLanguages == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
VA_START (Args, Iso639Language);
|
|
while ((Language = VA_ARG (Args, CHAR8 *)) != NULL) {
|
|
//
|
|
// Default to ISO 639-2 mode
|
|
//
|
|
CompareLength = 3;
|
|
LanguageLength = AsciiStrLen (Language);
|
|
if (LanguageLength > 3) {
|
|
LanguageLength = 3;
|
|
}
|
|
|
|
//
|
|
// If in RFC 4646 mode, then determine the length of the first RFC 4646 language code in Language
|
|
//
|
|
if (!Iso639Language) {
|
|
for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++);
|
|
}
|
|
|
|
//
|
|
// Trim back the length of Language used until it is empty
|
|
//
|
|
while (LanguageLength > 0) {
|
|
//
|
|
// Loop through all language codes in SupportedLanguages
|
|
//
|
|
for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) {
|
|
//
|
|
// In RFC 4646 mode, then Loop through all language codes in SupportedLanguages
|
|
//
|
|
if (!Iso639Language) {
|
|
//
|
|
// Skip ';' characters in Supported
|
|
//
|
|
for (; *Supported != '\0' && *Supported == ';'; Supported++);
|
|
//
|
|
// Determine the length of the next language code in Supported
|
|
//
|
|
for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++);
|
|
//
|
|
// If Language is longer than the Supported, then skip to the next language
|
|
//
|
|
if (LanguageLength > CompareLength) {
|
|
continue;
|
|
}
|
|
}
|
|
//
|
|
// See if the first LanguageLength characters in Supported match Language
|
|
//
|
|
if (AsciiStrnCmp (Supported, Language, LanguageLength) == 0) {
|
|
VA_END (Args);
|
|
//
|
|
// Allocate, copy, and return the best matching language code from SupportedLanguages
|
|
//
|
|
BestLanguage = AllocateZeroPool (CompareLength + 1);
|
|
if (BestLanguage == NULL) {
|
|
return NULL;
|
|
}
|
|
CopyMem (BestLanguage, Supported, CompareLength);
|
|
return BestLanguage;
|
|
}
|
|
}
|
|
|
|
if (Iso639Language) {
|
|
//
|
|
// If ISO 639 mode, then each language can only be tested once
|
|
//
|
|
LanguageLength = 0;
|
|
} else {
|
|
//
|
|
// If RFC 4646 mode, then trim Language from the right to the next '-' character
|
|
//
|
|
for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--);
|
|
}
|
|
}
|
|
}
|
|
VA_END (Args);
|
|
|
|
//
|
|
// No matches were found
|
|
//
|
|
return NULL;
|
|
}
|
|
|
|
EFI_STATUS
|
|
HiiLibGetString (
|
|
IN EFI_HII_HANDLE PackageList,
|
|
IN EFI_STRING_ID StringId,
|
|
OUT EFI_STRING String,
|
|
IN OUT UINTN *StringSize
|
|
)
|
|
{
|
|
CHAR8 PlatformLanguage[RFC_3066_ENTRY_SIZE];
|
|
CHAR8 *SupportedLanguages;
|
|
CHAR8 *BestLanguage;
|
|
UINTN Size;
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Get current language setting
|
|
//
|
|
Size = sizeof (PlatformLanguage);
|
|
Status = gRT->GetVariable (
|
|
L"PlatformLang",
|
|
&gEfiGlobalVariableGuid,
|
|
NULL,
|
|
&Size,
|
|
PlatformLanguage
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
AsciiStrCpyS (PlatformLanguage, sizeof (PlatformLanguage) / sizeof (CHAR8), (CHAR8 *) "en-US");
|
|
}
|
|
|
|
SupportedLanguages = GetSupportedLanguages (PackageList);
|
|
if (SupportedLanguages == NULL) {
|
|
//
|
|
// No supported language.
|
|
//
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Get the best matching language from SupportedLanguages
|
|
//
|
|
BestLanguage = HiiLibGetBestLanguage (
|
|
SupportedLanguages,
|
|
FALSE, // RFC 4646 mode
|
|
PlatformLanguage, // Highest priority
|
|
SupportedLanguages, // Lowest priority
|
|
NULL
|
|
);
|
|
|
|
if (NULL == gIfrLibHiiString) {
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiHiiStringProtocolGuid,
|
|
NULL,
|
|
(VOID **) &gIfrLibHiiString
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
Status = gIfrLibHiiString->GetString (
|
|
gIfrLibHiiString,
|
|
BestLanguage,
|
|
PackageList,
|
|
StringId,
|
|
String,
|
|
StringSize,
|
|
NULL
|
|
);
|
|
|
|
FreePool (SupportedLanguages);
|
|
FreePool (BestLanguage);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Construct Request String (L"&OFFSET=%x&WIDTH=%x") base on the input Offset and Width.
|
|
If the input RequestString is not NULL, new request will be cat at the end of it. The full
|
|
request string will be constructed and return. Caller is responsible to free it.
|
|
|
|
@param[in] RequestString Current request string.
|
|
@param[in] Offset Offset of data in Storage.
|
|
@param[in] Width Width of data.
|
|
|
|
@return String Request string with input Offset and Width.
|
|
**/
|
|
EFI_STRING
|
|
EFIAPI
|
|
HiiConstructRequestString (
|
|
IN EFI_STRING RequestString, OPTIONAL
|
|
IN UINTN Offset,
|
|
IN UINTN Width
|
|
)
|
|
{
|
|
CHAR16 RequestElement[30];
|
|
UINTN StringLength;
|
|
EFI_STRING NewString;
|
|
|
|
StringLength = UnicodeSPrint (
|
|
RequestElement,
|
|
sizeof (RequestElement),
|
|
L"&OFFSET=%x&WIDTH=%x",
|
|
Offset,
|
|
Width
|
|
);
|
|
if (RequestString != NULL) {
|
|
StringLength = StringLength + StrLen (RequestString);
|
|
}
|
|
NewString = AllocateZeroPool ((StringLength + 1) * sizeof (CHAR16));
|
|
if (NewString == NULL) {
|
|
return NULL;
|
|
}
|
|
if (RequestString != NULL) {
|
|
StrCatS (NewString, ((StringLength + 1) * sizeof (CHAR16)) / sizeof (CHAR16), RequestString);
|
|
FreePool (RequestString);
|
|
}
|
|
StrCatS (NewString, ((StringLength + 1) * sizeof (CHAR16)) / sizeof (CHAR16), RequestElement);
|
|
return NewString;
|
|
}
|