summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c
diff options
context:
space:
mode:
authorkx <kx@radix.pro>2024-06-04 06:43:08 +0300
committerkx <kx@radix.pro>2024-06-04 06:43:08 +0300
commit7e2ccccace24636f29ddc210b94606abd4c7e42b (patch)
tree545d43ea12671048956cafeb12303e84d601e571 /MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c
parent27b044605cd5f6b33a3d231576003850b3fe305b (diff)
downloadedk2-trunk.tar.xz
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c')
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c6840
1 files changed, 3420 insertions, 3420 deletions
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c
index 6e791783a6..1a06c18f23 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c
@@ -1,3420 +1,3420 @@
-/** @file
-Implementation of interfaces function for EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL.
-
-Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "HiiDatabase.h"
-
-extern HII_DATABASE_PRIVATE_DATA mPrivate;
-
-/**
- Convert the hex UNICODE %02x encoding of a UEFI device path to binary
- from <PathHdr> of <MultiKeywordRequest>.
-
- This is a internal function.
-
- @param String MultiKeywordRequest string.
- @param DevicePathData Binary of a UEFI device path.
- @param NextString string follow the possible PathHdr string.
-
- @retval EFI_INVALID_PARAMETER The device path is not valid or the incoming parameter is invalid.
- @retval EFI_OUT_OF_RESOURCES Lake of resources to store necessary structures.
- @retval EFI_SUCCESS The device path is retrieved and translated to binary format.
- The Input string not include PathHdr section.
-
-**/
-EFI_STATUS
-ExtractDevicePath (
- IN EFI_STRING String,
- OUT UINT8 **DevicePathData,
- OUT EFI_STRING *NextString
- )
-{
- UINTN Length;
- EFI_STRING PathHdr;
- UINT8 *DevicePathBuffer;
- CHAR16 TemStr[2];
- UINTN Index;
- UINT8 DigitUint8;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
-
- ASSERT (NextString != NULL && DevicePathData != NULL);
-
- //
- // KeywordRequest == NULL case.
- //
- if (String == NULL) {
- *DevicePathData = NULL;
- *NextString = NULL;
- return EFI_SUCCESS;
- }
-
- //
- // Skip '&' if exist.
- //
- if (*String == L'&') {
- String++;
- }
-
- //
- // Find the 'PATH=' of <PathHdr>.
- //
- if (StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0) {
- if (StrnCmp (String, L"KEYWORD=", StrLen (L"KEYWORD=")) != 0) {
- return EFI_INVALID_PARAMETER;
- } else {
- //
- // Not include PathHdr, return success and DevicePath = NULL.
- //
- *DevicePathData = NULL;
- *NextString = String;
- return EFI_SUCCESS;
- }
- }
-
- //
- // Check whether path data does exist.
- //
- String += StrLen (L"PATH=");
- if (*String == 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- PathHdr = String;
-
- //
- // The content between 'PATH=' of <ConfigHdr> and '&' of next element
- // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
- // of UEFI device path.
- //
- for (Length = 0; *String != 0 && *String != L'&'; String++, Length++) {
- }
-
- //
- // Save the return next keyword string value.
- //
- *NextString = String;
-
- //
- // Check DevicePath Length
- //
- if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
- // as the device path resides in RAM memory.
- // Translate the data into binary.
- //
- DevicePathBuffer = (UINT8 *)AllocateZeroPool ((Length + 1) / 2);
- if (DevicePathBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Convert DevicePath
- //
- ZeroMem (TemStr, sizeof (TemStr));
- for (Index = 0; Index < Length; Index++) {
- TemStr[0] = PathHdr[Index];
- DigitUint8 = (UINT8)StrHexToUint64 (TemStr);
- if ((Index & 1) == 0) {
- DevicePathBuffer[Index/2] = DigitUint8;
- } else {
- DevicePathBuffer[Index/2] = (UINT8)((DevicePathBuffer[Index/2] << 4) + DigitUint8);
- }
- }
-
- //
- // Validate DevicePath
- //
- DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePathBuffer;
- while (!IsDevicePathEnd (DevicePath)) {
- if ((DevicePath->Type == 0) || (DevicePath->SubType == 0) || (DevicePathNodeLength (DevicePath) < sizeof (EFI_DEVICE_PATH_PROTOCOL))) {
- //
- // Invalid device path
- //
- FreePool (DevicePathBuffer);
- return EFI_INVALID_PARAMETER;
- }
-
- DevicePath = NextDevicePathNode (DevicePath);
- }
-
- //
- // return the device path
- //
- *DevicePathData = DevicePathBuffer;
-
- return EFI_SUCCESS;
-}
-
-/**
- Get NameSpace from the input NameSpaceId string.
-
- This is a internal function.
-
- @param String <NameSpaceId> format string.
- @param NameSpace Return the name space string.
- @param NextString Return the next string follow namespace.
-
- @retval EFI_SUCCESS Get the namespace string success.
- @retval EFI_INVALID_PARAMETER The NameSpaceId string not follow spec definition.
-
-**/
-EFI_STATUS
-ExtractNameSpace (
- IN EFI_STRING String,
- OUT CHAR8 **NameSpace,
- OUT EFI_STRING *NextString
- )
-{
- CHAR16 *TmpPtr;
- UINTN NameSpaceSize;
-
- ASSERT (NameSpace != NULL);
-
- TmpPtr = NULL;
-
- //
- // Input NameSpaceId == NULL
- //
- if (String == NULL) {
- *NameSpace = NULL;
- if (NextString != NULL) {
- *NextString = NULL;
- }
-
- return EFI_SUCCESS;
- }
-
- //
- // Skip '&' if exist.
- //
- if (*String == L'&') {
- String++;
- }
-
- if (StrnCmp (String, L"NAMESPACE=", StrLen (L"NAMESPACE=")) != 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- String += StrLen (L"NAMESPACE=");
-
- TmpPtr = StrStr (String, L"&");
- if (TmpPtr != NULL) {
- *TmpPtr = 0;
- }
-
- if (NextString != NULL) {
- *NextString = String + StrLen (String);
- }
-
- //
- // Input NameSpace is unicode string. The language in String package is ascii string.
- // Here will convert the unicode string to ascii and save it.
- //
- NameSpaceSize = StrLen (String) + 1;
- *NameSpace = AllocatePool (NameSpaceSize);
- if (*NameSpace == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- UnicodeStrToAsciiStrS (String, *NameSpace, NameSpaceSize);
-
- if (TmpPtr != NULL) {
- *TmpPtr = L'&';
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Get Keyword from the input KeywordRequest string.
-
- This is a internal function.
-
- @param String KeywordRequestformat string.
- @param Keyword return the extract keyword string.
- @param NextString return the next string follow this keyword section.
-
- @retval EFI_SUCCESS Success to get the keyword string.
- @retval EFI_INVALID_PARAMETER Parse the input string return error.
-
-**/
-EFI_STATUS
-ExtractKeyword (
- IN EFI_STRING String,
- OUT EFI_STRING *Keyword,
- OUT EFI_STRING *NextString
- )
-{
- EFI_STRING TmpPtr;
-
- ASSERT ((Keyword != NULL) && (NextString != NULL));
-
- TmpPtr = NULL;
-
- //
- // KeywordRequest == NULL case.
- //
- if (String == NULL) {
- *Keyword = NULL;
- *NextString = NULL;
- return EFI_SUCCESS;
- }
-
- //
- // Skip '&' if exist.
- //
- if (*String == L'&') {
- String++;
- }
-
- if (StrnCmp (String, L"KEYWORD=", StrLen (L"KEYWORD=")) != 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- String += StrLen (L"KEYWORD=");
-
- TmpPtr = StrStr (String, L"&");
- if (TmpPtr != NULL) {
- *TmpPtr = 0;
- }
-
- *NextString = String + StrLen (String);
-
- *Keyword = AllocateCopyPool (StrSize (String), String);
- if (*Keyword == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- if (TmpPtr != NULL) {
- *TmpPtr = L'&';
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Get value from the input KeywordRequest string.
-
- This is a internal function.
-
- @param String KeywordRequestformat string.
- @param Value return the extract value string.
- @param NextString return the next string follow this keyword section.
-
- @retval EFI_SUCCESS Success to get the keyword string.
- @retval EFI_INVALID_PARAMETER Parse the input string return error.
-
-**/
-EFI_STATUS
-ExtractValue (
- IN EFI_STRING String,
- OUT EFI_STRING *Value,
- OUT EFI_STRING *NextString
- )
-{
- EFI_STRING TmpPtr;
-
- ASSERT ((Value != NULL) && (NextString != NULL) && (String != NULL));
-
- //
- // Skip '&' if exist.
- //
- if (*String == L'&') {
- String++;
- }
-
- if (StrnCmp (String, L"VALUE=", StrLen (L"VALUE=")) != 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- String += StrLen (L"VALUE=");
-
- TmpPtr = StrStr (String, L"&");
- if (TmpPtr != NULL) {
- *TmpPtr = 0;
- }
-
- *NextString = String + StrLen (String);
-
- *Value = AllocateCopyPool (StrSize (String), String);
- if (*Value == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- if (TmpPtr != NULL) {
- *TmpPtr = L'&';
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Get filter from the input KeywordRequest string.
-
- This is a internal function.
-
- @param String KeywordRequestformat string.
- @param FilterFlags return the filter condition.
- @param NextString return the next string follow this keyword section.
-
- @retval EFI_SUCCESS Success to get the keyword string.
- @retval EFI_INVALID_PARAMETER Parse the input string return error.
-
-**/
-BOOLEAN
-ExtractFilter (
- IN EFI_STRING String,
- OUT UINT8 *FilterFlags,
- OUT EFI_STRING *NextString
- )
-{
- CHAR16 *PathPtr;
- CHAR16 *KeywordPtr;
- BOOLEAN RetVal;
-
- ASSERT ((FilterFlags != NULL) && (NextString != NULL));
-
- //
- // String end, no filter section.
- //
- if (String == NULL) {
- *NextString = NULL;
- return FALSE;
- }
-
- *FilterFlags = 0;
- RetVal = TRUE;
-
- //
- // Skip '&' if exist.
- //
- if (*String == L'&') {
- String++;
- }
-
- if (StrnCmp (String, L"ReadOnly", StrLen (L"ReadOnly")) == 0) {
- //
- // Find ReadOnly filter.
- //
- *FilterFlags |= EFI_KEYWORD_FILTER_READONY;
- String += StrLen (L"ReadOnly");
- } else if (StrnCmp (String, L"ReadWrite", StrLen (L"ReadWrite")) == 0) {
- //
- // Find ReadWrite filter.
- //
- *FilterFlags |= EFI_KEYWORD_FILTER_REAWRITE;
- String += StrLen (L"ReadWrite");
- } else if (StrnCmp (String, L"Buffer", StrLen (L"Buffer")) == 0) {
- //
- // Find Buffer Filter.
- //
- *FilterFlags |= EFI_KEYWORD_FILTER_BUFFER;
- String += StrLen (L"Buffer");
- } else if (StrnCmp (String, L"Numeric", StrLen (L"Numeric")) == 0) {
- //
- // Find Numeric Filter
- //
- String += StrLen (L"Numeric");
- if (*String != L':') {
- *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC;
- } else {
- String++;
- switch (*String) {
- case L'1':
- *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_1;
- break;
- case L'2':
- *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_2;
- break;
- case L'4':
- *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_4;
- break;
- case L'8':
- *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_8;
- break;
- default:
- ASSERT (FALSE);
- break;
- }
-
- String++;
- }
- } else {
- //
- // Check whether other filter item defined by Platform.
- //
- if ((StrnCmp (String, L"&PATH", StrLen (L"&PATH")) == 0) ||
- (StrnCmp (String, L"&KEYWORD", StrLen (L"&KEYWORD")) == 0))
- {
- //
- // New KeywordRequest start, no platform defined filter.
- //
- } else {
- //
- // Platform defined filter rule.
- // Just skip platform defined filter rule, return success.
- //
- PathPtr = StrStr (String, L"&PATH");
- KeywordPtr = StrStr (String, L"&KEYWORD");
- if ((PathPtr != NULL) && (KeywordPtr != NULL)) {
- //
- // If both sections exist, return the first follow string.
- //
- String = KeywordPtr > PathPtr ? PathPtr : KeywordPtr;
- } else if (PathPtr != NULL) {
- //
- // Should not exist PathPtr != NULL && KeywordPtr == NULL case.
- //
- ASSERT (FALSE);
- } else if (KeywordPtr != NULL) {
- //
- // Just to the next keyword section.
- //
- String = KeywordPtr;
- } else {
- //
- // Only has platform defined filter section, just skip it.
- //
- String += StrLen (String);
- }
- }
-
- RetVal = FALSE;
- }
-
- *NextString = String;
-
- return RetVal;
-}
-
-/**
- Extract Readonly flag from opcode.
-
- This is a internal function.
-
- @param OpCodeData Input opcode for this question.
-
- @retval TRUE This question is readonly.
- @retval FALSE This question is not readonly.
-
-**/
-BOOLEAN
-ExtractReadOnlyFromOpCode (
- IN UINT8 *OpCodeData
- )
-{
- EFI_IFR_QUESTION_HEADER *QuestionHdr;
-
- ASSERT (OpCodeData != NULL);
-
- QuestionHdr = (EFI_IFR_QUESTION_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));
-
- return (QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) != 0;
-}
-
-/**
- Create a circuit to check the filter section.
-
- This is a internal function.
-
- @param OpCodeData The question binary ifr data.
- @param KeywordRequest KeywordRequestformat string.
- @param NextString return the next string follow this keyword section.
- @param ReadOnly Return whether this question is read only.
-
- @retval KEYWORD_HANDLER_NO_ERROR Success validate.
- @retval KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED Validate fail.
-
-**/
-UINT32
-ValidateFilter (
- IN UINT8 *OpCodeData,
- IN CHAR16 *KeywordRequest,
- OUT CHAR16 **NextString,
- OUT BOOLEAN *ReadOnly
- )
-{
- CHAR16 *NextFilter;
- CHAR16 *StringPtr;
- UINT8 FilterFlags;
- EFI_IFR_QUESTION_HEADER *QuestionHdr;
- EFI_IFR_OP_HEADER *OpCodeHdr;
- UINT8 Flags;
- UINT32 RetVal;
-
- RetVal = KEYWORD_HANDLER_NO_ERROR;
- StringPtr = KeywordRequest;
-
- OpCodeHdr = (EFI_IFR_OP_HEADER *)OpCodeData;
- QuestionHdr = (EFI_IFR_QUESTION_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));
- if ((OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP) || (OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP)) {
- Flags = *(OpCodeData + sizeof (EFI_IFR_OP_HEADER) + sizeof (EFI_IFR_QUESTION_HEADER));
- } else {
- Flags = 0;
- }
-
- //
- // Get ReadOnly flag from Question.
- //
- *ReadOnly = ExtractReadOnlyFromOpCode (OpCodeData);
-
- while (ExtractFilter (StringPtr, &FilterFlags, &NextFilter)) {
- switch (FilterFlags) {
- case EFI_KEYWORD_FILTER_READONY:
- if ((QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) == 0) {
- RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
- goto Done;
- }
-
- break;
-
- case EFI_KEYWORD_FILTER_REAWRITE:
- if ((QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) != 0) {
- RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
- goto Done;
- }
-
- break;
-
- case EFI_KEYWORD_FILTER_BUFFER:
- //
- // Only these three opcode use numeric value type.
- //
- if ((OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP) || (OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP) || (OpCodeHdr->OpCode == EFI_IFR_CHECKBOX_OP)) {
- RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
- goto Done;
- }
-
- break;
-
- case EFI_KEYWORD_FILTER_NUMERIC:
- if ((OpCodeHdr->OpCode != EFI_IFR_ONE_OF_OP) && (OpCodeHdr->OpCode != EFI_IFR_NUMERIC_OP) && (OpCodeHdr->OpCode != EFI_IFR_CHECKBOX_OP)) {
- RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
- goto Done;
- }
-
- break;
-
- case EFI_KEYWORD_FILTER_NUMERIC_1:
- case EFI_KEYWORD_FILTER_NUMERIC_2:
- case EFI_KEYWORD_FILTER_NUMERIC_4:
- case EFI_KEYWORD_FILTER_NUMERIC_8:
- if ((OpCodeHdr->OpCode != EFI_IFR_ONE_OF_OP) && (OpCodeHdr->OpCode != EFI_IFR_NUMERIC_OP) && (OpCodeHdr->OpCode != EFI_IFR_CHECKBOX_OP)) {
- RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
- goto Done;
- }
-
- //
- // For numeric and oneof, it has flags field to specify the detail numeric type.
- //
- if ((OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP) || (OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP)) {
- switch (Flags & EFI_IFR_NUMERIC_SIZE) {
- case EFI_IFR_NUMERIC_SIZE_1:
- if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_1) {
- RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
- goto Done;
- }
-
- break;
-
- case EFI_IFR_NUMERIC_SIZE_2:
- if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_2) {
- RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
- goto Done;
- }
-
- break;
-
- case EFI_IFR_NUMERIC_SIZE_4:
- if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_4) {
- RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
- goto Done;
- }
-
- break;
-
- case EFI_IFR_NUMERIC_SIZE_8:
- if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_8) {
- RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
- goto Done;
- }
-
- break;
-
- default:
- ASSERT (FALSE);
- break;
- }
- }
-
- break;
-
- default:
- ASSERT (FALSE);
- break;
- }
-
- //
- // Jump to the next filter.
- //
- StringPtr = NextFilter;
- }
-
-Done:
- //
- // The current filter which is processing.
- //
- *NextString = StringPtr;
-
- return RetVal;
-}
-
-/**
- Get HII_DATABASE_RECORD from the input device path info.
-
- This is a internal function.
-
- @param DevicePath UEFI device path protocol.
-
- @retval Internal data base record.
-
-**/
-HII_DATABASE_RECORD *
-GetRecordFromDevicePath (
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
-{
- LIST_ENTRY *Link;
- UINT8 *DevicePathPkg;
- UINT8 *CurrentDevicePath;
- UINTN DevicePathSize;
- HII_DATABASE_RECORD *TempDatabase;
-
- ASSERT (DevicePath != NULL);
-
- for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {
- TempDatabase = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- DevicePathPkg = TempDatabase->PackageList->DevicePathPkg;
- if (DevicePathPkg != NULL) {
- CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
- DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath);
- if ((CompareMem (DevicePath, CurrentDevicePath, DevicePathSize) == 0)) {
- return TempDatabase;
- }
- }
- }
-
- return NULL;
-}
-
-/**
- Calculate the size of StringSrc and output it. Also copy string text from src
- to dest.
-
- This is a internal function.
-
- @param StringSrc Points to current null-terminated string.
- @param BufferSize Length of the buffer.
- @param StringDest Buffer to store the string text.
-
- @retval EFI_SUCCESS The string text was outputted successfully.
- @retval EFI_OUT_OF_RESOURCES Out of resource.
-
-**/
-EFI_STATUS
-GetUnicodeStringTextAndSize (
- IN UINT8 *StringSrc,
- OUT UINTN *BufferSize,
- OUT EFI_STRING *StringDest
- )
-{
- UINTN StringSize;
- UINT8 *StringPtr;
-
- ASSERT (StringSrc != NULL && BufferSize != NULL && StringDest != NULL);
-
- StringSize = sizeof (CHAR16);
- StringPtr = StringSrc;
- while (ReadUnaligned16 ((UINT16 *)StringPtr) != 0) {
- StringSize += sizeof (CHAR16);
- StringPtr += sizeof (CHAR16);
- }
-
- *StringDest = AllocatePool (StringSize);
- if (*StringDest == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- CopyMem (*StringDest, StringSrc, StringSize);
-
- *BufferSize = StringSize;
- return EFI_SUCCESS;
-}
-
-/**
- Find the string id for the input keyword.
-
- @param StringPackage Hii string package instance.
- @param KeywordValue Input keyword value.
- @param StringId The string's id, which is unique within PackageList.
-
-
- @retval EFI_SUCCESS The string text and font is retrieved
- successfully.
- @retval EFI_NOT_FOUND The specified text or font info can not be found
- out.
- @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
- task.
-**/
-EFI_STATUS
-GetStringIdFromString (
- IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
- IN CHAR16 *KeywordValue,
- OUT EFI_STRING_ID *StringId
- )
-{
- UINT8 *BlockHdr;
- EFI_STRING_ID CurrentStringId;
- UINTN BlockSize;
- UINTN Index;
- UINT8 *StringTextPtr;
- UINTN Offset;
- UINT16 StringCount;
- UINT16 SkipCount;
- UINT8 Length8;
- EFI_HII_SIBT_EXT2_BLOCK Ext2;
- UINT32 Length32;
- UINTN StringSize;
- CHAR16 *String;
- CHAR8 *AsciiKeywordValue;
- UINTN KeywordValueSize;
- EFI_STATUS Status;
-
- ASSERT (StringPackage != NULL && KeywordValue != NULL && StringId != NULL);
- ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);
-
- CurrentStringId = 1;
- Status = EFI_SUCCESS;
- String = NULL;
- BlockHdr = StringPackage->StringBlock;
- BlockSize = 0;
- Offset = 0;
-
- //
- // Make a ascii keyword value for later use.
- //
- KeywordValueSize = StrLen (KeywordValue) + 1;
- AsciiKeywordValue = AllocatePool (KeywordValueSize);
- if (AsciiKeywordValue == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- UnicodeStrToAsciiStrS (KeywordValue, AsciiKeywordValue, KeywordValueSize);
-
- while (*BlockHdr != EFI_HII_SIBT_END) {
- switch (*BlockHdr) {
- case EFI_HII_SIBT_STRING_SCSU:
- Offset = sizeof (EFI_HII_STRING_BLOCK);
- StringTextPtr = BlockHdr + Offset;
- BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
- if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {
- *StringId = CurrentStringId;
- goto Done;
- }
-
- CurrentStringId++;
- break;
-
- case EFI_HII_SIBT_STRING_SCSU_FONT:
- Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);
- StringTextPtr = BlockHdr + Offset;
- if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {
- *StringId = CurrentStringId;
- goto Done;
- }
-
- BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
- CurrentStringId++;
- break;
-
- case EFI_HII_SIBT_STRINGS_SCSU:
- CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
- StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8));
- BlockSize += StringTextPtr - BlockHdr;
-
- for (Index = 0; Index < StringCount; Index++) {
- BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);
- if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {
- *StringId = CurrentStringId;
- goto Done;
- }
-
- StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
- CurrentStringId++;
- }
-
- break;
-
- case EFI_HII_SIBT_STRINGS_SCSU_FONT:
- CopyMem (
- &StringCount,
- (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
- sizeof (UINT16)
- );
- StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8));
- BlockSize += StringTextPtr - BlockHdr;
-
- for (Index = 0; Index < StringCount; Index++) {
- BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);
- if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {
- *StringId = CurrentStringId;
- goto Done;
- }
-
- StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
- CurrentStringId++;
- }
-
- break;
-
- case EFI_HII_SIBT_STRING_UCS2:
- Offset = sizeof (EFI_HII_STRING_BLOCK);
- StringTextPtr = BlockHdr + Offset;
- //
- // Use StringSize to store the size of the specified string, including the NULL
- // terminator.
- //
- Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- ASSERT (String != NULL);
- if (StrCmp (KeywordValue, String) == 0) {
- *StringId = CurrentStringId;
- goto Done;
- }
-
- BlockSize += Offset + StringSize;
- CurrentStringId++;
- break;
-
- case EFI_HII_SIBT_STRING_UCS2_FONT:
- Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);
- StringTextPtr = BlockHdr + Offset;
- //
- // Use StringSize to store the size of the specified string, including the NULL
- // terminator.
- //
- Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- ASSERT (String != NULL);
- if (StrCmp (KeywordValue, String) == 0) {
- *StringId = CurrentStringId;
- goto Done;
- }
-
- BlockSize += Offset + StringSize;
- CurrentStringId++;
- break;
-
- case EFI_HII_SIBT_STRINGS_UCS2:
- Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);
- StringTextPtr = BlockHdr + Offset;
- BlockSize += Offset;
- CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
- for (Index = 0; Index < StringCount; Index++) {
- Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- ASSERT (String != NULL);
- BlockSize += StringSize;
- if (StrCmp (KeywordValue, String) == 0) {
- *StringId = CurrentStringId;
- goto Done;
- }
-
- StringTextPtr = StringTextPtr + StringSize;
- CurrentStringId++;
- }
-
- break;
-
- case EFI_HII_SIBT_STRINGS_UCS2_FONT:
- Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);
- StringTextPtr = BlockHdr + Offset;
- BlockSize += Offset;
- CopyMem (
- &StringCount,
- (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
- sizeof (UINT16)
- );
- for (Index = 0; Index < StringCount; Index++) {
- Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- ASSERT (String != NULL);
- BlockSize += StringSize;
- if (StrCmp (KeywordValue, String) == 0) {
- *StringId = CurrentStringId;
- goto Done;
- }
-
- StringTextPtr = StringTextPtr + StringSize;
- CurrentStringId++;
- }
-
- break;
-
- case EFI_HII_SIBT_DUPLICATE:
- BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);
- CurrentStringId++;
- break;
-
- case EFI_HII_SIBT_SKIP1:
- SkipCount = (UINT16)(*(UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));
- CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
- BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
- break;
-
- case EFI_HII_SIBT_SKIP2:
- CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
- CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
- BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
- break;
-
- case EFI_HII_SIBT_EXT1:
- CopyMem (
- &Length8,
- (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
- sizeof (UINT8)
- );
- BlockSize += Length8;
- break;
-
- case EFI_HII_SIBT_EXT2:
- CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
- BlockSize += Ext2.Length;
- break;
-
- case EFI_HII_SIBT_EXT4:
- CopyMem (
- &Length32,
- (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
- sizeof (UINT32)
- );
-
- BlockSize += Length32;
- break;
-
- default:
- break;
- }
-
- if (String != NULL) {
- FreePool (String);
- String = NULL;
- }
-
- BlockHdr = StringPackage->StringBlock + BlockSize;
- }
-
- Status = EFI_NOT_FOUND;
-
-Done:
- if (AsciiKeywordValue != NULL) {
- FreePool (AsciiKeywordValue);
- }
-
- if (String != NULL) {
- FreePool (String);
- }
-
- return Status;
-}
-
-/**
- Find the next valid string id for the input string id.
-
- @param StringPackage Hii string package instance.
- @param StringId The current string id which is already got.
- 1 means just begin to get the string id.
- @param KeywordValue Return the string for the next string id.
-
-
- @retval EFI_STRING_ID Not 0 means a valid stringid found.
- 0 means not found a valid string id.
-**/
-EFI_STRING_ID
-GetNextStringId (
- IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
- IN EFI_STRING_ID StringId,
- OUT EFI_STRING *KeywordValue
- )
-{
- UINT8 *BlockHdr;
- EFI_STRING_ID CurrentStringId;
- UINTN BlockSize;
- UINTN Index;
- UINT8 *StringTextPtr;
- UINTN Offset;
- UINT16 StringCount;
- UINT16 SkipCount;
- UINT8 Length8;
- EFI_HII_SIBT_EXT2_BLOCK Ext2;
- UINT32 Length32;
- BOOLEAN FindString;
- UINTN StringSize;
- CHAR16 *String;
-
- ASSERT (StringPackage != NULL);
- ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);
-
- CurrentStringId = 1;
- FindString = FALSE;
- String = NULL;
-
- //
- // Parse the string blocks to get the string text and font.
- //
- BlockHdr = StringPackage->StringBlock;
- BlockSize = 0;
- Offset = 0;
- while (*BlockHdr != EFI_HII_SIBT_END) {
- switch (*BlockHdr) {
- case EFI_HII_SIBT_STRING_SCSU:
- Offset = sizeof (EFI_HII_STRING_BLOCK);
- StringTextPtr = BlockHdr + Offset;
-
- if (FindString) {
- StringSize = AsciiStrSize ((CHAR8 *)StringTextPtr);
- *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));
- if (*KeywordValue == NULL) {
- return 0;
- }
-
- AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);
- return CurrentStringId;
- } else if (CurrentStringId == StringId) {
- FindString = TRUE;
- }
-
- BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
- CurrentStringId++;
- break;
-
- case EFI_HII_SIBT_STRING_SCSU_FONT:
- Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);
- StringTextPtr = BlockHdr + Offset;
-
- if (FindString) {
- StringSize = AsciiStrSize ((CHAR8 *)StringTextPtr);
- *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));
- if (*KeywordValue == NULL) {
- return 0;
- }
-
- AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);
- return CurrentStringId;
- } else if (CurrentStringId == StringId) {
- FindString = TRUE;
- }
-
- BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
- CurrentStringId++;
- break;
-
- case EFI_HII_SIBT_STRINGS_SCSU:
- CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
- StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8));
- BlockSize += StringTextPtr - BlockHdr;
-
- for (Index = 0; Index < StringCount; Index++) {
- if (FindString) {
- StringSize = AsciiStrSize ((CHAR8 *)StringTextPtr);
- *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));
- if (*KeywordValue == NULL) {
- return 0;
- }
-
- AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);
- return CurrentStringId;
- } else if (CurrentStringId == StringId) {
- FindString = TRUE;
- }
-
- BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);
- StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
- CurrentStringId++;
- }
-
- break;
-
- case EFI_HII_SIBT_STRINGS_SCSU_FONT:
- CopyMem (
- &StringCount,
- (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
- sizeof (UINT16)
- );
- StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8));
- BlockSize += StringTextPtr - BlockHdr;
-
- for (Index = 0; Index < StringCount; Index++) {
- if (FindString) {
- StringSize = AsciiStrSize ((CHAR8 *)StringTextPtr);
- *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));
- if (*KeywordValue == NULL) {
- return 0;
- }
-
- AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);
- return CurrentStringId;
- } else if (CurrentStringId == StringId) {
- FindString = TRUE;
- }
-
- BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);
- StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
- CurrentStringId++;
- }
-
- break;
-
- case EFI_HII_SIBT_STRING_UCS2:
- Offset = sizeof (EFI_HII_STRING_BLOCK);
- StringTextPtr = BlockHdr + Offset;
- //
- // Use StringSize to store the size of the specified string, including the NULL
- // terminator.
- //
- GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
- if (FindString && (String != NULL) && (*String != L'\0')) {
- //
- // String protocol use this type for the string id which has value for other package.
- // It will allocate an empty string block for this string id. so here we also check
- // *String != L'\0' to prohibit this case.
- //
- *KeywordValue = String;
- return CurrentStringId;
- } else if (CurrentStringId == StringId) {
- FindString = TRUE;
- }
-
- BlockSize += Offset + StringSize;
- CurrentStringId++;
- break;
-
- case EFI_HII_SIBT_STRING_UCS2_FONT:
- Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);
- StringTextPtr = BlockHdr + Offset;
- //
- // Use StringSize to store the size of the specified string, including the NULL
- // terminator.
- //
- GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
- if (FindString) {
- *KeywordValue = String;
- return CurrentStringId;
- } else if (CurrentStringId == StringId) {
- FindString = TRUE;
- }
-
- BlockSize += Offset + StringSize;
- CurrentStringId++;
- break;
-
- case EFI_HII_SIBT_STRINGS_UCS2:
- Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);
- StringTextPtr = BlockHdr + Offset;
- BlockSize += Offset;
- CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
- for (Index = 0; Index < StringCount; Index++) {
- GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
-
- if (FindString) {
- *KeywordValue = String;
- return CurrentStringId;
- } else if (CurrentStringId == StringId) {
- FindString = TRUE;
- }
-
- BlockSize += StringSize;
- StringTextPtr = StringTextPtr + StringSize;
- CurrentStringId++;
- }
-
- break;
-
- case EFI_HII_SIBT_STRINGS_UCS2_FONT:
- Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);
- StringTextPtr = BlockHdr + Offset;
- BlockSize += Offset;
- CopyMem (
- &StringCount,
- (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
- sizeof (UINT16)
- );
- for (Index = 0; Index < StringCount; Index++) {
- GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
- if (FindString) {
- *KeywordValue = String;
- return CurrentStringId;
- } else if (CurrentStringId == StringId) {
- FindString = TRUE;
- }
-
- BlockSize += StringSize;
- StringTextPtr = StringTextPtr + StringSize;
- CurrentStringId++;
- }
-
- break;
-
- case EFI_HII_SIBT_DUPLICATE:
- BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);
- CurrentStringId++;
- break;
-
- case EFI_HII_SIBT_SKIP1:
- SkipCount = (UINT16)(*(UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));
- CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
- BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
- break;
-
- case EFI_HII_SIBT_SKIP2:
- CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
- CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
- BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
- break;
-
- case EFI_HII_SIBT_EXT1:
- CopyMem (
- &Length8,
- (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
- sizeof (UINT8)
- );
- BlockSize += Length8;
- break;
-
- case EFI_HII_SIBT_EXT2:
- CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
- BlockSize += Ext2.Length;
- break;
-
- case EFI_HII_SIBT_EXT4:
- CopyMem (
- &Length32,
- (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
- sizeof (UINT32)
- );
-
- BlockSize += Length32;
- break;
-
- default:
- break;
- }
-
- if (String != NULL) {
- FreePool (String);
- String = NULL;
- }
-
- BlockHdr = StringPackage->StringBlock + BlockSize;
- }
-
- return 0;
-}
-
-/**
- Get string package from the input NameSpace string.
-
- This is a internal function.
-
- @param DatabaseRecord HII_DATABASE_RECORD format string.
- @param NameSpace NameSpace format string.
- @param KeywordValue Keyword value.
- @param StringId String Id for this keyword.
-
- @retval KEYWORD_HANDLER_NO_ERROR Get String id successfully.
- @retval KEYWORD_HANDLER_KEYWORD_NOT_FOUND Not found the string id in the string package.
- @retval KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND Not found the string package for this namespace.
- @retval KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR Out of resource error.
-
-**/
-UINT32
-GetStringIdFromRecord (
- IN HII_DATABASE_RECORD *DatabaseRecord,
- IN CHAR8 **NameSpace,
- IN CHAR16 *KeywordValue,
- OUT EFI_STRING_ID *StringId
- )
-{
- LIST_ENTRY *Link;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
- HII_STRING_PACKAGE_INSTANCE *StringPackage;
- EFI_STATUS Status;
- CHAR8 *Name;
- UINT32 RetVal;
-
- ASSERT (DatabaseRecord != NULL && NameSpace != NULL && KeywordValue != NULL);
-
- PackageListNode = DatabaseRecord->PackageList;
- RetVal = KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND;
-
- if (*NameSpace != NULL) {
- Name = *NameSpace;
- } else {
- Name = UEFI_CONFIG_LANG;
- }
-
- for (Link = PackageListNode->StringPkgHdr.ForwardLink; Link != &PackageListNode->StringPkgHdr; Link = Link->ForwardLink) {
- StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
-
- if (AsciiStrnCmp (Name, StringPackage->StringPkgHdr->Language, AsciiStrLen (Name)) == 0) {
- Status = GetStringIdFromString (StringPackage, KeywordValue, StringId);
- if (EFI_ERROR (Status)) {
- return KEYWORD_HANDLER_KEYWORD_NOT_FOUND;
- } else {
- if (*NameSpace == NULL) {
- *NameSpace = AllocateCopyPool (AsciiStrSize (StringPackage->StringPkgHdr->Language), StringPackage->StringPkgHdr->Language);
- if (*NameSpace == NULL) {
- return KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;
- }
- }
-
- return KEYWORD_HANDLER_NO_ERROR;
- }
- }
- }
-
- return RetVal;
-}
-
-/**
- Tell whether this Operand is an Statement OpCode.
-
- @param Operand Operand of an IFR OpCode.
-
- @retval TRUE This is an Statement OpCode.
- @retval FALSE Not an Statement OpCode.
-
-**/
-BOOLEAN
-IsStatementOpCode (
- IN UINT8 Operand
- )
-{
- if ((Operand == EFI_IFR_SUBTITLE_OP) ||
- (Operand == EFI_IFR_TEXT_OP) ||
- (Operand == EFI_IFR_RESET_BUTTON_OP) ||
- (Operand == EFI_IFR_REF_OP) ||
- (Operand == EFI_IFR_ACTION_OP) ||
- (Operand == EFI_IFR_NUMERIC_OP) ||
- (Operand == EFI_IFR_ORDERED_LIST_OP) ||
- (Operand == EFI_IFR_CHECKBOX_OP) ||
- (Operand == EFI_IFR_STRING_OP) ||
- (Operand == EFI_IFR_PASSWORD_OP) ||
- (Operand == EFI_IFR_DATE_OP) ||
- (Operand == EFI_IFR_TIME_OP) ||
- (Operand == EFI_IFR_GUID_OP) ||
- (Operand == EFI_IFR_ONE_OF_OP))
- {
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- Tell whether this Operand is an Statement OpCode.
-
- @param Operand Operand of an IFR OpCode.
-
- @retval TRUE This is an Statement OpCode.
- @retval FALSE Not an Statement OpCode.
-
-**/
-BOOLEAN
-IsStorageOpCode (
- IN UINT8 Operand
- )
-{
- if ((Operand == EFI_IFR_VARSTORE_OP) ||
- (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) ||
- (Operand == EFI_IFR_VARSTORE_EFI_OP))
- {
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- Base on the prompt string id to find the question.
-
- @param FormPackage The input form package.
- @param KeywordStrId The input prompt string id for one question.
-
- @retval the opcode for the question.
-
-**/
-UINT8 *
-FindQuestionFromStringId (
- IN HII_IFR_PACKAGE_INSTANCE *FormPackage,
- IN EFI_STRING_ID KeywordStrId
- )
-{
- UINT8 *OpCodeData;
- UINT32 Offset;
- EFI_IFR_STATEMENT_HEADER *StatementHeader;
- EFI_IFR_OP_HEADER *OpCodeHeader;
- UINT32 FormDataLen;
-
- ASSERT (FormPackage != NULL);
-
- FormDataLen = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
- Offset = 0;
- while (Offset < FormDataLen) {
- OpCodeData = FormPackage->IfrData + Offset;
- OpCodeHeader = (EFI_IFR_OP_HEADER *)OpCodeData;
-
- if (IsStatementOpCode (OpCodeHeader->OpCode)) {
- StatementHeader = (EFI_IFR_STATEMENT_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));
- if (StatementHeader->Prompt == KeywordStrId) {
- return OpCodeData;
- }
- }
-
- Offset += OpCodeHeader->Length;
- }
-
- return NULL;
-}
-
-/**
- Base on the varstore id to find the storage info.
-
- @param FormPackage The input form package.
- @param VarStoreId The input storage id.
-
- @retval the opcode for the storage.
-
-**/
-UINT8 *
-FindStorageFromVarId (
- IN HII_IFR_PACKAGE_INSTANCE *FormPackage,
- IN EFI_VARSTORE_ID VarStoreId
- )
-{
- UINT8 *OpCodeData;
- UINT32 Offset;
- EFI_IFR_OP_HEADER *OpCodeHeader;
- UINT32 FormDataLen;
-
- ASSERT (FormPackage != NULL);
-
- FormDataLen = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
- Offset = 0;
- while (Offset < FormDataLen) {
- OpCodeData = FormPackage->IfrData + Offset;
- OpCodeHeader = (EFI_IFR_OP_HEADER *)OpCodeData;
-
- if (IsStorageOpCode (OpCodeHeader->OpCode)) {
- switch (OpCodeHeader->OpCode) {
- case EFI_IFR_VARSTORE_OP:
- if (VarStoreId == ((EFI_IFR_VARSTORE *)OpCodeData)->VarStoreId) {
- return OpCodeData;
- }
-
- break;
-
- case EFI_IFR_VARSTORE_NAME_VALUE_OP:
- if (VarStoreId == ((EFI_IFR_VARSTORE_NAME_VALUE *)OpCodeData)->VarStoreId) {
- return OpCodeData;
- }
-
- break;
-
- case EFI_IFR_VARSTORE_EFI_OP:
- if (VarStoreId == ((EFI_IFR_VARSTORE_EFI *)OpCodeData)->VarStoreId) {
- return OpCodeData;
- }
-
- break;
-
- default:
- break;
- }
- }
-
- Offset += OpCodeHeader->Length;
- }
-
- return NULL;
-}
-
-/**
- Get width info for one question.
-
- @param OpCodeData The input opcode for one question.
-
- @retval the width info for one question.
-
-**/
-UINT16
-GetWidth (
- IN UINT8 *OpCodeData
- )
-{
- UINT8 *NextOpCodeData;
-
- ASSERT (OpCodeData != NULL);
-
- switch (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode) {
- case EFI_IFR_REF_OP:
- return (UINT16)sizeof (EFI_HII_REF);
-
- case EFI_IFR_ONE_OF_OP:
- case EFI_IFR_NUMERIC_OP:
- switch (((EFI_IFR_ONE_OF *)OpCodeData)->Flags & EFI_IFR_NUMERIC_SIZE) {
- case EFI_IFR_NUMERIC_SIZE_1:
- return (UINT16)sizeof (UINT8);
-
- case EFI_IFR_NUMERIC_SIZE_2:
- return (UINT16)sizeof (UINT16);
-
- case EFI_IFR_NUMERIC_SIZE_4:
- return (UINT16)sizeof (UINT32);
-
- case EFI_IFR_NUMERIC_SIZE_8:
- return (UINT16)sizeof (UINT64);
-
- default:
- ASSERT (FALSE);
- return 0;
- }
-
- case EFI_IFR_ORDERED_LIST_OP:
- NextOpCodeData = OpCodeData + ((EFI_IFR_ORDERED_LIST *)OpCodeData)->Header.Length;
- //
- // OneOfOption must follow the orderedlist opcode.
- //
- ASSERT (((EFI_IFR_OP_HEADER *)NextOpCodeData)->OpCode == EFI_IFR_ONE_OF_OPTION_OP);
- switch (((EFI_IFR_ONE_OF_OPTION *)NextOpCodeData)->Type) {
- case EFI_IFR_TYPE_NUM_SIZE_8:
- return (UINT16)sizeof (UINT8) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
-
- case EFI_IFR_TYPE_NUM_SIZE_16:
- return (UINT16)sizeof (UINT16) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
-
- case EFI_IFR_TYPE_NUM_SIZE_32:
- return (UINT16)sizeof (UINT32) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
-
- case EFI_IFR_TYPE_NUM_SIZE_64:
- return (UINT16)sizeof (UINT64) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
-
- default:
- ASSERT (FALSE);
- return 0;
- }
-
- case EFI_IFR_CHECKBOX_OP:
- return (UINT16)sizeof (BOOLEAN);
-
- case EFI_IFR_PASSWORD_OP:
- return (UINT16)((UINTN)((EFI_IFR_PASSWORD *)OpCodeData)->MaxSize * sizeof (CHAR16));
-
- case EFI_IFR_STRING_OP:
- return (UINT16)((UINTN)((EFI_IFR_STRING *)OpCodeData)->MaxSize * sizeof (CHAR16));
-
- case EFI_IFR_DATE_OP:
- return (UINT16)sizeof (EFI_HII_DATE);
-
- case EFI_IFR_TIME_OP:
- return (UINT16)sizeof (EFI_HII_TIME);
-
- default:
- ASSERT (FALSE);
- return 0;
- }
-}
-
-/**
- Converts all hex string characters in range ['A'..'F'] to ['a'..'f'] for
- hex digits that appear between a '=' and a '&' in a config string.
-
- If ConfigString is NULL, then ASSERT().
-
- @param[in] ConfigString Pointer to a Null-terminated Unicode string.
-
- @return Pointer to the Null-terminated Unicode result string.
-
-**/
-EFI_STRING
-EFIAPI
-InternalLowerConfigString (
- IN EFI_STRING ConfigString
- )
-{
- EFI_STRING String;
- BOOLEAN Lower;
-
- ASSERT (ConfigString != NULL);
-
- //
- // Convert all hex digits in range [A-F] in the configuration header to [a-f]
- //
- for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
- if (*String == L'=') {
- Lower = TRUE;
- } else if (*String == L'&') {
- Lower = FALSE;
- } else if (Lower && (*String >= L'A') && (*String <= L'F')) {
- *String = (CHAR16)(*String - L'A' + L'a');
- }
- }
-
- return ConfigString;
-}
-
-/**
- Allocates and returns a Null-terminated Unicode <ConfigHdr> string.
-
- The format of a <ConfigHdr> is as follows:
-
- GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>
-
- @param[in] OpCodeData The opcode for the storage.
- @param[in] DriverHandle The driver handle which supports a Device Path Protocol
- that is the routing information PATH. Each byte of
- the Device Path associated with DriverHandle is converted
- to a 2 Unicode character hexadecimal string.
-
- @retval NULL DriverHandle does not support the Device Path Protocol.
- @retval Other A pointer to the Null-terminate Unicode <ConfigHdr> string
-
-**/
-EFI_STRING
-ConstructConfigHdr (
- IN UINT8 *OpCodeData,
- IN EFI_HANDLE DriverHandle
- )
-{
- UINTN NameLength;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- UINTN DevicePathSize;
- CHAR16 *String;
- CHAR16 *ReturnString;
- UINTN Index;
- UINT8 *Buffer;
- CHAR16 *Name;
- CHAR8 *AsciiName;
- UINTN NameSize;
- EFI_GUID *Guid;
- UINTN MaxLen;
-
- ASSERT (OpCodeData != NULL);
-
- switch (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode) {
- case EFI_IFR_VARSTORE_OP:
- Guid = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE *)OpCodeData)->Guid;
- AsciiName = (CHAR8 *)((EFI_IFR_VARSTORE *)OpCodeData)->Name;
- break;
-
- case EFI_IFR_VARSTORE_NAME_VALUE_OP:
- Guid = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE_NAME_VALUE *)OpCodeData)->Guid;
- AsciiName = NULL;
- break;
-
- case EFI_IFR_VARSTORE_EFI_OP:
- Guid = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Guid;
- AsciiName = (CHAR8 *)((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Name;
- break;
-
- default:
- ASSERT (FALSE);
- Guid = NULL;
- AsciiName = NULL;
- break;
- }
-
- if (AsciiName != NULL) {
- NameSize = AsciiStrSize (AsciiName);
- Name = AllocateZeroPool (NameSize * sizeof (CHAR16));
- ASSERT (Name != NULL);
- AsciiStrToUnicodeStrS (AsciiName, Name, NameSize);
- } else {
- Name = NULL;
- }
-
- //
- // Compute the length of Name in Unicode characters.
- // If Name is NULL, then the length is 0.
- //
- NameLength = 0;
- if (Name != NULL) {
- NameLength = StrLen (Name);
- }
-
- DevicePath = NULL;
- DevicePathSize = 0;
- //
- // Retrieve DevicePath Protocol associated with DriverHandle
- //
- if (DriverHandle != NULL) {
- DevicePath = DevicePathFromHandle (DriverHandle);
- if (DevicePath == NULL) {
- return NULL;
- }
-
- //
- // Compute the size of the device path in bytes
- //
- DevicePathSize = GetDevicePathSize (DevicePath);
- }
-
- //
- // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>
- // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |
- //
- MaxLen = 5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1;
- String = AllocateZeroPool (MaxLen * sizeof (CHAR16));
- if (String == NULL) {
- return NULL;
- }
-
- //
- // Start with L"GUID="
- //
- StrCpyS (String, MaxLen, L"GUID=");
- ReturnString = String;
- String += StrLen (String);
-
- if (Guid != NULL) {
- //
- // Append Guid converted to <HexCh>32
- //
- for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {
- UnicodeValueToStringS (
- String,
- MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),
- PREFIX_ZERO | RADIX_HEX,
- *(Buffer++),
- 2
- );
- String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));
- }
- }
-
- //
- // Append L"&NAME="
- //
- StrCatS (ReturnString, MaxLen, L"&NAME=");
- String += StrLen (String);
-
- if (Name != NULL) {
- //
- // Append Name converted to <Char>NameLength
- //
- for ( ; *Name != L'\0'; Name++) {
- UnicodeValueToStringS (
- String,
- MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),
- PREFIX_ZERO | RADIX_HEX,
- *Name,
- 4
- );
- String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));
- }
- }
-
- //
- // Append L"&PATH="
- //
- StrCatS (ReturnString, MaxLen, L"&PATH=");
- String += StrLen (String);
-
- //
- // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize
- //
- for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) {
- UnicodeValueToStringS (
- String,
- MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),
- PREFIX_ZERO | RADIX_HEX,
- *(Buffer++),
- 2
- );
- String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));
- }
-
- //
- // Null terminate the Unicode string
- //
- *String = L'\0';
-
- //
- // Convert all hex digits in range [A-F] in the configuration header to [a-f]
- //
- return InternalLowerConfigString (ReturnString);
-}
-
-/**
- Generate the Config request element for one question.
-
- @param Name The name info for one question.
- @param Offset The offset info for one question.
- @param Width The width info for one question.
-
- @return Pointer to the Null-terminated Unicode request element string.
-
-**/
-EFI_STRING
-ConstructRequestElement (
- IN CHAR16 *Name,
- IN UINT16 Offset,
- IN UINT16 Width
- )
-{
- CHAR16 *StringPtr;
- UINTN Length;
-
- if (Name != NULL) {
- //
- // Add <BlockName> length for each Name
- //
- // <BlockName> ::= Name + \0
- // StrLen(Name) | 1
- //
- Length = StrLen (Name) + 1;
- } else {
- //
- // Add <BlockName> length for each Offset/Width pair
- //
- // <BlockName> ::= OFFSET=1234&WIDTH=1234 + \0
- // | 7 | 4 | 7 | 4 | 1
- //
- Length = (7 + 4 + 7 + 4 + 1);
- }
-
- //
- // Allocate buffer for the entire <ConfigRequest>
- //
- StringPtr = AllocateZeroPool (Length * sizeof (CHAR16));
- ASSERT (StringPtr != NULL);
-
- if (Name != NULL) {
- //
- // Append Name\0
- //
- UnicodeSPrint (
- StringPtr,
- (StrLen (Name) + 1) * sizeof (CHAR16),
- L"%s",
- Name
- );
- } else {
- //
- // Append OFFSET=XXXX&WIDTH=YYYY\0
- //
- UnicodeSPrint (
- StringPtr,
- (7 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
- L"OFFSET=%04X&WIDTH=%04X",
- Offset,
- Width
- );
- }
-
- return StringPtr;
-}
-
-/**
- Get string value for question's name field.
-
- @param DatabaseRecord HII_DATABASE_RECORD format string.
- @param NameId The string id for the name field.
-
- @retval Name string.
-
-**/
-CHAR16 *
-GetNameFromId (
- IN HII_DATABASE_RECORD *DatabaseRecord,
- IN EFI_STRING_ID NameId
- )
-{
- CHAR16 *Name;
- CHAR8 *PlatformLanguage;
- CHAR8 *SupportedLanguages;
- CHAR8 *BestLanguage;
- UINTN StringSize;
- CHAR16 TempString;
- EFI_STATUS Status;
-
- Name = NULL;
- BestLanguage = NULL;
- PlatformLanguage = NULL;
- SupportedLanguages = NULL;
-
- GetEfiGlobalVariable2 (L"PlatformLang", (VOID **)&PlatformLanguage, NULL);
- SupportedLanguages = GetSupportedLanguages (DatabaseRecord->Handle);
-
- //
- // Get the best matching language from SupportedLanguages
- //
- BestLanguage = GetBestLanguage (
- SupportedLanguages,
- FALSE, // RFC 4646 mode
- PlatformLanguage != NULL ? PlatformLanguage : "", // Highest priority
- SupportedLanguages, // Lowest priority
- NULL
- );
- if (BestLanguage == NULL) {
- BestLanguage = AllocateCopyPool (sizeof ("en-US"), "en-US");
- ASSERT (BestLanguage != NULL);
- }
-
- StringSize = 0;
- Status = mPrivate.HiiString.GetString (
- &mPrivate.HiiString,
- BestLanguage,
- DatabaseRecord->Handle,
- NameId,
- &TempString,
- &StringSize,
- NULL
- );
- if (Status != EFI_BUFFER_TOO_SMALL) {
- goto Done;
- }
-
- Name = AllocateZeroPool (StringSize);
- if (Name == NULL) {
- goto Done;
- }
-
- Status = mPrivate.HiiString.GetString (
- &mPrivate.HiiString,
- BestLanguage,
- DatabaseRecord->Handle,
- NameId,
- Name,
- &StringSize,
- NULL
- );
-
- if (EFI_ERROR (Status)) {
- FreePool (Name);
- Name = NULL;
- goto Done;
- }
-
-Done:
- if (SupportedLanguages != NULL) {
- FreePool (SupportedLanguages);
- }
-
- if (BestLanguage != NULL) {
- FreePool (BestLanguage);
- }
-
- if (PlatformLanguage != NULL) {
- FreePool (PlatformLanguage);
- }
-
- return Name;
-}
-
-/**
- Base on the input parameter to generate the ConfigRequest string.
-
- This is a internal function.
-
- @param DatabaseRecord HII_DATABASE_RECORD format string.
- @param KeywordStrId Keyword string id.
- @param OpCodeData The IFR data for this question.
- @param ConfigRequest Return the generate ConfigRequest string.
-
- @retval EFI_SUCCESS Generate ConfigResp string success.
- @retval EFI_OUT_OF_RESOURCES System out of memory resource error.
- @retval EFI_NOT_FOUND Not found the question which use this string id
- as the prompt string id.
-**/
-EFI_STATUS
-ExtractConfigRequest (
- IN HII_DATABASE_RECORD *DatabaseRecord,
- IN EFI_STRING_ID KeywordStrId,
- OUT UINT8 **OpCodeData,
- OUT EFI_STRING *ConfigRequest
- )
-{
- LIST_ENTRY *Link;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
- HII_IFR_PACKAGE_INSTANCE *FormPackage;
- EFI_IFR_QUESTION_HEADER *Header;
- UINT8 *Storage;
- UINT8 *OpCode;
- CHAR16 *Name;
- UINT16 Offset;
- UINT16 Width;
- CHAR16 *ConfigHdr;
- CHAR16 *RequestElement;
- UINTN MaxLen;
- CHAR16 *StringPtr;
-
- ASSERT (DatabaseRecord != NULL && OpCodeData != NULL && ConfigRequest != NULL);
-
- OpCode = NULL;
- Name = NULL;
- Width = 0;
- Offset = 0;
-
- PackageListNode = DatabaseRecord->PackageList;
-
- //
- // Search the languages in the specified packagelist.
- //
- for (Link = PackageListNode->FormPkgHdr.ForwardLink; Link != &PackageListNode->FormPkgHdr; Link = Link->ForwardLink) {
- FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);
-
- OpCode = FindQuestionFromStringId (FormPackage, KeywordStrId);
- if (OpCode != NULL) {
- *OpCodeData = OpCode;
- Header = (EFI_IFR_QUESTION_HEADER *)(OpCode + sizeof (EFI_IFR_OP_HEADER));
- //
- // Header->VarStoreId == 0 means no storage for this question.
- //
- ASSERT (Header->VarStoreId != 0);
- DEBUG ((DEBUG_INFO, "Varstore Id: 0x%x\n", Header->VarStoreId));
-
- Storage = FindStorageFromVarId (FormPackage, Header->VarStoreId);
- ASSERT (Storage != NULL);
-
- if (((EFI_IFR_OP_HEADER *)Storage)->OpCode == EFI_IFR_VARSTORE_NAME_VALUE_OP) {
- Name = GetNameFromId (DatabaseRecord, Header->VarStoreInfo.VarName);
- } else {
- Offset = Header->VarStoreInfo.VarOffset;
- Width = GetWidth (OpCode);
- }
-
- RequestElement = ConstructRequestElement (Name, Offset, Width);
- ConfigHdr = ConstructConfigHdr (Storage, DatabaseRecord->DriverHandle);
- ASSERT (ConfigHdr != NULL);
-
- MaxLen = StrLen (ConfigHdr) + 1 + StrLen (RequestElement) + 1;
- *ConfigRequest = AllocatePool (MaxLen * sizeof (CHAR16));
- if (*ConfigRequest == NULL) {
- FreePool (ConfigHdr);
- FreePool (RequestElement);
- return EFI_OUT_OF_RESOURCES;
- }
-
- StringPtr = *ConfigRequest;
-
- StrCpyS (StringPtr, MaxLen, ConfigHdr);
-
- StrCatS (StringPtr, MaxLen, L"&");
-
- StrCatS (StringPtr, MaxLen, RequestElement);
-
- FreePool (ConfigHdr);
- FreePool (RequestElement);
-
- return EFI_SUCCESS;
- }
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- Base on the input parameter to generate the ConfigResp string.
-
- This is a internal function.
-
- @param DatabaseRecord HII_DATABASE_RECORD format string.
- @param KeywordStrId Keyword string id.
- @param ValueElement The value for the question which use keyword string id
- as the prompt string id.
- @param OpCodeData The IFR data for this question.
- @param ConfigResp Return the generate ConfigResp string.
-
- @retval EFI_SUCCESS Generate ConfigResp string success.
- @retval EFI_OUT_OF_RESOURCES System out of memory resource error.
- @retval EFI_NOT_FOUND Not found the question which use this string id
- as the prompt string id.
-**/
-EFI_STATUS
-ExtractConfigResp (
- IN HII_DATABASE_RECORD *DatabaseRecord,
- IN EFI_STRING_ID KeywordStrId,
- IN EFI_STRING ValueElement,
- OUT UINT8 **OpCodeData,
- OUT EFI_STRING *ConfigResp
- )
-{
- LIST_ENTRY *Link;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
- HII_IFR_PACKAGE_INSTANCE *FormPackage;
- EFI_IFR_QUESTION_HEADER *Header;
- UINT8 *Storage;
- UINT8 *OpCode;
- CHAR16 *Name;
- UINT16 Offset;
- UINT16 Width;
- CHAR16 *ConfigHdr;
- CHAR16 *RequestElement;
- UINTN MaxLen;
- CHAR16 *StringPtr;
-
- ASSERT ((DatabaseRecord != NULL) && (OpCodeData != NULL) && (ConfigResp != NULL) && (ValueElement != NULL));
-
- OpCode = NULL;
- Name = NULL;
- Width = 0;
- Offset = 0;
-
- PackageListNode = DatabaseRecord->PackageList;
-
- //
- // Search the languages in the specified packagelist.
- //
- for (Link = PackageListNode->FormPkgHdr.ForwardLink; Link != &PackageListNode->FormPkgHdr; Link = Link->ForwardLink) {
- FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);
-
- OpCode = FindQuestionFromStringId (FormPackage, KeywordStrId);
- if (OpCode != NULL) {
- *OpCodeData = OpCode;
- Header = (EFI_IFR_QUESTION_HEADER *)(OpCode + sizeof (EFI_IFR_OP_HEADER));
- //
- // Header->VarStoreId == 0 means no storage for this question.
- //
- ASSERT (Header->VarStoreId != 0);
- DEBUG ((DEBUG_INFO, "Varstore Id: 0x%x\n", Header->VarStoreId));
-
- Storage = FindStorageFromVarId (FormPackage, Header->VarStoreId);
- ASSERT (Storage != NULL);
-
- if (((EFI_IFR_OP_HEADER *)Storage)->OpCode == EFI_IFR_VARSTORE_NAME_VALUE_OP) {
- Name = GetNameFromId (DatabaseRecord, Header->VarStoreInfo.VarName);
- } else {
- Offset = Header->VarStoreInfo.VarOffset;
- Width = GetWidth (OpCode);
- }
-
- RequestElement = ConstructRequestElement (Name, Offset, Width);
-
- ConfigHdr = ConstructConfigHdr (Storage, DatabaseRecord->DriverHandle);
- ASSERT (ConfigHdr != NULL);
-
- MaxLen = StrLen (ConfigHdr) + 1 + StrLen (RequestElement) + 1 + StrLen (L"VALUE=") + StrLen (ValueElement) + 1;
- *ConfigResp = AllocatePool (MaxLen * sizeof (CHAR16));
- if (*ConfigResp == NULL) {
- FreePool (ConfigHdr);
- FreePool (RequestElement);
- return EFI_OUT_OF_RESOURCES;
- }
-
- StringPtr = *ConfigResp;
-
- StrCpyS (StringPtr, MaxLen, ConfigHdr);
-
- StrCatS (StringPtr, MaxLen, L"&");
-
- StrCatS (StringPtr, MaxLen, RequestElement);
-
- StrCatS (StringPtr, MaxLen, L"&");
-
- StrCatS (StringPtr, MaxLen, L"VALUE=");
-
- StrCatS (StringPtr, MaxLen, ValueElement);
-
- FreePool (ConfigHdr);
- FreePool (RequestElement);
-
- return EFI_SUCCESS;
- }
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- Get the Value section from the Hii driver.
-
- This is a internal function.
-
- @param ConfigRequest The input ConfigRequest string.
- @param ValueElement The respond Value section from the hii driver.
-
- @retval Misc value The error status return from ExtractConfig function.
- @retval EFI_OUT_OF_RESOURCES The memory can't be allocated
- @retval EFI_SUCCESS Get the value section success.
-
-**/
-EFI_STATUS
-ExtractValueFromDriver (
- IN CHAR16 *ConfigRequest,
- OUT CHAR16 **ValueElement
- )
-{
- EFI_STATUS Status;
- EFI_STRING Result;
- EFI_STRING Progress;
- CHAR16 *StringPtr;
- CHAR16 *StringEnd;
-
- ASSERT ((ConfigRequest != NULL) && (ValueElement != NULL));
-
- Status = mPrivate.ConfigRouting.ExtractConfig (
- &mPrivate.ConfigRouting,
- (EFI_STRING)ConfigRequest,
- &Progress,
- &Result
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Find Value Section and return it.
- //
- StringPtr = StrStr (Result, L"&VALUE=");
- ASSERT (StringPtr != NULL);
- StringEnd = StrStr (StringPtr + 1, L"&");
- if (StringEnd != NULL) {
- *StringEnd = L'\0';
- }
-
- *ValueElement = AllocateCopyPool (StrSize (StringPtr), StringPtr);
- if (*ValueElement == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- if (StringEnd != NULL) {
- *StringEnd = L'&';
- }
-
- FreePool (Result);
-
- return EFI_SUCCESS;
-}
-
-/**
- Get EFI_STRING_ID info from the input device path, namespace and keyword.
-
- This is a internal function.
-
- @param DevicePath Input device path info.
- @param NameSpace NameSpace format string.
- @param KeywordData Keyword used to get string id.
- @param ProgressErr Return extra error type.
- @param KeywordStringId Return EFI_STRING_ID.
- @param DataBaseRecord DataBase record data for this driver.
-
- @retval EFI_INVALID_PARAMETER Can't find the database record base on the input device path or namespace.
- @retval EFI_NOT_FOUND Can't find the EFI_STRING_ID for the keyword.
- @retval EFI_SUCCESS Find the EFI_STRING_ID.
-
-**/
-EFI_STATUS
-GetStringIdFromDatabase (
- IN EFI_DEVICE_PATH_PROTOCOL **DevicePath,
- IN CHAR8 **NameSpace,
- IN CHAR16 *KeywordData,
- OUT UINT32 *ProgressErr,
- OUT EFI_STRING_ID *KeywordStringId,
- OUT HII_DATABASE_RECORD **DataBaseRecord
- )
-{
- HII_DATABASE_RECORD *Record;
- LIST_ENTRY *Link;
- BOOLEAN FindNameSpace;
- EFI_DEVICE_PATH_PROTOCOL *DestDevicePath;
- UINT8 *DevicePathPkg;
- UINTN DevicePathSize;
-
- ASSERT ((NameSpace != NULL) && (KeywordData != NULL) && (ProgressErr != NULL) && (KeywordStringId != NULL) && (DataBaseRecord != NULL));
-
- FindNameSpace = FALSE;
-
- if (*DevicePath != NULL) {
- //
- // Get DataBaseRecord from device path protocol.
- //
- Record = GetRecordFromDevicePath (*DevicePath);
- if (Record == NULL) {
- //
- // Can't find the DatabaseRecord base on the input device path info.
- // NEED TO CONFIRM the return ProgressErr.
- //
- *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Get string id from the record.
- //
- *ProgressErr = GetStringIdFromRecord (Record, NameSpace, KeywordData, KeywordStringId);
- switch (*ProgressErr) {
- case KEYWORD_HANDLER_NO_ERROR:
- *DataBaseRecord = Record;
- return EFI_SUCCESS;
-
- case KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND:
- return EFI_INVALID_PARAMETER;
-
- default:
- ASSERT (*ProgressErr == KEYWORD_HANDLER_KEYWORD_NOT_FOUND);
- return EFI_NOT_FOUND;
- }
- } else {
- //
- // Find driver which matches the routing data.
- //
- for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {
- Record = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
-
- *ProgressErr = GetStringIdFromRecord (Record, NameSpace, KeywordData, KeywordStringId);
- if (*ProgressErr == KEYWORD_HANDLER_NO_ERROR) {
- *DataBaseRecord = Record;
-
- if ((DevicePathPkg = Record->PackageList->DevicePathPkg) != NULL) {
- DestDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)(DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER));
- DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DestDevicePath);
- *DevicePath = AllocateCopyPool (DevicePathSize, DestDevicePath);
- if (*DevicePath == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- } else {
- //
- // Need to verify this ASSERT.
- //
- ASSERT (FALSE);
- }
-
- return EFI_SUCCESS;
- } else if (*ProgressErr == KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR) {
- return EFI_OUT_OF_RESOURCES;
- } else if (*ProgressErr == KEYWORD_HANDLER_KEYWORD_NOT_FOUND) {
- FindNameSpace = TRUE;
- }
- }
-
- //
- // When PathHdr not input, if ever find the namespace, will return KEYWORD_HANDLER_KEYWORD_NOT_FOUND.
- // This is a bit more progress than KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND.
- //
- if (FindNameSpace) {
- return EFI_NOT_FOUND;
- } else {
- return EFI_INVALID_PARAMETER;
- }
- }
-}
-
-/**
- Generate the KeywordResp String.
-
- <KeywordResp> ::= <NameSpaceId><PathHdr>'&'<Keyword>'&VALUE='<Number>['&READONLY']
-
- @param NameSpace NameSpace format string.
- @param DevicePath Input device path info.
- @param KeywordData Keyword used to get string id.
- @param ValueStr The value section for the keyword.
- @param ReadOnly Whether this value is readonly.
- @param KeywordResp Return the point to the KeywordResp string.
-
- @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.
- @retval EFI_SUCCESS Generate the KeywordResp string.
-
-**/
-EFI_STATUS
-GenerateKeywordResp (
- IN CHAR8 *NameSpace,
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- IN EFI_STRING KeywordData,
- IN EFI_STRING ValueStr,
- IN BOOLEAN ReadOnly,
- OUT EFI_STRING *KeywordResp
- )
-{
- UINTN RespStrLen;
- CHAR16 *RespStr;
- CHAR16 *PathHdr;
- CHAR16 *UnicodeNameSpace;
- UINTN NameSpaceLength;
-
- ASSERT ((NameSpace != NULL) && (DevicePath != NULL) && (KeywordData != NULL) && (ValueStr != NULL) && (KeywordResp != NULL));
-
- //
- // 1. Calculate the string length.
- //
- //
- // 1.1 NameSpaceId size.
- // 'NAMESPACE='<String>
- //
- NameSpaceLength = AsciiStrLen (NameSpace);
- RespStrLen = 10 + NameSpaceLength;
- UnicodeNameSpace = AllocatePool ((NameSpaceLength + 1) * sizeof (CHAR16));
- if (UnicodeNameSpace == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- AsciiStrToUnicodeStrS (NameSpace, UnicodeNameSpace, NameSpaceLength + 1);
-
- //
- // 1.2 PathHdr size.
- // PATH=<UEFI binary Device Path represented as hex number>'&'
- // Attention: The output include the '&' at the end.
- //
- GenerateSubStr (
- L"&PATH=",
- GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DevicePath),
- (VOID *)DevicePath,
- 1,
- &PathHdr
- );
- RespStrLen += StrLen (PathHdr);
-
- //
- // 1.3 Keyword section.
- // 'KEYWORD='<String>[':'<DecCh>(1/4)]
- //
- RespStrLen += 8 + StrLen (KeywordData);
-
- //
- // 1.4 Value section.
- // ValueStr = '&VALUE='<Number>
- //
- RespStrLen += StrLen (ValueStr);
-
- //
- // 1.5 ReadOnly Section.
- // '&READONLY'
- //
- if (ReadOnly) {
- RespStrLen += 9;
- }
-
- //
- // 2. Allocate the buffer and create the KeywordResp string include '\0'.
- //
- RespStrLen += 1;
- *KeywordResp = AllocatePool (RespStrLen * sizeof (CHAR16));
- if (*KeywordResp == NULL) {
- if (UnicodeNameSpace != NULL) {
- FreePool (UnicodeNameSpace);
- }
-
- return EFI_OUT_OF_RESOURCES;
- }
-
- RespStr = *KeywordResp;
-
- //
- // 2.1 Copy NameSpaceId section.
- //
- StrCpyS (RespStr, RespStrLen, L"NAMESPACE=");
-
- StrCatS (RespStr, RespStrLen, UnicodeNameSpace);
-
- //
- // 2.2 Copy PathHdr section.
- //
- StrCatS (RespStr, RespStrLen, PathHdr);
-
- //
- // 2.3 Copy Keyword section.
- //
- StrCatS (RespStr, RespStrLen, L"KEYWORD=");
-
- StrCatS (RespStr, RespStrLen, KeywordData);
-
- //
- // 2.4 Copy the Value section.
- //
- StrCatS (RespStr, RespStrLen, ValueStr);
-
- //
- // 2.5 Copy ReadOnly section if exist.
- //
- if (ReadOnly) {
- StrCatS (RespStr, RespStrLen, L"&READONLY");
- }
-
- if (UnicodeNameSpace != NULL) {
- FreePool (UnicodeNameSpace);
- }
-
- if (PathHdr != NULL) {
- FreePool (PathHdr);
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Merge the KeywordResp String to MultiKeywordResp string.
-
- This is a internal function.
-
- @param MultiKeywordResp The existed multikeywordresp string.
- @param KeywordResp The input keywordResp string.
-
- @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.
- @retval EFI_SUCCESS Generate the MultiKeywordResp string.
-
-**/
-EFI_STATUS
-MergeToMultiKeywordResp (
- IN OUT EFI_STRING *MultiKeywordResp,
- IN EFI_STRING *KeywordResp
- )
-{
- UINTN MultiKeywordRespLen;
- EFI_STRING StringPtr;
-
- if (*MultiKeywordResp == NULL) {
- *MultiKeywordResp = *KeywordResp;
- *KeywordResp = NULL;
- return EFI_SUCCESS;
- }
-
- MultiKeywordRespLen = (StrLen (*MultiKeywordResp) + 1 + StrLen (*KeywordResp) + 1) * sizeof (CHAR16);
-
- StringPtr = ReallocatePool (
- StrSize (*MultiKeywordResp),
- MultiKeywordRespLen,
- *MultiKeywordResp
- );
- if (StringPtr == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- *MultiKeywordResp = StringPtr;
-
- StrCatS (StringPtr, MultiKeywordRespLen / sizeof (CHAR16), L"&");
-
- StrCatS (StringPtr, MultiKeywordRespLen / sizeof (CHAR16), *KeywordResp);
-
- return EFI_SUCCESS;
-}
-
-/**
- Enumerate all keyword in the system.
-
- If error occur when parse one keyword, just skip it and parse the next one.
-
- This is a internal function.
-
- @param NameSpace The namespace used to search the string.
- @param MultiResp Return the MultiKeywordResp string for the system.
- @param ProgressErr Return the error status.
-
- @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.
- @retval EFI_SUCCESS Generate the MultiKeywordResp string.
- @retval EFI_NOT_FOUND No keyword found.
-
-**/
-EFI_STATUS
-EnumerateAllKeywords (
- IN CHAR8 *NameSpace,
- OUT EFI_STRING *MultiResp,
- OUT UINT32 *ProgressErr
- )
-{
- LIST_ENTRY *Link;
- LIST_ENTRY *StringLink;
- UINT8 *DevicePathPkg;
- UINT8 *DevicePath;
- HII_DATABASE_RECORD *DataBaseRecord;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
- HII_STRING_PACKAGE_INSTANCE *StringPackage;
- CHAR8 *LocalNameSpace;
- EFI_STRING_ID NextStringId;
- EFI_STATUS Status;
- UINT8 *OpCode;
- CHAR16 *ConfigRequest;
- CHAR16 *ValueElement;
- CHAR16 *KeywordResp;
- CHAR16 *MultiKeywordResp;
- CHAR16 *KeywordData;
- BOOLEAN ReadOnly;
- BOOLEAN FindKeywordPackages;
-
- DataBaseRecord = NULL;
- Status = EFI_SUCCESS;
- MultiKeywordResp = NULL;
- DevicePath = NULL;
- LocalNameSpace = NULL;
- ConfigRequest = NULL;
- ValueElement = NULL;
- KeywordResp = NULL;
- FindKeywordPackages = FALSE;
-
- if (NameSpace == NULL) {
- NameSpace = UEFI_CONFIG_LANG;
- }
-
- //
- // Find driver which matches the routing data.
- //
- for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {
- DataBaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- if ((DevicePathPkg = DataBaseRecord->PackageList->DevicePathPkg) != NULL) {
- DevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
- }
-
- PackageListNode = DataBaseRecord->PackageList;
-
- for (StringLink = PackageListNode->StringPkgHdr.ForwardLink; StringLink != &PackageListNode->StringPkgHdr; StringLink = StringLink->ForwardLink) {
- StringPackage = CR (StringLink, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
-
- //
- // Check whether has keyword string package.
- //
- if (AsciiStrnCmp (NameSpace, StringPackage->StringPkgHdr->Language, AsciiStrLen (NameSpace)) == 0) {
- FindKeywordPackages = TRUE;
- //
- // Keep the NameSpace string.
- //
- LocalNameSpace = AllocateCopyPool (AsciiStrSize (StringPackage->StringPkgHdr->Language), StringPackage->StringPkgHdr->Language);
- if (LocalNameSpace == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // 1 means just begin the enumerate the valid string ids.
- // StringId == 1 is always used to save the language for this string package.
- // Any valid string start from 2. so here initial it to 1.
- //
- NextStringId = 1;
-
- //
- // Enumerate all valid stringid in the package.
- //
- while ((NextStringId = GetNextStringId (StringPackage, NextStringId, &KeywordData)) != 0) {
- //
- // 3.3 Construct the ConfigRequest string.
- //
- Status = ExtractConfigRequest (DataBaseRecord, NextStringId, &OpCode, &ConfigRequest);
- if (EFI_ERROR (Status)) {
- //
- // If can't generate ConfigRequest for this question, skip it and start the next.
- //
- goto Error;
- }
-
- //
- // 3.4 Extract Value for the input keyword.
- //
- Status = ExtractValueFromDriver (ConfigRequest, &ValueElement);
- if (EFI_ERROR (Status)) {
- if (Status != EFI_OUT_OF_RESOURCES) {
- //
- // If can't generate ConfigRequest for this question, skip it and start the next.
- //
- goto Error;
- }
-
- //
- // If EFI_OUT_OF_RESOURCES error occur, no need to continue.
- //
- goto Done;
- }
-
- //
- // Extract readonly flag from opcode.
- //
- ReadOnly = ExtractReadOnlyFromOpCode (OpCode);
-
- //
- // 5. Generate KeywordResp string.
- //
- ASSERT (DevicePath != NULL);
- Status = GenerateKeywordResp (LocalNameSpace, (EFI_DEVICE_PATH_PROTOCOL *)DevicePath, KeywordData, ValueElement, ReadOnly, &KeywordResp);
- if (Status != EFI_SUCCESS) {
- //
- // If EFI_OUT_OF_RESOURCES error occur, no need to continue.
- //
- goto Done;
- }
-
- //
- // 6. Merge to the MultiKeywordResp string.
- //
- Status = MergeToMultiKeywordResp (&MultiKeywordResp, &KeywordResp);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
-Error:
- //
- // Clean the temp buffer to later use again.
- //
- if (ConfigRequest != NULL) {
- FreePool (ConfigRequest);
- ConfigRequest = NULL;
- }
-
- if (ValueElement != NULL) {
- FreePool (ValueElement);
- ValueElement = NULL;
- }
-
- if (KeywordResp != NULL) {
- FreePool (KeywordResp);
- KeywordResp = NULL;
- }
- }
-
- if (LocalNameSpace != NULL) {
- FreePool (LocalNameSpace);
- LocalNameSpace = NULL;
- }
- }
- }
- }
-
- //
- // return the already get MultiKeywordString even error occurred.
- //
- if (MultiKeywordResp == NULL) {
- Status = EFI_NOT_FOUND;
- if (!FindKeywordPackages) {
- *ProgressErr = KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND;
- } else {
- *ProgressErr = KEYWORD_HANDLER_KEYWORD_NOT_FOUND;
- }
- } else {
- Status = EFI_SUCCESS;
- }
-
- *MultiResp = MultiKeywordResp;
-
-Done:
- if (LocalNameSpace != NULL) {
- FreePool (LocalNameSpace);
- }
-
- if (ConfigRequest != NULL) {
- FreePool (ConfigRequest);
- }
-
- if (ValueElement != NULL) {
- FreePool (ValueElement);
- }
-
- return Status;
-}
-
-/**
-
- This function accepts a <MultiKeywordResp> formatted string, finds the associated
- keyword owners, creates a <MultiConfigResp> string from it and forwards it to the
- EFI_HII_ROUTING_PROTOCOL.RouteConfig function.
-
- If there is an issue in resolving the contents of the KeywordString, then the
- function returns an error and also sets the Progress and ProgressErr with the
- appropriate information about where the issue occurred and additional data about
- the nature of the issue.
-
- In the case when KeywordString containing multiple keywords, when an EFI_NOT_FOUND
- error is generated during processing the second or later keyword element, the system
- storage associated with earlier keywords is not modified. All elements of the
- KeywordString must successfully pass all tests for format and access prior to making
- any modifications to storage.
-
- In the case when EFI_DEVICE_ERROR is returned from the processing of a KeywordString
- containing multiple keywords, the state of storage associated with earlier keywords
- is undefined.
-
-
- @param This Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.
-
- @param KeywordString A null-terminated string in <MultiKeywordResp> format.
-
- @param Progress On return, points to a character in the KeywordString.
- Points to the string's NULL terminator if the request
- was successful. Points to the most recent '&' before
- the first failing name / value pair (or the beginning
- of the string if the failure is in the first name / value
- pair) if the request was not successful.
-
- @param ProgressErr If during the processing of the KeywordString there was
- a failure, this parameter gives additional information
- about the possible source of the problem. The various
- errors are defined in "Related Definitions" below.
-
-
- @retval EFI_SUCCESS The specified action was completed successfully.
-
- @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
- 1. KeywordString is NULL.
- 2. Parsing of the KeywordString resulted in an
- error. See Progress and ProgressErr for more data.
-
- @retval EFI_NOT_FOUND An element of the KeywordString was not found.
- See ProgressErr for more data.
-
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- See ProgressErr for more data.
-
- @retval EFI_ACCESS_DENIED The action violated system policy. See ProgressErr
- for more data.
-
- @retval EFI_DEVICE_ERROR An unexpected system error occurred. See ProgressErr
- for more data.
-
-**/
-EFI_STATUS
-EFIAPI
-EfiConfigKeywordHandlerSetData (
- IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *This,
- IN CONST EFI_STRING KeywordString,
- OUT EFI_STRING *Progress,
- OUT UINT32 *ProgressErr
- )
-{
- CHAR8 *NameSpace;
- EFI_STATUS Status;
- CHAR16 *StringPtr;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- CHAR16 *NextStringPtr;
- CHAR16 *KeywordData;
- EFI_STRING_ID KeywordStringId;
- UINT32 RetVal;
- HII_DATABASE_RECORD *DataBaseRecord;
- UINT8 *OpCode;
- CHAR16 *ConfigResp;
- CHAR16 *MultiConfigResp;
- CHAR16 *ValueElement;
- BOOLEAN ReadOnly;
- EFI_STRING InternalProgress;
- CHAR16 *TempString;
- CHAR16 *KeywordStartPos;
-
- if ((This == NULL) || (Progress == NULL) || (ProgressErr == NULL) || (KeywordString == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- *Progress = KeywordString;
- *ProgressErr = KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;
- Status = EFI_SUCCESS;
- MultiConfigResp = NULL;
- NameSpace = NULL;
- DevicePath = NULL;
- KeywordData = NULL;
- ValueElement = NULL;
- ConfigResp = NULL;
- KeywordStartPos = NULL;
- KeywordStringId = 0;
-
- //
- // Use temp string to avoid changing input string buffer.
- //
- TempString = AllocateCopyPool (StrSize (KeywordString), KeywordString);
- ASSERT (TempString != NULL);
- StringPtr = TempString;
-
- while ((StringPtr != NULL) && (*StringPtr != L'\0')) {
- //
- // 1. Get NameSpace from NameSpaceId keyword.
- //
- Status = ExtractNameSpace (StringPtr, &NameSpace, &NextStringPtr);
- if (EFI_ERROR (Status)) {
- *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
- goto Done;
- }
-
- ASSERT (NameSpace != NULL);
- //
- // 1.1 Check whether the input namespace is valid.
- //
- if (AsciiStrnCmp (NameSpace, UEFI_CONFIG_LANG, AsciiStrLen (UEFI_CONFIG_LANG)) != 0) {
- *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- StringPtr = NextStringPtr;
-
- //
- // 2. Get possible Device Path info from KeywordString.
- //
- Status = ExtractDevicePath (StringPtr, (UINT8 **)&DevicePath, &NextStringPtr);
- if (EFI_ERROR (Status)) {
- *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
- goto Done;
- }
-
- StringPtr = NextStringPtr;
-
- //
- // 3. Extract keyword from the KeywordRequest string.
- //
- KeywordStartPos = StringPtr;
- Status = ExtractKeyword (StringPtr, &KeywordData, &NextStringPtr);
- if (EFI_ERROR (Status)) {
- //
- // Can't find Keyword base on the input device path info.
- //
- *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- StringPtr = NextStringPtr;
-
- //
- // 4. Extract Value from the KeywordRequest string.
- //
- Status = ExtractValue (StringPtr, &ValueElement, &NextStringPtr);
- if (EFI_ERROR (Status)) {
- //
- // Can't find Value base on the input device path info.
- //
- *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- StringPtr = NextStringPtr;
-
- //
- // 5. Find READONLY tag.
- //
- if ((StringPtr != NULL) && (StrnCmp (StringPtr, L"&READONLY", StrLen (L"&READONLY")) == 0)) {
- ReadOnly = TRUE;
- StringPtr += StrLen (L"&READONLY");
- } else {
- ReadOnly = FALSE;
- }
-
- //
- // 6. Get EFI_STRING_ID for the input keyword.
- //
- Status = GetStringIdFromDatabase (&DevicePath, &NameSpace, KeywordData, &RetVal, &KeywordStringId, &DataBaseRecord);
- if (EFI_ERROR (Status)) {
- *ProgressErr = RetVal;
- goto Done;
- }
-
- //
- // 7. Construct the ConfigRequest string.
- //
- Status = ExtractConfigResp (DataBaseRecord, KeywordStringId, ValueElement, &OpCode, &ConfigResp);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- //
- // 8. Check the readonly flag.
- //
- if (ExtractReadOnlyFromOpCode (OpCode) != ReadOnly) {
- //
- // Extracting readonly flag form opcode and extracting "READONLY" tag form KeywordString should have the same results.
- // If not, the input KeywordString must be incorrect, return the error status to caller.
- //
- *ProgressErr = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- if (ReadOnly) {
- *ProgressErr = KEYWORD_HANDLER_ACCESS_NOT_PERMITTED;
- Status = EFI_ACCESS_DENIED;
- goto Done;
- }
-
- //
- // 9. Merge to the MultiKeywordResp string.
- //
- Status = MergeToMultiKeywordResp (&MultiConfigResp, &ConfigResp);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- //
- // 10. Clean the temp buffer point.
- //
- FreePool (NameSpace);
- FreePool (DevicePath);
- FreePool (KeywordData);
- FreePool (ValueElement);
- NameSpace = NULL;
- DevicePath = NULL;
- KeywordData = NULL;
- ValueElement = NULL;
- if (ConfigResp != NULL) {
- FreePool (ConfigResp);
- ConfigResp = NULL;
- }
-
- KeywordStartPos = NULL;
- }
-
- //
- // 11. Set value to driver.
- //
- Status = mPrivate.ConfigRouting.RouteConfig (
- &mPrivate.ConfigRouting,
- (EFI_STRING)MultiConfigResp,
- &InternalProgress
- );
- if (EFI_ERROR (Status)) {
- Status = EFI_DEVICE_ERROR;
- goto Done;
- }
-
- *ProgressErr = KEYWORD_HANDLER_NO_ERROR;
-
-Done:
- if (KeywordStartPos != NULL) {
- *Progress = KeywordString + (KeywordStartPos - TempString);
- } else {
- *Progress = KeywordString + (StringPtr - TempString);
- }
-
- ASSERT (TempString != NULL);
- FreePool (TempString);
- if (NameSpace != NULL) {
- FreePool (NameSpace);
- }
-
- if (DevicePath != NULL) {
- FreePool (DevicePath);
- }
-
- if (KeywordData != NULL) {
- FreePool (KeywordData);
- }
-
- if (ValueElement != NULL) {
- FreePool (ValueElement);
- }
-
- if (ConfigResp != NULL) {
- FreePool (ConfigResp);
- }
-
- if ((MultiConfigResp != NULL) && (MultiConfigResp != ConfigResp)) {
- FreePool (MultiConfigResp);
- }
-
- return Status;
-}
-
-/**
-
- This function accepts a <MultiKeywordRequest> formatted string, finds the underlying
- keyword owners, creates a <MultiConfigRequest> string from it and forwards it to the
- EFI_HII_ROUTING_PROTOCOL.ExtractConfig function.
-
- If there is an issue in resolving the contents of the KeywordString, then the function
- returns an EFI_INVALID_PARAMETER and also set the Progress and ProgressErr with the
- appropriate information about where the issue occurred and additional data about the
- nature of the issue.
-
- In the case when KeywordString is NULL, or contains multiple keywords, or when
- EFI_NOT_FOUND is generated while processing the keyword elements, the Results string
- contains values returned for all keywords processed prior to the keyword generating the
- error but no values for the keyword with error or any following keywords.
-
-
- @param This Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.
-
- @param NameSpaceId A null-terminated string containing the platform configuration
- language to search through in the system. If a NULL is passed
- in, then it is assumed that any platform configuration language
- with the prefix of "x-UEFI-" are searched.
-
- @param KeywordString A null-terminated string in <MultiKeywordRequest> format. If a
- NULL is passed in the KeywordString field, all of the known
- keywords in the system for the NameSpaceId specified are
- returned in the Results field.
-
- @param Progress On return, points to a character in the KeywordString. Points
- to the string's NULL terminator if the request was successful.
- Points to the most recent '&' before the first failing name / value
- pair (or the beginning of the string if the failure is in the first
- name / value pair) if the request was not successful.
-
- @param ProgressErr If during the processing of the KeywordString there was a
- failure, this parameter gives additional information about the
- possible source of the problem. See the definitions in SetData()
- for valid value definitions.
-
- @param Results A null-terminated string in <MultiKeywordResp> format is returned
- which has all the values filled in for the keywords in the
- KeywordString. This is a callee-allocated field, and must be freed
- by the caller after being used.
-
- @retval EFI_SUCCESS The specified action was completed successfully.
-
- @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
- 1.Progress, ProgressErr, or Results is NULL.
- 2.Parsing of the KeywordString resulted in an error. See
- Progress and ProgressErr for more data.
-
-
- @retval EFI_NOT_FOUND An element of the KeywordString was not found. See
- ProgressErr for more data.
-
- @retval EFI_NOT_FOUND The NamespaceId specified was not found. See ProgressErr
- for more data.
-
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. See
- ProgressErr for more data.
-
- @retval EFI_ACCESS_DENIED The action violated system policy. See ProgressErr for
- more data.
-
- @retval EFI_DEVICE_ERROR An unexpected system error occurred. See ProgressErr
- for more data.
-
-**/
-EFI_STATUS
-EFIAPI
-EfiConfigKeywordHandlerGetData (
- IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *This,
- IN CONST EFI_STRING NameSpaceId OPTIONAL,
- IN CONST EFI_STRING KeywordString OPTIONAL,
- OUT EFI_STRING *Progress,
- OUT UINT32 *ProgressErr,
- OUT EFI_STRING *Results
- )
-{
- CHAR8 *NameSpace;
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- HII_DATABASE_RECORD *DataBaseRecord;
- CHAR16 *StringPtr;
- CHAR16 *NextStringPtr;
- CHAR16 *KeywordData;
- EFI_STRING_ID KeywordStringId;
- UINT8 *OpCode;
- CHAR16 *ConfigRequest;
- CHAR16 *ValueElement;
- UINT32 RetVal;
- BOOLEAN ReadOnly;
- CHAR16 *KeywordResp;
- CHAR16 *MultiKeywordResp;
- CHAR16 *TempString;
-
- if ((This == NULL) || (Progress == NULL) || (ProgressErr == NULL) || (Results == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- *ProgressErr = KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;
- Status = EFI_SUCCESS;
- DevicePath = NULL;
- NameSpace = NULL;
- KeywordData = NULL;
- ConfigRequest = NULL;
- StringPtr = KeywordString;
- ReadOnly = FALSE;
- MultiKeywordResp = NULL;
- KeywordStringId = 0;
- TempString = NULL;
-
- //
- // Use temp string to avoid changing input string buffer.
- //
- if (NameSpaceId != NULL) {
- TempString = AllocateCopyPool (StrSize (NameSpaceId), NameSpaceId);
- ASSERT (TempString != NULL);
- }
-
- //
- // 1. Get NameSpace from NameSpaceId keyword.
- //
- Status = ExtractNameSpace (TempString, &NameSpace, NULL);
- if (TempString != NULL) {
- FreePool (TempString);
- TempString = NULL;
- }
-
- if (EFI_ERROR (Status)) {
- *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
- return Status;
- }
-
- //
- // 1.1 Check whether the input namespace is valid.
- //
- if (NameSpace != NULL) {
- if (AsciiStrnCmp (NameSpace, UEFI_CONFIG_LANG, AsciiStrLen (UEFI_CONFIG_LANG)) != 0) {
- *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
- return EFI_INVALID_PARAMETER;
- }
- }
-
- if (KeywordString != NULL) {
- //
- // Use temp string to avoid changing input string buffer.
- //
- TempString = AllocateCopyPool (StrSize (KeywordString), KeywordString);
- ASSERT (TempString != NULL);
- StringPtr = TempString;
-
- while (*StringPtr != L'\0') {
- //
- // 2. Get possible Device Path info from KeywordString.
- //
- Status = ExtractDevicePath (StringPtr, (UINT8 **)&DevicePath, &NextStringPtr);
- if (EFI_ERROR (Status)) {
- *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
- goto Done;
- }
-
- StringPtr = NextStringPtr;
-
- //
- // 3. Process Keyword section from the input keywordRequest string.
- //
- // 3.1 Extract keyword from the KeywordRequest string.
- //
- Status = ExtractKeyword (StringPtr, &KeywordData, &NextStringPtr);
- if (EFI_ERROR (Status)) {
- //
- // Can't find Keyword base on the input device path info.
- //
- *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // 3.2 Get EFI_STRING_ID for the input keyword.
- //
- Status = GetStringIdFromDatabase (&DevicePath, &NameSpace, KeywordData, &RetVal, &KeywordStringId, &DataBaseRecord);
- if (EFI_ERROR (Status)) {
- *ProgressErr = RetVal;
- goto Done;
- }
-
- //
- // 3.3 Construct the ConfigRequest string.
- //
- Status = ExtractConfigRequest (DataBaseRecord, KeywordStringId, &OpCode, &ConfigRequest);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- //
- // 3.4 Extract Value for the input keyword.
- //
- Status = ExtractValueFromDriver (ConfigRequest, &ValueElement);
- if (EFI_ERROR (Status)) {
- if (Status != EFI_OUT_OF_RESOURCES) {
- Status = EFI_DEVICE_ERROR;
- }
-
- goto Done;
- }
-
- StringPtr = NextStringPtr;
-
- //
- // 4. Process the possible filter section.
- //
- RetVal = ValidateFilter (OpCode, StringPtr, &NextStringPtr, &ReadOnly);
- if (RetVal != KEYWORD_HANDLER_NO_ERROR) {
- *ProgressErr = RetVal;
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- StringPtr = NextStringPtr;
-
- //
- // 5. Generate KeywordResp string.
- //
- Status = GenerateKeywordResp (NameSpace, DevicePath, KeywordData, ValueElement, ReadOnly, &KeywordResp);
- if (Status != EFI_SUCCESS) {
- goto Done;
- }
-
- //
- // 6. Merge to the MultiKeywordResp string.
- //
- Status = MergeToMultiKeywordResp (&MultiKeywordResp, &KeywordResp);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- //
- // 7. Update return value.
- //
- *Results = MultiKeywordResp;
-
- //
- // 8. Clean the temp buffer.
- //
- FreePool (DevicePath);
- FreePool (KeywordData);
- FreePool (ValueElement);
- FreePool (ConfigRequest);
- DevicePath = NULL;
- KeywordData = NULL;
- ValueElement = NULL;
- ConfigRequest = NULL;
- if (KeywordResp != NULL) {
- FreePool (KeywordResp);
- KeywordResp = NULL;
- }
- }
- } else {
- //
- // Enumerate all keyword in the system.
- //
- Status = EnumerateAllKeywords (NameSpace, &MultiKeywordResp, ProgressErr);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- *Results = MultiKeywordResp;
- }
-
- *ProgressErr = KEYWORD_HANDLER_NO_ERROR;
-
-Done:
- *Progress = KeywordString + (StringPtr - TempString);
-
- if (TempString != NULL) {
- FreePool (TempString);
- }
-
- if (NameSpace != NULL) {
- FreePool (NameSpace);
- }
-
- if (DevicePath != NULL) {
- FreePool (DevicePath);
- }
-
- if (KeywordData != NULL) {
- FreePool (KeywordData);
- }
-
- return Status;
-}
+/** @file
+Implementation of interfaces function for EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL.
+
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "HiiDatabase.h"
+
+extern HII_DATABASE_PRIVATE_DATA mPrivate;
+
+/**
+ Convert the hex UNICODE %02x encoding of a UEFI device path to binary
+ from <PathHdr> of <MultiKeywordRequest>.
+
+ This is a internal function.
+
+ @param String MultiKeywordRequest string.
+ @param DevicePathData Binary of a UEFI device path.
+ @param NextString string follow the possible PathHdr string.
+
+ @retval EFI_INVALID_PARAMETER The device path is not valid or the incoming parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES Lake of resources to store necessary structures.
+ @retval EFI_SUCCESS The device path is retrieved and translated to binary format.
+ The Input string not include PathHdr section.
+
+**/
+EFI_STATUS
+ExtractDevicePath (
+ IN EFI_STRING String,
+ OUT UINT8 **DevicePathData,
+ OUT EFI_STRING *NextString
+ )
+{
+ UINTN Length;
+ EFI_STRING PathHdr;
+ UINT8 *DevicePathBuffer;
+ CHAR16 TemStr[2];
+ UINTN Index;
+ UINT8 DigitUint8;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ ASSERT (NextString != NULL && DevicePathData != NULL);
+
+ //
+ // KeywordRequest == NULL case.
+ //
+ if (String == NULL) {
+ *DevicePathData = NULL;
+ *NextString = NULL;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Skip '&' if exist.
+ //
+ if (*String == L'&') {
+ String++;
+ }
+
+ //
+ // Find the 'PATH=' of <PathHdr>.
+ //
+ if (StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0) {
+ if (StrnCmp (String, L"KEYWORD=", StrLen (L"KEYWORD=")) != 0) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ //
+ // Not include PathHdr, return success and DevicePath = NULL.
+ //
+ *DevicePathData = NULL;
+ *NextString = String;
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Check whether path data does exist.
+ //
+ String += StrLen (L"PATH=");
+ if (*String == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PathHdr = String;
+
+ //
+ // The content between 'PATH=' of <ConfigHdr> and '&' of next element
+ // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
+ // of UEFI device path.
+ //
+ for (Length = 0; *String != 0 && *String != L'&'; String++, Length++) {
+ }
+
+ //
+ // Save the return next keyword string value.
+ //
+ *NextString = String;
+
+ //
+ // Check DevicePath Length
+ //
+ if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
+ // as the device path resides in RAM memory.
+ // Translate the data into binary.
+ //
+ DevicePathBuffer = (UINT8 *)AllocateZeroPool ((Length + 1) / 2);
+ if (DevicePathBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Convert DevicePath
+ //
+ ZeroMem (TemStr, sizeof (TemStr));
+ for (Index = 0; Index < Length; Index++) {
+ TemStr[0] = PathHdr[Index];
+ DigitUint8 = (UINT8)StrHexToUint64 (TemStr);
+ if ((Index & 1) == 0) {
+ DevicePathBuffer[Index/2] = DigitUint8;
+ } else {
+ DevicePathBuffer[Index/2] = (UINT8)((DevicePathBuffer[Index/2] << 4) + DigitUint8);
+ }
+ }
+
+ //
+ // Validate DevicePath
+ //
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePathBuffer;
+ while (!IsDevicePathEnd (DevicePath)) {
+ if ((DevicePath->Type == 0) || (DevicePath->SubType == 0) || (DevicePathNodeLength (DevicePath) < sizeof (EFI_DEVICE_PATH_PROTOCOL))) {
+ //
+ // Invalid device path
+ //
+ FreePool (DevicePathBuffer);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DevicePath = NextDevicePathNode (DevicePath);
+ }
+
+ //
+ // return the device path
+ //
+ *DevicePathData = DevicePathBuffer;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get NameSpace from the input NameSpaceId string.
+
+ This is a internal function.
+
+ @param String <NameSpaceId> format string.
+ @param NameSpace Return the name space string.
+ @param NextString Return the next string follow namespace.
+
+ @retval EFI_SUCCESS Get the namespace string success.
+ @retval EFI_INVALID_PARAMETER The NameSpaceId string not follow spec definition.
+
+**/
+EFI_STATUS
+ExtractNameSpace (
+ IN EFI_STRING String,
+ OUT CHAR8 **NameSpace,
+ OUT EFI_STRING *NextString
+ )
+{
+ CHAR16 *TmpPtr;
+ UINTN NameSpaceSize;
+
+ ASSERT (NameSpace != NULL);
+
+ TmpPtr = NULL;
+
+ //
+ // Input NameSpaceId == NULL
+ //
+ if (String == NULL) {
+ *NameSpace = NULL;
+ if (NextString != NULL) {
+ *NextString = NULL;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Skip '&' if exist.
+ //
+ if (*String == L'&') {
+ String++;
+ }
+
+ if (StrnCmp (String, L"NAMESPACE=", StrLen (L"NAMESPACE=")) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ String += StrLen (L"NAMESPACE=");
+
+ TmpPtr = StrStr (String, L"&");
+ if (TmpPtr != NULL) {
+ *TmpPtr = 0;
+ }
+
+ if (NextString != NULL) {
+ *NextString = String + StrLen (String);
+ }
+
+ //
+ // Input NameSpace is unicode string. The language in String package is ascii string.
+ // Here will convert the unicode string to ascii and save it.
+ //
+ NameSpaceSize = StrLen (String) + 1;
+ *NameSpace = AllocatePool (NameSpaceSize);
+ if (*NameSpace == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ UnicodeStrToAsciiStrS (String, *NameSpace, NameSpaceSize);
+
+ if (TmpPtr != NULL) {
+ *TmpPtr = L'&';
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get Keyword from the input KeywordRequest string.
+
+ This is a internal function.
+
+ @param String KeywordRequestformat string.
+ @param Keyword return the extract keyword string.
+ @param NextString return the next string follow this keyword section.
+
+ @retval EFI_SUCCESS Success to get the keyword string.
+ @retval EFI_INVALID_PARAMETER Parse the input string return error.
+
+**/
+EFI_STATUS
+ExtractKeyword (
+ IN EFI_STRING String,
+ OUT EFI_STRING *Keyword,
+ OUT EFI_STRING *NextString
+ )
+{
+ EFI_STRING TmpPtr;
+
+ ASSERT ((Keyword != NULL) && (NextString != NULL));
+
+ TmpPtr = NULL;
+
+ //
+ // KeywordRequest == NULL case.
+ //
+ if (String == NULL) {
+ *Keyword = NULL;
+ *NextString = NULL;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Skip '&' if exist.
+ //
+ if (*String == L'&') {
+ String++;
+ }
+
+ if (StrnCmp (String, L"KEYWORD=", StrLen (L"KEYWORD=")) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ String += StrLen (L"KEYWORD=");
+
+ TmpPtr = StrStr (String, L"&");
+ if (TmpPtr != NULL) {
+ *TmpPtr = 0;
+ }
+
+ *NextString = String + StrLen (String);
+
+ *Keyword = AllocateCopyPool (StrSize (String), String);
+ if (*Keyword == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (TmpPtr != NULL) {
+ *TmpPtr = L'&';
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get value from the input KeywordRequest string.
+
+ This is a internal function.
+
+ @param String KeywordRequestformat string.
+ @param Value return the extract value string.
+ @param NextString return the next string follow this keyword section.
+
+ @retval EFI_SUCCESS Success to get the keyword string.
+ @retval EFI_INVALID_PARAMETER Parse the input string return error.
+
+**/
+EFI_STATUS
+ExtractValue (
+ IN EFI_STRING String,
+ OUT EFI_STRING *Value,
+ OUT EFI_STRING *NextString
+ )
+{
+ EFI_STRING TmpPtr;
+
+ ASSERT ((Value != NULL) && (NextString != NULL) && (String != NULL));
+
+ //
+ // Skip '&' if exist.
+ //
+ if (*String == L'&') {
+ String++;
+ }
+
+ if (StrnCmp (String, L"VALUE=", StrLen (L"VALUE=")) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ String += StrLen (L"VALUE=");
+
+ TmpPtr = StrStr (String, L"&");
+ if (TmpPtr != NULL) {
+ *TmpPtr = 0;
+ }
+
+ *NextString = String + StrLen (String);
+
+ *Value = AllocateCopyPool (StrSize (String), String);
+ if (*Value == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (TmpPtr != NULL) {
+ *TmpPtr = L'&';
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get filter from the input KeywordRequest string.
+
+ This is a internal function.
+
+ @param String KeywordRequestformat string.
+ @param FilterFlags return the filter condition.
+ @param NextString return the next string follow this keyword section.
+
+ @retval EFI_SUCCESS Success to get the keyword string.
+ @retval EFI_INVALID_PARAMETER Parse the input string return error.
+
+**/
+BOOLEAN
+ExtractFilter (
+ IN EFI_STRING String,
+ OUT UINT8 *FilterFlags,
+ OUT EFI_STRING *NextString
+ )
+{
+ CHAR16 *PathPtr;
+ CHAR16 *KeywordPtr;
+ BOOLEAN RetVal;
+
+ ASSERT ((FilterFlags != NULL) && (NextString != NULL));
+
+ //
+ // String end, no filter section.
+ //
+ if (String == NULL) {
+ *NextString = NULL;
+ return FALSE;
+ }
+
+ *FilterFlags = 0;
+ RetVal = TRUE;
+
+ //
+ // Skip '&' if exist.
+ //
+ if (*String == L'&') {
+ String++;
+ }
+
+ if (StrnCmp (String, L"ReadOnly", StrLen (L"ReadOnly")) == 0) {
+ //
+ // Find ReadOnly filter.
+ //
+ *FilterFlags |= EFI_KEYWORD_FILTER_READONY;
+ String += StrLen (L"ReadOnly");
+ } else if (StrnCmp (String, L"ReadWrite", StrLen (L"ReadWrite")) == 0) {
+ //
+ // Find ReadWrite filter.
+ //
+ *FilterFlags |= EFI_KEYWORD_FILTER_REAWRITE;
+ String += StrLen (L"ReadWrite");
+ } else if (StrnCmp (String, L"Buffer", StrLen (L"Buffer")) == 0) {
+ //
+ // Find Buffer Filter.
+ //
+ *FilterFlags |= EFI_KEYWORD_FILTER_BUFFER;
+ String += StrLen (L"Buffer");
+ } else if (StrnCmp (String, L"Numeric", StrLen (L"Numeric")) == 0) {
+ //
+ // Find Numeric Filter
+ //
+ String += StrLen (L"Numeric");
+ if (*String != L':') {
+ *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC;
+ } else {
+ String++;
+ switch (*String) {
+ case L'1':
+ *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_1;
+ break;
+ case L'2':
+ *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_2;
+ break;
+ case L'4':
+ *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_4;
+ break;
+ case L'8':
+ *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_8;
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ String++;
+ }
+ } else {
+ //
+ // Check whether other filter item defined by Platform.
+ //
+ if ((StrnCmp (String, L"&PATH", StrLen (L"&PATH")) == 0) ||
+ (StrnCmp (String, L"&KEYWORD", StrLen (L"&KEYWORD")) == 0))
+ {
+ //
+ // New KeywordRequest start, no platform defined filter.
+ //
+ } else {
+ //
+ // Platform defined filter rule.
+ // Just skip platform defined filter rule, return success.
+ //
+ PathPtr = StrStr (String, L"&PATH");
+ KeywordPtr = StrStr (String, L"&KEYWORD");
+ if ((PathPtr != NULL) && (KeywordPtr != NULL)) {
+ //
+ // If both sections exist, return the first follow string.
+ //
+ String = KeywordPtr > PathPtr ? PathPtr : KeywordPtr;
+ } else if (PathPtr != NULL) {
+ //
+ // Should not exist PathPtr != NULL && KeywordPtr == NULL case.
+ //
+ ASSERT (FALSE);
+ } else if (KeywordPtr != NULL) {
+ //
+ // Just to the next keyword section.
+ //
+ String = KeywordPtr;
+ } else {
+ //
+ // Only has platform defined filter section, just skip it.
+ //
+ String += StrLen (String);
+ }
+ }
+
+ RetVal = FALSE;
+ }
+
+ *NextString = String;
+
+ return RetVal;
+}
+
+/**
+ Extract Readonly flag from opcode.
+
+ This is a internal function.
+
+ @param OpCodeData Input opcode for this question.
+
+ @retval TRUE This question is readonly.
+ @retval FALSE This question is not readonly.
+
+**/
+BOOLEAN
+ExtractReadOnlyFromOpCode (
+ IN UINT8 *OpCodeData
+ )
+{
+ EFI_IFR_QUESTION_HEADER *QuestionHdr;
+
+ ASSERT (OpCodeData != NULL);
+
+ QuestionHdr = (EFI_IFR_QUESTION_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));
+
+ return (QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) != 0;
+}
+
+/**
+ Create a circuit to check the filter section.
+
+ This is a internal function.
+
+ @param OpCodeData The question binary ifr data.
+ @param KeywordRequest KeywordRequestformat string.
+ @param NextString return the next string follow this keyword section.
+ @param ReadOnly Return whether this question is read only.
+
+ @retval KEYWORD_HANDLER_NO_ERROR Success validate.
+ @retval KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED Validate fail.
+
+**/
+UINT32
+ValidateFilter (
+ IN UINT8 *OpCodeData,
+ IN CHAR16 *KeywordRequest,
+ OUT CHAR16 **NextString,
+ OUT BOOLEAN *ReadOnly
+ )
+{
+ CHAR16 *NextFilter;
+ CHAR16 *StringPtr;
+ UINT8 FilterFlags;
+ EFI_IFR_QUESTION_HEADER *QuestionHdr;
+ EFI_IFR_OP_HEADER *OpCodeHdr;
+ UINT8 Flags;
+ UINT32 RetVal;
+
+ RetVal = KEYWORD_HANDLER_NO_ERROR;
+ StringPtr = KeywordRequest;
+
+ OpCodeHdr = (EFI_IFR_OP_HEADER *)OpCodeData;
+ QuestionHdr = (EFI_IFR_QUESTION_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));
+ if ((OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP) || (OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP)) {
+ Flags = *(OpCodeData + sizeof (EFI_IFR_OP_HEADER) + sizeof (EFI_IFR_QUESTION_HEADER));
+ } else {
+ Flags = 0;
+ }
+
+ //
+ // Get ReadOnly flag from Question.
+ //
+ *ReadOnly = ExtractReadOnlyFromOpCode (OpCodeData);
+
+ while (ExtractFilter (StringPtr, &FilterFlags, &NextFilter)) {
+ switch (FilterFlags) {
+ case EFI_KEYWORD_FILTER_READONY:
+ if ((QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) == 0) {
+ RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
+ goto Done;
+ }
+
+ break;
+
+ case EFI_KEYWORD_FILTER_REAWRITE:
+ if ((QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) != 0) {
+ RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
+ goto Done;
+ }
+
+ break;
+
+ case EFI_KEYWORD_FILTER_BUFFER:
+ //
+ // Only these three opcode use numeric value type.
+ //
+ if ((OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP) || (OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP) || (OpCodeHdr->OpCode == EFI_IFR_CHECKBOX_OP)) {
+ RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
+ goto Done;
+ }
+
+ break;
+
+ case EFI_KEYWORD_FILTER_NUMERIC:
+ if ((OpCodeHdr->OpCode != EFI_IFR_ONE_OF_OP) && (OpCodeHdr->OpCode != EFI_IFR_NUMERIC_OP) && (OpCodeHdr->OpCode != EFI_IFR_CHECKBOX_OP)) {
+ RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
+ goto Done;
+ }
+
+ break;
+
+ case EFI_KEYWORD_FILTER_NUMERIC_1:
+ case EFI_KEYWORD_FILTER_NUMERIC_2:
+ case EFI_KEYWORD_FILTER_NUMERIC_4:
+ case EFI_KEYWORD_FILTER_NUMERIC_8:
+ if ((OpCodeHdr->OpCode != EFI_IFR_ONE_OF_OP) && (OpCodeHdr->OpCode != EFI_IFR_NUMERIC_OP) && (OpCodeHdr->OpCode != EFI_IFR_CHECKBOX_OP)) {
+ RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
+ goto Done;
+ }
+
+ //
+ // For numeric and oneof, it has flags field to specify the detail numeric type.
+ //
+ if ((OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP) || (OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP)) {
+ switch (Flags & EFI_IFR_NUMERIC_SIZE) {
+ case EFI_IFR_NUMERIC_SIZE_1:
+ if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_1) {
+ RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
+ goto Done;
+ }
+
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_2:
+ if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_2) {
+ RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
+ goto Done;
+ }
+
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_4:
+ if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_4) {
+ RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
+ goto Done;
+ }
+
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_8:
+ if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_8) {
+ RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
+ goto Done;
+ }
+
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+ }
+
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ //
+ // Jump to the next filter.
+ //
+ StringPtr = NextFilter;
+ }
+
+Done:
+ //
+ // The current filter which is processing.
+ //
+ *NextString = StringPtr;
+
+ return RetVal;
+}
+
+/**
+ Get HII_DATABASE_RECORD from the input device path info.
+
+ This is a internal function.
+
+ @param DevicePath UEFI device path protocol.
+
+ @retval Internal data base record.
+
+**/
+HII_DATABASE_RECORD *
+GetRecordFromDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ LIST_ENTRY *Link;
+ UINT8 *DevicePathPkg;
+ UINT8 *CurrentDevicePath;
+ UINTN DevicePathSize;
+ HII_DATABASE_RECORD *TempDatabase;
+
+ ASSERT (DevicePath != NULL);
+
+ for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {
+ TempDatabase = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ DevicePathPkg = TempDatabase->PackageList->DevicePathPkg;
+ if (DevicePathPkg != NULL) {
+ CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
+ DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath);
+ if ((CompareMem (DevicePath, CurrentDevicePath, DevicePathSize) == 0)) {
+ return TempDatabase;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ Calculate the size of StringSrc and output it. Also copy string text from src
+ to dest.
+
+ This is a internal function.
+
+ @param StringSrc Points to current null-terminated string.
+ @param BufferSize Length of the buffer.
+ @param StringDest Buffer to store the string text.
+
+ @retval EFI_SUCCESS The string text was outputted successfully.
+ @retval EFI_OUT_OF_RESOURCES Out of resource.
+
+**/
+EFI_STATUS
+GetUnicodeStringTextAndSize (
+ IN UINT8 *StringSrc,
+ OUT UINTN *BufferSize,
+ OUT EFI_STRING *StringDest
+ )
+{
+ UINTN StringSize;
+ UINT8 *StringPtr;
+
+ ASSERT (StringSrc != NULL && BufferSize != NULL && StringDest != NULL);
+
+ StringSize = sizeof (CHAR16);
+ StringPtr = StringSrc;
+ while (ReadUnaligned16 ((UINT16 *)StringPtr) != 0) {
+ StringSize += sizeof (CHAR16);
+ StringPtr += sizeof (CHAR16);
+ }
+
+ *StringDest = AllocatePool (StringSize);
+ if (*StringDest == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (*StringDest, StringSrc, StringSize);
+
+ *BufferSize = StringSize;
+ return EFI_SUCCESS;
+}
+
+/**
+ Find the string id for the input keyword.
+
+ @param StringPackage Hii string package instance.
+ @param KeywordValue Input keyword value.
+ @param StringId The string's id, which is unique within PackageList.
+
+
+ @retval EFI_SUCCESS The string text and font is retrieved
+ successfully.
+ @retval EFI_NOT_FOUND The specified text or font info can not be found
+ out.
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
+ task.
+**/
+EFI_STATUS
+GetStringIdFromString (
+ IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
+ IN CHAR16 *KeywordValue,
+ OUT EFI_STRING_ID *StringId
+ )
+{
+ UINT8 *BlockHdr;
+ EFI_STRING_ID CurrentStringId;
+ UINTN BlockSize;
+ UINTN Index;
+ UINT8 *StringTextPtr;
+ UINTN Offset;
+ UINT16 StringCount;
+ UINT16 SkipCount;
+ UINT8 Length8;
+ EFI_HII_SIBT_EXT2_BLOCK Ext2;
+ UINT32 Length32;
+ UINTN StringSize;
+ CHAR16 *String;
+ CHAR8 *AsciiKeywordValue;
+ UINTN KeywordValueSize;
+ EFI_STATUS Status;
+
+ ASSERT (StringPackage != NULL && KeywordValue != NULL && StringId != NULL);
+ ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);
+
+ CurrentStringId = 1;
+ Status = EFI_SUCCESS;
+ String = NULL;
+ BlockHdr = StringPackage->StringBlock;
+ BlockSize = 0;
+ Offset = 0;
+
+ //
+ // Make a ascii keyword value for later use.
+ //
+ KeywordValueSize = StrLen (KeywordValue) + 1;
+ AsciiKeywordValue = AllocatePool (KeywordValueSize);
+ if (AsciiKeywordValue == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ UnicodeStrToAsciiStrS (KeywordValue, AsciiKeywordValue, KeywordValueSize);
+
+ while (*BlockHdr != EFI_HII_SIBT_END) {
+ switch (*BlockHdr) {
+ case EFI_HII_SIBT_STRING_SCSU:
+ Offset = sizeof (EFI_HII_STRING_BLOCK);
+ StringTextPtr = BlockHdr + Offset;
+ BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
+ if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {
+ *StringId = CurrentStringId;
+ goto Done;
+ }
+
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_STRING_SCSU_FONT:
+ Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);
+ StringTextPtr = BlockHdr + Offset;
+ if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {
+ *StringId = CurrentStringId;
+ goto Done;
+ }
+
+ BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_STRINGS_SCSU:
+ CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
+ StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8));
+ BlockSize += StringTextPtr - BlockHdr;
+
+ for (Index = 0; Index < StringCount; Index++) {
+ BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);
+ if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {
+ *StringId = CurrentStringId;
+ goto Done;
+ }
+
+ StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
+ CurrentStringId++;
+ }
+
+ break;
+
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:
+ CopyMem (
+ &StringCount,
+ (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
+ sizeof (UINT16)
+ );
+ StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8));
+ BlockSize += StringTextPtr - BlockHdr;
+
+ for (Index = 0; Index < StringCount; Index++) {
+ BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);
+ if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {
+ *StringId = CurrentStringId;
+ goto Done;
+ }
+
+ StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
+ CurrentStringId++;
+ }
+
+ break;
+
+ case EFI_HII_SIBT_STRING_UCS2:
+ Offset = sizeof (EFI_HII_STRING_BLOCK);
+ StringTextPtr = BlockHdr + Offset;
+ //
+ // Use StringSize to store the size of the specified string, including the NULL
+ // terminator.
+ //
+ Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ ASSERT (String != NULL);
+ if (StrCmp (KeywordValue, String) == 0) {
+ *StringId = CurrentStringId;
+ goto Done;
+ }
+
+ BlockSize += Offset + StringSize;
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_STRING_UCS2_FONT:
+ Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);
+ StringTextPtr = BlockHdr + Offset;
+ //
+ // Use StringSize to store the size of the specified string, including the NULL
+ // terminator.
+ //
+ Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ ASSERT (String != NULL);
+ if (StrCmp (KeywordValue, String) == 0) {
+ *StringId = CurrentStringId;
+ goto Done;
+ }
+
+ BlockSize += Offset + StringSize;
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_STRINGS_UCS2:
+ Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);
+ StringTextPtr = BlockHdr + Offset;
+ BlockSize += Offset;
+ CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
+ for (Index = 0; Index < StringCount; Index++) {
+ Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ ASSERT (String != NULL);
+ BlockSize += StringSize;
+ if (StrCmp (KeywordValue, String) == 0) {
+ *StringId = CurrentStringId;
+ goto Done;
+ }
+
+ StringTextPtr = StringTextPtr + StringSize;
+ CurrentStringId++;
+ }
+
+ break;
+
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:
+ Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);
+ StringTextPtr = BlockHdr + Offset;
+ BlockSize += Offset;
+ CopyMem (
+ &StringCount,
+ (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
+ sizeof (UINT16)
+ );
+ for (Index = 0; Index < StringCount; Index++) {
+ Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ ASSERT (String != NULL);
+ BlockSize += StringSize;
+ if (StrCmp (KeywordValue, String) == 0) {
+ *StringId = CurrentStringId;
+ goto Done;
+ }
+
+ StringTextPtr = StringTextPtr + StringSize;
+ CurrentStringId++;
+ }
+
+ break;
+
+ case EFI_HII_SIBT_DUPLICATE:
+ BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_SKIP1:
+ SkipCount = (UINT16)(*(UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));
+ CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
+ BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
+ break;
+
+ case EFI_HII_SIBT_SKIP2:
+ CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
+ CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
+ BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
+ break;
+
+ case EFI_HII_SIBT_EXT1:
+ CopyMem (
+ &Length8,
+ (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
+ sizeof (UINT8)
+ );
+ BlockSize += Length8;
+ break;
+
+ case EFI_HII_SIBT_EXT2:
+ CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
+ BlockSize += Ext2.Length;
+ break;
+
+ case EFI_HII_SIBT_EXT4:
+ CopyMem (
+ &Length32,
+ (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
+ sizeof (UINT32)
+ );
+
+ BlockSize += Length32;
+ break;
+
+ default:
+ break;
+ }
+
+ if (String != NULL) {
+ FreePool (String);
+ String = NULL;
+ }
+
+ BlockHdr = StringPackage->StringBlock + BlockSize;
+ }
+
+ Status = EFI_NOT_FOUND;
+
+Done:
+ if (AsciiKeywordValue != NULL) {
+ FreePool (AsciiKeywordValue);
+ }
+
+ if (String != NULL) {
+ FreePool (String);
+ }
+
+ return Status;
+}
+
+/**
+ Find the next valid string id for the input string id.
+
+ @param StringPackage Hii string package instance.
+ @param StringId The current string id which is already got.
+ 1 means just begin to get the string id.
+ @param KeywordValue Return the string for the next string id.
+
+
+ @retval EFI_STRING_ID Not 0 means a valid stringid found.
+ 0 means not found a valid string id.
+**/
+EFI_STRING_ID
+GetNextStringId (
+ IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
+ IN EFI_STRING_ID StringId,
+ OUT EFI_STRING *KeywordValue
+ )
+{
+ UINT8 *BlockHdr;
+ EFI_STRING_ID CurrentStringId;
+ UINTN BlockSize;
+ UINTN Index;
+ UINT8 *StringTextPtr;
+ UINTN Offset;
+ UINT16 StringCount;
+ UINT16 SkipCount;
+ UINT8 Length8;
+ EFI_HII_SIBT_EXT2_BLOCK Ext2;
+ UINT32 Length32;
+ BOOLEAN FindString;
+ UINTN StringSize;
+ CHAR16 *String;
+
+ ASSERT (StringPackage != NULL);
+ ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);
+
+ CurrentStringId = 1;
+ FindString = FALSE;
+ String = NULL;
+
+ //
+ // Parse the string blocks to get the string text and font.
+ //
+ BlockHdr = StringPackage->StringBlock;
+ BlockSize = 0;
+ Offset = 0;
+ while (*BlockHdr != EFI_HII_SIBT_END) {
+ switch (*BlockHdr) {
+ case EFI_HII_SIBT_STRING_SCSU:
+ Offset = sizeof (EFI_HII_STRING_BLOCK);
+ StringTextPtr = BlockHdr + Offset;
+
+ if (FindString) {
+ StringSize = AsciiStrSize ((CHAR8 *)StringTextPtr);
+ *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));
+ if (*KeywordValue == NULL) {
+ return 0;
+ }
+
+ AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);
+ return CurrentStringId;
+ } else if (CurrentStringId == StringId) {
+ FindString = TRUE;
+ }
+
+ BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_STRING_SCSU_FONT:
+ Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);
+ StringTextPtr = BlockHdr + Offset;
+
+ if (FindString) {
+ StringSize = AsciiStrSize ((CHAR8 *)StringTextPtr);
+ *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));
+ if (*KeywordValue == NULL) {
+ return 0;
+ }
+
+ AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);
+ return CurrentStringId;
+ } else if (CurrentStringId == StringId) {
+ FindString = TRUE;
+ }
+
+ BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_STRINGS_SCSU:
+ CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
+ StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8));
+ BlockSize += StringTextPtr - BlockHdr;
+
+ for (Index = 0; Index < StringCount; Index++) {
+ if (FindString) {
+ StringSize = AsciiStrSize ((CHAR8 *)StringTextPtr);
+ *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));
+ if (*KeywordValue == NULL) {
+ return 0;
+ }
+
+ AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);
+ return CurrentStringId;
+ } else if (CurrentStringId == StringId) {
+ FindString = TRUE;
+ }
+
+ BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);
+ StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
+ CurrentStringId++;
+ }
+
+ break;
+
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:
+ CopyMem (
+ &StringCount,
+ (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
+ sizeof (UINT16)
+ );
+ StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8));
+ BlockSize += StringTextPtr - BlockHdr;
+
+ for (Index = 0; Index < StringCount; Index++) {
+ if (FindString) {
+ StringSize = AsciiStrSize ((CHAR8 *)StringTextPtr);
+ *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));
+ if (*KeywordValue == NULL) {
+ return 0;
+ }
+
+ AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);
+ return CurrentStringId;
+ } else if (CurrentStringId == StringId) {
+ FindString = TRUE;
+ }
+
+ BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);
+ StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
+ CurrentStringId++;
+ }
+
+ break;
+
+ case EFI_HII_SIBT_STRING_UCS2:
+ Offset = sizeof (EFI_HII_STRING_BLOCK);
+ StringTextPtr = BlockHdr + Offset;
+ //
+ // Use StringSize to store the size of the specified string, including the NULL
+ // terminator.
+ //
+ GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
+ if (FindString && (String != NULL) && (*String != L'\0')) {
+ //
+ // String protocol use this type for the string id which has value for other package.
+ // It will allocate an empty string block for this string id. so here we also check
+ // *String != L'\0' to prohibit this case.
+ //
+ *KeywordValue = String;
+ return CurrentStringId;
+ } else if (CurrentStringId == StringId) {
+ FindString = TRUE;
+ }
+
+ BlockSize += Offset + StringSize;
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_STRING_UCS2_FONT:
+ Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);
+ StringTextPtr = BlockHdr + Offset;
+ //
+ // Use StringSize to store the size of the specified string, including the NULL
+ // terminator.
+ //
+ GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
+ if (FindString) {
+ *KeywordValue = String;
+ return CurrentStringId;
+ } else if (CurrentStringId == StringId) {
+ FindString = TRUE;
+ }
+
+ BlockSize += Offset + StringSize;
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_STRINGS_UCS2:
+ Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);
+ StringTextPtr = BlockHdr + Offset;
+ BlockSize += Offset;
+ CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
+ for (Index = 0; Index < StringCount; Index++) {
+ GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
+
+ if (FindString) {
+ *KeywordValue = String;
+ return CurrentStringId;
+ } else if (CurrentStringId == StringId) {
+ FindString = TRUE;
+ }
+
+ BlockSize += StringSize;
+ StringTextPtr = StringTextPtr + StringSize;
+ CurrentStringId++;
+ }
+
+ break;
+
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:
+ Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);
+ StringTextPtr = BlockHdr + Offset;
+ BlockSize += Offset;
+ CopyMem (
+ &StringCount,
+ (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
+ sizeof (UINT16)
+ );
+ for (Index = 0; Index < StringCount; Index++) {
+ GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
+ if (FindString) {
+ *KeywordValue = String;
+ return CurrentStringId;
+ } else if (CurrentStringId == StringId) {
+ FindString = TRUE;
+ }
+
+ BlockSize += StringSize;
+ StringTextPtr = StringTextPtr + StringSize;
+ CurrentStringId++;
+ }
+
+ break;
+
+ case EFI_HII_SIBT_DUPLICATE:
+ BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_SKIP1:
+ SkipCount = (UINT16)(*(UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));
+ CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
+ BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
+ break;
+
+ case EFI_HII_SIBT_SKIP2:
+ CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
+ CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
+ BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
+ break;
+
+ case EFI_HII_SIBT_EXT1:
+ CopyMem (
+ &Length8,
+ (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
+ sizeof (UINT8)
+ );
+ BlockSize += Length8;
+ break;
+
+ case EFI_HII_SIBT_EXT2:
+ CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
+ BlockSize += Ext2.Length;
+ break;
+
+ case EFI_HII_SIBT_EXT4:
+ CopyMem (
+ &Length32,
+ (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
+ sizeof (UINT32)
+ );
+
+ BlockSize += Length32;
+ break;
+
+ default:
+ break;
+ }
+
+ if (String != NULL) {
+ FreePool (String);
+ String = NULL;
+ }
+
+ BlockHdr = StringPackage->StringBlock + BlockSize;
+ }
+
+ return 0;
+}
+
+/**
+ Get string package from the input NameSpace string.
+
+ This is a internal function.
+
+ @param DatabaseRecord HII_DATABASE_RECORD format string.
+ @param NameSpace NameSpace format string.
+ @param KeywordValue Keyword value.
+ @param StringId String Id for this keyword.
+
+ @retval KEYWORD_HANDLER_NO_ERROR Get String id successfully.
+ @retval KEYWORD_HANDLER_KEYWORD_NOT_FOUND Not found the string id in the string package.
+ @retval KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND Not found the string package for this namespace.
+ @retval KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR Out of resource error.
+
+**/
+UINT32
+GetStringIdFromRecord (
+ IN HII_DATABASE_RECORD *DatabaseRecord,
+ IN CHAR8 **NameSpace,
+ IN CHAR16 *KeywordValue,
+ OUT EFI_STRING_ID *StringId
+ )
+{
+ LIST_ENTRY *Link;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+ EFI_STATUS Status;
+ CHAR8 *Name;
+ UINT32 RetVal;
+
+ ASSERT (DatabaseRecord != NULL && NameSpace != NULL && KeywordValue != NULL);
+
+ PackageListNode = DatabaseRecord->PackageList;
+ RetVal = KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND;
+
+ if (*NameSpace != NULL) {
+ Name = *NameSpace;
+ } else {
+ Name = UEFI_CONFIG_LANG;
+ }
+
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink; Link != &PackageListNode->StringPkgHdr; Link = Link->ForwardLink) {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+
+ if (AsciiStrnCmp (Name, StringPackage->StringPkgHdr->Language, AsciiStrLen (Name)) == 0) {
+ Status = GetStringIdFromString (StringPackage, KeywordValue, StringId);
+ if (EFI_ERROR (Status)) {
+ return KEYWORD_HANDLER_KEYWORD_NOT_FOUND;
+ } else {
+ if (*NameSpace == NULL) {
+ *NameSpace = AllocateCopyPool (AsciiStrSize (StringPackage->StringPkgHdr->Language), StringPackage->StringPkgHdr->Language);
+ if (*NameSpace == NULL) {
+ return KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;
+ }
+ }
+
+ return KEYWORD_HANDLER_NO_ERROR;
+ }
+ }
+ }
+
+ return RetVal;
+}
+
+/**
+ Tell whether this Operand is an Statement OpCode.
+
+ @param Operand Operand of an IFR OpCode.
+
+ @retval TRUE This is an Statement OpCode.
+ @retval FALSE Not an Statement OpCode.
+
+**/
+BOOLEAN
+IsStatementOpCode (
+ IN UINT8 Operand
+ )
+{
+ if ((Operand == EFI_IFR_SUBTITLE_OP) ||
+ (Operand == EFI_IFR_TEXT_OP) ||
+ (Operand == EFI_IFR_RESET_BUTTON_OP) ||
+ (Operand == EFI_IFR_REF_OP) ||
+ (Operand == EFI_IFR_ACTION_OP) ||
+ (Operand == EFI_IFR_NUMERIC_OP) ||
+ (Operand == EFI_IFR_ORDERED_LIST_OP) ||
+ (Operand == EFI_IFR_CHECKBOX_OP) ||
+ (Operand == EFI_IFR_STRING_OP) ||
+ (Operand == EFI_IFR_PASSWORD_OP) ||
+ (Operand == EFI_IFR_DATE_OP) ||
+ (Operand == EFI_IFR_TIME_OP) ||
+ (Operand == EFI_IFR_GUID_OP) ||
+ (Operand == EFI_IFR_ONE_OF_OP))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Tell whether this Operand is an Statement OpCode.
+
+ @param Operand Operand of an IFR OpCode.
+
+ @retval TRUE This is an Statement OpCode.
+ @retval FALSE Not an Statement OpCode.
+
+**/
+BOOLEAN
+IsStorageOpCode (
+ IN UINT8 Operand
+ )
+{
+ if ((Operand == EFI_IFR_VARSTORE_OP) ||
+ (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) ||
+ (Operand == EFI_IFR_VARSTORE_EFI_OP))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Base on the prompt string id to find the question.
+
+ @param FormPackage The input form package.
+ @param KeywordStrId The input prompt string id for one question.
+
+ @retval the opcode for the question.
+
+**/
+UINT8 *
+FindQuestionFromStringId (
+ IN HII_IFR_PACKAGE_INSTANCE *FormPackage,
+ IN EFI_STRING_ID KeywordStrId
+ )
+{
+ UINT8 *OpCodeData;
+ UINT32 Offset;
+ EFI_IFR_STATEMENT_HEADER *StatementHeader;
+ EFI_IFR_OP_HEADER *OpCodeHeader;
+ UINT32 FormDataLen;
+
+ ASSERT (FormPackage != NULL);
+
+ FormDataLen = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
+ Offset = 0;
+ while (Offset < FormDataLen) {
+ OpCodeData = FormPackage->IfrData + Offset;
+ OpCodeHeader = (EFI_IFR_OP_HEADER *)OpCodeData;
+
+ if (IsStatementOpCode (OpCodeHeader->OpCode)) {
+ StatementHeader = (EFI_IFR_STATEMENT_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));
+ if (StatementHeader->Prompt == KeywordStrId) {
+ return OpCodeData;
+ }
+ }
+
+ Offset += OpCodeHeader->Length;
+ }
+
+ return NULL;
+}
+
+/**
+ Base on the varstore id to find the storage info.
+
+ @param FormPackage The input form package.
+ @param VarStoreId The input storage id.
+
+ @retval the opcode for the storage.
+
+**/
+UINT8 *
+FindStorageFromVarId (
+ IN HII_IFR_PACKAGE_INSTANCE *FormPackage,
+ IN EFI_VARSTORE_ID VarStoreId
+ )
+{
+ UINT8 *OpCodeData;
+ UINT32 Offset;
+ EFI_IFR_OP_HEADER *OpCodeHeader;
+ UINT32 FormDataLen;
+
+ ASSERT (FormPackage != NULL);
+
+ FormDataLen = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
+ Offset = 0;
+ while (Offset < FormDataLen) {
+ OpCodeData = FormPackage->IfrData + Offset;
+ OpCodeHeader = (EFI_IFR_OP_HEADER *)OpCodeData;
+
+ if (IsStorageOpCode (OpCodeHeader->OpCode)) {
+ switch (OpCodeHeader->OpCode) {
+ case EFI_IFR_VARSTORE_OP:
+ if (VarStoreId == ((EFI_IFR_VARSTORE *)OpCodeData)->VarStoreId) {
+ return OpCodeData;
+ }
+
+ break;
+
+ case EFI_IFR_VARSTORE_NAME_VALUE_OP:
+ if (VarStoreId == ((EFI_IFR_VARSTORE_NAME_VALUE *)OpCodeData)->VarStoreId) {
+ return OpCodeData;
+ }
+
+ break;
+
+ case EFI_IFR_VARSTORE_EFI_OP:
+ if (VarStoreId == ((EFI_IFR_VARSTORE_EFI *)OpCodeData)->VarStoreId) {
+ return OpCodeData;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ Offset += OpCodeHeader->Length;
+ }
+
+ return NULL;
+}
+
+/**
+ Get width info for one question.
+
+ @param OpCodeData The input opcode for one question.
+
+ @retval the width info for one question.
+
+**/
+UINT16
+GetWidth (
+ IN UINT8 *OpCodeData
+ )
+{
+ UINT8 *NextOpCodeData;
+
+ ASSERT (OpCodeData != NULL);
+
+ switch (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode) {
+ case EFI_IFR_REF_OP:
+ return (UINT16)sizeof (EFI_HII_REF);
+
+ case EFI_IFR_ONE_OF_OP:
+ case EFI_IFR_NUMERIC_OP:
+ switch (((EFI_IFR_ONE_OF *)OpCodeData)->Flags & EFI_IFR_NUMERIC_SIZE) {
+ case EFI_IFR_NUMERIC_SIZE_1:
+ return (UINT16)sizeof (UINT8);
+
+ case EFI_IFR_NUMERIC_SIZE_2:
+ return (UINT16)sizeof (UINT16);
+
+ case EFI_IFR_NUMERIC_SIZE_4:
+ return (UINT16)sizeof (UINT32);
+
+ case EFI_IFR_NUMERIC_SIZE_8:
+ return (UINT16)sizeof (UINT64);
+
+ default:
+ ASSERT (FALSE);
+ return 0;
+ }
+
+ case EFI_IFR_ORDERED_LIST_OP:
+ NextOpCodeData = OpCodeData + ((EFI_IFR_ORDERED_LIST *)OpCodeData)->Header.Length;
+ //
+ // OneOfOption must follow the orderedlist opcode.
+ //
+ ASSERT (((EFI_IFR_OP_HEADER *)NextOpCodeData)->OpCode == EFI_IFR_ONE_OF_OPTION_OP);
+ switch (((EFI_IFR_ONE_OF_OPTION *)NextOpCodeData)->Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ return (UINT16)sizeof (UINT8) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ return (UINT16)sizeof (UINT16) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ return (UINT16)sizeof (UINT32) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
+
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ return (UINT16)sizeof (UINT64) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
+
+ default:
+ ASSERT (FALSE);
+ return 0;
+ }
+
+ case EFI_IFR_CHECKBOX_OP:
+ return (UINT16)sizeof (BOOLEAN);
+
+ case EFI_IFR_PASSWORD_OP:
+ return (UINT16)((UINTN)((EFI_IFR_PASSWORD *)OpCodeData)->MaxSize * sizeof (CHAR16));
+
+ case EFI_IFR_STRING_OP:
+ return (UINT16)((UINTN)((EFI_IFR_STRING *)OpCodeData)->MaxSize * sizeof (CHAR16));
+
+ case EFI_IFR_DATE_OP:
+ return (UINT16)sizeof (EFI_HII_DATE);
+
+ case EFI_IFR_TIME_OP:
+ return (UINT16)sizeof (EFI_HII_TIME);
+
+ default:
+ ASSERT (FALSE);
+ return 0;
+ }
+}
+
+/**
+ Converts all hex string characters in range ['A'..'F'] to ['a'..'f'] for
+ hex digits that appear between a '=' and a '&' in a config string.
+
+ If ConfigString is NULL, then ASSERT().
+
+ @param[in] ConfigString Pointer to a Null-terminated Unicode string.
+
+ @return Pointer to the Null-terminated Unicode result string.
+
+**/
+EFI_STRING
+EFIAPI
+InternalLowerConfigString (
+ IN EFI_STRING ConfigString
+ )
+{
+ EFI_STRING String;
+ BOOLEAN Lower;
+
+ ASSERT (ConfigString != NULL);
+
+ //
+ // Convert all hex digits in range [A-F] in the configuration header to [a-f]
+ //
+ for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
+ if (*String == L'=') {
+ Lower = TRUE;
+ } else if (*String == L'&') {
+ Lower = FALSE;
+ } else if (Lower && (*String >= L'A') && (*String <= L'F')) {
+ *String = (CHAR16)(*String - L'A' + L'a');
+ }
+ }
+
+ return ConfigString;
+}
+
+/**
+ Allocates and returns a Null-terminated Unicode <ConfigHdr> string.
+
+ The format of a <ConfigHdr> is as follows:
+
+ GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>
+
+ @param[in] OpCodeData The opcode for the storage.
+ @param[in] DriverHandle The driver handle which supports a Device Path Protocol
+ that is the routing information PATH. Each byte of
+ the Device Path associated with DriverHandle is converted
+ to a 2 Unicode character hexadecimal string.
+
+ @retval NULL DriverHandle does not support the Device Path Protocol.
+ @retval Other A pointer to the Null-terminate Unicode <ConfigHdr> string
+
+**/
+EFI_STRING
+ConstructConfigHdr (
+ IN UINT8 *OpCodeData,
+ IN EFI_HANDLE DriverHandle
+ )
+{
+ UINTN NameLength;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN DevicePathSize;
+ CHAR16 *String;
+ CHAR16 *ReturnString;
+ UINTN Index;
+ UINT8 *Buffer;
+ CHAR16 *Name;
+ CHAR8 *AsciiName;
+ UINTN NameSize;
+ EFI_GUID *Guid;
+ UINTN MaxLen;
+
+ ASSERT (OpCodeData != NULL);
+
+ switch (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode) {
+ case EFI_IFR_VARSTORE_OP:
+ Guid = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE *)OpCodeData)->Guid;
+ AsciiName = (CHAR8 *)((EFI_IFR_VARSTORE *)OpCodeData)->Name;
+ break;
+
+ case EFI_IFR_VARSTORE_NAME_VALUE_OP:
+ Guid = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE_NAME_VALUE *)OpCodeData)->Guid;
+ AsciiName = NULL;
+ break;
+
+ case EFI_IFR_VARSTORE_EFI_OP:
+ Guid = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Guid;
+ AsciiName = (CHAR8 *)((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Name;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ Guid = NULL;
+ AsciiName = NULL;
+ break;
+ }
+
+ if (AsciiName != NULL) {
+ NameSize = AsciiStrSize (AsciiName);
+ Name = AllocateZeroPool (NameSize * sizeof (CHAR16));
+ ASSERT (Name != NULL);
+ AsciiStrToUnicodeStrS (AsciiName, Name, NameSize);
+ } else {
+ Name = NULL;
+ }
+
+ //
+ // Compute the length of Name in Unicode characters.
+ // If Name is NULL, then the length is 0.
+ //
+ NameLength = 0;
+ if (Name != NULL) {
+ NameLength = StrLen (Name);
+ }
+
+ DevicePath = NULL;
+ DevicePathSize = 0;
+ //
+ // Retrieve DevicePath Protocol associated with DriverHandle
+ //
+ if (DriverHandle != NULL) {
+ DevicePath = DevicePathFromHandle (DriverHandle);
+ if (DevicePath == NULL) {
+ return NULL;
+ }
+
+ //
+ // Compute the size of the device path in bytes
+ //
+ DevicePathSize = GetDevicePathSize (DevicePath);
+ }
+
+ //
+ // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>
+ // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |
+ //
+ MaxLen = 5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1;
+ String = AllocateZeroPool (MaxLen * sizeof (CHAR16));
+ if (String == NULL) {
+ return NULL;
+ }
+
+ //
+ // Start with L"GUID="
+ //
+ StrCpyS (String, MaxLen, L"GUID=");
+ ReturnString = String;
+ String += StrLen (String);
+
+ if (Guid != NULL) {
+ //
+ // Append Guid converted to <HexCh>32
+ //
+ for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {
+ UnicodeValueToStringS (
+ String,
+ MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),
+ PREFIX_ZERO | RADIX_HEX,
+ *(Buffer++),
+ 2
+ );
+ String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));
+ }
+ }
+
+ //
+ // Append L"&NAME="
+ //
+ StrCatS (ReturnString, MaxLen, L"&NAME=");
+ String += StrLen (String);
+
+ if (Name != NULL) {
+ //
+ // Append Name converted to <Char>NameLength
+ //
+ for ( ; *Name != L'\0'; Name++) {
+ UnicodeValueToStringS (
+ String,
+ MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),
+ PREFIX_ZERO | RADIX_HEX,
+ *Name,
+ 4
+ );
+ String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));
+ }
+ }
+
+ //
+ // Append L"&PATH="
+ //
+ StrCatS (ReturnString, MaxLen, L"&PATH=");
+ String += StrLen (String);
+
+ //
+ // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize
+ //
+ for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) {
+ UnicodeValueToStringS (
+ String,
+ MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),
+ PREFIX_ZERO | RADIX_HEX,
+ *(Buffer++),
+ 2
+ );
+ String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));
+ }
+
+ //
+ // Null terminate the Unicode string
+ //
+ *String = L'\0';
+
+ //
+ // Convert all hex digits in range [A-F] in the configuration header to [a-f]
+ //
+ return InternalLowerConfigString (ReturnString);
+}
+
+/**
+ Generate the Config request element for one question.
+
+ @param Name The name info for one question.
+ @param Offset The offset info for one question.
+ @param Width The width info for one question.
+
+ @return Pointer to the Null-terminated Unicode request element string.
+
+**/
+EFI_STRING
+ConstructRequestElement (
+ IN CHAR16 *Name,
+ IN UINT16 Offset,
+ IN UINT16 Width
+ )
+{
+ CHAR16 *StringPtr;
+ UINTN Length;
+
+ if (Name != NULL) {
+ //
+ // Add <BlockName> length for each Name
+ //
+ // <BlockName> ::= Name + \0
+ // StrLen(Name) | 1
+ //
+ Length = StrLen (Name) + 1;
+ } else {
+ //
+ // Add <BlockName> length for each Offset/Width pair
+ //
+ // <BlockName> ::= OFFSET=1234&WIDTH=1234 + \0
+ // | 7 | 4 | 7 | 4 | 1
+ //
+ Length = (7 + 4 + 7 + 4 + 1);
+ }
+
+ //
+ // Allocate buffer for the entire <ConfigRequest>
+ //
+ StringPtr = AllocateZeroPool (Length * sizeof (CHAR16));
+ ASSERT (StringPtr != NULL);
+
+ if (Name != NULL) {
+ //
+ // Append Name\0
+ //
+ UnicodeSPrint (
+ StringPtr,
+ (StrLen (Name) + 1) * sizeof (CHAR16),
+ L"%s",
+ Name
+ );
+ } else {
+ //
+ // Append OFFSET=XXXX&WIDTH=YYYY\0
+ //
+ UnicodeSPrint (
+ StringPtr,
+ (7 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
+ L"OFFSET=%04X&WIDTH=%04X",
+ Offset,
+ Width
+ );
+ }
+
+ return StringPtr;
+}
+
+/**
+ Get string value for question's name field.
+
+ @param DatabaseRecord HII_DATABASE_RECORD format string.
+ @param NameId The string id for the name field.
+
+ @retval Name string.
+
+**/
+CHAR16 *
+GetNameFromId (
+ IN HII_DATABASE_RECORD *DatabaseRecord,
+ IN EFI_STRING_ID NameId
+ )
+{
+ CHAR16 *Name;
+ CHAR8 *PlatformLanguage;
+ CHAR8 *SupportedLanguages;
+ CHAR8 *BestLanguage;
+ UINTN StringSize;
+ CHAR16 TempString;
+ EFI_STATUS Status;
+
+ Name = NULL;
+ BestLanguage = NULL;
+ PlatformLanguage = NULL;
+ SupportedLanguages = NULL;
+
+ GetEfiGlobalVariable2 (L"PlatformLang", (VOID **)&PlatformLanguage, NULL);
+ SupportedLanguages = GetSupportedLanguages (DatabaseRecord->Handle);
+
+ //
+ // Get the best matching language from SupportedLanguages
+ //
+ BestLanguage = GetBestLanguage (
+ SupportedLanguages,
+ FALSE, // RFC 4646 mode
+ PlatformLanguage != NULL ? PlatformLanguage : "", // Highest priority
+ SupportedLanguages, // Lowest priority
+ NULL
+ );
+ if (BestLanguage == NULL) {
+ BestLanguage = AllocateCopyPool (sizeof ("en-US"), "en-US");
+ ASSERT (BestLanguage != NULL);
+ }
+
+ StringSize = 0;
+ Status = mPrivate.HiiString.GetString (
+ &mPrivate.HiiString,
+ BestLanguage,
+ DatabaseRecord->Handle,
+ NameId,
+ &TempString,
+ &StringSize,
+ NULL
+ );
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ goto Done;
+ }
+
+ Name = AllocateZeroPool (StringSize);
+ if (Name == NULL) {
+ goto Done;
+ }
+
+ Status = mPrivate.HiiString.GetString (
+ &mPrivate.HiiString,
+ BestLanguage,
+ DatabaseRecord->Handle,
+ NameId,
+ Name,
+ &StringSize,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePool (Name);
+ Name = NULL;
+ goto Done;
+ }
+
+Done:
+ if (SupportedLanguages != NULL) {
+ FreePool (SupportedLanguages);
+ }
+
+ if (BestLanguage != NULL) {
+ FreePool (BestLanguage);
+ }
+
+ if (PlatformLanguage != NULL) {
+ FreePool (PlatformLanguage);
+ }
+
+ return Name;
+}
+
+/**
+ Base on the input parameter to generate the ConfigRequest string.
+
+ This is a internal function.
+
+ @param DatabaseRecord HII_DATABASE_RECORD format string.
+ @param KeywordStrId Keyword string id.
+ @param OpCodeData The IFR data for this question.
+ @param ConfigRequest Return the generate ConfigRequest string.
+
+ @retval EFI_SUCCESS Generate ConfigResp string success.
+ @retval EFI_OUT_OF_RESOURCES System out of memory resource error.
+ @retval EFI_NOT_FOUND Not found the question which use this string id
+ as the prompt string id.
+**/
+EFI_STATUS
+ExtractConfigRequest (
+ IN HII_DATABASE_RECORD *DatabaseRecord,
+ IN EFI_STRING_ID KeywordStrId,
+ OUT UINT8 **OpCodeData,
+ OUT EFI_STRING *ConfigRequest
+ )
+{
+ LIST_ENTRY *Link;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_IFR_PACKAGE_INSTANCE *FormPackage;
+ EFI_IFR_QUESTION_HEADER *Header;
+ UINT8 *Storage;
+ UINT8 *OpCode;
+ CHAR16 *Name;
+ UINT16 Offset;
+ UINT16 Width;
+ CHAR16 *ConfigHdr;
+ CHAR16 *RequestElement;
+ UINTN MaxLen;
+ CHAR16 *StringPtr;
+
+ ASSERT (DatabaseRecord != NULL && OpCodeData != NULL && ConfigRequest != NULL);
+
+ OpCode = NULL;
+ Name = NULL;
+ Width = 0;
+ Offset = 0;
+
+ PackageListNode = DatabaseRecord->PackageList;
+
+ //
+ // Search the languages in the specified packagelist.
+ //
+ for (Link = PackageListNode->FormPkgHdr.ForwardLink; Link != &PackageListNode->FormPkgHdr; Link = Link->ForwardLink) {
+ FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);
+
+ OpCode = FindQuestionFromStringId (FormPackage, KeywordStrId);
+ if (OpCode != NULL) {
+ *OpCodeData = OpCode;
+ Header = (EFI_IFR_QUESTION_HEADER *)(OpCode + sizeof (EFI_IFR_OP_HEADER));
+ //
+ // Header->VarStoreId == 0 means no storage for this question.
+ //
+ ASSERT (Header->VarStoreId != 0);
+ DEBUG ((DEBUG_INFO, "Varstore Id: 0x%x\n", Header->VarStoreId));
+
+ Storage = FindStorageFromVarId (FormPackage, Header->VarStoreId);
+ ASSERT (Storage != NULL);
+
+ if (((EFI_IFR_OP_HEADER *)Storage)->OpCode == EFI_IFR_VARSTORE_NAME_VALUE_OP) {
+ Name = GetNameFromId (DatabaseRecord, Header->VarStoreInfo.VarName);
+ } else {
+ Offset = Header->VarStoreInfo.VarOffset;
+ Width = GetWidth (OpCode);
+ }
+
+ RequestElement = ConstructRequestElement (Name, Offset, Width);
+ ConfigHdr = ConstructConfigHdr (Storage, DatabaseRecord->DriverHandle);
+ ASSERT (ConfigHdr != NULL);
+
+ MaxLen = StrLen (ConfigHdr) + 1 + StrLen (RequestElement) + 1;
+ *ConfigRequest = AllocatePool (MaxLen * sizeof (CHAR16));
+ if (*ConfigRequest == NULL) {
+ FreePool (ConfigHdr);
+ FreePool (RequestElement);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StringPtr = *ConfigRequest;
+
+ StrCpyS (StringPtr, MaxLen, ConfigHdr);
+
+ StrCatS (StringPtr, MaxLen, L"&");
+
+ StrCatS (StringPtr, MaxLen, RequestElement);
+
+ FreePool (ConfigHdr);
+ FreePool (RequestElement);
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Base on the input parameter to generate the ConfigResp string.
+
+ This is a internal function.
+
+ @param DatabaseRecord HII_DATABASE_RECORD format string.
+ @param KeywordStrId Keyword string id.
+ @param ValueElement The value for the question which use keyword string id
+ as the prompt string id.
+ @param OpCodeData The IFR data for this question.
+ @param ConfigResp Return the generate ConfigResp string.
+
+ @retval EFI_SUCCESS Generate ConfigResp string success.
+ @retval EFI_OUT_OF_RESOURCES System out of memory resource error.
+ @retval EFI_NOT_FOUND Not found the question which use this string id
+ as the prompt string id.
+**/
+EFI_STATUS
+ExtractConfigResp (
+ IN HII_DATABASE_RECORD *DatabaseRecord,
+ IN EFI_STRING_ID KeywordStrId,
+ IN EFI_STRING ValueElement,
+ OUT UINT8 **OpCodeData,
+ OUT EFI_STRING *ConfigResp
+ )
+{
+ LIST_ENTRY *Link;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_IFR_PACKAGE_INSTANCE *FormPackage;
+ EFI_IFR_QUESTION_HEADER *Header;
+ UINT8 *Storage;
+ UINT8 *OpCode;
+ CHAR16 *Name;
+ UINT16 Offset;
+ UINT16 Width;
+ CHAR16 *ConfigHdr;
+ CHAR16 *RequestElement;
+ UINTN MaxLen;
+ CHAR16 *StringPtr;
+
+ ASSERT ((DatabaseRecord != NULL) && (OpCodeData != NULL) && (ConfigResp != NULL) && (ValueElement != NULL));
+
+ OpCode = NULL;
+ Name = NULL;
+ Width = 0;
+ Offset = 0;
+
+ PackageListNode = DatabaseRecord->PackageList;
+
+ //
+ // Search the languages in the specified packagelist.
+ //
+ for (Link = PackageListNode->FormPkgHdr.ForwardLink; Link != &PackageListNode->FormPkgHdr; Link = Link->ForwardLink) {
+ FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);
+
+ OpCode = FindQuestionFromStringId (FormPackage, KeywordStrId);
+ if (OpCode != NULL) {
+ *OpCodeData = OpCode;
+ Header = (EFI_IFR_QUESTION_HEADER *)(OpCode + sizeof (EFI_IFR_OP_HEADER));
+ //
+ // Header->VarStoreId == 0 means no storage for this question.
+ //
+ ASSERT (Header->VarStoreId != 0);
+ DEBUG ((DEBUG_INFO, "Varstore Id: 0x%x\n", Header->VarStoreId));
+
+ Storage = FindStorageFromVarId (FormPackage, Header->VarStoreId);
+ ASSERT (Storage != NULL);
+
+ if (((EFI_IFR_OP_HEADER *)Storage)->OpCode == EFI_IFR_VARSTORE_NAME_VALUE_OP) {
+ Name = GetNameFromId (DatabaseRecord, Header->VarStoreInfo.VarName);
+ } else {
+ Offset = Header->VarStoreInfo.VarOffset;
+ Width = GetWidth (OpCode);
+ }
+
+ RequestElement = ConstructRequestElement (Name, Offset, Width);
+
+ ConfigHdr = ConstructConfigHdr (Storage, DatabaseRecord->DriverHandle);
+ ASSERT (ConfigHdr != NULL);
+
+ MaxLen = StrLen (ConfigHdr) + 1 + StrLen (RequestElement) + 1 + StrLen (L"VALUE=") + StrLen (ValueElement) + 1;
+ *ConfigResp = AllocatePool (MaxLen * sizeof (CHAR16));
+ if (*ConfigResp == NULL) {
+ FreePool (ConfigHdr);
+ FreePool (RequestElement);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StringPtr = *ConfigResp;
+
+ StrCpyS (StringPtr, MaxLen, ConfigHdr);
+
+ StrCatS (StringPtr, MaxLen, L"&");
+
+ StrCatS (StringPtr, MaxLen, RequestElement);
+
+ StrCatS (StringPtr, MaxLen, L"&");
+
+ StrCatS (StringPtr, MaxLen, L"VALUE=");
+
+ StrCatS (StringPtr, MaxLen, ValueElement);
+
+ FreePool (ConfigHdr);
+ FreePool (RequestElement);
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Get the Value section from the Hii driver.
+
+ This is a internal function.
+
+ @param ConfigRequest The input ConfigRequest string.
+ @param ValueElement The respond Value section from the hii driver.
+
+ @retval Misc value The error status return from ExtractConfig function.
+ @retval EFI_OUT_OF_RESOURCES The memory can't be allocated
+ @retval EFI_SUCCESS Get the value section success.
+
+**/
+EFI_STATUS
+ExtractValueFromDriver (
+ IN CHAR16 *ConfigRequest,
+ OUT CHAR16 **ValueElement
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING Result;
+ EFI_STRING Progress;
+ CHAR16 *StringPtr;
+ CHAR16 *StringEnd;
+
+ ASSERT ((ConfigRequest != NULL) && (ValueElement != NULL));
+
+ Status = mPrivate.ConfigRouting.ExtractConfig (
+ &mPrivate.ConfigRouting,
+ (EFI_STRING)ConfigRequest,
+ &Progress,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Find Value Section and return it.
+ //
+ StringPtr = StrStr (Result, L"&VALUE=");
+ ASSERT (StringPtr != NULL);
+ StringEnd = StrStr (StringPtr + 1, L"&");
+ if (StringEnd != NULL) {
+ *StringEnd = L'\0';
+ }
+
+ *ValueElement = AllocateCopyPool (StrSize (StringPtr), StringPtr);
+ if (*ValueElement == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (StringEnd != NULL) {
+ *StringEnd = L'&';
+ }
+
+ FreePool (Result);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get EFI_STRING_ID info from the input device path, namespace and keyword.
+
+ This is a internal function.
+
+ @param DevicePath Input device path info.
+ @param NameSpace NameSpace format string.
+ @param KeywordData Keyword used to get string id.
+ @param ProgressErr Return extra error type.
+ @param KeywordStringId Return EFI_STRING_ID.
+ @param DataBaseRecord DataBase record data for this driver.
+
+ @retval EFI_INVALID_PARAMETER Can't find the database record base on the input device path or namespace.
+ @retval EFI_NOT_FOUND Can't find the EFI_STRING_ID for the keyword.
+ @retval EFI_SUCCESS Find the EFI_STRING_ID.
+
+**/
+EFI_STATUS
+GetStringIdFromDatabase (
+ IN EFI_DEVICE_PATH_PROTOCOL **DevicePath,
+ IN CHAR8 **NameSpace,
+ IN CHAR16 *KeywordData,
+ OUT UINT32 *ProgressErr,
+ OUT EFI_STRING_ID *KeywordStringId,
+ OUT HII_DATABASE_RECORD **DataBaseRecord
+ )
+{
+ HII_DATABASE_RECORD *Record;
+ LIST_ENTRY *Link;
+ BOOLEAN FindNameSpace;
+ EFI_DEVICE_PATH_PROTOCOL *DestDevicePath;
+ UINT8 *DevicePathPkg;
+ UINTN DevicePathSize;
+
+ ASSERT ((NameSpace != NULL) && (KeywordData != NULL) && (ProgressErr != NULL) && (KeywordStringId != NULL) && (DataBaseRecord != NULL));
+
+ FindNameSpace = FALSE;
+
+ if (*DevicePath != NULL) {
+ //
+ // Get DataBaseRecord from device path protocol.
+ //
+ Record = GetRecordFromDevicePath (*DevicePath);
+ if (Record == NULL) {
+ //
+ // Can't find the DatabaseRecord base on the input device path info.
+ // NEED TO CONFIRM the return ProgressErr.
+ //
+ *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get string id from the record.
+ //
+ *ProgressErr = GetStringIdFromRecord (Record, NameSpace, KeywordData, KeywordStringId);
+ switch (*ProgressErr) {
+ case KEYWORD_HANDLER_NO_ERROR:
+ *DataBaseRecord = Record;
+ return EFI_SUCCESS;
+
+ case KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND:
+ return EFI_INVALID_PARAMETER;
+
+ default:
+ ASSERT (*ProgressErr == KEYWORD_HANDLER_KEYWORD_NOT_FOUND);
+ return EFI_NOT_FOUND;
+ }
+ } else {
+ //
+ // Find driver which matches the routing data.
+ //
+ for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {
+ Record = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+
+ *ProgressErr = GetStringIdFromRecord (Record, NameSpace, KeywordData, KeywordStringId);
+ if (*ProgressErr == KEYWORD_HANDLER_NO_ERROR) {
+ *DataBaseRecord = Record;
+
+ if ((DevicePathPkg = Record->PackageList->DevicePathPkg) != NULL) {
+ DestDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)(DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER));
+ DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DestDevicePath);
+ *DevicePath = AllocateCopyPool (DevicePathSize, DestDevicePath);
+ if (*DevicePath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ //
+ // Need to verify this ASSERT.
+ //
+ ASSERT (FALSE);
+ }
+
+ return EFI_SUCCESS;
+ } else if (*ProgressErr == KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR) {
+ return EFI_OUT_OF_RESOURCES;
+ } else if (*ProgressErr == KEYWORD_HANDLER_KEYWORD_NOT_FOUND) {
+ FindNameSpace = TRUE;
+ }
+ }
+
+ //
+ // When PathHdr not input, if ever find the namespace, will return KEYWORD_HANDLER_KEYWORD_NOT_FOUND.
+ // This is a bit more progress than KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND.
+ //
+ if (FindNameSpace) {
+ return EFI_NOT_FOUND;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+}
+
+/**
+ Generate the KeywordResp String.
+
+ <KeywordResp> ::= <NameSpaceId><PathHdr>'&'<Keyword>'&VALUE='<Number>['&READONLY']
+
+ @param NameSpace NameSpace format string.
+ @param DevicePath Input device path info.
+ @param KeywordData Keyword used to get string id.
+ @param ValueStr The value section for the keyword.
+ @param ReadOnly Whether this value is readonly.
+ @param KeywordResp Return the point to the KeywordResp string.
+
+ @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.
+ @retval EFI_SUCCESS Generate the KeywordResp string.
+
+**/
+EFI_STATUS
+GenerateKeywordResp (
+ IN CHAR8 *NameSpace,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_STRING KeywordData,
+ IN EFI_STRING ValueStr,
+ IN BOOLEAN ReadOnly,
+ OUT EFI_STRING *KeywordResp
+ )
+{
+ UINTN RespStrLen;
+ CHAR16 *RespStr;
+ CHAR16 *PathHdr;
+ CHAR16 *UnicodeNameSpace;
+ UINTN NameSpaceLength;
+
+ ASSERT ((NameSpace != NULL) && (DevicePath != NULL) && (KeywordData != NULL) && (ValueStr != NULL) && (KeywordResp != NULL));
+
+ //
+ // 1. Calculate the string length.
+ //
+ //
+ // 1.1 NameSpaceId size.
+ // 'NAMESPACE='<String>
+ //
+ NameSpaceLength = AsciiStrLen (NameSpace);
+ RespStrLen = 10 + NameSpaceLength;
+ UnicodeNameSpace = AllocatePool ((NameSpaceLength + 1) * sizeof (CHAR16));
+ if (UnicodeNameSpace == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ AsciiStrToUnicodeStrS (NameSpace, UnicodeNameSpace, NameSpaceLength + 1);
+
+ //
+ // 1.2 PathHdr size.
+ // PATH=<UEFI binary Device Path represented as hex number>'&'
+ // Attention: The output include the '&' at the end.
+ //
+ GenerateSubStr (
+ L"&PATH=",
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DevicePath),
+ (VOID *)DevicePath,
+ 1,
+ &PathHdr
+ );
+ RespStrLen += StrLen (PathHdr);
+
+ //
+ // 1.3 Keyword section.
+ // 'KEYWORD='<String>[':'<DecCh>(1/4)]
+ //
+ RespStrLen += 8 + StrLen (KeywordData);
+
+ //
+ // 1.4 Value section.
+ // ValueStr = '&VALUE='<Number>
+ //
+ RespStrLen += StrLen (ValueStr);
+
+ //
+ // 1.5 ReadOnly Section.
+ // '&READONLY'
+ //
+ if (ReadOnly) {
+ RespStrLen += 9;
+ }
+
+ //
+ // 2. Allocate the buffer and create the KeywordResp string include '\0'.
+ //
+ RespStrLen += 1;
+ *KeywordResp = AllocatePool (RespStrLen * sizeof (CHAR16));
+ if (*KeywordResp == NULL) {
+ if (UnicodeNameSpace != NULL) {
+ FreePool (UnicodeNameSpace);
+ }
+
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RespStr = *KeywordResp;
+
+ //
+ // 2.1 Copy NameSpaceId section.
+ //
+ StrCpyS (RespStr, RespStrLen, L"NAMESPACE=");
+
+ StrCatS (RespStr, RespStrLen, UnicodeNameSpace);
+
+ //
+ // 2.2 Copy PathHdr section.
+ //
+ StrCatS (RespStr, RespStrLen, PathHdr);
+
+ //
+ // 2.3 Copy Keyword section.
+ //
+ StrCatS (RespStr, RespStrLen, L"KEYWORD=");
+
+ StrCatS (RespStr, RespStrLen, KeywordData);
+
+ //
+ // 2.4 Copy the Value section.
+ //
+ StrCatS (RespStr, RespStrLen, ValueStr);
+
+ //
+ // 2.5 Copy ReadOnly section if exist.
+ //
+ if (ReadOnly) {
+ StrCatS (RespStr, RespStrLen, L"&READONLY");
+ }
+
+ if (UnicodeNameSpace != NULL) {
+ FreePool (UnicodeNameSpace);
+ }
+
+ if (PathHdr != NULL) {
+ FreePool (PathHdr);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Merge the KeywordResp String to MultiKeywordResp string.
+
+ This is a internal function.
+
+ @param MultiKeywordResp The existed multikeywordresp string.
+ @param KeywordResp The input keywordResp string.
+
+ @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.
+ @retval EFI_SUCCESS Generate the MultiKeywordResp string.
+
+**/
+EFI_STATUS
+MergeToMultiKeywordResp (
+ IN OUT EFI_STRING *MultiKeywordResp,
+ IN EFI_STRING *KeywordResp
+ )
+{
+ UINTN MultiKeywordRespLen;
+ EFI_STRING StringPtr;
+
+ if (*MultiKeywordResp == NULL) {
+ *MultiKeywordResp = *KeywordResp;
+ *KeywordResp = NULL;
+ return EFI_SUCCESS;
+ }
+
+ MultiKeywordRespLen = (StrLen (*MultiKeywordResp) + 1 + StrLen (*KeywordResp) + 1) * sizeof (CHAR16);
+
+ StringPtr = ReallocatePool (
+ StrSize (*MultiKeywordResp),
+ MultiKeywordRespLen,
+ *MultiKeywordResp
+ );
+ if (StringPtr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *MultiKeywordResp = StringPtr;
+
+ StrCatS (StringPtr, MultiKeywordRespLen / sizeof (CHAR16), L"&");
+
+ StrCatS (StringPtr, MultiKeywordRespLen / sizeof (CHAR16), *KeywordResp);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Enumerate all keyword in the system.
+
+ If error occur when parse one keyword, just skip it and parse the next one.
+
+ This is a internal function.
+
+ @param NameSpace The namespace used to search the string.
+ @param MultiResp Return the MultiKeywordResp string for the system.
+ @param ProgressErr Return the error status.
+
+ @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.
+ @retval EFI_SUCCESS Generate the MultiKeywordResp string.
+ @retval EFI_NOT_FOUND No keyword found.
+
+**/
+EFI_STATUS
+EnumerateAllKeywords (
+ IN CHAR8 *NameSpace,
+ OUT EFI_STRING *MultiResp,
+ OUT UINT32 *ProgressErr
+ )
+{
+ LIST_ENTRY *Link;
+ LIST_ENTRY *StringLink;
+ UINT8 *DevicePathPkg;
+ UINT8 *DevicePath;
+ HII_DATABASE_RECORD *DataBaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+ CHAR8 *LocalNameSpace;
+ EFI_STRING_ID NextStringId;
+ EFI_STATUS Status;
+ UINT8 *OpCode;
+ CHAR16 *ConfigRequest;
+ CHAR16 *ValueElement;
+ CHAR16 *KeywordResp;
+ CHAR16 *MultiKeywordResp;
+ CHAR16 *KeywordData;
+ BOOLEAN ReadOnly;
+ BOOLEAN FindKeywordPackages;
+
+ DataBaseRecord = NULL;
+ Status = EFI_SUCCESS;
+ MultiKeywordResp = NULL;
+ DevicePath = NULL;
+ LocalNameSpace = NULL;
+ ConfigRequest = NULL;
+ ValueElement = NULL;
+ KeywordResp = NULL;
+ FindKeywordPackages = FALSE;
+
+ if (NameSpace == NULL) {
+ NameSpace = UEFI_CONFIG_LANG;
+ }
+
+ //
+ // Find driver which matches the routing data.
+ //
+ for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {
+ DataBaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if ((DevicePathPkg = DataBaseRecord->PackageList->DevicePathPkg) != NULL) {
+ DevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
+ }
+
+ PackageListNode = DataBaseRecord->PackageList;
+
+ for (StringLink = PackageListNode->StringPkgHdr.ForwardLink; StringLink != &PackageListNode->StringPkgHdr; StringLink = StringLink->ForwardLink) {
+ StringPackage = CR (StringLink, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+
+ //
+ // Check whether has keyword string package.
+ //
+ if (AsciiStrnCmp (NameSpace, StringPackage->StringPkgHdr->Language, AsciiStrLen (NameSpace)) == 0) {
+ FindKeywordPackages = TRUE;
+ //
+ // Keep the NameSpace string.
+ //
+ LocalNameSpace = AllocateCopyPool (AsciiStrSize (StringPackage->StringPkgHdr->Language), StringPackage->StringPkgHdr->Language);
+ if (LocalNameSpace == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // 1 means just begin the enumerate the valid string ids.
+ // StringId == 1 is always used to save the language for this string package.
+ // Any valid string start from 2. so here initial it to 1.
+ //
+ NextStringId = 1;
+
+ //
+ // Enumerate all valid stringid in the package.
+ //
+ while ((NextStringId = GetNextStringId (StringPackage, NextStringId, &KeywordData)) != 0) {
+ //
+ // 3.3 Construct the ConfigRequest string.
+ //
+ Status = ExtractConfigRequest (DataBaseRecord, NextStringId, &OpCode, &ConfigRequest);
+ if (EFI_ERROR (Status)) {
+ //
+ // If can't generate ConfigRequest for this question, skip it and start the next.
+ //
+ goto Error;
+ }
+
+ //
+ // 3.4 Extract Value for the input keyword.
+ //
+ Status = ExtractValueFromDriver (ConfigRequest, &ValueElement);
+ if (EFI_ERROR (Status)) {
+ if (Status != EFI_OUT_OF_RESOURCES) {
+ //
+ // If can't generate ConfigRequest for this question, skip it and start the next.
+ //
+ goto Error;
+ }
+
+ //
+ // If EFI_OUT_OF_RESOURCES error occur, no need to continue.
+ //
+ goto Done;
+ }
+
+ //
+ // Extract readonly flag from opcode.
+ //
+ ReadOnly = ExtractReadOnlyFromOpCode (OpCode);
+
+ //
+ // 5. Generate KeywordResp string.
+ //
+ ASSERT (DevicePath != NULL);
+ Status = GenerateKeywordResp (LocalNameSpace, (EFI_DEVICE_PATH_PROTOCOL *)DevicePath, KeywordData, ValueElement, ReadOnly, &KeywordResp);
+ if (Status != EFI_SUCCESS) {
+ //
+ // If EFI_OUT_OF_RESOURCES error occur, no need to continue.
+ //
+ goto Done;
+ }
+
+ //
+ // 6. Merge to the MultiKeywordResp string.
+ //
+ Status = MergeToMultiKeywordResp (&MultiKeywordResp, &KeywordResp);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+Error:
+ //
+ // Clean the temp buffer to later use again.
+ //
+ if (ConfigRequest != NULL) {
+ FreePool (ConfigRequest);
+ ConfigRequest = NULL;
+ }
+
+ if (ValueElement != NULL) {
+ FreePool (ValueElement);
+ ValueElement = NULL;
+ }
+
+ if (KeywordResp != NULL) {
+ FreePool (KeywordResp);
+ KeywordResp = NULL;
+ }
+ }
+
+ if (LocalNameSpace != NULL) {
+ FreePool (LocalNameSpace);
+ LocalNameSpace = NULL;
+ }
+ }
+ }
+ }
+
+ //
+ // return the already get MultiKeywordString even error occurred.
+ //
+ if (MultiKeywordResp == NULL) {
+ Status = EFI_NOT_FOUND;
+ if (!FindKeywordPackages) {
+ *ProgressErr = KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND;
+ } else {
+ *ProgressErr = KEYWORD_HANDLER_KEYWORD_NOT_FOUND;
+ }
+ } else {
+ Status = EFI_SUCCESS;
+ }
+
+ *MultiResp = MultiKeywordResp;
+
+Done:
+ if (LocalNameSpace != NULL) {
+ FreePool (LocalNameSpace);
+ }
+
+ if (ConfigRequest != NULL) {
+ FreePool (ConfigRequest);
+ }
+
+ if (ValueElement != NULL) {
+ FreePool (ValueElement);
+ }
+
+ return Status;
+}
+
+/**
+
+ This function accepts a <MultiKeywordResp> formatted string, finds the associated
+ keyword owners, creates a <MultiConfigResp> string from it and forwards it to the
+ EFI_HII_ROUTING_PROTOCOL.RouteConfig function.
+
+ If there is an issue in resolving the contents of the KeywordString, then the
+ function returns an error and also sets the Progress and ProgressErr with the
+ appropriate information about where the issue occurred and additional data about
+ the nature of the issue.
+
+ In the case when KeywordString containing multiple keywords, when an EFI_NOT_FOUND
+ error is generated during processing the second or later keyword element, the system
+ storage associated with earlier keywords is not modified. All elements of the
+ KeywordString must successfully pass all tests for format and access prior to making
+ any modifications to storage.
+
+ In the case when EFI_DEVICE_ERROR is returned from the processing of a KeywordString
+ containing multiple keywords, the state of storage associated with earlier keywords
+ is undefined.
+
+
+ @param This Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.
+
+ @param KeywordString A null-terminated string in <MultiKeywordResp> format.
+
+ @param Progress On return, points to a character in the KeywordString.
+ Points to the string's NULL terminator if the request
+ was successful. Points to the most recent '&' before
+ the first failing name / value pair (or the beginning
+ of the string if the failure is in the first name / value
+ pair) if the request was not successful.
+
+ @param ProgressErr If during the processing of the KeywordString there was
+ a failure, this parameter gives additional information
+ about the possible source of the problem. The various
+ errors are defined in "Related Definitions" below.
+
+
+ @retval EFI_SUCCESS The specified action was completed successfully.
+
+ @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
+ 1. KeywordString is NULL.
+ 2. Parsing of the KeywordString resulted in an
+ error. See Progress and ProgressErr for more data.
+
+ @retval EFI_NOT_FOUND An element of the KeywordString was not found.
+ See ProgressErr for more data.
+
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ See ProgressErr for more data.
+
+ @retval EFI_ACCESS_DENIED The action violated system policy. See ProgressErr
+ for more data.
+
+ @retval EFI_DEVICE_ERROR An unexpected system error occurred. See ProgressErr
+ for more data.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiConfigKeywordHandlerSetData (
+ IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *This,
+ IN CONST EFI_STRING KeywordString,
+ OUT EFI_STRING *Progress,
+ OUT UINT32 *ProgressErr
+ )
+{
+ CHAR8 *NameSpace;
+ EFI_STATUS Status;
+ CHAR16 *StringPtr;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ CHAR16 *NextStringPtr;
+ CHAR16 *KeywordData;
+ EFI_STRING_ID KeywordStringId;
+ UINT32 RetVal;
+ HII_DATABASE_RECORD *DataBaseRecord;
+ UINT8 *OpCode;
+ CHAR16 *ConfigResp;
+ CHAR16 *MultiConfigResp;
+ CHAR16 *ValueElement;
+ BOOLEAN ReadOnly;
+ EFI_STRING InternalProgress;
+ CHAR16 *TempString;
+ CHAR16 *KeywordStartPos;
+
+ if ((This == NULL) || (Progress == NULL) || (ProgressErr == NULL) || (KeywordString == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Progress = KeywordString;
+ *ProgressErr = KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;
+ Status = EFI_SUCCESS;
+ MultiConfigResp = NULL;
+ NameSpace = NULL;
+ DevicePath = NULL;
+ KeywordData = NULL;
+ ValueElement = NULL;
+ ConfigResp = NULL;
+ KeywordStartPos = NULL;
+ KeywordStringId = 0;
+
+ //
+ // Use temp string to avoid changing input string buffer.
+ //
+ TempString = AllocateCopyPool (StrSize (KeywordString), KeywordString);
+ ASSERT (TempString != NULL);
+ StringPtr = TempString;
+
+ while ((StringPtr != NULL) && (*StringPtr != L'\0')) {
+ //
+ // 1. Get NameSpace from NameSpaceId keyword.
+ //
+ Status = ExtractNameSpace (StringPtr, &NameSpace, &NextStringPtr);
+ if (EFI_ERROR (Status)) {
+ *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
+ goto Done;
+ }
+
+ ASSERT (NameSpace != NULL);
+ //
+ // 1.1 Check whether the input namespace is valid.
+ //
+ if (AsciiStrnCmp (NameSpace, UEFI_CONFIG_LANG, AsciiStrLen (UEFI_CONFIG_LANG)) != 0) {
+ *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ StringPtr = NextStringPtr;
+
+ //
+ // 2. Get possible Device Path info from KeywordString.
+ //
+ Status = ExtractDevicePath (StringPtr, (UINT8 **)&DevicePath, &NextStringPtr);
+ if (EFI_ERROR (Status)) {
+ *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
+ goto Done;
+ }
+
+ StringPtr = NextStringPtr;
+
+ //
+ // 3. Extract keyword from the KeywordRequest string.
+ //
+ KeywordStartPos = StringPtr;
+ Status = ExtractKeyword (StringPtr, &KeywordData, &NextStringPtr);
+ if (EFI_ERROR (Status)) {
+ //
+ // Can't find Keyword base on the input device path info.
+ //
+ *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ StringPtr = NextStringPtr;
+
+ //
+ // 4. Extract Value from the KeywordRequest string.
+ //
+ Status = ExtractValue (StringPtr, &ValueElement, &NextStringPtr);
+ if (EFI_ERROR (Status)) {
+ //
+ // Can't find Value base on the input device path info.
+ //
+ *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ StringPtr = NextStringPtr;
+
+ //
+ // 5. Find READONLY tag.
+ //
+ if ((StringPtr != NULL) && (StrnCmp (StringPtr, L"&READONLY", StrLen (L"&READONLY")) == 0)) {
+ ReadOnly = TRUE;
+ StringPtr += StrLen (L"&READONLY");
+ } else {
+ ReadOnly = FALSE;
+ }
+
+ //
+ // 6. Get EFI_STRING_ID for the input keyword.
+ //
+ Status = GetStringIdFromDatabase (&DevicePath, &NameSpace, KeywordData, &RetVal, &KeywordStringId, &DataBaseRecord);
+ if (EFI_ERROR (Status)) {
+ *ProgressErr = RetVal;
+ goto Done;
+ }
+
+ //
+ // 7. Construct the ConfigRequest string.
+ //
+ Status = ExtractConfigResp (DataBaseRecord, KeywordStringId, ValueElement, &OpCode, &ConfigResp);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // 8. Check the readonly flag.
+ //
+ if (ExtractReadOnlyFromOpCode (OpCode) != ReadOnly) {
+ //
+ // Extracting readonly flag form opcode and extracting "READONLY" tag form KeywordString should have the same results.
+ // If not, the input KeywordString must be incorrect, return the error status to caller.
+ //
+ *ProgressErr = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (ReadOnly) {
+ *ProgressErr = KEYWORD_HANDLER_ACCESS_NOT_PERMITTED;
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+
+ //
+ // 9. Merge to the MultiKeywordResp string.
+ //
+ Status = MergeToMultiKeywordResp (&MultiConfigResp, &ConfigResp);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // 10. Clean the temp buffer point.
+ //
+ FreePool (NameSpace);
+ FreePool (DevicePath);
+ FreePool (KeywordData);
+ FreePool (ValueElement);
+ NameSpace = NULL;
+ DevicePath = NULL;
+ KeywordData = NULL;
+ ValueElement = NULL;
+ if (ConfigResp != NULL) {
+ FreePool (ConfigResp);
+ ConfigResp = NULL;
+ }
+
+ KeywordStartPos = NULL;
+ }
+
+ //
+ // 11. Set value to driver.
+ //
+ Status = mPrivate.ConfigRouting.RouteConfig (
+ &mPrivate.ConfigRouting,
+ (EFI_STRING)MultiConfigResp,
+ &InternalProgress
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ *ProgressErr = KEYWORD_HANDLER_NO_ERROR;
+
+Done:
+ if (KeywordStartPos != NULL) {
+ *Progress = KeywordString + (KeywordStartPos - TempString);
+ } else {
+ *Progress = KeywordString + (StringPtr - TempString);
+ }
+
+ ASSERT (TempString != NULL);
+ FreePool (TempString);
+ if (NameSpace != NULL) {
+ FreePool (NameSpace);
+ }
+
+ if (DevicePath != NULL) {
+ FreePool (DevicePath);
+ }
+
+ if (KeywordData != NULL) {
+ FreePool (KeywordData);
+ }
+
+ if (ValueElement != NULL) {
+ FreePool (ValueElement);
+ }
+
+ if (ConfigResp != NULL) {
+ FreePool (ConfigResp);
+ }
+
+ if ((MultiConfigResp != NULL) && (MultiConfigResp != ConfigResp)) {
+ FreePool (MultiConfigResp);
+ }
+
+ return Status;
+}
+
+/**
+
+ This function accepts a <MultiKeywordRequest> formatted string, finds the underlying
+ keyword owners, creates a <MultiConfigRequest> string from it and forwards it to the
+ EFI_HII_ROUTING_PROTOCOL.ExtractConfig function.
+
+ If there is an issue in resolving the contents of the KeywordString, then the function
+ returns an EFI_INVALID_PARAMETER and also set the Progress and ProgressErr with the
+ appropriate information about where the issue occurred and additional data about the
+ nature of the issue.
+
+ In the case when KeywordString is NULL, or contains multiple keywords, or when
+ EFI_NOT_FOUND is generated while processing the keyword elements, the Results string
+ contains values returned for all keywords processed prior to the keyword generating the
+ error but no values for the keyword with error or any following keywords.
+
+
+ @param This Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.
+
+ @param NameSpaceId A null-terminated string containing the platform configuration
+ language to search through in the system. If a NULL is passed
+ in, then it is assumed that any platform configuration language
+ with the prefix of "x-UEFI-" are searched.
+
+ @param KeywordString A null-terminated string in <MultiKeywordRequest> format. If a
+ NULL is passed in the KeywordString field, all of the known
+ keywords in the system for the NameSpaceId specified are
+ returned in the Results field.
+
+ @param Progress On return, points to a character in the KeywordString. Points
+ to the string's NULL terminator if the request was successful.
+ Points to the most recent '&' before the first failing name / value
+ pair (or the beginning of the string if the failure is in the first
+ name / value pair) if the request was not successful.
+
+ @param ProgressErr If during the processing of the KeywordString there was a
+ failure, this parameter gives additional information about the
+ possible source of the problem. See the definitions in SetData()
+ for valid value definitions.
+
+ @param Results A null-terminated string in <MultiKeywordResp> format is returned
+ which has all the values filled in for the keywords in the
+ KeywordString. This is a callee-allocated field, and must be freed
+ by the caller after being used.
+
+ @retval EFI_SUCCESS The specified action was completed successfully.
+
+ @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
+ 1.Progress, ProgressErr, or Results is NULL.
+ 2.Parsing of the KeywordString resulted in an error. See
+ Progress and ProgressErr for more data.
+
+
+ @retval EFI_NOT_FOUND An element of the KeywordString was not found. See
+ ProgressErr for more data.
+
+ @retval EFI_NOT_FOUND The NamespaceId specified was not found. See ProgressErr
+ for more data.
+
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. See
+ ProgressErr for more data.
+
+ @retval EFI_ACCESS_DENIED The action violated system policy. See ProgressErr for
+ more data.
+
+ @retval EFI_DEVICE_ERROR An unexpected system error occurred. See ProgressErr
+ for more data.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiConfigKeywordHandlerGetData (
+ IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *This,
+ IN CONST EFI_STRING NameSpaceId OPTIONAL,
+ IN CONST EFI_STRING KeywordString OPTIONAL,
+ OUT EFI_STRING *Progress,
+ OUT UINT32 *ProgressErr,
+ OUT EFI_STRING *Results
+ )
+{
+ CHAR8 *NameSpace;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ HII_DATABASE_RECORD *DataBaseRecord;
+ CHAR16 *StringPtr;
+ CHAR16 *NextStringPtr;
+ CHAR16 *KeywordData;
+ EFI_STRING_ID KeywordStringId;
+ UINT8 *OpCode;
+ CHAR16 *ConfigRequest;
+ CHAR16 *ValueElement;
+ UINT32 RetVal;
+ BOOLEAN ReadOnly;
+ CHAR16 *KeywordResp;
+ CHAR16 *MultiKeywordResp;
+ CHAR16 *TempString;
+
+ if ((This == NULL) || (Progress == NULL) || (ProgressErr == NULL) || (Results == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ProgressErr = KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;
+ Status = EFI_SUCCESS;
+ DevicePath = NULL;
+ NameSpace = NULL;
+ KeywordData = NULL;
+ ConfigRequest = NULL;
+ StringPtr = KeywordString;
+ ReadOnly = FALSE;
+ MultiKeywordResp = NULL;
+ KeywordStringId = 0;
+ TempString = NULL;
+
+ //
+ // Use temp string to avoid changing input string buffer.
+ //
+ if (NameSpaceId != NULL) {
+ TempString = AllocateCopyPool (StrSize (NameSpaceId), NameSpaceId);
+ ASSERT (TempString != NULL);
+ }
+
+ //
+ // 1. Get NameSpace from NameSpaceId keyword.
+ //
+ Status = ExtractNameSpace (TempString, &NameSpace, NULL);
+ if (TempString != NULL) {
+ FreePool (TempString);
+ TempString = NULL;
+ }
+
+ if (EFI_ERROR (Status)) {
+ *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
+ return Status;
+ }
+
+ //
+ // 1.1 Check whether the input namespace is valid.
+ //
+ if (NameSpace != NULL) {
+ if (AsciiStrnCmp (NameSpace, UEFI_CONFIG_LANG, AsciiStrLen (UEFI_CONFIG_LANG)) != 0) {
+ *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ if (KeywordString != NULL) {
+ //
+ // Use temp string to avoid changing input string buffer.
+ //
+ TempString = AllocateCopyPool (StrSize (KeywordString), KeywordString);
+ ASSERT (TempString != NULL);
+ StringPtr = TempString;
+
+ while (*StringPtr != L'\0') {
+ //
+ // 2. Get possible Device Path info from KeywordString.
+ //
+ Status = ExtractDevicePath (StringPtr, (UINT8 **)&DevicePath, &NextStringPtr);
+ if (EFI_ERROR (Status)) {
+ *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
+ goto Done;
+ }
+
+ StringPtr = NextStringPtr;
+
+ //
+ // 3. Process Keyword section from the input keywordRequest string.
+ //
+ // 3.1 Extract keyword from the KeywordRequest string.
+ //
+ Status = ExtractKeyword (StringPtr, &KeywordData, &NextStringPtr);
+ if (EFI_ERROR (Status)) {
+ //
+ // Can't find Keyword base on the input device path info.
+ //
+ *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // 3.2 Get EFI_STRING_ID for the input keyword.
+ //
+ Status = GetStringIdFromDatabase (&DevicePath, &NameSpace, KeywordData, &RetVal, &KeywordStringId, &DataBaseRecord);
+ if (EFI_ERROR (Status)) {
+ *ProgressErr = RetVal;
+ goto Done;
+ }
+
+ //
+ // 3.3 Construct the ConfigRequest string.
+ //
+ Status = ExtractConfigRequest (DataBaseRecord, KeywordStringId, &OpCode, &ConfigRequest);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // 3.4 Extract Value for the input keyword.
+ //
+ Status = ExtractValueFromDriver (ConfigRequest, &ValueElement);
+ if (EFI_ERROR (Status)) {
+ if (Status != EFI_OUT_OF_RESOURCES) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ goto Done;
+ }
+
+ StringPtr = NextStringPtr;
+
+ //
+ // 4. Process the possible filter section.
+ //
+ RetVal = ValidateFilter (OpCode, StringPtr, &NextStringPtr, &ReadOnly);
+ if (RetVal != KEYWORD_HANDLER_NO_ERROR) {
+ *ProgressErr = RetVal;
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ StringPtr = NextStringPtr;
+
+ //
+ // 5. Generate KeywordResp string.
+ //
+ Status = GenerateKeywordResp (NameSpace, DevicePath, KeywordData, ValueElement, ReadOnly, &KeywordResp);
+ if (Status != EFI_SUCCESS) {
+ goto Done;
+ }
+
+ //
+ // 6. Merge to the MultiKeywordResp string.
+ //
+ Status = MergeToMultiKeywordResp (&MultiKeywordResp, &KeywordResp);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // 7. Update return value.
+ //
+ *Results = MultiKeywordResp;
+
+ //
+ // 8. Clean the temp buffer.
+ //
+ FreePool (DevicePath);
+ FreePool (KeywordData);
+ FreePool (ValueElement);
+ FreePool (ConfigRequest);
+ DevicePath = NULL;
+ KeywordData = NULL;
+ ValueElement = NULL;
+ ConfigRequest = NULL;
+ if (KeywordResp != NULL) {
+ FreePool (KeywordResp);
+ KeywordResp = NULL;
+ }
+ }
+ } else {
+ //
+ // Enumerate all keyword in the system.
+ //
+ Status = EnumerateAllKeywords (NameSpace, &MultiKeywordResp, ProgressErr);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ *Results = MultiKeywordResp;
+ }
+
+ *ProgressErr = KEYWORD_HANDLER_NO_ERROR;
+
+Done:
+ *Progress = KeywordString + (StringPtr - TempString);
+
+ if (TempString != NULL) {
+ FreePool (TempString);
+ }
+
+ if (NameSpace != NULL) {
+ FreePool (NameSpace);
+ }
+
+ if (DevicePath != NULL) {
+ FreePool (DevicePath);
+ }
+
+ if (KeywordData != NULL) {
+ FreePool (KeywordData);
+ }
+
+ return Status;
+}