summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/HiiDatabaseDxe
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Universal/HiiDatabaseDxe')
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c6840
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c12892
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/Database.c9444
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/Font.c6036
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h4680
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.uni34
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf188
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c500
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseExtra.uni28
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/Image.c3166
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/ImageEx.c858
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/String.c4240
12 files changed, 24453 insertions, 24453 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;
+}
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
index 5ae6189a28..1556fb72df 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
@@ -1,6446 +1,6446 @@
-/** @file
-Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
-
-Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "HiiDatabase.h"
-extern HII_DATABASE_PRIVATE_DATA mPrivate;
-
-/**
- Calculate the number of Unicode characters of the incoming Configuration string,
- not including NULL terminator.
-
- This is a internal function.
-
- @param String String in <MultiConfigRequest> or
- <MultiConfigResp> format.
-
- @return The number of Unicode characters.
-
-**/
-UINTN
-CalculateConfigStringLen (
- IN EFI_STRING String
- )
-{
- EFI_STRING TmpPtr;
-
- //
- // "GUID=" should be the first element of incoming string.
- //
- ASSERT (String != NULL);
- ASSERT (StrnCmp (String, L"GUID=", StrLen (L"GUID=")) == 0);
-
- //
- // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
- // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
- //
- TmpPtr = StrStr (String, L"&GUID=");
- if (TmpPtr == NULL) {
- return StrLen (String);
- }
-
- return (TmpPtr - String);
-}
-
-/**
- Convert the hex UNICODE %02x encoding of a UEFI device path to binary
- from <PathHdr> of <ConfigHdr>.
-
- This is a internal function.
-
- @param String UEFI configuration string
- @param DevicePathData Binary of a UEFI device path.
-
- @retval EFI_NOT_FOUND The device path is not invalid.
- @retval EFI_INVALID_PARAMETER Any 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.
-
-**/
-EFI_STATUS
-GetDevicePath (
- IN EFI_STRING String,
- OUT UINT8 **DevicePathData
- )
-{
- UINTN Length;
- EFI_STRING PathHdr;
- UINT8 *DevicePathBuffer;
- CHAR16 TemStr[2];
- UINTN Index;
- UINT8 DigitUint8;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
-
- if ((String == NULL) || (DevicePathData == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Find the 'PATH=' of <PathHdr> and skip it.
- //
- for ( ; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++) {
- }
-
- if (*String == 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // 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++) {
- }
-
- //
- // Check DevicePath Length
- //
- if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
- return EFI_NOT_FOUND;
- }
-
- //
- // 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_NOT_FOUND;
- }
-
- DevicePath = NextDevicePathNode (DevicePath);
- }
-
- //
- // return the device path
- //
- *DevicePathData = DevicePathBuffer;
- return EFI_SUCCESS;
-}
-
-/**
- Converts the unicode character of the string from uppercase to lowercase.
- This is a internal function.
-
- @param ConfigString String to be converted
-
-**/
-VOID
-EFIAPI
-HiiToLower (
- 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;
-}
-
-/**
- Generate a sub string then output it.
-
- This is a internal function.
-
- @param String A constant string which is the prefix of the to be
- generated string, e.g. GUID=
-
- @param BufferLen The length of the Buffer in bytes.
-
- @param Buffer Points to a buffer which will be converted to be the
- content of the generated string.
-
- @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
- UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
- if 3, the buffer contains other data.
-
- @param SubStr Points to the output string. It's caller's
- responsibility to free this buffer.
-
-
-**/
-VOID
-GenerateSubStr (
- IN CONST EFI_STRING String,
- IN UINTN BufferLen,
- IN VOID *Buffer,
- IN UINT8 Flag,
- OUT EFI_STRING *SubStr
- )
-{
- UINTN Length;
- EFI_STRING Str;
- EFI_STRING StringHeader;
- CHAR16 *TemString;
- CHAR16 *TemName;
- UINT8 *TemBuffer;
- UINTN Index;
-
- ASSERT (String != NULL && SubStr != NULL);
-
- if (Buffer == NULL) {
- *SubStr = AllocateCopyPool (StrSize (String), String);
- ASSERT (*SubStr != NULL);
- return;
- }
-
- //
- // Header + Data + '&' + '\0'
- //
- Length = StrLen (String) + BufferLen * 2 + 1 + 1;
- Str = AllocateZeroPool (Length * sizeof (CHAR16));
- ASSERT (Str != NULL);
-
- StrCpyS (Str, Length, String);
-
- StringHeader = Str + StrLen (String);
- TemString = (CHAR16 *)StringHeader;
-
- switch (Flag) {
- case 1:
- //
- // Convert Buffer to Hex String in reverse order
- //
- TemBuffer = ((UINT8 *)Buffer);
- for (Index = 0; Index < BufferLen; Index++, TemBuffer++) {
- UnicodeValueToStringS (
- TemString,
- sizeof (CHAR16) * (Length - StrnLenS (Str, Length)),
- PREFIX_ZERO | RADIX_HEX,
- *TemBuffer,
- 2
- );
- TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length));
- }
-
- break;
- case 2:
- //
- // Check buffer is enough
- //
- TemName = (CHAR16 *)Buffer;
- ASSERT ((BufferLen * 2 + 1) >= (StrLen (TemName) * 4 + 1));
- //
- // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
- //
- for ( ; *TemName != L'\0'; TemName++) {
- UnicodeValueToStringS (
- TemString,
- sizeof (CHAR16) * (Length - StrnLenS (Str, Length)),
- PREFIX_ZERO | RADIX_HEX,
- *TemName,
- 4
- );
- TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length));
- }
-
- break;
- case 3:
- //
- // Convert Buffer to Hex String
- //
- TemBuffer = ((UINT8 *)Buffer) + BufferLen - 1;
- for (Index = 0; Index < BufferLen; Index++, TemBuffer--) {
- UnicodeValueToStringS (
- TemString,
- sizeof (CHAR16) * (Length - StrnLenS (Str, Length)),
- PREFIX_ZERO | RADIX_HEX,
- *TemBuffer,
- 2
- );
- TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length));
- }
-
- break;
- default:
- break;
- }
-
- //
- // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
- //
- StrCatS (Str, Length, L"&");
- HiiToLower (Str);
-
- *SubStr = Str;
-}
-
-/**
- Retrieve the <ConfigBody> from String then output it.
-
- This is a internal function.
-
- @param String A sub string of a configuration string in
- <MultiConfigAltResp> format.
- @param ConfigBody Points to the output string. It's caller's
- responsibility to free this buffer.
-
- @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
- @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
- @retval EFI_SUCCESS All existing storage is exported.
-
-**/
-EFI_STATUS
-OutputConfigBody (
- IN EFI_STRING String,
- OUT EFI_STRING *ConfigBody
- )
-{
- EFI_STRING TmpPtr;
- EFI_STRING Result;
- UINTN Length;
-
- if ((String == NULL) || (ConfigBody == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // The setting information should start OFFSET, not ALTCFG.
- //
- if (StrnCmp (String, L"&ALTCFG=", StrLen (L"&ALTCFG=")) == 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- TmpPtr = StrStr (String, L"GUID=");
- if (TmpPtr == NULL) {
- //
- // It is the last <ConfigResp> of the incoming configuration string.
- //
- Result = AllocateCopyPool (StrSize (String), String);
- if (Result == NULL) {
- return EFI_OUT_OF_RESOURCES;
- } else {
- *ConfigBody = Result;
- return EFI_SUCCESS;
- }
- }
-
- Length = TmpPtr - String;
- if (Length == 0) {
- return EFI_NOT_FOUND;
- }
-
- Result = AllocateCopyPool (Length * sizeof (CHAR16), String);
- if (Result == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- *(Result + Length - 1) = 0;
- *ConfigBody = Result;
- return EFI_SUCCESS;
-}
-
-/**
- Append a string to a multi-string format.
-
- This is a internal function.
-
- @param MultiString String in <MultiConfigRequest>,
- <MultiConfigAltResp>, or <MultiConfigResp>. On
- input, the buffer length of this string is
- MAX_STRING_LENGTH. On output, the buffer length
- might be updated.
- @param AppendString NULL-terminated Unicode string.
-
- @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
- @retval EFI_SUCCESS AppendString is append to the end of MultiString
-
-**/
-EFI_STATUS
-AppendToMultiString (
- IN OUT EFI_STRING *MultiString,
- IN EFI_STRING AppendString
- )
-{
- UINTN AppendStringSize;
- UINTN MultiStringSize;
- UINTN MaxLen;
-
- if ((MultiString == NULL) || (*MultiString == NULL) || (AppendString == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- AppendStringSize = StrSize (AppendString);
- MultiStringSize = StrSize (*MultiString);
- MaxLen = MAX_STRING_LENGTH / sizeof (CHAR16);
-
- //
- // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
- //
- if ((MultiStringSize + AppendStringSize > MAX_STRING_LENGTH) ||
- (MultiStringSize > MAX_STRING_LENGTH))
- {
- *MultiString = (EFI_STRING)ReallocatePool (
- MultiStringSize,
- MultiStringSize + AppendStringSize,
- (VOID *)(*MultiString)
- );
- MaxLen = (MultiStringSize + AppendStringSize) / sizeof (CHAR16);
- ASSERT (*MultiString != NULL);
- }
-
- //
- // Append the incoming string
- //
- StrCatS (*MultiString, MaxLen, AppendString);
-
- return EFI_SUCCESS;
-}
-
-/**
- Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
- or WIDTH or VALUE.
- <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
-
- This is a internal function.
-
- @param StringPtr String in <BlockConfig> format and points to the
- first character of <Number>.
- @param Number The output value. Caller takes the responsibility
- to free memory.
- @param Len Length of the <Number>, in characters.
-
- @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary
- structures.
- @retval EFI_SUCCESS Value of <Number> is outputted in Number
- successfully.
-
-**/
-EFI_STATUS
-GetValueOfNumber (
- IN EFI_STRING StringPtr,
- OUT UINT8 **Number,
- OUT UINTN *Len
- )
-{
- EFI_STRING TmpPtr;
- UINTN Length;
- EFI_STRING Str;
- UINT8 *Buf;
- EFI_STATUS Status;
- UINT8 DigitUint8;
- UINTN Index;
- CHAR16 TemStr[2];
-
- if ((StringPtr == NULL) || (*StringPtr == L'\0') || (Number == NULL) || (Len == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Buf = NULL;
-
- TmpPtr = StringPtr;
- while (*StringPtr != L'\0' && *StringPtr != L'&') {
- StringPtr++;
- }
-
- *Len = StringPtr - TmpPtr;
- Length = *Len + 1;
-
- Str = (EFI_STRING)AllocateZeroPool (Length * sizeof (CHAR16));
- if (Str == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));
- *(Str + *Len) = L'\0';
-
- Length = (Length + 1) / 2;
- Buf = (UINT8 *)AllocateZeroPool (Length);
- if (Buf == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- Length = *Len;
- ZeroMem (TemStr, sizeof (TemStr));
- for (Index = 0; Index < Length; Index++) {
- TemStr[0] = Str[Length - Index - 1];
- DigitUint8 = (UINT8)StrHexToUint64 (TemStr);
- if ((Index & 1) == 0) {
- Buf[Index/2] = DigitUint8;
- } else {
- Buf[Index/2] = (UINT8)((DigitUint8 << 4) + Buf[Index/2]);
- }
- }
-
- *Number = Buf;
- Status = EFI_SUCCESS;
-
-Exit:
- if (Str != NULL) {
- FreePool (Str);
- }
-
- return Status;
-}
-
-/**
- To find the BlockName in the string with same value.
-
- @param String Pointer to a Null-terminated Unicode string.
- @param BlockName Pointer to a Null-terminated Unicode string to search for.
- @param Buffer Pointer to the value correspond to the BlockName.
- @param Found The Block whether has been found.
- @param BufferLen The length of the buffer.
-
- @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
- @retval EFI_SUCCESS The function finishes successfully.
-
-**/
-EFI_STATUS
-FindSameBlockElement (
- IN EFI_STRING String,
- IN EFI_STRING BlockName,
- IN UINT8 *Buffer,
- OUT BOOLEAN *Found,
- IN UINTN BufferLen
- )
-{
- EFI_STRING BlockPtr;
- UINTN Length;
- UINT8 *TempBuffer;
- EFI_STATUS Status;
-
- TempBuffer = NULL;
- *Found = FALSE;
- BlockPtr = StrStr (String, BlockName);
-
- while (BlockPtr != NULL) {
- BlockPtr += StrLen (BlockName);
- Status = GetValueOfNumber (BlockPtr, &TempBuffer, &Length);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- ASSERT (TempBuffer != NULL);
- if ((BufferLen == Length) && (0 == CompareMem (Buffer, TempBuffer, Length))) {
- *Found = TRUE;
- FreePool (TempBuffer);
- TempBuffer = NULL;
- return EFI_SUCCESS;
- } else {
- FreePool (TempBuffer);
- TempBuffer = NULL;
- BlockPtr = StrStr (BlockPtr + 1, BlockName);
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
- in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
-
- @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
- <MultiConfigAltResp> format. The default value
- string may contain more than one ConfigAltResp
- string for the different varstore buffer.
- @param ConfigAltResp Pointer to a null-terminated Unicode string in
- <ConfigAltResp> format.
- @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
- @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
-
- @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
- @retval EFI_SUCCESS The function finishes successfully.
-
-**/
-EFI_STATUS
-CompareBlockElementDefault (
- IN EFI_STRING DefaultAltCfgResp,
- IN OUT EFI_STRING *ConfigAltResp,
- IN EFI_STRING AltConfigHdr,
- IN OUT BOOLEAN *ConfigAltRespChanged
- )
-{
- EFI_STATUS Status;
- EFI_STRING BlockPtr;
- EFI_STRING BlockPtrStart;
- EFI_STRING StringPtr;
- EFI_STRING AppendString;
- EFI_STRING AltConfigHdrPtr;
- UINT8 *TempBuffer;
- UINTN OffsetLength;
- UINTN AppendSize;
- UINTN TotalSize;
- BOOLEAN FoundOffset;
-
- AppendString = NULL;
- TempBuffer = NULL;
- //
- // Make BlockPtr point to the first <BlockConfig> with AltConfigHdr in DefaultAltCfgResp.
- //
- AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
- ASSERT (AltConfigHdrPtr != NULL);
- BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET=");
- //
- // Make StringPtr point to the AltConfigHdr in ConfigAltResp.
- //
- StringPtr = StrStr (*ConfigAltResp, AltConfigHdr);
- ASSERT (StringPtr != NULL);
-
- while (BlockPtr != NULL) {
- //
- // Find the "&OFFSET=<Number>" block and get the value of the Number with AltConfigHdr in DefaultAltCfgResp.
- //
- BlockPtrStart = BlockPtr;
- BlockPtr += StrLen (L"&OFFSET=");
- Status = GetValueOfNumber (BlockPtr, &TempBuffer, &OffsetLength);
- if (EFI_ERROR (Status)) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- //
- // To find the same "&OFFSET=<Number>" block in ConfigAltResp.
- //
- Status = FindSameBlockElement (StringPtr, L"&OFFSET=", TempBuffer, &FoundOffset, OffsetLength);
- if (TempBuffer != NULL) {
- FreePool (TempBuffer);
- TempBuffer = NULL;
- }
-
- if (EFI_ERROR (Status)) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- if (!FoundOffset) {
- //
- // Don't find the same "&OFFSET=<Number>" block in ConfigAltResp.
- // Calculate the size of <BlockConfig>.
- // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number>.
- //
- BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET=");
- if (BlockPtr != NULL) {
- AppendSize = (BlockPtr - BlockPtrStart) * sizeof (CHAR16);
- } else {
- AppendSize = StrSize (BlockPtrStart);
- }
-
- //
- // Copy the <BlockConfig> to AppendString.
- //
- if (AppendString == NULL) {
- AppendString = (EFI_STRING)AllocateZeroPool (AppendSize + sizeof (CHAR16));
- StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, BlockPtrStart, AppendSize / sizeof (CHAR16));
- } else {
- TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16);
- AppendString = (EFI_STRING)ReallocatePool (
- StrSize (AppendString),
- TotalSize,
- AppendString
- );
- if (AppendString == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- StrnCatS (AppendString, TotalSize / sizeof (CHAR16), BlockPtrStart, AppendSize / sizeof (CHAR16));
- }
- } else {
- //
- // To find next "&OFFSET=<Number>" block with AltConfigHdr in DefaultAltCfgResp.
- //
- BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET=");
- }
- }
-
- if (AppendString != NULL) {
- //
- // Reallocate ConfigAltResp to copy the AppendString.
- //
- TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16);
- *ConfigAltResp = (EFI_STRING)ReallocatePool (
- StrSize (*ConfigAltResp),
- TotalSize,
- *ConfigAltResp
- );
- if (*ConfigAltResp == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString);
- *ConfigAltRespChanged = TRUE;
- }
-
- Status = EFI_SUCCESS;
-
-Exit:
- if (AppendString != NULL) {
- FreePool (AppendString);
- }
-
- return Status;
-}
-
-/**
- Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
- in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
-
- @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
- <MultiConfigAltResp> format. The default value
- string may contain more than one ConfigAltResp
- string for the different varstore buffer.
- @param ConfigAltResp Pointer to a null-terminated Unicode string in
- <ConfigAltResp> format.
- @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
- @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
-
- @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
- @retval EFI_SUCCESS The function finishes successfully.
-
-**/
-EFI_STATUS
-CompareNameElementDefault (
- IN EFI_STRING DefaultAltCfgResp,
- IN OUT EFI_STRING *ConfigAltResp,
- IN EFI_STRING AltConfigHdr,
- IN OUT BOOLEAN *ConfigAltRespChanged
- )
-{
- EFI_STATUS Status;
- EFI_STRING NvConfigPtr;
- EFI_STRING NvConfigStart;
- EFI_STRING NvConfigValuePtr;
- EFI_STRING StringPtr;
- EFI_STRING NvConfigExist;
- EFI_STRING AppendString;
- CHAR16 TempChar;
- UINTN AppendSize;
- UINTN TotalSize;
-
- AppendString = NULL;
- NvConfigExist = NULL;
- //
- // Make NvConfigPtr point to the first <NvConfig> with AltConfigHdr in DefaultAltCfgResp.
- //
- NvConfigPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
- ASSERT (NvConfigPtr != NULL);
- NvConfigPtr = StrStr (NvConfigPtr + StrLen (AltConfigHdr), L"&");
- //
- // Make StringPtr point to the first <NvConfig> with AltConfigHdr in ConfigAltResp.
- //
- StringPtr = StrStr (*ConfigAltResp, AltConfigHdr);
- ASSERT (StringPtr != NULL);
- StringPtr = StrStr (StringPtr + StrLen (AltConfigHdr), L"&");
- ASSERT (StringPtr != NULL);
-
- while (NvConfigPtr != NULL) {
- //
- // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number>.
- // Get the <Label> with AltConfigHdr in DefaultAltCfgResp.
- //
- NvConfigStart = NvConfigPtr;
- NvConfigValuePtr = StrStr (NvConfigPtr + 1, L"=");
- ASSERT (NvConfigValuePtr != NULL);
- TempChar = *NvConfigValuePtr;
- *NvConfigValuePtr = L'\0';
- //
- // Get the <Label> with AltConfigHdr in ConfigAltResp.
- //
- NvConfigExist = StrStr (StringPtr, NvConfigPtr);
- if (NvConfigExist == NULL) {
- //
- // Don't find same <Label> in ConfigAltResp.
- // Calculate the size of <NvConfig>.
- //
- *NvConfigValuePtr = TempChar;
- NvConfigPtr = StrStr (NvConfigPtr + 1, L"&");
- if (NvConfigPtr != NULL) {
- AppendSize = (NvConfigPtr - NvConfigStart) * sizeof (CHAR16);
- } else {
- AppendSize = StrSize (NvConfigStart);
- }
-
- //
- // Copy the <NvConfig> to AppendString.
- //
- if (AppendString == NULL) {
- AppendString = (EFI_STRING)AllocateZeroPool (AppendSize + sizeof (CHAR16));
- StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, NvConfigStart, AppendSize / sizeof (CHAR16));
- } else {
- TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16);
- AppendString = (EFI_STRING)ReallocatePool (
- StrSize (AppendString),
- TotalSize,
- AppendString
- );
- if (AppendString == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- StrnCatS (AppendString, TotalSize / sizeof (CHAR16), NvConfigStart, AppendSize / sizeof (CHAR16));
- }
- } else {
- //
- // To find next <Label> in DefaultAltCfgResp.
- //
- *NvConfigValuePtr = TempChar;
- NvConfigPtr = StrStr (NvConfigPtr + 1, L"&");
- }
- }
-
- if (AppendString != NULL) {
- //
- // Reallocate ConfigAltResp to copy the AppendString.
- //
- TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16);
- *ConfigAltResp = (EFI_STRING)ReallocatePool (
- StrSize (*ConfigAltResp),
- StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16),
- *ConfigAltResp
- );
- if (*ConfigAltResp == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString);
- *ConfigAltRespChanged = TRUE;
- }
-
- Status = EFI_SUCCESS;
-
-Exit:
- if (AppendString != NULL) {
- FreePool (AppendString);
- }
-
- return Status;
-}
-
-/**
- Compare the <AltResp> in AltCfgResp and DefaultAltCfgResp, if the <AltResp>
- in DefaultAltCfgResp but not in AltCfgResp,add it to the AltCfgResp.
-
- @param AltCfgResp Pointer to a null-terminated Unicode string in
- <ConfigAltResp> format.
- @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
- <MultiConfigAltResp> format. The default value
- string may contain more than one ConfigAltResp
- string for the different varstore buffer.
- @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
-
- @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary
- structures.
- @retval EFI_SUCCESS The function finishes successfully.
-
-**/
-EFI_STATUS
-CompareAndMergeDefaultString (
- IN OUT EFI_STRING *AltCfgResp,
- IN EFI_STRING DefaultAltCfgResp,
- IN EFI_STRING AltConfigHdr
- )
-{
- EFI_STATUS Status;
- EFI_STRING AltCfgRespBackup;
- EFI_STRING AltConfigHdrPtr;
- EFI_STRING AltConfigHdrPtrNext;
- EFI_STRING ConfigAltResp;
- EFI_STRING StringPtr;
- EFI_STRING StringPtrNext;
- EFI_STRING BlockPtr;
- UINTN ReallocateSize;
- CHAR16 TempChar;
- CHAR16 TempCharA;
- BOOLEAN ConfigAltRespChanged;
-
- Status = EFI_OUT_OF_RESOURCES;
- BlockPtr = NULL;
- AltConfigHdrPtrNext = NULL;
- StringPtrNext = NULL;
- ConfigAltResp = NULL;
- AltCfgRespBackup = NULL;
- TempChar = L'\0';
- TempCharA = L'\0';
- ConfigAltRespChanged = FALSE;
-
- //
- // To find the <AltResp> with AltConfigHdr in DefaultAltCfgResp, ignore other <AltResp> which follow it.
- //
- AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
- ASSERT (AltConfigHdrPtr != NULL);
- AltConfigHdrPtrNext = StrStr (AltConfigHdrPtr + 1, L"&GUID");
- if (AltConfigHdrPtrNext != NULL) {
- TempChar = *AltConfigHdrPtrNext;
- *AltConfigHdrPtrNext = L'\0';
- }
-
- //
- // To find the <AltResp> with AltConfigHdr in AltCfgResp, ignore other <AltResp> which follow it.
- //
- StringPtr = StrStr (*AltCfgResp, AltConfigHdr);
- ASSERT (StringPtr != NULL);
- StringPtrNext = StrStr (StringPtr + 1, L"&GUID");
- if (StringPtrNext != NULL) {
- TempCharA = *StringPtrNext;
- *StringPtrNext = L'\0';
- }
-
- //
- // Copy the content of <ConfigAltResp> which contain current AltConfigHdr in AltCfgResp.
- //
- ConfigAltResp = AllocateCopyPool (StrSize (*AltCfgResp), *AltCfgResp);
- if (ConfigAltResp == NULL) {
- goto Exit;
- }
-
- //
- // To find the <ConfigBody> with AltConfigHdr in DefaultAltCfgResp.
- //
- BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET=");
- if (BlockPtr != NULL) {
- //
- // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number> style.
- // Call function CompareBlockElementDefault to compare the <BlockConfig> in DefaultAltCfgResp and ConfigAltResp.
- // The ConfigAltResp which may contain the new <BlockConfig> get from DefaultAltCfgResp.
- //
- Status = CompareBlockElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged);
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
- } else {
- //
- // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number> style.
- // Call function CompareNameElementDefault to compare the <NvConfig> in DefaultAltCfgResp and ConfigAltResp.
- // The ConfigAltResp which may contain the new <NvConfig> get from DefaultAltCfgResp.
- //
- Status = CompareNameElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged);
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
- }
-
- //
- // Restore the AltCfgResp.
- //
- if (StringPtrNext != NULL) {
- *StringPtrNext = TempCharA;
- }
-
- //
- // If the ConfigAltResp has no change,no need to update the content in AltCfgResp.
- //
- if (!ConfigAltRespChanged) {
- Status = EFI_SUCCESS;
- goto Exit;
- }
-
- //
- // ConfigAltResp has been changed, need to update the content in AltCfgResp.
- //
- if (StringPtrNext != NULL) {
- ReallocateSize = StrSize (ConfigAltResp) + StrSize (StringPtrNext) + sizeof (CHAR16);
- } else {
- ReallocateSize = StrSize (ConfigAltResp) + sizeof (CHAR16);
- }
-
- AltCfgRespBackup = (EFI_STRING)AllocateZeroPool (ReallocateSize);
- if (AltCfgRespBackup == NULL) {
- goto Exit;
- }
-
- StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), ConfigAltResp);
- if (StringPtrNext != NULL) {
- StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), StringPtrNext);
- }
-
- FreePool (*AltCfgResp);
- *AltCfgResp = AltCfgRespBackup;
-
- Status = EFI_SUCCESS;
-
-Exit:
- if (ConfigAltResp != NULL) {
- FreePool (ConfigAltResp);
- }
-
- //
- // Restore the DefaultAltCfgResp.
- //
- if ( AltConfigHdrPtrNext != NULL) {
- *AltConfigHdrPtrNext = TempChar;
- AltConfigHdrPtrNext = NULL;
- }
-
- return Status;
-}
-
-/**
- This function merges DefaultAltCfgResp string into AltCfgResp string for
- the missing AltCfgId in AltCfgResq.
-
- @param AltCfgResp Pointer to a null-terminated Unicode string in
- <ConfigAltResp> format. The default value string
- will be merged into it.
- @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
- <MultiConfigAltResp> format. The default value
- string may contain more than one ConfigAltResp
- string for the different varstore buffer.
-
- @retval EFI_SUCCESS The merged string returns.
- @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
-**/
-EFI_STATUS
-EFIAPI
-MergeDefaultString (
- IN OUT EFI_STRING *AltCfgResp,
- IN EFI_STRING DefaultAltCfgResp
- )
-{
- EFI_STRING StringPtrDefault;
- EFI_STRING StringPtrEnd;
- CHAR16 TempChar;
- EFI_STRING StringPtr;
- EFI_STRING AltConfigHdr;
- UINTN HeaderLength;
- UINTN SizeAltCfgResp;
- UINTN MaxLen;
- UINTN TotalSize;
-
- if (*AltCfgResp == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Get the request ConfigHdr
- //
- SizeAltCfgResp = 0;
- StringPtr = *AltCfgResp;
-
- //
- // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
- //
- if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
- StringPtr++;
- }
-
- while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
- StringPtr++;
- }
-
- if (*StringPtr == L'\0') {
- return EFI_INVALID_PARAMETER;
- }
-
- StringPtr += StrLen (L"&PATH=");
- while (*StringPtr != L'\0' && *StringPtr != L'&') {
- StringPtr++;
- }
-
- HeaderLength = StringPtr - *AltCfgResp;
-
- //
- // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
- // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
- //
- MaxLen = 1 + HeaderLength + 8 + 4 + 1;
- AltConfigHdr = AllocateZeroPool (MaxLen * sizeof (CHAR16));
- if (AltConfigHdr == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- StrCpyS (AltConfigHdr, MaxLen, L"&");
- StrnCatS (AltConfigHdr, MaxLen, *AltCfgResp, HeaderLength);
- StrCatS (AltConfigHdr, MaxLen, L"&ALTCFG=");
- HeaderLength = StrLen (AltConfigHdr);
-
- StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);
- while (StringPtrDefault != NULL) {
- //
- // Get AltCfg Name
- //
- StrnCatS (AltConfigHdr, MaxLen, StringPtrDefault + HeaderLength, 4);
- StringPtr = StrStr (*AltCfgResp, AltConfigHdr);
-
- //
- // Append the found default value string to the input AltCfgResp
- //
- if (StringPtr == NULL) {
- StringPtrEnd = StrStr (StringPtrDefault + 1, L"&GUID");
- SizeAltCfgResp = StrSize (*AltCfgResp);
- if (StringPtrEnd == NULL) {
- //
- // No more default string is found.
- //
- TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);
- *AltCfgResp = (EFI_STRING)ReallocatePool (
- SizeAltCfgResp,
- TotalSize,
- (VOID *)(*AltCfgResp)
- );
- if (*AltCfgResp == NULL) {
- FreePool (AltConfigHdr);
- return EFI_OUT_OF_RESOURCES;
- }
-
- StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);
- break;
- } else {
- TempChar = *StringPtrEnd;
- *StringPtrEnd = L'\0';
- TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);
- *AltCfgResp = (EFI_STRING)ReallocatePool (
- SizeAltCfgResp,
- TotalSize,
- (VOID *)(*AltCfgResp)
- );
- if (*AltCfgResp == NULL) {
- FreePool (AltConfigHdr);
- return EFI_OUT_OF_RESOURCES;
- }
-
- StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);
- *StringPtrEnd = TempChar;
- }
- } else {
- //
- // The AltCfgResp contains <AltCfgResp>.
- // If the <ConfigElement> in <AltCfgResp> in the DefaultAltCfgResp but not in the
- // related <AltCfgResp> in AltCfgResp, merge it to AltCfgResp. else no need to merge.
- //
- CompareAndMergeDefaultString (AltCfgResp, DefaultAltCfgResp, AltConfigHdr);
- }
-
- //
- // Find next AltCfg String
- //
- *(AltConfigHdr + HeaderLength) = L'\0';
- StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr);
- }
-
- FreePool (AltConfigHdr);
- return EFI_SUCCESS;
-}
-
-/**
- This function inserts new DefaultValueData into the BlockData DefaultValue array.
-
- @param BlockData The BlockData is updated to add new default value.
- @param DefaultValueData The DefaultValue is added.
-
-**/
-VOID
-InsertDefaultValue (
- IN IFR_BLOCK_DATA *BlockData,
- IN IFR_DEFAULT_DATA *DefaultValueData
- )
-{
- LIST_ENTRY *Link;
- IFR_DEFAULT_DATA *DefaultValueArray;
- LIST_ENTRY *DefaultLink;
-
- DefaultLink = &BlockData->DefaultValueEntry;
-
- for (Link = DefaultLink->ForwardLink; Link != DefaultLink; Link = Link->ForwardLink) {
- DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
- if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {
- //
- // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
- // When default types are DEFAULT_VALUE_FROM_OTHER_DEFAULT, the default value can be overrode.
- //
- if ((DefaultValueData->Type > DefaultValueArray->Type) || ((DefaultValueData->Type == DefaultValueArray->Type) && (DefaultValueData->Type == DefaultValueFromOtherDefault))) {
- //
- // Update the default value array in BlockData.
- //
- CopyMem (&DefaultValueArray->Value, &DefaultValueData->Value, sizeof (EFI_IFR_TYPE_VALUE));
- DefaultValueArray->Type = DefaultValueData->Type;
- DefaultValueArray->Cleaned = DefaultValueData->Cleaned;
- }
-
- return;
- }
- }
-
- //
- // Insert new default value data in tail.
- //
- DefaultValueArray = AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
- ASSERT (DefaultValueArray != NULL);
- CopyMem (DefaultValueArray, DefaultValueData, sizeof (IFR_DEFAULT_DATA));
- InsertTailList (Link, &DefaultValueArray->Entry);
-}
-
-/**
- This function inserts new BlockData into the block link
-
- @param BlockLink The list entry points to block array.
- @param BlockData The point to BlockData is added.
-
-**/
-VOID
-InsertBlockData (
- IN LIST_ENTRY *BlockLink,
- IN IFR_BLOCK_DATA **BlockData
- )
-{
- LIST_ENTRY *Link;
- IFR_BLOCK_DATA *BlockArray;
- IFR_BLOCK_DATA *BlockSingleData;
-
- BlockSingleData = *BlockData;
-
- if (BlockSingleData->Name != NULL) {
- InsertTailList (BlockLink, &BlockSingleData->Entry);
- return;
- }
-
- //
- // Insert block data in its Offset and Width order.
- //
- for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
- BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
- if (BlockArray->Offset == BlockSingleData->Offset) {
- if ((BlockArray->Width > BlockSingleData->Width) || (BlockSingleData->IsBitVar && (BlockArray->Width == BlockSingleData->Width))) {
- //
- // Insert this block data in the front of block array
- //
- InsertTailList (Link, &BlockSingleData->Entry);
- return;
- }
-
- if ((!BlockSingleData->IsBitVar) && (BlockArray->Width == BlockSingleData->Width)) {
- //
- // The same block array has been added.
- //
- if (BlockSingleData != BlockArray) {
- FreePool (BlockSingleData);
- *BlockData = BlockArray;
- }
-
- return;
- }
- } else if (BlockArray->Offset > BlockSingleData->Offset) {
- //
- // Insert new block data in the front of block array
- //
- InsertTailList (Link, &BlockSingleData->Entry);
- return;
- }
- }
-
- //
- // Add new block data into the tail.
- //
- InsertTailList (Link, &BlockSingleData->Entry);
-}
-
-/**
- Retrieves a pointer to the a Null-terminated ASCII string containing the list
- of languages that an HII handle in the HII Database supports. The returned
- string is allocated using AllocatePool(). The caller is responsible for freeing
- the returned string using FreePool(). The format of the returned string follows
- the language format assumed the HII Database.
-
- If HiiHandle is NULL, then ASSERT().
-
- @param[in] HiiHandle A handle that was previously registered in the HII Database.
-
- @retval NULL HiiHandle is not registered in the HII database
- @retval NULL There are not enough resources available to retrieve the supported
- languages.
- @retval NULL The list of supported languages could not be retrieved.
- @retval Other A pointer to the Null-terminated ASCII string of supported languages.
-
-**/
-CHAR8 *
-GetSupportedLanguages (
- IN EFI_HII_HANDLE HiiHandle
- )
-{
- EFI_STATUS Status;
- UINTN LanguageSize;
- CHAR8 TempSupportedLanguages;
- CHAR8 *SupportedLanguages;
-
- ASSERT (HiiHandle != NULL);
-
- //
- // Retrieve the size required for the supported languages buffer.
- //
- LanguageSize = 0;
- Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, &TempSupportedLanguages, &LanguageSize);
-
- //
- // If GetLanguages() returns EFI_SUCCESS for a zero size,
- // then there are no supported languages registered for HiiHandle. If GetLanguages()
- // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
- // in the HII Database
- //
- if (Status != EFI_BUFFER_TOO_SMALL) {
- //
- // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
- //
- return NULL;
- }
-
- //
- // Allocate the supported languages buffer.
- //
- SupportedLanguages = AllocateZeroPool (LanguageSize);
- if (SupportedLanguages == NULL) {
- //
- // Return NULL if allocation fails.
- //
- return NULL;
- }
-
- //
- // Retrieve the supported languages string
- //
- Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, SupportedLanguages, &LanguageSize);
- if (EFI_ERROR (Status)) {
- //
- // Free the buffer and return NULL if the supported languages can not be retrieved.
- //
- FreePool (SupportedLanguages);
- return NULL;
- }
-
- //
- // Return the Null-terminated ASCII string of supported languages
- //
- return SupportedLanguages;
-}
-
-/**
- Retrieves a string from a string package.
-
- If HiiHandle is NULL, then ASSERT().
- If StringId is 0, then ASSET.
-
- @param[in] HiiHandle A handle that was previously registered in the HII Database.
- @param[in] StringId The identifier of the string to retrieved from the string
- package associated with HiiHandle.
-
- @retval NULL The string specified by StringId is not present in the string package.
- @retval Other The string was returned.
-
-**/
-EFI_STRING
-InternalGetString (
- IN EFI_HII_HANDLE HiiHandle,
- IN EFI_STRING_ID StringId
- )
-{
- EFI_STATUS Status;
- UINTN StringSize;
- CHAR16 TempString;
- EFI_STRING String;
- CHAR8 *SupportedLanguages;
- CHAR8 *PlatformLanguage;
- CHAR8 *BestLanguage;
- CHAR8 *Language;
-
- ASSERT (HiiHandle != NULL);
- ASSERT (StringId != 0);
-
- //
- // Initialize all allocated buffers to NULL
- //
- SupportedLanguages = NULL;
- PlatformLanguage = NULL;
- BestLanguage = NULL;
- String = NULL;
- Language = "";
-
- //
- // Get the languages that the package specified by HiiHandle supports
- //
- SupportedLanguages = GetSupportedLanguages (HiiHandle);
- if (SupportedLanguages == NULL) {
- goto Error;
- }
-
- //
- // Get the current platform language setting
- //
- GetEfiGlobalVariable2 (L"PlatformLang", (VOID **)&PlatformLanguage, NULL);
-
- //
- // Get the best matching language from SupportedLanguages
- //
- BestLanguage = GetBestLanguage (
- SupportedLanguages,
- FALSE, // RFC 4646 mode
- Language, // Highest priority
- PlatformLanguage != NULL ? PlatformLanguage : "", // Next highest priority
- SupportedLanguages, // Lowest priority
- NULL
- );
- if (BestLanguage == NULL) {
- goto Error;
- }
-
- //
- // Retrieve the size of the string in the string package for the BestLanguage
- //
- StringSize = 0;
- Status = mPrivate.HiiString.GetString (
- &mPrivate.HiiString,
- BestLanguage,
- HiiHandle,
- StringId,
- &TempString,
- &StringSize,
- NULL
- );
- //
- // If GetString() returns EFI_SUCCESS for a zero size,
- // then there are no supported languages registered for HiiHandle. If GetString()
- // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
- // in the HII Database
- //
- if (Status != EFI_BUFFER_TOO_SMALL) {
- goto Error;
- }
-
- //
- // Allocate a buffer for the return string
- //
- String = AllocateZeroPool (StringSize);
- if (String == NULL) {
- goto Error;
- }
-
- //
- // Retrieve the string from the string package
- //
- Status = mPrivate.HiiString.GetString (
- &mPrivate.HiiString,
- BestLanguage,
- HiiHandle,
- StringId,
- String,
- &StringSize,
- NULL
- );
- if (EFI_ERROR (Status)) {
- //
- // Free the buffer and return NULL if the supported languages can not be retrieved.
- //
- FreePool (String);
- String = NULL;
- }
-
-Error:
- //
- // Free allocated buffers
- //
- if (SupportedLanguages != NULL) {
- FreePool (SupportedLanguages);
- }
-
- if (PlatformLanguage != NULL) {
- FreePool (PlatformLanguage);
- }
-
- if (BestLanguage != NULL) {
- FreePool (BestLanguage);
- }
-
- //
- // Return the Null-terminated Unicode string
- //
- return String;
-}
-
-/**
- This function checks VarOffset and VarWidth is in the block range.
-
- @param RequestBlockArray The block array is to be checked.
- @param VarOffset Offset of var to the structure
- @param VarWidth Width of var.
- @param IsNameValueType Whether this varstore is name/value varstore or not.
- @param HiiHandle Hii handle for this hii package.
-
- @retval TRUE This Var is in the block range.
- @retval FALSE This Var is not in the block range.
-**/
-BOOLEAN
-BlockArrayCheck (
- IN IFR_BLOCK_DATA *RequestBlockArray,
- IN UINT16 VarOffset,
- IN UINT16 VarWidth,
- IN BOOLEAN IsNameValueType,
- IN EFI_HII_HANDLE HiiHandle
- )
-{
- LIST_ENTRY *Link;
- IFR_BLOCK_DATA *BlockData;
- EFI_STRING Name;
-
- //
- // No Request Block array, all vars are got.
- //
- if (RequestBlockArray == NULL) {
- return TRUE;
- }
-
- //
- // Check the input var is in the request block range.
- //
- for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {
- BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
-
- if (IsNameValueType) {
- Name = InternalGetString (HiiHandle, VarOffset);
- ASSERT (Name != NULL);
-
- if (StrnCmp (BlockData->Name, Name, StrLen (Name)) == 0) {
- FreePool (Name);
- return TRUE;
- }
-
- FreePool (Name);
- } else {
- if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
-/**
- Get form package data from data base.
-
- @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
- @param HiiFormPackage The buffer saves the package data.
- @param PackageSize The buffer size of the package data.
-
-**/
-EFI_STATUS
-GetFormPackageData (
- IN HII_DATABASE_RECORD *DataBaseRecord,
- IN OUT UINT8 **HiiFormPackage,
- OUT UINTN *PackageSize
- )
-{
- EFI_STATUS Status;
- UINTN Size;
- UINTN ResultSize;
-
- if ((DataBaseRecord == NULL) || (HiiFormPackage == NULL) || (PackageSize == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Size = 0;
- ResultSize = 0;
- //
- // 0. Get Hii Form Package by HiiHandle
- //
- Status = ExportFormPackages (
- &mPrivate,
- DataBaseRecord->Handle,
- DataBaseRecord->PackageList,
- 0,
- Size,
- HiiFormPackage,
- &ResultSize
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- (*HiiFormPackage) = AllocatePool (ResultSize);
- if (*HiiFormPackage == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- return Status;
- }
-
- //
- // Get HiiFormPackage by HiiHandle
- //
- Size = ResultSize;
- ResultSize = 0;
- Status = ExportFormPackages (
- &mPrivate,
- DataBaseRecord->Handle,
- DataBaseRecord->PackageList,
- 0,
- Size,
- *HiiFormPackage,
- &ResultSize
- );
- if (EFI_ERROR (Status)) {
- FreePool (*HiiFormPackage);
- }
-
- *PackageSize = Size;
-
- return Status;
-}
-
-/**
- This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
-
- @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
- @param ConfigHdr Request string ConfigHdr. If it is NULL,
- the first found varstore will be as ConfigHdr.
- @param IsEfiVarstore Whether the request storage type is efi varstore type.
- @param EfiVarStore The efi varstore info which will return.
-**/
-EFI_STATUS
-GetVarStoreType (
- IN HII_DATABASE_RECORD *DataBaseRecord,
- IN EFI_STRING ConfigHdr,
- OUT BOOLEAN *IsEfiVarstore,
- OUT EFI_IFR_VARSTORE_EFI **EfiVarStore
- )
-{
- EFI_STATUS Status;
- UINTN IfrOffset;
- UINTN PackageOffset;
- EFI_IFR_OP_HEADER *IfrOpHdr;
- CHAR16 *VarStoreName;
- UINTN NameSize;
- EFI_STRING GuidStr;
- EFI_STRING NameStr;
- EFI_STRING TempStr;
- UINTN LengthString;
- UINT8 *HiiFormPackage;
- UINTN PackageSize;
- EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
- EFI_HII_PACKAGE_HEADER *PackageHeader;
-
- HiiFormPackage = NULL;
- LengthString = 0;
- Status = EFI_SUCCESS;
- GuidStr = NULL;
- NameStr = NULL;
- TempStr = NULL;
- *IsEfiVarstore = FALSE;
-
- Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
- PackageOffset = IfrOffset;
- PackageHeader = (EFI_HII_PACKAGE_HEADER *)HiiFormPackage;
-
- while (IfrOffset < PackageSize) {
- //
- // More than one form packages exist.
- //
- if (PackageOffset >= PackageHeader->Length) {
- //
- // Process the new form package.
- //
- PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
- IfrOffset += PackageOffset;
- PackageHeader = (EFI_HII_PACKAGE_HEADER *)(HiiFormPackage + IfrOffset);
- }
-
- IfrOpHdr = (EFI_IFR_OP_HEADER *)(HiiFormPackage + IfrOffset);
- IfrOffset += IfrOpHdr->Length;
- PackageOffset += IfrOpHdr->Length;
-
- if (IfrOpHdr->OpCode == EFI_IFR_VARSTORE_EFI_OP ) {
- IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *)IfrOpHdr;
- //
- // If the length is small than the structure, this is from old efi
- // varstore definition. Old efi varstore get config directly from
- // GetVariable function.
- //
- if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
- continue;
- }
-
- NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
- VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
- if (VarStoreName == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);
-
- GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)&IfrEfiVarStore->Guid, 1, &GuidStr);
- GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *)VarStoreName, 2, &NameStr);
- LengthString = StrLen (GuidStr);
- LengthString = LengthString + StrLen (NameStr) + 1;
- TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
- if (TempStr == NULL) {
- FreePool (GuidStr);
- FreePool (NameStr);
- FreePool (VarStoreName);
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- StrCpyS (TempStr, LengthString, GuidStr);
- StrCatS (TempStr, LengthString, NameStr);
- if ((ConfigHdr == NULL) || (StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0)) {
- *EfiVarStore = (EFI_IFR_VARSTORE_EFI *)AllocateZeroPool (IfrOpHdr->Length);
- if (*EfiVarStore == NULL) {
- FreePool (VarStoreName);
- FreePool (GuidStr);
- FreePool (NameStr);
- FreePool (TempStr);
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- *IsEfiVarstore = TRUE;
- CopyMem (*EfiVarStore, IfrEfiVarStore, IfrOpHdr->Length);
- }
-
- //
- // Free allocated temp string.
- //
- FreePool (VarStoreName);
- FreePool (GuidStr);
- FreePool (NameStr);
- FreePool (TempStr);
-
- //
- // Already found the varstore, break;
- //
- if (*IsEfiVarstore) {
- break;
- }
- }
- }
-
-Done:
- if (HiiFormPackage != NULL) {
- FreePool (HiiFormPackage);
- }
-
- return Status;
-}
-
-/**
- Check whether the ConfigRequest string has the request elements.
- For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
- For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
-
- @param ConfigRequest The input config request string.
-
- @retval TRUE The input include config request elements.
- @retval FALSE The input string not includes.
-
-**/
-BOOLEAN
-GetElementsFromRequest (
- IN EFI_STRING ConfigRequest
- )
-{
- EFI_STRING TmpRequest;
-
- TmpRequest = StrStr (ConfigRequest, L"PATH=");
- ASSERT (TmpRequest != NULL);
-
- if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- Check whether the this varstore is the request varstore.
-
- @param VarstoreGuid Varstore guid.
- @param Name Varstore name.
- @param ConfigHdr Current configRequest info.
-
- @retval TRUE This varstore is the request one.
- @retval FALSE This varstore is not the request one.
-
-**/
-BOOLEAN
-IsThisVarstore (
- IN EFI_GUID *VarstoreGuid,
- IN CHAR16 *Name,
- IN CHAR16 *ConfigHdr
- )
-{
- EFI_STRING GuidStr;
- EFI_STRING NameStr;
- EFI_STRING TempStr;
- UINTN LengthString;
- BOOLEAN RetVal;
-
- RetVal = FALSE;
- GuidStr = NULL;
- TempStr = NULL;
-
- //
- // If ConfigHdr has name field and varstore not has name, return FALSE.
- //
- if ((Name == NULL) && (ConfigHdr != NULL) && (StrStr (ConfigHdr, L"NAME=&") == NULL)) {
- return FALSE;
- }
-
- GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)VarstoreGuid, 1, &GuidStr);
- if (Name != NULL) {
- GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *)Name, 2, &NameStr);
- } else {
- GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
- }
-
- LengthString = StrLen (GuidStr);
- LengthString = LengthString + StrLen (NameStr) + 1;
- TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
- if (TempStr == NULL) {
- goto Done;
- }
-
- StrCpyS (TempStr, LengthString, GuidStr);
- StrCatS (TempStr, LengthString, NameStr);
-
- if ((ConfigHdr == NULL) || (StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0)) {
- RetVal = TRUE;
- }
-
-Done:
- if (GuidStr != NULL) {
- FreePool (GuidStr);
- }
-
- if (NameStr != NULL) {
- FreePool (NameStr);
- }
-
- if (TempStr != NULL) {
- FreePool (TempStr);
- }
-
- return RetVal;
-}
-
-/**
- This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
-
- @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
- @param ConfigHdr Request string ConfigHdr. If it is NULL,
- the first found varstore will be as ConfigHdr.
- @retval TRUE This hii package is the request one.
- @retval FALSE This hii package is not the request one.
-**/
-BOOLEAN
-IsThisPackageList (
- IN HII_DATABASE_RECORD *DataBaseRecord,
- IN EFI_STRING ConfigHdr
- )
-{
- EFI_STATUS Status;
- UINTN IfrOffset;
- UINTN PackageOffset;
- EFI_IFR_OP_HEADER *IfrOpHdr;
- CHAR16 *VarStoreName;
- UINTN NameSize;
- UINT8 *HiiFormPackage;
- UINTN PackageSize;
- EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
- EFI_HII_PACKAGE_HEADER *PackageHeader;
- EFI_IFR_VARSTORE *IfrVarStore;
- EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
- BOOLEAN FindVarstore;
-
- HiiFormPackage = NULL;
- VarStoreName = NULL;
- Status = EFI_SUCCESS;
- FindVarstore = FALSE;
-
- Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
-
- IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
- PackageOffset = IfrOffset;
- PackageHeader = (EFI_HII_PACKAGE_HEADER *)HiiFormPackage;
-
- while (IfrOffset < PackageSize) {
- //
- // More than one form packages exist.
- //
- if (PackageOffset >= PackageHeader->Length) {
- //
- // Process the new form package.
- //
- PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
- IfrOffset += PackageOffset;
- PackageHeader = (EFI_HII_PACKAGE_HEADER *)(HiiFormPackage + IfrOffset);
- }
-
- IfrOpHdr = (EFI_IFR_OP_HEADER *)(HiiFormPackage + IfrOffset);
- IfrOffset += IfrOpHdr->Length;
- PackageOffset += IfrOpHdr->Length;
-
- switch (IfrOpHdr->OpCode) {
- case EFI_IFR_VARSTORE_OP:
- IfrVarStore = (EFI_IFR_VARSTORE *)IfrOpHdr;
-
- NameSize = AsciiStrSize ((CHAR8 *)IfrVarStore->Name);
- VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
- if (VarStoreName == NULL) {
- goto Done;
- }
-
- AsciiStrToUnicodeStrS ((CHAR8 *)IfrVarStore->Name, VarStoreName, NameSize);
-
- if (IsThisVarstore ((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
- FindVarstore = TRUE;
- goto Done;
- } else {
- FreePool (VarStoreName);
- VarStoreName = NULL;
- }
-
- break;
-
- case EFI_IFR_VARSTORE_EFI_OP:
- IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *)IfrOpHdr;
- NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
- VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
- if (VarStoreName == NULL) {
- goto Done;
- }
-
- AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);
-
- if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
- FindVarstore = TRUE;
- goto Done;
- } else {
- FreePool (VarStoreName);
- VarStoreName = NULL;
- }
-
- break;
-
- case EFI_IFR_VARSTORE_NAME_VALUE_OP:
- IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *)IfrOpHdr;
-
- if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
- FindVarstore = TRUE;
- goto Done;
- }
-
- break;
-
- case EFI_IFR_FORM_OP:
- case EFI_IFR_FORM_MAP_OP:
- //
- // No matched varstore is found and directly return.
- //
- goto Done;
-
- default:
- break;
- }
- }
-
-Done:
- if (HiiFormPackage != NULL) {
- FreePool (HiiFormPackage);
- }
-
- if (VarStoreName != NULL) {
- FreePool (VarStoreName);
- }
-
- return FindVarstore;
-}
-
-/**
- Check whether the this op code is required.
-
- @param RequestBlockArray The array includes all the request info or NULL.
- @param HiiHandle The hii handle for this form package.
- @param VarStorageData The varstore data structure.
- @param IfrOpHdr Ifr opcode header for this opcode.
- @param VarWidth The buffer width for this opcode.
- @param ReturnData The data block added for this opcode.
- @param IsBitVar Whether the the opcode refers to bit storage.
-
- @retval EFI_SUCCESS This opcode is required.
- @retval EFI_NOT_FOUND This opcode is not required.
- @retval Others Contain some error.
-
-**/
-EFI_STATUS
-IsThisOpcodeRequired (
- IN IFR_BLOCK_DATA *RequestBlockArray,
- IN EFI_HII_HANDLE HiiHandle,
- IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
- IN EFI_IFR_OP_HEADER *IfrOpHdr,
- IN UINT16 VarWidth,
- OUT IFR_BLOCK_DATA **ReturnData,
- IN BOOLEAN IsBitVar
- )
-{
- IFR_BLOCK_DATA *BlockData;
- UINT16 VarOffset;
- EFI_STRING_ID NameId;
- EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;
- UINT16 BitOffset;
- UINT16 BitWidth;
- UINT16 TotalBits;
-
- NameId = 0;
- VarOffset = 0;
- BitOffset = 0;
- BitWidth = 0;
- IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)((CHAR8 *)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER));
-
- if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
- NameId = IfrQuestionHdr->VarStoreInfo.VarName;
-
- //
- // Check whether this question is in requested block array.
- //
- if (!BlockArrayCheck (RequestBlockArray, NameId, 0, TRUE, HiiHandle)) {
- //
- // This question is not in the requested string. Skip it.
- //
- return EFI_NOT_FOUND;
- }
- } else {
- //
- // Get the byte offset/with and bit offset/width
- //
- if (IsBitVar) {
- BitOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
- BitWidth = VarWidth;
- VarOffset = BitOffset / 8;
- //
- // Use current bit width and the bit width before current bit (with same byte offset) to calculate the byte width.
- //
- TotalBits = BitOffset % 8 + BitWidth;
- VarWidth = (TotalBits % 8 == 0 ? TotalBits / 8 : TotalBits / 8 + 1);
- } else {
- VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
- BitWidth = VarWidth;
- BitOffset = VarOffset * 8;
- }
-
- //
- // Check whether this question is in requested block array.
- //
- if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth, FALSE, HiiHandle)) {
- //
- // This question is not in the requested string. Skip it.
- //
- return EFI_NOT_FOUND;
- }
-
- //
- // Check this var question is in the var storage
- //
- if (((VarOffset + VarWidth) > VarStorageData->Size)) {
- return EFI_INVALID_PARAMETER;
- }
- }
-
- BlockData = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (BlockData == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
- BlockData->Name = InternalGetString (HiiHandle, NameId);
- } else {
- BlockData->Offset = VarOffset;
- }
-
- BlockData->Width = VarWidth;
- BlockData->QuestionId = IfrQuestionHdr->QuestionId;
- BlockData->OpCode = IfrOpHdr->OpCode;
- BlockData->Scope = IfrOpHdr->Scope;
- BlockData->IsBitVar = IsBitVar;
- BlockData->BitOffset = BitOffset;
- BlockData->BitWidth = BitWidth;
- InitializeListHead (&BlockData->DefaultValueEntry);
- //
- // Add Block Data into VarStorageData BlockEntry
- //
- InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
- *ReturnData = BlockData;
-
- return EFI_SUCCESS;
-}
-
-/**
- This function parses Form Package to get the block array and the default
- value array according to the request ConfigHdr.
-
- @param HiiHandle Hii Handle for this hii package.
- @param Package Pointer to the form package data.
- @param PackageLength Length of the package.
- @param ConfigHdr Request string ConfigHdr. If it is NULL,
- the first found varstore will be as ConfigHdr.
- @param RequestBlockArray The block array is retrieved from the request string.
- @param VarStorageData VarStorage structure contains the got block and default value.
- @param DefaultIdArray Point to the got default id and default name array.
-
- @retval EFI_SUCCESS The block array and the default value array are got.
- @retval EFI_INVALID_PARAMETER The varstore definition in the different form packages
- are conflicted.
- @retval EFI_OUT_OF_RESOURCES No enough memory.
-**/
-EFI_STATUS
-EFIAPI
-ParseIfrData (
- IN EFI_HII_HANDLE HiiHandle,
- IN UINT8 *Package,
- IN UINT32 PackageLength,
- IN EFI_STRING ConfigHdr,
- IN IFR_BLOCK_DATA *RequestBlockArray,
- IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
- OUT IFR_DEFAULT_DATA *DefaultIdArray
- )
-{
- EFI_STATUS Status;
- UINTN IfrOffset;
- UINTN PackageOffset;
- EFI_IFR_VARSTORE *IfrVarStore;
- EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
- EFI_IFR_VARSTORE_EFI *IfrEfiVarStoreTmp;
- EFI_IFR_OP_HEADER *IfrOpHdr;
- EFI_IFR_ONE_OF *IfrOneOf;
- EFI_IFR_REF4 *IfrRef;
- EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
- EFI_IFR_DEFAULT *IfrDefault;
- EFI_IFR_ORDERED_LIST *IfrOrderedList;
- EFI_IFR_CHECKBOX *IfrCheckBox;
- EFI_IFR_PASSWORD *IfrPassword;
- EFI_IFR_STRING *IfrString;
- EFI_IFR_DATE *IfrDate;
- EFI_IFR_TIME *IfrTime;
- IFR_DEFAULT_DATA DefaultData;
- IFR_DEFAULT_DATA *DefaultDataPtr;
- IFR_BLOCK_DATA *BlockData;
- CHAR16 *VarStoreName;
- UINTN NameSize;
- UINTN NvDefaultStoreSize;
- UINT16 VarWidth;
- UINT16 VarDefaultId;
- BOOLEAN FirstOneOfOption;
- BOOLEAN FirstOrderedList;
- LIST_ENTRY *LinkData;
- LIST_ENTRY *LinkDefault;
- EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
- EFI_HII_PACKAGE_HEADER *PackageHeader;
- EFI_VARSTORE_ID VarStoreId;
- UINT16 SmallestDefaultId;
- BOOLEAN SmallestIdFromFlag;
- BOOLEAN FromOtherDefaultOpcode;
- BOOLEAN QuestionReferBitField;
-
- Status = EFI_SUCCESS;
- BlockData = NULL;
- DefaultDataPtr = NULL;
- FirstOneOfOption = FALSE;
- VarStoreId = 0;
- FirstOrderedList = FALSE;
- VarStoreName = NULL;
- ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));
- SmallestDefaultId = 0xFFFF;
- FromOtherDefaultOpcode = FALSE;
- QuestionReferBitField = FALSE;
- IfrEfiVarStoreTmp = NULL;
-
- //
- // Go through the form package to parse OpCode one by one.
- //
- PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
- PackageHeader = (EFI_HII_PACKAGE_HEADER *)Package;
- IfrOffset = PackageOffset;
- while (IfrOffset < PackageLength) {
- //
- // More than one form package found.
- //
- if (PackageOffset >= PackageHeader->Length) {
- //
- // Already found varstore for this request, break;
- //
- if (VarStoreId != 0) {
- VarStoreId = 0;
- }
-
- //
- // Get next package header info.
- //
- IfrOffset += sizeof (EFI_HII_PACKAGE_HEADER);
- PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
- PackageHeader = (EFI_HII_PACKAGE_HEADER *)(Package + IfrOffset);
- }
-
- IfrOpHdr = (EFI_IFR_OP_HEADER *)(Package + IfrOffset);
- switch (IfrOpHdr->OpCode) {
- case EFI_IFR_VARSTORE_OP:
- //
- // VarStore is found. Don't need to search any more.
- //
- if (VarStoreId != 0) {
- break;
- }
-
- IfrVarStore = (EFI_IFR_VARSTORE *)IfrOpHdr;
-
- NameSize = AsciiStrSize ((CHAR8 *)IfrVarStore->Name);
- VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
- if (VarStoreName == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- AsciiStrToUnicodeStrS ((CHAR8 *)IfrVarStore->Name, VarStoreName, NameSize);
-
- if (IsThisVarstore ((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
- //
- // Find the matched VarStore
- //
- CopyGuid (&VarStorageData->Guid, (EFI_GUID *)(VOID *)&IfrVarStore->Guid);
- VarStorageData->Size = IfrVarStore->Size;
- VarStorageData->Name = VarStoreName;
- VarStorageData->Type = EFI_HII_VARSTORE_BUFFER;
- VarStoreId = IfrVarStore->VarStoreId;
- } else {
- FreePool (VarStoreName);
- VarStoreName = NULL;
- }
-
- break;
-
- case EFI_IFR_VARSTORE_EFI_OP:
- //
- // VarStore is found. Don't need to search any more.
- //
- if (VarStoreId != 0) {
- break;
- }
-
- IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *)IfrOpHdr;
-
- //
- // If the length is small than the structure, this is from old efi
- // varstore definition. Old efi varstore get config directly from
- // GetVariable function.
- //
- if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
- break;
- }
-
- NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
- VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
- if (VarStoreName == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);
- if (IfrEfiVarStoreTmp != NULL) {
- FreePool (IfrEfiVarStoreTmp);
- }
-
- IfrEfiVarStoreTmp = AllocatePool (IfrEfiVarStore->Header.Length + AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name));
- if (IfrEfiVarStoreTmp == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- CopyMem (IfrEfiVarStoreTmp, IfrEfiVarStore, IfrEfiVarStore->Header.Length);
- AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, (CHAR16 *)&(IfrEfiVarStoreTmp->Name[0]), AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
-
- if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
- //
- // Find the matched VarStore
- //
- CopyGuid (&VarStorageData->Guid, (EFI_GUID *)(VOID *)&IfrEfiVarStore->Guid);
- VarStorageData->Size = IfrEfiVarStore->Size;
- VarStorageData->Name = VarStoreName;
- VarStorageData->Type = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;
- VarStoreId = IfrEfiVarStore->VarStoreId;
- } else {
- FreePool (VarStoreName);
- VarStoreName = NULL;
- }
-
- break;
-
- case EFI_IFR_VARSTORE_NAME_VALUE_OP:
- //
- // VarStore is found. Don't need to search any more.
- //
- if (VarStoreId != 0) {
- break;
- }
-
- IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *)IfrOpHdr;
-
- if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
- //
- // Find the matched VarStore
- //
- CopyGuid (&VarStorageData->Guid, (EFI_GUID *)(VOID *)&IfrNameValueVarStore->Guid);
- VarStorageData->Type = EFI_HII_VARSTORE_NAME_VALUE;
- VarStoreId = IfrNameValueVarStore->VarStoreId;
- }
-
- break;
-
- case EFI_IFR_DEFAULTSTORE_OP:
- //
- // Add new the map between default id and default name.
- //
- DefaultDataPtr = (IFR_DEFAULT_DATA *)AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
- if (DefaultDataPtr == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- DefaultDataPtr->DefaultId = ((EFI_IFR_DEFAULTSTORE *)IfrOpHdr)->DefaultId;
- InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);
- DefaultDataPtr = NULL;
- break;
-
- case EFI_IFR_FORM_OP:
- case EFI_IFR_FORM_MAP_OP:
- //
- // No matched varstore is found and directly return.
- //
- if ( VarStoreId == 0) {
- Status = EFI_SUCCESS;
- goto Done;
- }
-
- break;
-
- case EFI_IFR_REF_OP:
- //
- // Ref question is not in IFR Form. This IFR form is not valid.
- //
- if ( VarStoreId == 0) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Check whether this question is for the requested varstore.
- //
- IfrRef = (EFI_IFR_REF4 *)IfrOpHdr;
- if (IfrRef->Question.VarStoreId != VarStoreId) {
- break;
- }
-
- VarWidth = (UINT16)(sizeof (EFI_HII_REF));
-
- //
- // The BlockData may allocate by other opcode,need to clean.
- //
- if (BlockData != NULL) {
- BlockData = NULL;
- }
-
- Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
- if (EFI_ERROR (Status)) {
- if (Status == EFI_NOT_FOUND) {
- //
- // The opcode is not required,exit and parse other opcode.
- //
- break;
- }
-
- goto Done;
- }
-
- break;
-
- case EFI_IFR_ONE_OF_OP:
- case EFI_IFR_NUMERIC_OP:
- //
- // Numeric and OneOf has the same opcode structure.
- //
-
- //
- // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
- //
- if (VarStoreId == 0) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Check whether this question is for the requested varstore.
- //
- IfrOneOf = (EFI_IFR_ONE_OF *)IfrOpHdr;
- if (IfrOneOf->Question.VarStoreId != VarStoreId) {
- break;
- }
-
- if (QuestionReferBitField) {
- VarWidth = IfrOneOf->Flags & EDKII_IFR_NUMERIC_SIZE_BIT;
- } else {
- VarWidth = (UINT16)(1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
- }
-
- //
- // The BlockData may allocate by other opcode,need to clean.
- //
- if (BlockData != NULL) {
- BlockData = NULL;
- }
-
- Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, QuestionReferBitField);
- if (EFI_ERROR (Status)) {
- if (Status == EFI_NOT_FOUND) {
- //
- // The opcode is not required,exit and parse other opcode.
- //
- break;
- }
-
- goto Done;
- }
-
- //
- // when go to there,BlockData can't be NULLL.
- //
- ASSERT (BlockData != NULL);
-
- if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {
- //
- // Set this flag to TRUE for the first oneof option.
- //
- FirstOneOfOption = TRUE;
- } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {
- //
- // Numeric minimum value will be used as default value when no default is specified.
- //
- DefaultData.Type = DefaultValueFromDefault;
- if (QuestionReferBitField) {
- //
- // Since default value in bit field was stored as UINT32 type.
- //
- CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));
- } else {
- switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {
- case EFI_IFR_NUMERIC_SIZE_1:
- DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;
- break;
-
- case EFI_IFR_NUMERIC_SIZE_2:
- CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));
- break;
-
- case EFI_IFR_NUMERIC_SIZE_4:
- CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));
- break;
-
- case EFI_IFR_NUMERIC_SIZE_8:
- CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));
- break;
-
- default:
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
- }
-
- //
- // Set default value base on the DefaultId list get from IFR data.
- //
- NvDefaultStoreSize = PcdGetSize (PcdNvStoreDefaultValueBuffer);
- for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
- DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
- DefaultData.DefaultId = DefaultDataPtr->DefaultId;
- if (NvDefaultStoreSize > sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) {
- FindQuestionDefaultSetting (DefaultData.DefaultId, IfrEfiVarStoreTmp, &(IfrOneOf->Question), &DefaultData.Value, VarWidth, QuestionReferBitField);
- }
-
- InsertDefaultValue (BlockData, &DefaultData);
- }
- }
-
- break;
-
- case EFI_IFR_ORDERED_LIST_OP:
- //
- // offset by question header
- // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
- //
-
- FirstOrderedList = TRUE;
- //
- // OrderedList question is not in IFR Form. This IFR form is not valid.
- //
- if (VarStoreId == 0) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Check whether this question is for the requested varstore.
- //
- IfrOrderedList = (EFI_IFR_ORDERED_LIST *)IfrOpHdr;
- if (IfrOrderedList->Question.VarStoreId != VarStoreId) {
- BlockData = NULL;
- break;
- }
-
- VarWidth = IfrOrderedList->MaxContainers;
-
- //
- // The BlockData may allocate by other opcode,need to clean.
- //
- if (BlockData != NULL) {
- BlockData = NULL;
- }
-
- Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
- if (EFI_ERROR (Status)) {
- if (Status == EFI_NOT_FOUND) {
- //
- // The opcode is not required,exit and parse other opcode.
- //
- break;
- }
-
- goto Done;
- }
-
- break;
-
- case EFI_IFR_CHECKBOX_OP:
- //
- // EFI_IFR_DEFAULT_OP
- // offset by question header
- // width is 1 sizeof (BOOLEAN)
- // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
- // value by DefaultOption
- // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
- //
-
- //
- // CheckBox question is not in IFR Form. This IFR form is not valid.
- //
- if (VarStoreId == 0) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Check whether this question is for the requested varstore.
- //
- IfrCheckBox = (EFI_IFR_CHECKBOX *)IfrOpHdr;
- if (IfrCheckBox->Question.VarStoreId != VarStoreId) {
- break;
- }
-
- VarWidth = (UINT16)sizeof (BOOLEAN);
-
- //
- // The BlockData may allocate by other opcode,need to clean.
- //
- if (BlockData != NULL) {
- BlockData = NULL;
- }
-
- if (QuestionReferBitField) {
- VarWidth = 1;
- }
-
- Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, QuestionReferBitField);
- if (EFI_ERROR (Status)) {
- if (Status == EFI_NOT_FOUND) {
- //
- // The opcode is not required,exit and parse other opcode.
- //
- break;
- }
-
- goto Done;
- }
-
- //
- // when go to there,BlockData can't be NULLL.
- //
- ASSERT (BlockData != NULL);
-
- SmallestIdFromFlag = FALSE;
-
- //
- // Add default value for standard ID by CheckBox Flag
- //
- VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
- //
- // Prepare new DefaultValue
- //
- DefaultData.DefaultId = VarDefaultId;
- if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {
- //
- // When flag is set, default value is TRUE.
- //
- DefaultData.Type = DefaultValueFromFlag;
- if (QuestionReferBitField) {
- DefaultData.Value.u32 = TRUE;
- } else {
- DefaultData.Value.b = TRUE;
- }
-
- InsertDefaultValue (BlockData, &DefaultData);
-
- if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {
- //
- // Record the SmallestDefaultId and update the SmallestIdFromFlag.
- //
- SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
- SmallestIdFromFlag = TRUE;
- }
- }
-
- //
- // Add default value for Manufacture ID by CheckBox Flag
- //
- VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
- //
- // Prepare new DefaultValue
- //
- DefaultData.DefaultId = VarDefaultId;
- if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {
- //
- // When flag is set, default value is TRUE.
- //
- DefaultData.Type = DefaultValueFromFlag;
- if (QuestionReferBitField) {
- DefaultData.Value.u32 = TRUE;
- } else {
- DefaultData.Value.b = TRUE;
- }
-
- InsertDefaultValue (BlockData, &DefaultData);
-
- if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
- //
- // Record the SmallestDefaultId and update the SmallestIdFromFlag.
- //
- SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
- SmallestIdFromFlag = TRUE;
- }
- }
-
- if (SmallestIdFromFlag) {
- //
- // When smallest default Id is given by the flag of CheckBox, set default value with TRUE for other default Id in the DefaultId list.
- //
- DefaultData.Type = DefaultValueFromOtherDefault;
- if (QuestionReferBitField) {
- DefaultData.Value.u32 = TRUE;
- } else {
- DefaultData.Value.b = TRUE;
- }
-
- //
- // Set default value for all the default id in the DefaultId list.
- //
- for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
- DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
- DefaultData.DefaultId = DefaultDataPtr->DefaultId;
- InsertDefaultValue (BlockData, &DefaultData);
- }
- } else {
- //
- // When flag is not set, default value is FASLE.
- //
- DefaultData.Type = DefaultValueFromDefault;
- if (QuestionReferBitField) {
- DefaultData.Value.u32 = FALSE;
- } else {
- DefaultData.Value.b = FALSE;
- }
-
- //
- // Set default value for all the default id in the DefaultId list.
- //
- for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
- DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
- DefaultData.DefaultId = DefaultDataPtr->DefaultId;
- InsertDefaultValue (BlockData, &DefaultData);
- }
- }
-
- break;
-
- case EFI_IFR_DATE_OP:
- //
- // offset by question header
- // width MaxSize * sizeof (CHAR16)
- // no default value, only block array
- //
-
- //
- // Date question is not in IFR Form. This IFR form is not valid.
- //
- if (VarStoreId == 0) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Check whether this question is for the requested varstore.
- //
- IfrDate = (EFI_IFR_DATE *)IfrOpHdr;
- if (IfrDate->Question.VarStoreId != VarStoreId) {
- break;
- }
-
- //
- // The BlockData may allocate by other opcode,need to clean.
- //
- if (BlockData != NULL) {
- BlockData = NULL;
- }
-
- VarWidth = (UINT16)sizeof (EFI_HII_DATE);
- Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
- if (EFI_ERROR (Status)) {
- if (Status == EFI_NOT_FOUND) {
- //
- // The opcode is not required,exit and parse other opcode.
- //
- break;
- }
-
- goto Done;
- }
-
- break;
-
- case EFI_IFR_TIME_OP:
- //
- // offset by question header
- // width MaxSize * sizeof (CHAR16)
- // no default value, only block array
- //
-
- //
- // Time question is not in IFR Form. This IFR form is not valid.
- //
- if (VarStoreId == 0) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Check whether this question is for the requested varstore.
- //
- IfrTime = (EFI_IFR_TIME *)IfrOpHdr;
- if (IfrTime->Question.VarStoreId != VarStoreId) {
- break;
- }
-
- //
- // The BlockData may allocate by other opcode,need to clean.
- //
- if (BlockData != NULL) {
- BlockData = NULL;
- }
-
- VarWidth = (UINT16)sizeof (EFI_HII_TIME);
- Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
- if (EFI_ERROR (Status)) {
- if (Status == EFI_NOT_FOUND) {
- //
- // The opcode is not required,exit and parse other opcode.
- //
- break;
- }
-
- goto Done;
- }
-
- break;
-
- case EFI_IFR_STRING_OP:
- //
- // offset by question header
- // width MaxSize * sizeof (CHAR16)
- // no default value, only block array
- //
-
- //
- // String question is not in IFR Form. This IFR form is not valid.
- //
- if (VarStoreId == 0) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Check whether this question is for the requested varstore.
- //
- IfrString = (EFI_IFR_STRING *)IfrOpHdr;
- if (IfrString->Question.VarStoreId != VarStoreId) {
- break;
- }
-
- //
- // The BlockData may allocate by other opcode,need to clean.
- //
- if (BlockData != NULL) {
- BlockData = NULL;
- }
-
- VarWidth = (UINT16)(IfrString->MaxSize * sizeof (UINT16));
- Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
- if (EFI_ERROR (Status)) {
- if (Status == EFI_NOT_FOUND) {
- //
- // The opcode is not required,exit and parse other opcode.
- //
- break;
- }
-
- goto Done;
- }
-
- break;
-
- case EFI_IFR_PASSWORD_OP:
- //
- // offset by question header
- // width MaxSize * sizeof (CHAR16)
- // no default value, only block array
- //
-
- //
- // Password question is not in IFR Form. This IFR form is not valid.
- //
- if (VarStoreId == 0) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Check whether this question is for the requested varstore.
- //
- IfrPassword = (EFI_IFR_PASSWORD *)IfrOpHdr;
- if (IfrPassword->Question.VarStoreId != VarStoreId) {
- break;
- }
-
- //
- // The BlockData may allocate by other opcode,need to clean.
- //
- if (BlockData != NULL) {
- BlockData = NULL;
- }
-
- VarWidth = (UINT16)(IfrPassword->MaxSize * sizeof (UINT16));
- Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
- if (EFI_ERROR (Status)) {
- if (Status == EFI_NOT_FOUND) {
- //
- // The opcode is not required,exit and parse other opcode.
- //
- break;
- }
-
- goto Done;
- }
-
- //
- // No default value for string.
- //
- BlockData = NULL;
- break;
-
- case EFI_IFR_ONE_OF_OPTION_OP:
- //
- // No matched block data is ignored.
- //
- if ((BlockData == NULL) || (BlockData->Scope == 0)) {
- break;
- }
-
- IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *)IfrOpHdr;
- if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
- if (!FirstOrderedList) {
- break;
- }
-
- //
- // Get ordered list option data type.
- //
- if ((IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8) || (IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN)) {
- VarWidth = 1;
- } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
- VarWidth = 2;
- } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
- VarWidth = 4;
- } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
- VarWidth = 8;
- } else {
- //
- // Invalid ordered list option data type.
- //
- Status = EFI_INVALID_PARAMETER;
- if (BlockData->Name != NULL) {
- FreePool (BlockData->Name);
- }
-
- FreePool (BlockData);
- goto Done;
- }
-
- //
- // Calculate Ordered list QuestionId width.
- //
- BlockData->Width = (UINT16)(BlockData->Width * VarWidth);
- //
- // Check whether this question is in requested block array.
- //
- if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, (BOOLEAN)(BlockData->Name != NULL), HiiHandle)) {
- //
- // This question is not in the requested string. Skip it.
- //
- if (BlockData->Name != NULL) {
- FreePool (BlockData->Name);
- }
-
- FreePool (BlockData);
- BlockData = NULL;
- break;
- }
-
- //
- // Check this var question is in the var storage
- //
- if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {
- Status = EFI_INVALID_PARAMETER;
- FreePool (BlockData);
- goto Done;
- }
-
- //
- // Add Block Data into VarStorageData BlockEntry
- //
- InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
-
- FirstOrderedList = FALSE;
-
- break;
- }
-
- //
- // 1. Set default value for OneOf option when flag field has default attribute.
- // And set the default value with the smallest default id for other default id in the DefaultId list.
- //
- if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||
- ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG))
- {
- //
- // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
- // The first oneof option value will be used as default value when no default value is specified.
- //
- FirstOneOfOption = FALSE;
-
- SmallestIdFromFlag = FALSE;
-
- // Prepare new DefaultValue
- //
- DefaultData.Type = DefaultValueFromFlag;
- CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
- if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {
- DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
- InsertDefaultValue (BlockData, &DefaultData);
- if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {
- //
- // Record the SmallestDefaultId and update the SmallestIdFromFlag.
- //
- SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
- SmallestIdFromFlag = TRUE;
- }
- }
-
- if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {
- DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
- InsertDefaultValue (BlockData, &DefaultData);
- if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
- //
- // Record the SmallestDefaultId and update the SmallestIdFromFlag.
- //
- SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
- SmallestIdFromFlag = TRUE;
- }
- }
-
- if (SmallestIdFromFlag) {
- //
- // When smallest default Id is given by the flag of oneofOption, set this option value for other default Id in the DefaultId list.
- //
- DefaultData.Type = DefaultValueFromOtherDefault;
- //
- // Set default value for other default id in the DefaultId list.
- //
- for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
- DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
- DefaultData.DefaultId = DefaultDataPtr->DefaultId;
- InsertDefaultValue (BlockData, &DefaultData);
- }
- }
- }
-
- //
- // 2. Set as the default value when this is the first option.
- // The first oneof option value will be used as default value when no default value is specified.
- //
- if (FirstOneOfOption) {
- // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
- FirstOneOfOption = FALSE;
-
- //
- // Prepare new DefaultValue
- //
- DefaultData.Type = DefaultValueFromDefault;
- CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
- for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
- DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
- DefaultData.DefaultId = DefaultDataPtr->DefaultId;
- InsertDefaultValue (BlockData, &DefaultData);
- }
- }
-
- break;
-
- case EFI_IFR_DEFAULT_OP:
- //
- // Update Current BlockData to the default value.
- //
- if ((BlockData == NULL) || (BlockData->Scope == 0)) {
- //
- // No matched block data is ignored.
- //
- break;
- }
-
- //
- // Get the DefaultId
- //
- IfrDefault = (EFI_IFR_DEFAULT *)IfrOpHdr;
- VarDefaultId = IfrDefault->DefaultId;
- //
- // Prepare new DefaultValue
- //
- DefaultData.Type = DefaultValueFromOpcode;
- DefaultData.DefaultId = VarDefaultId;
- if (QuestionReferBitField) {
- CopyMem (&DefaultData.Value.u32, &IfrDefault->Value.u32, sizeof (UINT32));
- } else {
- CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));
- }
-
- // If the value field is expression, set the cleaned flag.
- if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {
- DefaultData.Cleaned = TRUE;
- }
-
- //
- // Add DefaultValue into current BlockData
- //
- InsertDefaultValue (BlockData, &DefaultData);
-
- //
- // Set default value for other default id in the DefaultId list.
- // when SmallestDefaultId == VarDefaultId means there are two defaults with same default Id.
- // If the two defaults are both from default opcode, use the first default as the default value of other default Id.
- // If one from flag and the other form default opcode, use the default opcode value as the default value of other default Id.
- //
- if ((SmallestDefaultId > VarDefaultId) || ((SmallestDefaultId == VarDefaultId) && !FromOtherDefaultOpcode)) {
- FromOtherDefaultOpcode = TRUE;
- SmallestDefaultId = VarDefaultId;
- for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
- DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
- if (DefaultDataPtr->DefaultId != DefaultData.DefaultId) {
- DefaultData.Type = DefaultValueFromOtherDefault;
- DefaultData.DefaultId = DefaultDataPtr->DefaultId;
- InsertDefaultValue (BlockData, &DefaultData);
- }
- }
- }
-
- //
- // After insert the default value, reset the cleaned value for next
- // time used. If not set here, need to set the value before every time.
- // use it.
- //
- DefaultData.Cleaned = FALSE;
- break;
-
- case EFI_IFR_END_OP:
- //
- // End Opcode is for Var question.
- //
- QuestionReferBitField = FALSE;
- if (BlockData != NULL) {
- if (BlockData->Scope > 0) {
- BlockData->Scope--;
- }
-
- if (BlockData->Scope == 0) {
- BlockData = NULL;
- //
- // when finishing parsing a question, clean the SmallestDefaultId and GetDefaultFromDefaultOpcode.
- //
- SmallestDefaultId = 0xFFFF;
- FromOtherDefaultOpcode = FALSE;
- }
- }
-
- break;
-
- case EFI_IFR_GUID_OP:
- if (CompareGuid ((EFI_GUID *)((UINT8 *)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {
- QuestionReferBitField = TRUE;
- }
-
- break;
-
- default:
- if (BlockData != NULL) {
- if (BlockData->Scope > 0) {
- BlockData->Scope = (UINT8)(BlockData->Scope + IfrOpHdr->Scope);
- }
-
- if (BlockData->Scope == 0) {
- BlockData = NULL;
- }
- }
-
- break;
- }
-
- IfrOffset += IfrOpHdr->Length;
- PackageOffset += IfrOpHdr->Length;
- }
-
- //
- // if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
- // so set the Status to EFI_SUCCESS.
- //
- if (Status == EFI_NOT_FOUND) {
- Status = EFI_SUCCESS;
- }
-
-Done:
- for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
- BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
- for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {
- DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
- LinkDefault = LinkDefault->ForwardLink;
- if (DefaultDataPtr->Cleaned == TRUE) {
- RemoveEntryList (&DefaultDataPtr->Entry);
- FreePool (DefaultDataPtr);
- }
- }
- }
-
- if (IfrEfiVarStoreTmp != NULL) {
- FreePool (IfrEfiVarStoreTmp);
- }
-
- return Status;
-}
-
-/**
- parse the configrequest string, get the elements.
-
- @param ConfigRequest The input configrequest string.
- @param Progress Return the progress data.
-
- @retval Block data pointer.
-**/
-IFR_BLOCK_DATA *
-GetBlockElement (
- IN EFI_STRING ConfigRequest,
- OUT EFI_STRING *Progress
- )
-{
- EFI_STRING StringPtr;
- IFR_BLOCK_DATA *BlockData;
- IFR_BLOCK_DATA *RequestBlockArray;
- EFI_STATUS Status;
- UINT8 *TmpBuffer;
- UINT16 Offset;
- UINT16 Width;
- LIST_ENTRY *Link;
- IFR_BLOCK_DATA *NextBlockData;
- UINTN Length;
-
- TmpBuffer = NULL;
-
- //
- // Init RequestBlockArray
- //
- RequestBlockArray = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (RequestBlockArray == NULL) {
- goto Done;
- }
-
- InitializeListHead (&RequestBlockArray->Entry);
-
- //
- // Get the request Block array from the request string
- // Offset and Width
- //
-
- //
- // Parse each <RequestElement> if exists
- // Only <BlockName> format is supported by this help function.
- // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
- //
- StringPtr = ConfigRequest;
- while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
- //
- // Skip the OFFSET string
- //
- *Progress = StringPtr;
- StringPtr += StrLen (L"&OFFSET=");
- //
- // Get Offset
- //
- Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- Offset = 0;
- CopyMem (
- &Offset,
- TmpBuffer,
- (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
- );
- FreePool (TmpBuffer);
-
- StringPtr += Length;
- if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
- goto Done;
- }
-
- StringPtr += StrLen (L"&WIDTH=");
-
- //
- // Get Width
- //
- Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- Width = 0;
- CopyMem (
- &Width,
- TmpBuffer,
- (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
- );
- FreePool (TmpBuffer);
-
- StringPtr += Length;
- if ((*StringPtr != 0) && (*StringPtr != L'&')) {
- goto Done;
- }
-
- //
- // Set Block Data
- //
- BlockData = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (BlockData == NULL) {
- goto Done;
- }
-
- BlockData->Offset = Offset;
- BlockData->Width = Width;
- InsertBlockData (&RequestBlockArray->Entry, &BlockData);
-
- //
- // Skip &VALUE string if &VALUE does exists.
- //
- if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {
- StringPtr += StrLen (L"&VALUE=");
-
- //
- // Get Value
- //
- Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- FreePool (TmpBuffer);
- StringPtr += Length;
- if ((*StringPtr != 0) && (*StringPtr != L'&')) {
- goto Done;
- }
- }
-
- //
- // If '\0', parsing is finished.
- //
- if (*StringPtr == 0) {
- break;
- }
- }
-
- //
- // Merge the requested block data.
- //
- Link = RequestBlockArray->Entry.ForwardLink;
- while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {
- BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
- NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
- if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
- if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
- BlockData->Width = (UINT16)(NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);
- }
-
- RemoveEntryList (Link->ForwardLink);
- FreePool (NextBlockData);
- continue;
- }
-
- Link = Link->ForwardLink;
- }
-
- return RequestBlockArray;
-
-Done:
- if (RequestBlockArray != NULL) {
- //
- // Free Link Array RequestBlockArray
- //
- while (!IsListEmpty (&RequestBlockArray->Entry)) {
- BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
- RemoveEntryList (&BlockData->Entry);
- FreePool (BlockData);
- }
-
- FreePool (RequestBlockArray);
- }
-
- return NULL;
-}
-
-/**
- parse the configrequest string, get the elements.
-
- @param ConfigRequest The input config request string.
- @param Progress Return the progress data.
-
- @retval return data block array.
-**/
-IFR_BLOCK_DATA *
-GetNameElement (
- IN EFI_STRING ConfigRequest,
- OUT EFI_STRING *Progress
- )
-{
- EFI_STRING StringPtr;
- EFI_STRING NextTag;
- IFR_BLOCK_DATA *BlockData;
- IFR_BLOCK_DATA *RequestBlockArray;
- BOOLEAN HasValue;
-
- StringPtr = ConfigRequest;
-
- //
- // Init RequestBlockArray
- //
- RequestBlockArray = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (RequestBlockArray == NULL) {
- goto Done;
- }
-
- InitializeListHead (&RequestBlockArray->Entry);
-
- //
- // Get the request Block array from the request string
- //
-
- //
- // Parse each <RequestElement> if exists
- // Only <BlockName> format is supported by this help function.
- // <BlockName> ::= &'Name***=***
- //
- while (StringPtr != NULL && *StringPtr == L'&') {
- *Progress = StringPtr;
- //
- // Skip the L"&" string
- //
- StringPtr += 1;
-
- HasValue = FALSE;
- if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {
- *NextTag = L'\0';
- HasValue = TRUE;
- } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {
- *NextTag = L'\0';
- }
-
- //
- // Set Block Data
- //
- BlockData = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (BlockData == NULL) {
- goto Done;
- }
-
- //
- // Get Name
- //
- BlockData->Name = AllocateCopyPool (StrSize (StringPtr), StringPtr);
- InsertBlockData (&RequestBlockArray->Entry, &BlockData);
-
- if (HasValue) {
- //
- // If has value, skip the value.
- //
- StringPtr = NextTag + 1;
- *NextTag = L'=';
- StringPtr = StrStr (StringPtr, L"&");
- } else if (NextTag != NULL) {
- //
- // restore the '&' text.
- //
- StringPtr = NextTag;
- *NextTag = L'&';
- }
- }
-
- return RequestBlockArray;
-
-Done:
- if (RequestBlockArray != NULL) {
- //
- // Free Link Array RequestBlockArray
- //
- while (!IsListEmpty (&RequestBlockArray->Entry)) {
- BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
- RemoveEntryList (&BlockData->Entry);
- if (BlockData->Name != NULL) {
- FreePool (BlockData->Name);
- }
-
- FreePool (BlockData);
- }
-
- FreePool (RequestBlockArray);
- }
-
- return NULL;
-}
-
-/**
- Generate ConfigRequest string base on the varstore info.
-
- @param ConfigHdr The config header for this varstore.
- @param VarStorageData The varstore info.
- @param Status Return Status.
- @param ConfigRequest The ConfigRequest info may be return.
-
- @retval TRUE Need to continue
- @retval Others NO need to continue or error occur.
-**/
-BOOLEAN
-GenerateConfigRequest (
- IN CHAR16 *ConfigHdr,
- IN IFR_VARSTORAGE_DATA *VarStorageData,
- OUT EFI_STATUS *Status,
- IN OUT EFI_STRING *ConfigRequest
- )
-{
- BOOLEAN DataExist;
- UINTN Length;
- LIST_ENTRY *Link;
- CHAR16 *FullConfigRequest;
- CHAR16 *StringPtr;
- IFR_BLOCK_DATA *BlockData;
-
- //
- // Append VarStorageData BlockEntry into *Request string
- // Now support only one varstore in a form package.
- //
-
- //
- // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
- // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
- //
-
- //
- // Compute the length of the entire request starting with <ConfigHdr> and a
- // Null-terminator
- //
- DataExist = FALSE;
- Length = StrLen (ConfigHdr) + 1;
-
- for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
- DataExist = TRUE;
- BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
- if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
- //
- // Add <BlockName> length for each Name
- //
- // <BlockName> ::= &Name1&Name2&...
- // |1| StrLen(Name1)
- //
- Length = Length + (1 + StrLen (BlockData->Name));
- } else {
- //
- // Add <BlockName> length for each Offset/Width pair
- //
- // <BlockName> ::= &OFFSET=1234&WIDTH=1234
- // | 8 | 4 | 7 | 4 |
- //
- Length = Length + (8 + 4 + 7 + 4);
- }
- }
-
- //
- // No any request block data is found. The request string can't be constructed.
- //
- if (!DataExist) {
- *Status = EFI_SUCCESS;
- return FALSE;
- }
-
- //
- // Allocate buffer for the entire <ConfigRequest>
- //
- FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));
- if (FullConfigRequest == NULL) {
- *Status = EFI_OUT_OF_RESOURCES;
- return FALSE;
- }
-
- StringPtr = FullConfigRequest;
-
- //
- // Start with <ConfigHdr>
- //
- StrCpyS (StringPtr, Length, ConfigHdr);
- StringPtr += StrLen (StringPtr);
-
- //
- // Loop through all the Offset/Width pairs and append them to ConfigRequest
- //
- for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
- BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
- if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
- //
- // Append &Name1\0
- //
- UnicodeSPrint (
- StringPtr,
- (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),
- L"&%s",
- BlockData->Name
- );
- } else {
- //
- // Append &OFFSET=XXXX&WIDTH=YYYY\0
- //
- UnicodeSPrint (
- StringPtr,
- (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
- L"&OFFSET=%04X&WIDTH=%04X",
- BlockData->Offset,
- BlockData->Width
- );
- }
-
- StringPtr += StrLen (StringPtr);
- }
-
- //
- // Set to the got full request string.
- //
- HiiToLower (FullConfigRequest);
-
- if (*ConfigRequest != NULL) {
- FreePool (*ConfigRequest);
- }
-
- *ConfigRequest = FullConfigRequest;
-
- return TRUE;
-}
-
-/**
- Generate ConfigRequest Header base on the varstore info.
-
- @param VarStorageData The varstore info.
- @param DevicePath Device path for this varstore.
- @param ConfigHdr The config header for this varstore.
-
- @retval EFI_SUCCESS Generate the header success.
- @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
-**/
-EFI_STATUS
-GenerateHdr (
- IN IFR_VARSTORAGE_DATA *VarStorageData,
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- OUT EFI_STRING *ConfigHdr
- )
-{
- EFI_STRING GuidStr;
- EFI_STRING NameStr;
- EFI_STRING PathStr;
- UINTN Length;
- EFI_STATUS Status;
-
- Status = EFI_SUCCESS;
- NameStr = NULL;
- GuidStr = NULL;
- PathStr = NULL;
-
- //
- // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
- //
- GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)&VarStorageData->Guid, 1, &GuidStr);
- if (VarStorageData->Name != NULL) {
- GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *)VarStorageData->Name, 2, &NameStr);
- } else {
- GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
- }
-
- GenerateSubStr (
- L"PATH=",
- GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DevicePath),
- (VOID *)DevicePath,
- 1,
- &PathStr
- );
- Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;
- if (VarStorageData->Name == NULL) {
- Length += 1;
- }
-
- *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));
- if (*ConfigHdr == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- StrCpyS (*ConfigHdr, Length, GuidStr);
- StrCatS (*ConfigHdr, Length, NameStr);
- if (VarStorageData->Name == NULL) {
- StrCatS (*ConfigHdr, Length, L"&");
- }
-
- StrCatS (*ConfigHdr, Length, PathStr);
-
- //
- // Remove the last character L'&'
- //
- *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';
-
-Done:
- if (GuidStr != NULL) {
- FreePool (GuidStr);
- }
-
- if (NameStr != NULL) {
- FreePool (NameStr);
- }
-
- if (PathStr != NULL) {
- FreePool (PathStr);
- }
-
- return Status;
-}
-
-/**
- Update the default value in the block data which is used as bit var store.
-
- For example:
- A question value saved in a bit fied: bitoffset = 1; bitwidth = 2;default value = 1.
- And corresponding block data info: offset==0; width==1;currently the default value
- is saved as 1.Actually the default value 1 need to be set to bit field 1, so the
- default value of this block data shuold be:2.
-
- typedef struct {
- UINT8 Bit1 : 1; //
- UINT8 Bit2 : 2; // Question saved in Bit2,so originalBlock info: offset = 0; width = 1;(byte level) defaul = 1.
- // (default value record for the bit field)
- ......
- }ExampleData;
-
- After function UpdateDefaultValue,the Block info is: offset = 0; width = 1;(byte level) default = 2.
- (default value record for the Block)
-
- UpdateDefaultValue function update default value of bit var block based on the bit field info in the block.
-
- @param BlockLink The Link of the block data.
-
-**/
-VOID
-UpdateDefaultValue (
- IN LIST_ENTRY *BlockLink
- )
-{
- LIST_ENTRY *Link;
- LIST_ENTRY *ListEntry;
- LIST_ENTRY *LinkDefault;
- IFR_BLOCK_DATA *BlockData;
- IFR_DEFAULT_DATA *DefaultValueData;
- UINTN StartBit;
- UINTN EndBit;
- UINT32 BitFieldDefaultValue;
-
- for ( Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
- BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
- if (!BlockData->IsBitVar) {
- continue;
- }
-
- ListEntry = &BlockData->DefaultValueEntry;
- //
- // Update the default value in the block data with all existing default id.
- //
- for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
- //
- // Get the default data, and the value of the default data is for some field in the block.
- // Note: Default value for bit field question is stored as UINT32.
- //
- DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
- BitFieldDefaultValue = DefaultValueData->Value.u32;
-
- StartBit = BlockData->BitOffset % 8;
- EndBit = StartBit + BlockData->BitWidth - 1;
-
- //
- // Set the bit field default value to related bit filed, then we will got the new default vaule for the block data.
- //
- DefaultValueData->Value.u32 = BitFieldWrite32 (0, StartBit, EndBit, BitFieldDefaultValue);
- }
- }
-}
-
-/**
-Merge the default value in two block datas which have overlap region.
-
-For bit fields, their related block data may have overlap region, such as:
-
-typedef struct {
- UINT16 Bit1 : 6; // Question1 refer Bit1, Block1: offset = 0; width = 1;(byte level) default = 1
- UINT16 Bit2 : 5; // Question2 refer Bit2, Block2: offset = 0; width = 2;(byte level) default = 5
- // (default value record for the bit field)
- ......
-}ExampleData;
-
-After function UpdateDefaultValue:
-Block1: offset = 0; width = 1;(byte level) default = 1
-Block2: offset = 0; width = 2;(byte level) default = 320 (5 * (2 << 6))
-(default value record for block)
-
-After function MergeBlockDefaultValue:
-Block1: offset = 0; width = 1;(byte level) default = 65
-Block2: offset = 0; width = 2;(byte level) default = 321
-(Block1 and Block2 has overlap region, merge the overlap value to Block1 and Blcok2)
-
-Block1 and Block2 have overlap byte region, but currntly the default value of Block1 only contains
-value of Bit1 (low 6 bits),the default value of Block2 only contains the value of Bit2 (middle 5 bits).
-
-This fuction merge the default value of these two blocks, and make the default value of block1
-also contain the value of lower 2 bits of the Bit2. And make the default value of Block2 also
-contain the default value of Bit1.
-
-We can get the total value of the whole block that just cover these two blocks(in this case is:
-block: offset =0; width =2;) then the value of block2 is same as block, the value of block1 is
-the first byte value of block.
-
-@param FirstBlock Point to the block date whose default value need to be merged.
-@param SecondBlock Point to the block date whose default value need to be merged.
-
-**/
-VOID
-MergeBlockDefaultValue (
- IN OUT IFR_BLOCK_DATA *FirstBlock,
- IN OUT IFR_BLOCK_DATA *SecondBlock
- )
-{
- LIST_ENTRY *FirstListEntry;
- LIST_ENTRY *SecondListEntry;
- LIST_ENTRY *FirstDefaultLink;
- LIST_ENTRY *SecondDefaultLink;
- IFR_DEFAULT_DATA *FirstDefaultValueData;
- IFR_DEFAULT_DATA *SecondDefaultValueData;
- UINT32 *FirstDefaultValue;
- UINT32 *SecondDefaultValue;
- UINT64 TotalValue;
- UINT64 ShiftedValue;
- UINT16 OffsetShift;
-
- FirstListEntry = &FirstBlock->DefaultValueEntry;
- for (FirstDefaultLink = FirstListEntry->ForwardLink; FirstDefaultLink != FirstListEntry; FirstDefaultLink = FirstDefaultLink->ForwardLink) {
- FirstDefaultValueData = BASE_CR (FirstDefaultLink, IFR_DEFAULT_DATA, Entry);
- SecondListEntry = &SecondBlock->DefaultValueEntry;
- for (SecondDefaultLink = SecondListEntry->ForwardLink; SecondDefaultLink != SecondListEntry; SecondDefaultLink = SecondDefaultLink->ForwardLink) {
- SecondDefaultValueData = BASE_CR (SecondDefaultLink, IFR_DEFAULT_DATA, Entry);
- if (FirstDefaultValueData->DefaultId != SecondDefaultValueData->DefaultId) {
- continue;
- }
-
- //
- // Find default value with same default id in the two blocks.
- // Note: Default value for bit field question is stored as UINT32 type.
- //
- FirstDefaultValue = &FirstDefaultValueData->Value.u32;
- SecondDefaultValue = &SecondDefaultValueData->Value.u32;
- //
- // 1. Get the default value of the whole blcok that can just cover FirstBlock and SecondBlock.
- // 2. Get the default value of FirstBlock and SecondBlock form the value of whole block based
- // on the offset and width of FirstBlock and SecondBlock.
- //
- if (FirstBlock->Offset > SecondBlock->Offset) {
- OffsetShift = FirstBlock->Offset - SecondBlock->Offset;
- ShiftedValue = LShiftU64 ((UINT64)(*FirstDefaultValue), OffsetShift * 8);
- TotalValue = ShiftedValue | (UINT64)(*SecondDefaultValue);
- *SecondDefaultValue = (UINT32)BitFieldRead64 (TotalValue, 0, SecondBlock->Width * 8 -1);
- *FirstDefaultValue = (UINT32)BitFieldRead64 (TotalValue, OffsetShift * 8, OffsetShift * 8 + FirstBlock->Width *8 -1);
- } else {
- OffsetShift = SecondBlock->Offset -FirstBlock->Offset;
- ShiftedValue = LShiftU64 ((UINT64)(*SecondDefaultValue), OffsetShift * 8);
- TotalValue = ShiftedValue | (UINT64)(*FirstDefaultValue);
- *FirstDefaultValue = (UINT32)BitFieldRead64 (TotalValue, 0, FirstBlock->Width * 8 -1);
- *SecondDefaultValue = (UINT32)BitFieldRead64 (TotalValue, OffsetShift * 8, OffsetShift * 8 + SecondBlock->Width *8 -1);
- }
- }
- }
-}
-
-/**
-
-Update the default value in the block data which used as Bit VarStore
-
-@param BlockLink The Link of the block data.
-
-**/
-VOID
-UpdateBlockDataArray (
- IN LIST_ENTRY *BlockLink
- )
-{
- LIST_ENTRY *Link;
- LIST_ENTRY *TempLink;
- IFR_BLOCK_DATA *BlockData;
- IFR_BLOCK_DATA *NextBlockData;
-
- //
- // 1. Update default value in BitVar block data.
- // Sine some block datas are used as BitVarStore, then the default value recored in the block
- // is for related bit field in the block. so we need to set the default value to the related bit
- // fields in the block data if the block data is used as bit varstore, then the default value of
- // the block will be updated.
- //
- UpdateDefaultValue (BlockLink);
-
- //
- // 2.Update default value for overlap BitVar blcok datas.
- // For block datas have overlap region, we need to merge the default value in different blocks.
- //
- for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
- BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
- if (!BlockData->IsBitVar) {
- continue;
- }
-
- for (TempLink = Link->ForwardLink; TempLink != BlockLink; TempLink = TempLink->ForwardLink) {
- NextBlockData = BASE_CR (TempLink, IFR_BLOCK_DATA, Entry);
- if (!NextBlockData->IsBitVar || (NextBlockData->Offset >= BlockData->Offset + BlockData->Width) || (BlockData->Offset >= NextBlockData->Offset + NextBlockData->Width)) {
- continue;
- }
-
- //
- // Find two blocks are used as bit VarStore and have overlap region, so need to merge default value of these two blocks.
- //
- MergeBlockDefaultValue (BlockData, NextBlockData);
- }
- }
-}
-
-/**
- Generate ConfigAltResp string base on the varstore info.
-
- @param HiiHandle Hii Handle for this hii package.
- @param ConfigHdr The config header for this varstore.
- @param VarStorageData The varstore info.
- @param DefaultIdArray The Default id array.
- @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
-
- @retval TRUE Need to continue
- @retval Others NO need to continue or error occur.
-**/
-EFI_STATUS
-GenerateAltConfigResp (
- IN EFI_HII_HANDLE HiiHandle,
- IN CHAR16 *ConfigHdr,
- IN IFR_VARSTORAGE_DATA *VarStorageData,
- IN IFR_DEFAULT_DATA *DefaultIdArray,
- IN OUT EFI_STRING *DefaultAltCfgResp
- )
-{
- BOOLEAN DataExist;
- UINTN Length;
- LIST_ENTRY *Link;
- LIST_ENTRY *LinkData;
- LIST_ENTRY *LinkDefault;
- LIST_ENTRY *ListEntry;
- CHAR16 *StringPtr;
- IFR_BLOCK_DATA *BlockData;
- IFR_DEFAULT_DATA *DefaultId;
- IFR_DEFAULT_DATA *DefaultValueData;
- UINTN Width;
- UINT8 *TmpBuffer;
- CHAR16 *DefaultString;
- UINTN StrSize;
-
- BlockData = NULL;
- DataExist = FALSE;
- DefaultString = NULL;
- //
- // Add length for <ConfigHdr> + '\0'
- //
- Length = StrLen (ConfigHdr) + 1;
-
- UpdateBlockDataArray (&VarStorageData->BlockEntry);
-
- for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
- DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
- //
- // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
- // |1| StrLen (ConfigHdr) | 8 | 4 |
- //
- Length += (1 + StrLen (ConfigHdr) + 8 + 4);
-
- for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
- BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
- ListEntry = &BlockData->DefaultValueEntry;
- for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
- DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
- if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
- continue;
- }
-
- if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
- //
- // Add length for "&Name1=zzzzzzzzzzzz"
- // |1|Name|1|Value|
- //
- Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);
- } else {
- //
- // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
- // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
- //
- Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);
- }
-
- DataExist = TRUE;
- }
- }
- }
-
- //
- // No default value is found. The default string doesn't exist.
- //
- if (!DataExist) {
- return EFI_SUCCESS;
- }
-
- //
- // Allocate buffer for the entire <DefaultAltCfgResp>
- //
- *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
- if (*DefaultAltCfgResp == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- StringPtr = *DefaultAltCfgResp;
-
- //
- // Start with <ConfigHdr>
- //
- StrCpyS (StringPtr, Length, ConfigHdr);
- StringPtr += StrLen (StringPtr);
-
- for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
- DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
- //
- // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
- // |1| StrLen (ConfigHdr) | 8 | 4 |
- //
- UnicodeSPrint (
- StringPtr,
- (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
- L"&%s&ALTCFG=%04X",
- ConfigHdr,
- DefaultId->DefaultId
- );
- StringPtr += StrLen (StringPtr);
-
- for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
- BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
- ListEntry = &BlockData->DefaultValueEntry;
- for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
- DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
- if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
- continue;
- }
-
- if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
- UnicodeSPrint (
- StringPtr,
- (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16),
- L"&%s=",
- BlockData->Name
- );
- StringPtr += StrLen (StringPtr);
- } else {
- //
- // Add <BlockConfig>
- // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
- //
- UnicodeSPrint (
- StringPtr,
- (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),
- L"&OFFSET=%04X&WIDTH=%04X&VALUE=",
- BlockData->Offset,
- BlockData->Width
- );
- StringPtr += StrLen (StringPtr);
- }
-
- Width = BlockData->Width;
- //
- // Convert Value to a hex string in "%x" format
- // NOTE: This is in the opposite byte that GUID and PATH use
- //
- if (BlockData->OpCode == EFI_IFR_STRING_OP) {
- DefaultString = InternalGetString (HiiHandle, DefaultValueData->Value.string);
- TmpBuffer = AllocateZeroPool (Width);
- ASSERT (TmpBuffer != NULL);
- if (DefaultString != NULL) {
- StrSize = StrLen (DefaultString)* sizeof (CHAR16);
- if (StrSize > Width) {
- StrSize = Width;
- }
-
- CopyMem (TmpBuffer, (UINT8 *)DefaultString, StrSize);
- }
- } else {
- TmpBuffer = (UINT8 *)&(DefaultValueData->Value);
- }
-
- for ( ; Width > 0 && (TmpBuffer != NULL); Width--) {
- UnicodeValueToStringS (
- StringPtr,
- Length * sizeof (CHAR16) - ((UINTN)StringPtr - (UINTN)*DefaultAltCfgResp),
- PREFIX_ZERO | RADIX_HEX,
- TmpBuffer[Width - 1],
- 2
- );
- StringPtr += StrnLenS (StringPtr, Length - ((UINTN)StringPtr - (UINTN)*DefaultAltCfgResp) / sizeof (CHAR16));
- }
-
- if (DefaultString != NULL) {
- FreePool (DefaultString);
- DefaultString = NULL;
- }
-
- if ((BlockData->OpCode == EFI_IFR_STRING_OP) && (TmpBuffer != NULL)) {
- FreePool (TmpBuffer);
- TmpBuffer = NULL;
- }
- }
- }
- }
-
- HiiToLower (*DefaultAltCfgResp);
-
- return EFI_SUCCESS;
-}
-
-/**
- This function gets the full request string and full default value string by
- parsing IFR data in HII form packages.
-
- When Request points to NULL string, the request string and default value string
- for each varstore in form package will return.
-
- @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
- @param DevicePath Device Path which Hii Config Access Protocol is registered.
- @param Request Pointer to a null-terminated Unicode string in
- <ConfigRequest> format. When it doesn't contain
- any RequestElement, it will be updated to return
- the full RequestElement retrieved from IFR data.
- If it points to NULL, the request string for the first
- varstore in form package will be merged into a
- <MultiConfigRequest> format string and return.
- @param AltCfgResp Pointer to a null-terminated Unicode string in
- <ConfigAltResp> format. When the pointer is to NULL,
- the full default value string retrieved from IFR data
- will return. When the pinter is to a string, the
- full default value string retrieved from IFR data
- will be merged into the input string and return.
- When Request points to NULL, the default value string
- for each varstore in form package will be merged into
- a <MultiConfigAltResp> format string and return.
- @param PointerProgress Optional parameter, it can be NULL.
- When it is not NULL, if Request is NULL, it returns NULL.
- On return, points to a character in the Request
- string. Points to the string's null terminator if
- 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.
- @retval EFI_SUCCESS The Results string is set to the full request string.
- And AltCfgResp contains all default value string.
- @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
- @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
- can't be found in Form package.
- @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
- @retval EFI_INVALID_PARAMETER Request points to NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-GetFullStringFromHiiFormPackages (
- IN HII_DATABASE_RECORD *DataBaseRecord,
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- IN OUT EFI_STRING *Request,
- IN OUT EFI_STRING *AltCfgResp,
- OUT EFI_STRING *PointerProgress OPTIONAL
- )
-{
- EFI_STATUS Status;
- UINT8 *HiiFormPackage;
- UINTN PackageSize;
- IFR_BLOCK_DATA *RequestBlockArray;
- IFR_BLOCK_DATA *BlockData;
- IFR_DEFAULT_DATA *DefaultValueData;
- IFR_DEFAULT_DATA *DefaultId;
- IFR_DEFAULT_DATA *DefaultIdArray;
- IFR_VARSTORAGE_DATA *VarStorageData;
- EFI_STRING DefaultAltCfgResp;
- EFI_STRING ConfigHdr;
- EFI_STRING StringPtr;
- EFI_STRING Progress;
-
- if ((DataBaseRecord == NULL) || (DevicePath == NULL) || (Request == NULL) || (AltCfgResp == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Initialize the local variables.
- //
- RequestBlockArray = NULL;
- DefaultIdArray = NULL;
- VarStorageData = NULL;
- DefaultAltCfgResp = NULL;
- ConfigHdr = NULL;
- HiiFormPackage = NULL;
- PackageSize = 0;
- Progress = *Request;
-
- Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- //
- // 1. Get the request block array by Request String when Request string contains the block array.
- //
- StringPtr = NULL;
- if (*Request != NULL) {
- StringPtr = *Request;
- //
- // Jump <ConfigHdr>
- //
- if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- StringPtr += StrLen (L"GUID=");
- while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
- StringPtr++;
- }
-
- if (*StringPtr == L'\0') {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- StringPtr += StrLen (L"&NAME=");
- while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
- StringPtr++;
- }
-
- if (*StringPtr == L'\0') {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- StringPtr += StrLen (L"&PATH=");
- while (*StringPtr != L'\0' && *StringPtr != L'&') {
- StringPtr++;
- }
-
- if (*StringPtr == L'\0') {
- //
- // No request block is found.
- //
- StringPtr = NULL;
- }
- }
-
- //
- // If StringPtr != NULL, get the request elements.
- //
- if (StringPtr != NULL) {
- if (StrStr (StringPtr, L"&OFFSET=") != NULL) {
- RequestBlockArray = GetBlockElement (StringPtr, &Progress);
- } else {
- RequestBlockArray = GetNameElement (StringPtr, &Progress);
- }
-
- if (RequestBlockArray == NULL) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
- }
-
- //
- // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
- //
- DefaultIdArray = (IFR_DEFAULT_DATA *)AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
- if (DefaultIdArray == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- InitializeListHead (&DefaultIdArray->Entry);
-
- //
- // Initialize VarStorageData to store the var store Block and Default value information.
- //
- VarStorageData = (IFR_VARSTORAGE_DATA *)AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));
- if (VarStorageData == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- InitializeListHead (&VarStorageData->Entry);
- InitializeListHead (&VarStorageData->BlockEntry);
-
- //
- // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
- //
-
- //
- // Parse the opcode in form package to get the default setting.
- //
- Status = ParseIfrData (
- DataBaseRecord->Handle,
- HiiFormPackage,
- (UINT32)PackageSize,
- *Request,
- RequestBlockArray,
- VarStorageData,
- DefaultIdArray
- );
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- //
- // No requested varstore in IFR data and directly return
- //
- if ((VarStorageData->Type == 0) && (VarStorageData->Name == NULL)) {
- Status = EFI_SUCCESS;
- goto Done;
- }
-
- //
- // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
- //
- Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- if (RequestBlockArray == NULL) {
- if (!GenerateConfigRequest (ConfigHdr, VarStorageData, &Status, Request)) {
- goto Done;
- }
- }
-
- //
- // 4. Construct Default Value string in AltResp according to request element.
- // Go through all VarStorageData Entry and get the DefaultId array for each one
- // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
- //
- Status = GenerateAltConfigResp (DataBaseRecord->Handle, ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- //
- // 5. Merge string into the input AltCfgResp if the input *AltCfgResp is not NULL.
- //
- if ((*AltCfgResp != NULL) && (DefaultAltCfgResp != NULL)) {
- Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);
- FreePool (DefaultAltCfgResp);
- } else if (*AltCfgResp == NULL) {
- *AltCfgResp = DefaultAltCfgResp;
- }
-
-Done:
- if (RequestBlockArray != NULL) {
- //
- // Free Link Array RequestBlockArray
- //
- while (!IsListEmpty (&RequestBlockArray->Entry)) {
- BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
- RemoveEntryList (&BlockData->Entry);
- if (BlockData->Name != NULL) {
- FreePool (BlockData->Name);
- }
-
- FreePool (BlockData);
- }
-
- FreePool (RequestBlockArray);
- }
-
- if (VarStorageData != NULL) {
- //
- // Free link array VarStorageData
- //
- while (!IsListEmpty (&VarStorageData->BlockEntry)) {
- BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);
- RemoveEntryList (&BlockData->Entry);
- if (BlockData->Name != NULL) {
- FreePool (BlockData->Name);
- }
-
- //
- // Free default value link array
- //
- while (!IsListEmpty (&BlockData->DefaultValueEntry)) {
- DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);
- RemoveEntryList (&DefaultValueData->Entry);
- FreePool (DefaultValueData);
- }
-
- FreePool (BlockData);
- }
-
- if (VarStorageData->Name != NULL) {
- FreePool (VarStorageData->Name);
- VarStorageData->Name = NULL;
- }
-
- FreePool (VarStorageData);
- }
-
- if (DefaultIdArray != NULL) {
- //
- // Free DefaultId Array
- //
- while (!IsListEmpty (&DefaultIdArray->Entry)) {
- DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);
- RemoveEntryList (&DefaultId->Entry);
- FreePool (DefaultId);
- }
-
- FreePool (DefaultIdArray);
- }
-
- //
- // Free the allocated string
- //
- if (ConfigHdr != NULL) {
- FreePool (ConfigHdr);
- }
-
- //
- // Free Package data
- //
- if (HiiFormPackage != NULL) {
- FreePool (HiiFormPackage);
- }
-
- if (PointerProgress != NULL) {
- if (*Request == NULL) {
- *PointerProgress = NULL;
- } else if (EFI_ERROR (Status)) {
- *PointerProgress = *Request;
- } else {
- *PointerProgress = *Request + StrLen (*Request);
- }
- }
-
- return Status;
-}
-
-/**
- This function gets the full request resp string by
- parsing IFR data in HII form packages.
-
- @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
- instance.
- @param EfiVarStoreInfo The efi varstore info which is save in the EFI
- varstore data structure.
- @param Request Pointer to a null-terminated Unicode string in
- <ConfigRequest> format.
- @param RequestResp Pointer to a null-terminated Unicode string in
- <ConfigResp> format.
- @param AccessProgress On return, points to a character in the Request
- string. Points to the string's null terminator if
- 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.
-
- @retval EFI_SUCCESS The Results string is set to the full request string.
- And AltCfgResp contains all default value string.
- @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
- @retval EFI_INVALID_PARAMETER Request points to NULL.
-
-**/
-EFI_STATUS
-GetConfigRespFromEfiVarStore (
- IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
- IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
- IN EFI_STRING Request,
- OUT EFI_STRING *RequestResp,
- OUT EFI_STRING *AccessProgress
- )
-{
- EFI_STATUS Status;
- EFI_STRING VarStoreName;
- UINTN NameSize;
- UINT8 *VarStore;
- UINTN BufferSize;
-
- Status = EFI_SUCCESS;
- BufferSize = 0;
- VarStore = NULL;
- VarStoreName = NULL;
- *AccessProgress = Request;
-
- NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);
- VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
- if (VarStoreName == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- AsciiStrToUnicodeStrS ((CHAR8 *)EfiVarStoreInfo->Name, VarStoreName, NameSize);
-
- Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
- if (Status != EFI_BUFFER_TOO_SMALL) {
- goto Done;
- }
-
- VarStore = AllocateZeroPool (BufferSize);
- ASSERT (VarStore != NULL);
- Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- Status = HiiBlockToConfig (This, Request, VarStore, BufferSize, RequestResp, AccessProgress);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
-Done:
- if (VarStoreName != NULL) {
- FreePool (VarStoreName);
- }
-
- if (VarStore != NULL) {
- FreePool (VarStore);
- }
-
- return Status;
-}
-
-/**
- This function route the full request resp string for efi varstore.
-
- @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
- instance.
- @param EfiVarStoreInfo The efi varstore info which is save in the EFI
- varstore data structure.
- @param RequestResp Pointer to a null-terminated Unicode string in
- <ConfigResp> format.
- @param Result Pointer to a null-terminated Unicode string in
- <ConfigResp> format.
-
- @retval EFI_SUCCESS The Results string is set to the full request string.
- And AltCfgResp contains all default value string.
- @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
- @retval EFI_INVALID_PARAMETER Request points to NULL.
-
-**/
-EFI_STATUS
-RouteConfigRespForEfiVarStore (
- IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
- IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
- IN EFI_STRING RequestResp,
- OUT EFI_STRING *Result
- )
-{
- EFI_STATUS Status;
- EFI_STRING VarStoreName;
- UINTN NameSize;
- UINT8 *VarStore;
- UINTN BufferSize;
- UINTN BlockSize;
-
- Status = EFI_SUCCESS;
- BufferSize = 0;
- VarStore = NULL;
- VarStoreName = NULL;
- *Result = RequestResp;
-
- NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);
- VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
- if (VarStoreName == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- AsciiStrToUnicodeStrS ((CHAR8 *)EfiVarStoreInfo->Name, VarStoreName, NameSize);
-
- Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
- if (Status != EFI_BUFFER_TOO_SMALL) {
- DEBUG ((DEBUG_ERROR, "The variable does not exist!"));
- goto Done;
- }
-
- BlockSize = BufferSize;
- VarStore = AllocateZeroPool (BufferSize);
- ASSERT (VarStore != NULL);
- Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- Status = HiiConfigToBlock (This, RequestResp, VarStore, &BlockSize, Result);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);
- if (EFI_ERROR (Status)) {
- *Result = RequestResp;
- goto Done;
- }
-
-Done:
- if (VarStoreName != NULL) {
- FreePool (VarStoreName);
- }
-
- if (VarStore != NULL) {
- FreePool (VarStore);
- }
-
- return Status;
-}
-
-/**
- Validate the config request elements.
-
- @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
- without configHdr field.
-
- @retval CHAR16 * THE first Name/value pair not correct.
- @retval NULL Success parse the name/value pair
-**/
-CHAR16 *
-OffsetWidthValidate (
- CHAR16 *ConfigElements
- )
-{
- CHAR16 *StringPtr;
- CHAR16 *RetVal;
-
- StringPtr = ConfigElements;
-
- while (1) {
- RetVal = StringPtr;
- if (StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
- return RetVal;
- }
-
- while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
- StringPtr++;
- }
-
- if (*StringPtr == L'\0') {
- return RetVal;
- }
-
- StringPtr += StrLen (L"&WIDTH=");
- while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
- StringPtr++;
- }
-
- if (*StringPtr == L'\0') {
- return NULL;
- }
- }
-}
-
-/**
- Validate the config request elements.
-
- @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
- without configHdr field.
-
- @retval CHAR16 * THE first Name/value pair not correct.
- @retval NULL Success parse the name/value pair
-
-**/
-CHAR16 *
-NameValueValidate (
- CHAR16 *ConfigElements
- )
-{
- CHAR16 *StringPtr;
- CHAR16 *RetVal;
-
- StringPtr = ConfigElements;
-
- while (1) {
- RetVal = StringPtr;
- if (*StringPtr != L'&') {
- return RetVal;
- }
-
- StringPtr += 1;
-
- StringPtr = StrStr (StringPtr, L"&");
-
- if (StringPtr == NULL) {
- return NULL;
- }
- }
-}
-
-/**
- Validate the config request string.
-
- @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
-
- @retval CHAR16 * THE first element not correct.
- @retval NULL Success parse the name/value pair
-
-**/
-CHAR16 *
-ConfigRequestValidate (
- CHAR16 *ConfigRequest
- )
-{
- BOOLEAN HasNameField;
- CHAR16 *StringPtr;
-
- HasNameField = TRUE;
- StringPtr = ConfigRequest;
-
- //
- // Check <ConfigHdr>
- //
- if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
- return ConfigRequest;
- }
-
- StringPtr += StrLen (L"GUID=");
- while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
- StringPtr++;
- }
-
- if (*StringPtr == L'\0') {
- return ConfigRequest;
- }
-
- StringPtr += StrLen (L"&NAME=");
- if (*StringPtr == L'&') {
- HasNameField = FALSE;
- }
-
- while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
- StringPtr++;
- }
-
- if (*StringPtr == L'\0') {
- return ConfigRequest;
- }
-
- StringPtr += StrLen (L"&PATH=");
- while (*StringPtr != L'\0' && *StringPtr != L'&') {
- StringPtr++;
- }
-
- if (*StringPtr == L'\0') {
- return NULL;
- }
-
- if (HasNameField) {
- //
- // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
- //
- return OffsetWidthValidate (StringPtr);
- } else {
- //
- // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
- //
- return NameValueValidate (StringPtr);
- }
-}
-
-/**
- This function allows a caller to extract the current configuration
- for one or more named elements from one or more drivers.
-
- @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
- instance.
- @param Request A null-terminated Unicode string in
- <MultiConfigRequest> format.
- @param Progress On return, points to a character in the Request
- string. Points to the string's null terminator if
- 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 Results Null-terminated Unicode string in
- <MultiConfigAltResp> format which has all values
- filled in for the names in the Request string.
- String to be allocated by the called function.
-
- @retval EFI_SUCCESS The Results string is filled with the values
- corresponding to all requested names.
- @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
- results that must be stored awaiting possible
- future protocols.
- @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
- Progress set to the "G" in "GUID" of the routing
- header that doesn't match. Note: There is no
- requirement that all routing data be validated
- before any configuration extraction.
- @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
- parameter would result in this type of error. The
- Progress parameter is set to NULL.
- @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
- before the error or the beginning of the string.
- @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
- Configuration Access Protocol returned
- EFI_INVALID_PARAMETER. Progress set to most recent
- & before the error or the beginning of the string.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiConfigRoutingExtractConfig (
- IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
- IN CONST EFI_STRING Request,
- OUT EFI_STRING *Progress,
- OUT EFI_STRING *Results
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
- EFI_STRING StringPtr;
- EFI_STRING ConfigRequest;
- UINTN Length;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
- EFI_STATUS Status;
- LIST_ENTRY *Link;
- HII_DATABASE_RECORD *Database;
- UINT8 *DevicePathPkg;
- UINT8 *CurrentDevicePath;
- EFI_HANDLE DriverHandle;
- EFI_HII_HANDLE HiiHandle;
- EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
- EFI_STRING AccessProgress;
- EFI_STRING AccessResults;
- EFI_STRING AccessProgressBackup;
- EFI_STRING AccessResultsBackup;
- EFI_STRING DefaultResults;
- BOOLEAN FirstElement;
- BOOLEAN IfrDataParsedFlag;
- BOOLEAN IsEfiVarStore;
- EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
- EFI_STRING ErrorPtr;
- UINTN DevicePathSize;
- UINTN ConigStringSize;
- UINTN ConigStringSizeNewsize;
- EFI_STRING ConfigStringPtr;
-
- if ((This == NULL) || (Progress == NULL) || (Results == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Request == NULL) {
- *Progress = NULL;
- return EFI_INVALID_PARAMETER;
- }
-
- Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- StringPtr = Request;
- *Progress = StringPtr;
- DefaultResults = NULL;
- ConfigRequest = NULL;
- Status = EFI_SUCCESS;
- AccessResults = NULL;
- AccessProgress = NULL;
- AccessResultsBackup = NULL;
- AccessProgressBackup = NULL;
- DevicePath = NULL;
- IfrDataParsedFlag = FALSE;
- IsEfiVarStore = FALSE;
- EfiVarStoreInfo = NULL;
-
- //
- // The first element of <MultiConfigRequest> should be
- // <GuidHdr>, which is in 'GUID='<Guid> syntax.
- //
- if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- FirstElement = TRUE;
-
- //
- // Allocate a fix length of memory to store Results. Reallocate memory for
- // Results if this fix length is insufficient.
- //
- *Results = (EFI_STRING)AllocateZeroPool (MAX_STRING_LENGTH);
- if (*Results == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
- //
- // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
- // or most recent & before the error.
- //
- if (StringPtr == Request) {
- *Progress = StringPtr;
- } else {
- *Progress = StringPtr - 1;
- }
-
- //
- // Process each <ConfigRequest> of <MultiConfigRequest>
- //
- Length = CalculateConfigStringLen (StringPtr);
- ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
- if (ConfigRequest == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- *(ConfigRequest + Length) = 0;
-
- //
- // Get the UEFI device path
- //
- Status = GetDevicePath (ConfigRequest, (UINT8 **)&DevicePath);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- //
- // Find driver which matches the routing data.
- //
- DriverHandle = NULL;
- HiiHandle = NULL;
- Database = NULL;
- for (Link = Private->DatabaseList.ForwardLink;
- Link != &Private->DatabaseList;
- Link = Link->ForwardLink
- )
- {
- Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
- CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
- DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath);
- if ((CompareMem (DevicePath, CurrentDevicePath, DevicePathSize) == 0) && IsThisPackageList (Database, ConfigRequest)) {
- DriverHandle = Database->DriverHandle;
- HiiHandle = Database->Handle;
- break;
- }
- }
- }
-
- //
- // Try to find driver handle by device path.
- //
- if (DriverHandle == NULL) {
- TempDevicePath = DevicePath;
- Status = gBS->LocateDevicePath (
- &gEfiDevicePathProtocolGuid,
- &TempDevicePath,
- &DriverHandle
- );
- if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
- //
- // Routing data does not match any known driver.
- // Set Progress to the 'G' in "GUID" of the routing header.
- //
- *Progress = StringPtr;
- Status = EFI_NOT_FOUND;
- goto Done;
- }
- }
-
- //
- // Validate ConfigRequest String.
- //
- ErrorPtr = ConfigRequestValidate (ConfigRequest);
- if (ErrorPtr != NULL) {
- *Progress = StrStr (StringPtr, ErrorPtr);
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Check whether ConfigRequest contains request string.
- //
- IfrDataParsedFlag = FALSE;
- if ((HiiHandle != NULL) && !GetElementsFromRequest (ConfigRequest)) {
- //
- // Get the full request string from IFR when HiiPackage is registered to HiiHandle
- //
- IfrDataParsedFlag = TRUE;
- Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);
- if (EFI_ERROR (Status)) {
- //
- // AccessProgress indicates the parsing progress on <ConfigRequest>.
- // Map it to the progress on <MultiConfigRequest> then return it.
- //
- ASSERT (AccessProgress != NULL);
- *Progress = StrStr (StringPtr, AccessProgress);
- goto Done;
- }
-
- //
- // Not any request block is found.
- //
- if (!GetElementsFromRequest (ConfigRequest)) {
- AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
- goto NextConfigString;
- }
- }
-
- //
- // Check whether this ConfigRequest is search from Efi varstore type storage.
- //
- Status = GetVarStoreType (Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- if (IsEfiVarStore) {
- //
- // Call the GetVariable function to extract settings.
- //
- Status = GetConfigRespFromEfiVarStore (This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);
- FreePool (EfiVarStoreInfo);
- if (EFI_ERROR (Status)) {
- //
- // AccessProgress indicates the parsing progress on <ConfigRequest>.
- // Map it to the progress on <MultiConfigRequest> then return it.
- //
- *Progress = StrStr (StringPtr, AccessProgress);
- goto Done;
- }
-
- //
- // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
- //
- Status = gBS->HandleProtocol (
- DriverHandle,
- &gEfiHiiConfigAccessProtocolGuid,
- (VOID **)&ConfigAccess
- );
- if (EFI_ERROR (Status)) {
- //
- // The driver has EfiVarStore, may not install ConfigAccess protocol.
- // So ignore the error status in this case.
- //
- Status = EFI_SUCCESS;
- } else {
- Status = ConfigAccess->ExtractConfig (
- ConfigAccess,
- ConfigRequest,
- &AccessProgressBackup,
- &AccessResultsBackup
- );
- if (!EFI_ERROR (Status)) {
- //
- // Merge the AltCfgResp in AccessResultsBackup to AccessResults
- //
- if ((AccessResultsBackup != NULL) && (StrStr (AccessResultsBackup, L"&ALTCFG=") != NULL)) {
- ConigStringSize = StrSize (AccessResults);
- ConfigStringPtr = StrStr (AccessResultsBackup, L"&GUID=");
- ConigStringSizeNewsize = StrSize (ConfigStringPtr) + ConigStringSize + sizeof (CHAR16);
- AccessResults = (EFI_STRING)ReallocatePool (
- ConigStringSize,
- ConigStringSizeNewsize,
- AccessResults
- );
- StrCatS (AccessResults, ConigStringSizeNewsize / sizeof (CHAR16), ConfigStringPtr);
- }
- } else {
- //
- // In the ExtractConfig function of some driver may not support EfiVarStore,
- // may return error status, just ignore the error status in this case.
- //
- Status = EFI_SUCCESS;
- }
-
- if (AccessResultsBackup != NULL) {
- FreePool (AccessResultsBackup);
- AccessResultsBackup = NULL;
- }
- }
- } else {
- //
- // Call corresponding ConfigAccess protocol to extract settings
- //
- Status = gBS->HandleProtocol (
- DriverHandle,
- &gEfiHiiConfigAccessProtocolGuid,
- (VOID **)&ConfigAccess
- );
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- Status = ConfigAccess->ExtractConfig (
- ConfigAccess,
- ConfigRequest,
- &AccessProgress,
- &AccessResults
- );
- }
-
- if (EFI_ERROR (Status)) {
- //
- // AccessProgress indicates the parsing progress on <ConfigRequest>.
- // Map it to the progress on <MultiConfigRequest> then return it.
- //
- *Progress = StrStr (StringPtr, AccessProgress);
- goto Done;
- }
-
- //
- // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
- // which separates the first <ConfigAltResp> and the following ones.
- //
- ASSERT (*AccessProgress == 0);
-
- //
- // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
- //
- if (!IfrDataParsedFlag && (HiiHandle != NULL)) {
- Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
- ASSERT_EFI_ERROR (Status);
- }
-
- FreePool (DevicePath);
- DevicePath = NULL;
-
- if (DefaultResults != NULL) {
- Status = MergeDefaultString (&AccessResults, DefaultResults);
- ASSERT_EFI_ERROR (Status);
- FreePool (DefaultResults);
- DefaultResults = NULL;
- }
-
-NextConfigString:
- if (!FirstElement) {
- Status = AppendToMultiString (Results, L"&");
- ASSERT_EFI_ERROR (Status);
- }
-
- Status = AppendToMultiString (Results, AccessResults);
- ASSERT_EFI_ERROR (Status);
-
- FirstElement = FALSE;
-
- FreePool (AccessResults);
- AccessResults = NULL;
- FreePool (ConfigRequest);
- ConfigRequest = NULL;
-
- //
- // Go to next <ConfigRequest> (skip '&').
- //
- StringPtr += Length;
- if (*StringPtr == 0) {
- *Progress = StringPtr;
- break;
- }
-
- StringPtr++;
- }
-
-Done:
- if (EFI_ERROR (Status)) {
- FreePool (*Results);
- *Results = NULL;
- }
-
- if (ConfigRequest != NULL) {
- FreePool (ConfigRequest);
- }
-
- if (AccessResults != NULL) {
- FreePool (AccessResults);
- }
-
- if (DefaultResults != NULL) {
- FreePool (DefaultResults);
- }
-
- if (DevicePath != NULL) {
- FreePool (DevicePath);
- }
-
- return Status;
-}
-
-/**
- This function allows the caller to request the current configuration for the
- entirety of the current HII database and returns the data in a
- null-terminated Unicode string.
-
- @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
- instance.
- @param Results Null-terminated Unicode string in
- <MultiConfigAltResp> format which has all values
- filled in for the entirety of the current HII
- database. String to be allocated by the called
- function. De-allocation is up to the caller.
-
- @retval EFI_SUCCESS The Results string is filled with the values
- corresponding to all requested names.
- @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
- results that must be stored awaiting possible
- future protocols.
- @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
- parameter would result in this type of error.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiConfigRoutingExportConfig (
- IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
- OUT EFI_STRING *Results
- )
-{
- EFI_STATUS Status;
- EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
- EFI_STRING AccessResults;
- EFI_STRING Progress;
- EFI_STRING StringPtr;
- EFI_STRING ConfigRequest;
- UINTN Index;
- EFI_HANDLE *ConfigAccessHandles;
- UINTN NumberConfigAccessHandles;
- BOOLEAN FirstElement;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_HII_HANDLE HiiHandle;
- EFI_STRING DefaultResults;
- HII_DATABASE_PRIVATE_DATA *Private;
- LIST_ENTRY *Link;
- HII_DATABASE_RECORD *Database;
- UINT8 *DevicePathPkg;
- UINT8 *CurrentDevicePath;
- BOOLEAN IfrDataParsedFlag;
-
- if ((This == NULL) || (Results == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
-
- //
- // Allocate a fix length of memory to store Results. Reallocate memory for
- // Results if this fix length is insufficient.
- //
- *Results = (EFI_STRING)AllocateZeroPool (MAX_STRING_LENGTH);
- if (*Results == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- NumberConfigAccessHandles = 0;
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiHiiConfigAccessProtocolGuid,
- NULL,
- &NumberConfigAccessHandles,
- &ConfigAccessHandles
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- FirstElement = TRUE;
-
- for (Index = 0; Index < NumberConfigAccessHandles; Index++) {
- Status = gBS->HandleProtocol (
- ConfigAccessHandles[Index],
- &gEfiHiiConfigAccessProtocolGuid,
- (VOID **)&ConfigAccess
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- //
- // Get DevicePath and HiiHandle for this ConfigAccess driver handle
- //
- IfrDataParsedFlag = FALSE;
- Progress = NULL;
- HiiHandle = NULL;
- DefaultResults = NULL;
- Database = NULL;
- ConfigRequest = NULL;
- DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);
- if (DevicePath != NULL) {
- for (Link = Private->DatabaseList.ForwardLink;
- Link != &Private->DatabaseList;
- Link = Link->ForwardLink
- )
- {
- Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
- CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
- if (CompareMem (
- DevicePath,
- CurrentDevicePath,
- GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath)
- ) == 0)
- {
- HiiHandle = Database->Handle;
- break;
- }
- }
- }
- }
-
- Status = ConfigAccess->ExtractConfig (
- ConfigAccess,
- NULL,
- &Progress,
- &AccessResults
- );
- if (EFI_ERROR (Status)) {
- //
- // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
- //
- if ((HiiHandle != NULL) && (DevicePath != NULL)) {
- IfrDataParsedFlag = TRUE;
- Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
- //
- // Get the full request string to get the Current setting again.
- //
- if (!EFI_ERROR (Status) && (ConfigRequest != NULL)) {
- Status = ConfigAccess->ExtractConfig (
- ConfigAccess,
- ConfigRequest,
- &Progress,
- &AccessResults
- );
- FreePool (ConfigRequest);
- } else {
- Status = EFI_NOT_FOUND;
- }
- }
- }
-
- if (!EFI_ERROR (Status)) {
- //
- // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
- //
- if (!IfrDataParsedFlag && (HiiHandle != NULL) && (DevicePath != NULL)) {
- StringPtr = StrStr (AccessResults, L"&GUID=");
- if (StringPtr != NULL) {
- *StringPtr = 0;
- }
-
- if (GetElementsFromRequest (AccessResults)) {
- Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);
- ASSERT_EFI_ERROR (Status);
- }
-
- if (StringPtr != NULL) {
- *StringPtr = L'&';
- }
- }
-
- //
- // Merge the default sting from IFR code into the got setting from driver.
- //
- if (DefaultResults != NULL) {
- Status = MergeDefaultString (&AccessResults, DefaultResults);
- ASSERT_EFI_ERROR (Status);
- FreePool (DefaultResults);
- DefaultResults = NULL;
- }
-
- //
- // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
- // which separates the first <ConfigAltResp> and the following ones.
- //
- if (!FirstElement) {
- Status = AppendToMultiString (Results, L"&");
- ASSERT_EFI_ERROR (Status);
- }
-
- Status = AppendToMultiString (Results, AccessResults);
- ASSERT_EFI_ERROR (Status);
-
- FirstElement = FALSE;
-
- FreePool (AccessResults);
- AccessResults = NULL;
- }
- }
-
- FreePool (ConfigAccessHandles);
-
- return EFI_SUCCESS;
-}
-
-/**
- This function processes the results of processing forms and routes it to the
- appropriate handlers or storage.
-
- @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
- instance.
- @param Configuration A null-terminated Unicode string in
- <MulltiConfigResp> format.
- @param Progress A pointer to a string filled in with the offset of
- 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) or the
- terminating NULL if all was successful.
-
- @retval EFI_SUCCESS The results have been distributed or are awaiting
- distribution.
- @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
- results that must be stored awaiting possible
- future protocols.
- @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
- would result in this type of error.
- @retval EFI_NOT_FOUND Target for the specified routing data was not
- found.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiConfigRoutingRouteConfig (
- IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
- IN CONST EFI_STRING Configuration,
- OUT EFI_STRING *Progress
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
- EFI_STRING StringPtr;
- EFI_STRING ConfigResp;
- UINTN Length;
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
- LIST_ENTRY *Link;
- HII_DATABASE_RECORD *Database;
- UINT8 *DevicePathPkg;
- UINT8 *CurrentDevicePath;
- EFI_HANDLE DriverHandle;
- EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
- EFI_STRING AccessProgress;
- EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
- BOOLEAN IsEfiVarstore;
- UINTN DevicePathSize;
-
- if ((This == NULL) || (Progress == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Configuration == NULL) {
- *Progress = NULL;
- return EFI_INVALID_PARAMETER;
- }
-
- Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- StringPtr = Configuration;
- *Progress = StringPtr;
- Database = NULL;
- AccessProgress = NULL;
- EfiVarStoreInfo = NULL;
- IsEfiVarstore = FALSE;
-
- //
- // The first element of <MultiConfigResp> should be
- // <GuidHdr>, which is in 'GUID='<Guid> syntax.
- //
- if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
- //
- // If parsing error, set Progress to the beginning of the <MultiConfigResp>
- // or most recent & before the error.
- //
- if (StringPtr == Configuration) {
- *Progress = StringPtr;
- } else {
- *Progress = StringPtr - 1;
- }
-
- //
- // Process each <ConfigResp> of <MultiConfigResp>
- //
- Length = CalculateConfigStringLen (StringPtr);
- ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
- if (ConfigResp == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Append '\0' to the end of ConfigRequest
- //
- *(ConfigResp + Length) = 0;
-
- //
- // Get the UEFI device path
- //
- Status = GetDevicePath (ConfigResp, (UINT8 **)&DevicePath);
- if (EFI_ERROR (Status)) {
- FreePool (ConfigResp);
- return Status;
- }
-
- //
- // Find driver which matches the routing data.
- //
- DriverHandle = NULL;
- for (Link = Private->DatabaseList.ForwardLink;
- Link != &Private->DatabaseList;
- Link = Link->ForwardLink
- )
- {
- Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
-
- if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
- CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
- DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath);
- if ((CompareMem (DevicePath, CurrentDevicePath, DevicePathSize) == 0) && IsThisPackageList (Database, ConfigResp)) {
- DriverHandle = Database->DriverHandle;
- break;
- }
- }
- }
-
- //
- // Try to find driver handle by device path.
- //
- if (DriverHandle == NULL) {
- TempDevicePath = DevicePath;
- Status = gBS->LocateDevicePath (
- &gEfiDevicePathProtocolGuid,
- &TempDevicePath,
- &DriverHandle
- );
- if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
- //
- // Routing data does not match any known driver.
- // Set Progress to the 'G' in "GUID" of the routing header.
- //
- FreePool (DevicePath);
- *Progress = StringPtr;
- FreePool (ConfigResp);
- return EFI_NOT_FOUND;
- }
- }
-
- FreePool (DevicePath);
-
- //
- // Check whether this ConfigRequest is search from Efi varstore type storage.
- //
- Status = GetVarStoreType (Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (IsEfiVarstore) {
- //
- // Call the SetVariable function to route settings.
- //
- Status = RouteConfigRespForEfiVarStore (This, EfiVarStoreInfo, ConfigResp, &AccessProgress);
- FreePool (EfiVarStoreInfo);
- } else {
- //
- // Call corresponding ConfigAccess protocol to route settings
- //
- Status = gBS->HandleProtocol (
- DriverHandle,
- &gEfiHiiConfigAccessProtocolGuid,
- (VOID **)&ConfigAccess
- );
- if (EFI_ERROR (Status)) {
- *Progress = StringPtr;
- FreePool (ConfigResp);
- return EFI_NOT_FOUND;
- }
-
- Status = ConfigAccess->RouteConfig (
- ConfigAccess,
- ConfigResp,
- &AccessProgress
- );
- }
-
- if (EFI_ERROR (Status)) {
- ASSERT (AccessProgress != NULL);
- //
- // AccessProgress indicates the parsing progress on <ConfigResp>.
- // Map it to the progress on <MultiConfigResp> then return it.
- //
- *Progress = StrStr (StringPtr, AccessProgress);
-
- FreePool (ConfigResp);
- return Status;
- }
-
- FreePool (ConfigResp);
- ConfigResp = NULL;
-
- //
- // Go to next <ConfigResp> (skip '&').
- //
- StringPtr += Length;
- if (*StringPtr == 0) {
- *Progress = StringPtr;
- break;
- }
-
- StringPtr++;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This helper function is to be called by drivers to map configuration data
- stored in byte array ("block") formats such as UEFI Variables into current
- configuration strings.
-
- @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
- instance.
- @param ConfigRequest A null-terminated Unicode string in
- <ConfigRequest> format.
- @param Block Array of bytes defining the block's configuration.
- @param BlockSize Length in bytes of Block.
- @param Config Filled-in configuration string. String allocated
- by the function. Returned only if call is
- successful. It is <ConfigResp> string format.
- @param Progress A pointer to a string filled in with the offset of
- 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) or
- the terminating NULL if all was successful.
-
- @retval EFI_SUCCESS The request succeeded. Progress points to the null
- terminator at the end of the ConfigRequest
- string.
- @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
- points to the first character of ConfigRequest.
- @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
- Block parameter would result in this type of
- error. Progress points to the first character of
- ConfigRequest.
- @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
- @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
- Block is left updated and Progress points at
- the "&" preceding the first non-<BlockName>.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiBlockToConfig (
- IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
- IN CONST EFI_STRING ConfigRequest,
- IN CONST UINT8 *Block,
- IN CONST UINTN BlockSize,
- OUT EFI_STRING *Config,
- OUT EFI_STRING *Progress
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
- EFI_STRING StringPtr;
- UINTN Length;
- EFI_STATUS Status;
- EFI_STRING TmpPtr;
- UINT8 *TmpBuffer;
- UINTN Offset;
- UINTN Width;
- UINT8 *Value;
- EFI_STRING ValueStr;
- EFI_STRING ConfigElement;
- UINTN Index;
- UINT8 *TemBuffer;
- CHAR16 *TemString;
-
- TmpBuffer = NULL;
-
- if ((This == NULL) || (Progress == NULL) || (Config == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((Block == NULL) || (ConfigRequest == NULL)) {
- *Progress = ConfigRequest;
- return EFI_INVALID_PARAMETER;
- }
-
- Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- ASSERT (Private != NULL);
-
- StringPtr = ConfigRequest;
- ValueStr = NULL;
- Value = NULL;
- ConfigElement = NULL;
-
- //
- // Allocate a fix length of memory to store Results. Reallocate memory for
- // Results if this fix length is insufficient.
- //
- *Config = (EFI_STRING)AllocateZeroPool (MAX_STRING_LENGTH);
- if (*Config == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Jump <ConfigHdr>
- //
- if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
- *Progress = StringPtr;
- Status = EFI_INVALID_PARAMETER;
- goto Exit;
- }
-
- while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
- StringPtr++;
- }
-
- if (*StringPtr == 0) {
- *Progress = StringPtr - 1;
- Status = EFI_INVALID_PARAMETER;
- goto Exit;
- }
-
- while (*StringPtr != L'&' && *StringPtr != 0) {
- StringPtr++;
- }
-
- if (*StringPtr == 0) {
- *Progress = StringPtr;
-
- AppendToMultiString (Config, ConfigRequest);
- HiiToLower (*Config);
-
- return EFI_SUCCESS;
- }
-
- //
- // Skip '&'
- //
- StringPtr++;
-
- //
- // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
- //
- TemString = AllocateCopyPool (sizeof (CHAR16) * (StringPtr - ConfigRequest + 1), ConfigRequest);
- if (TemString == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- TemString[StringPtr - ConfigRequest] = '\0';
- AppendToMultiString (Config, TemString);
- FreePool (TemString);
-
- //
- // Parse each <RequestElement> if exists
- // Only <BlockName> format is supported by this help function.
- // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
- //
- while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
- //
- // Back up the header of one <BlockName>
- //
- TmpPtr = StringPtr;
-
- StringPtr += StrLen (L"OFFSET=");
- //
- // Get Offset
- //
- Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
- if (EFI_ERROR (Status)) {
- *Progress = TmpPtr - 1;
- goto Exit;
- }
-
- Offset = 0;
- CopyMem (
- &Offset,
- TmpBuffer,
- (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
- );
- FreePool (TmpBuffer);
-
- StringPtr += Length;
- if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
- *Progress = TmpPtr - 1;
- Status = EFI_INVALID_PARAMETER;
- goto Exit;
- }
-
- StringPtr += StrLen (L"&WIDTH=");
-
- //
- // Get Width
- //
- Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
- if (EFI_ERROR (Status)) {
- *Progress = TmpPtr - 1;
- goto Exit;
- }
-
- Width = 0;
- CopyMem (
- &Width,
- TmpBuffer,
- (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
- );
- FreePool (TmpBuffer);
-
- StringPtr += Length;
- if ((*StringPtr != 0) && (*StringPtr != L'&')) {
- *Progress = TmpPtr - 1;
- Status = EFI_INVALID_PARAMETER;
- goto Exit;
- }
-
- //
- // Calculate Value and convert it to hex string.
- //
- if (Offset + Width > BlockSize) {
- *Progress = StringPtr;
- Status = EFI_DEVICE_ERROR;
- goto Exit;
- }
-
- Value = (UINT8 *)AllocateZeroPool (Width);
- if (Value == NULL) {
- *Progress = ConfigRequest;
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- CopyMem (Value, (UINT8 *)Block + Offset, Width);
-
- Length = Width * 2 + 1;
- ValueStr = (EFI_STRING)AllocateZeroPool (Length * sizeof (CHAR16));
- if (ValueStr == NULL) {
- *Progress = ConfigRequest;
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- TemString = ValueStr;
- TemBuffer = Value + Width - 1;
- for (Index = 0; Index < Width; Index++, TemBuffer--) {
- UnicodeValueToStringS (
- TemString,
- Length * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ValueStr),
- PREFIX_ZERO | RADIX_HEX,
- *TemBuffer,
- 2
- );
- TemString += StrnLenS (TemString, Length - ((UINTN)TemString - (UINTN)ValueStr) / sizeof (CHAR16));
- }
-
- FreePool (Value);
- Value = NULL;
-
- //
- // Build a ConfigElement
- //
- Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");
- ConfigElement = (EFI_STRING)AllocateZeroPool (Length * sizeof (CHAR16));
- if (ConfigElement == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));
- if (*StringPtr == 0) {
- *(ConfigElement + (StringPtr - TmpPtr)) = L'&';
- }
-
- *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;
- StrCatS (ConfigElement, Length, L"VALUE=");
- StrCatS (ConfigElement, Length, ValueStr);
-
- AppendToMultiString (Config, ConfigElement);
-
- FreePool (ConfigElement);
- FreePool (ValueStr);
- ConfigElement = NULL;
- ValueStr = NULL;
-
- //
- // If '\0', parsing is finished. Otherwise skip '&' to continue
- //
- if (*StringPtr == 0) {
- break;
- }
-
- AppendToMultiString (Config, L"&");
- StringPtr++;
- }
-
- if (*StringPtr != 0) {
- *Progress = StringPtr - 1;
- Status = EFI_INVALID_PARAMETER;
- goto Exit;
- }
-
- HiiToLower (*Config);
- *Progress = StringPtr;
- return EFI_SUCCESS;
-
-Exit:
- if (*Config != NULL) {
- FreePool (*Config);
- *Config = NULL;
- }
-
- if (ValueStr != NULL) {
- FreePool (ValueStr);
- }
-
- if (Value != NULL) {
- FreePool (Value);
- }
-
- if (ConfigElement != NULL) {
- FreePool (ConfigElement);
- }
-
- return Status;
-}
-
-/**
- This helper function is to be called by drivers to map configuration strings
- to configurations stored in byte array ("block") formats such as UEFI Variables.
-
- @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
- instance.
- @param ConfigResp A null-terminated Unicode string in <ConfigResp>
- format.
- @param Block A possibly null array of bytes representing the
- current block. Only bytes referenced in the
- ConfigResp string in the block are modified. If
- this parameter is null or if the *BlockSize
- parameter is (on input) shorter than required by
- the Configuration string, only the BlockSize
- parameter is updated and an appropriate status
- (see below) is returned.
- @param BlockSize The length of the Block in units of UINT8. On
- input, this is the size of the Block. On output,
- if successful, contains the largest index of the
- modified byte in the Block, or the required buffer
- size if the Block is not large enough.
- @param Progress On return, points to an element of the ConfigResp
- string filled in with the offset of 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) or the
- terminating NULL if all was successful.
-
- @retval EFI_SUCCESS The request succeeded. Progress points to the null
- terminator at the end of the ConfigResp string.
- @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
- points to the first character of ConfigResp.
- @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
- Block parameter would result in this type of
- error. Progress points to the first character of
- ConfigResp.
- @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
- value pair. Block is left updated and
- Progress points at the '&' preceding the first
- non-<BlockName>.
- @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
- BlockSize is updated with the required buffer size.
- @retval EFI_NOT_FOUND Target for the specified routing data was not found.
- Progress points to the "G" in "GUID" of the errant
- routing data.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiConfigToBlock (
- IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
- IN CONST EFI_STRING ConfigResp,
- IN OUT UINT8 *Block,
- IN OUT UINTN *BlockSize,
- OUT EFI_STRING *Progress
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
- EFI_STRING StringPtr;
- EFI_STRING TmpPtr;
- UINTN Length;
- EFI_STATUS Status;
- UINT8 *TmpBuffer;
- UINTN Offset;
- UINTN Width;
- UINT8 *Value;
- UINTN BufferSize;
- UINTN MaxBlockSize;
-
- TmpBuffer = NULL;
-
- if ((This == NULL) || (BlockSize == NULL) || (Progress == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- *Progress = ConfigResp;
- if (ConfigResp == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- ASSERT (Private != NULL);
-
- StringPtr = ConfigResp;
- BufferSize = *BlockSize;
- Value = NULL;
- MaxBlockSize = 0;
-
- //
- // Jump <ConfigHdr>
- //
- if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
- *Progress = StringPtr;
- Status = EFI_INVALID_PARAMETER;
- goto Exit;
- }
-
- while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
- StringPtr++;
- }
-
- if (*StringPtr == 0) {
- *Progress = StringPtr;
- Status = EFI_INVALID_PARAMETER;
- goto Exit;
- }
-
- while (*StringPtr != L'&' && *StringPtr != 0) {
- StringPtr++;
- }
-
- if (*StringPtr == 0) {
- *Progress = StringPtr;
- Status = EFI_INVALID_PARAMETER;
- goto Exit;
- }
-
- //
- // Parse each <ConfigElement> if exists
- // Only '&'<BlockConfig> format is supported by this help function.
- // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
- //
- while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
- TmpPtr = StringPtr;
- StringPtr += StrLen (L"&OFFSET=");
- //
- // Get Offset
- //
- Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
- if (EFI_ERROR (Status)) {
- *Progress = TmpPtr;
- goto Exit;
- }
-
- Offset = 0;
- CopyMem (
- &Offset,
- TmpBuffer,
- (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
- );
- FreePool (TmpBuffer);
-
- StringPtr += Length;
- if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
- *Progress = TmpPtr;
- Status = EFI_INVALID_PARAMETER;
- goto Exit;
- }
-
- StringPtr += StrLen (L"&WIDTH=");
-
- //
- // Get Width
- //
- Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
- if (EFI_ERROR (Status)) {
- *Progress = TmpPtr;
- goto Exit;
- }
-
- Width = 0;
- CopyMem (
- &Width,
- TmpBuffer,
- (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
- );
- FreePool (TmpBuffer);
-
- StringPtr += Length;
- if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
- *Progress = TmpPtr;
- Status = EFI_INVALID_PARAMETER;
- goto Exit;
- }
-
- StringPtr += StrLen (L"&VALUE=");
-
- //
- // Get Value
- //
- Status = GetValueOfNumber (StringPtr, &Value, &Length);
- if (EFI_ERROR (Status)) {
- *Progress = TmpPtr;
- goto Exit;
- }
-
- StringPtr += Length;
- if ((*StringPtr != 0) && (*StringPtr != L'&')) {
- *Progress = TmpPtr;
- Status = EFI_INVALID_PARAMETER;
- goto Exit;
- }
-
- //
- // Update the Block with configuration info
- //
- if ((Block != NULL) && (Offset + Width <= BufferSize)) {
- CopyMem (Block + Offset, Value, Width);
- }
-
- if (Offset + Width > MaxBlockSize) {
- MaxBlockSize = Offset + Width;
- }
-
- FreePool (Value);
- Value = NULL;
-
- //
- // If '\0', parsing is finished.
- //
- if (*StringPtr == 0) {
- break;
- }
- }
-
- //
- // The input string is not ConfigResp format, return error.
- //
- if (*StringPtr != 0) {
- *Progress = StringPtr;
- Status = EFI_INVALID_PARAMETER;
- goto Exit;
- }
-
- *Progress = StringPtr + StrLen (StringPtr);
- *BlockSize = MaxBlockSize - 1;
-
- if (MaxBlockSize > BufferSize) {
- *BlockSize = MaxBlockSize;
- if (Block != NULL) {
- return EFI_BUFFER_TOO_SMALL;
- }
- }
-
- if (Block == NULL) {
- *Progress = ConfigResp;
- return EFI_INVALID_PARAMETER;
- }
-
- return EFI_SUCCESS;
-
-Exit:
-
- if (Value != NULL) {
- FreePool (Value);
- }
-
- return Status;
-}
-
-/**
- This helper function is to be called by drivers to extract portions of
- a larger configuration string.
-
- @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
- instance.
- @param Configuration A null-terminated Unicode string in
- <MultiConfigAltResp> format.
- @param Guid A pointer to the GUID value to search for in the
- routing portion of the ConfigResp string when
- retrieving the requested data. If Guid is NULL,
- then all GUID values will be searched for.
- @param Name A pointer to the NAME value to search for in the
- routing portion of the ConfigResp string when
- retrieving the requested data. If Name is NULL,
- then all Name values will be searched for.
- @param DevicePath A pointer to the PATH value to search for in the
- routing portion of the ConfigResp string when
- retrieving the requested data. If DevicePath is
- NULL, then all DevicePath values will be searched
- for.
- @param AltCfgId A pointer to the ALTCFG value to search for in the
- routing portion of the ConfigResp string when
- retrieving the requested data. If this parameter
- is NULL, then the current setting will be
- retrieved.
- @param AltCfgResp A pointer to a buffer which will be allocated by
- the function which contains the retrieved string
- as requested. This buffer is only allocated if
- the call was successful. It is <ConfigResp> format.
-
- @retval EFI_SUCCESS The request succeeded. The requested data was
- extracted and placed in the newly allocated
- AltCfgResp buffer.
- @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
- @retval EFI_INVALID_PARAMETER Any parameter is invalid.
- @retval EFI_NOT_FOUND Target for the specified routing data was not
- found.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetAltCfg (
- IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
- IN CONST EFI_STRING Configuration,
- IN CONST EFI_GUID *Guid,
- IN CONST EFI_STRING Name,
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- IN CONST UINT16 *AltCfgId,
- OUT EFI_STRING *AltCfgResp
- )
-{
- EFI_STATUS Status;
- EFI_STRING StringPtr;
- EFI_STRING HdrStart;
- EFI_STRING HdrEnd;
- EFI_STRING TmpPtr;
- UINTN Length;
- EFI_STRING GuidStr;
- EFI_STRING NameStr;
- EFI_STRING PathStr;
- EFI_STRING AltIdStr;
- EFI_STRING Result;
- BOOLEAN GuidFlag;
- BOOLEAN NameFlag;
- BOOLEAN PathFlag;
-
- HdrStart = NULL;
- HdrEnd = NULL;
- GuidStr = NULL;
- NameStr = NULL;
- PathStr = NULL;
- AltIdStr = NULL;
- Result = NULL;
- GuidFlag = FALSE;
- NameFlag = FALSE;
- PathFlag = FALSE;
-
- if ((This == NULL) || (Configuration == NULL) || (AltCfgResp == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- StringPtr = Configuration;
- if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Generate the sub string for later matching.
- //
- GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)Guid, 1, &GuidStr);
- GenerateSubStr (
- L"PATH=",
- GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DevicePath),
- (VOID *)DevicePath,
- 1,
- &PathStr
- );
- if (AltCfgId != NULL) {
- GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *)AltCfgId, 3, &AltIdStr);
- }
-
- if (Name != NULL) {
- GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *)Name, 2, &NameStr);
- } else {
- GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
- }
-
- while (*StringPtr != 0) {
- //
- // Try to match the GUID
- //
- if (!GuidFlag) {
- TmpPtr = StrStr (StringPtr, GuidStr);
- if (TmpPtr == NULL) {
- Status = EFI_NOT_FOUND;
- goto Exit;
- }
-
- HdrStart = TmpPtr;
-
- //
- // Jump to <NameHdr>
- //
- if (Guid != NULL) {
- StringPtr = TmpPtr + StrLen (GuidStr);
- } else {
- StringPtr = StrStr (TmpPtr, L"NAME=");
- if (StringPtr == NULL) {
- Status = EFI_NOT_FOUND;
- goto Exit;
- }
- }
-
- GuidFlag = TRUE;
- }
-
- //
- // Try to match the NAME
- //
- if (GuidFlag && !NameFlag) {
- if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {
- GuidFlag = FALSE;
- } else {
- //
- // Jump to <PathHdr>
- //
- if (Name != NULL) {
- StringPtr += StrLen (NameStr);
- } else {
- StringPtr = StrStr (StringPtr, L"PATH=");
- if (StringPtr == NULL) {
- Status = EFI_NOT_FOUND;
- goto Exit;
- }
- }
-
- NameFlag = TRUE;
- }
- }
-
- //
- // Try to match the DevicePath
- //
- if (GuidFlag && NameFlag && !PathFlag) {
- if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {
- GuidFlag = FALSE;
- NameFlag = FALSE;
- } else {
- //
- // Jump to '&' before <DescHdr> or <ConfigBody>
- //
- if (DevicePath != NULL) {
- StringPtr += StrLen (PathStr);
- } else {
- StringPtr = StrStr (StringPtr, L"&");
- if (StringPtr == NULL) {
- Status = EFI_NOT_FOUND;
- goto Exit;
- }
-
- StringPtr++;
- }
-
- PathFlag = TRUE;
- HdrEnd = StringPtr;
- }
- }
-
- //
- // Try to match the AltCfgId
- //
- if (GuidFlag && NameFlag && PathFlag) {
- if (AltCfgId == NULL) {
- //
- // Return Current Setting when AltCfgId is NULL.
- //
- Status = OutputConfigBody (StringPtr, &Result);
- goto Exit;
- }
-
- //
- // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
- //
- if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {
- GuidFlag = FALSE;
- NameFlag = FALSE;
- PathFlag = FALSE;
- } else {
- //
- // Skip AltIdStr and &
- //
- StringPtr = StringPtr + StrLen (AltIdStr);
- Status = OutputConfigBody (StringPtr, &Result);
- goto Exit;
- }
- }
- }
-
- Status = EFI_NOT_FOUND;
-
-Exit:
- *AltCfgResp = NULL;
- if (!EFI_ERROR (Status) && (Result != NULL)) {
- //
- // Copy the <ConfigHdr> and <ConfigBody>
- //
- Length = HdrEnd - HdrStart + StrLen (Result) + 1;
- *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
- if (*AltCfgResp == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- } else {
- StrnCpyS (*AltCfgResp, Length, HdrStart, HdrEnd - HdrStart);
- StrCatS (*AltCfgResp, Length, Result);
- Status = EFI_SUCCESS;
- }
- }
-
- if (GuidStr != NULL) {
- FreePool (GuidStr);
- }
-
- if (NameStr != NULL) {
- FreePool (NameStr);
- }
-
- if (PathStr != NULL) {
- FreePool (PathStr);
- }
-
- if (AltIdStr != NULL) {
- FreePool (AltIdStr);
- }
-
- if (Result != NULL) {
- FreePool (Result);
- }
-
- return Status;
-}
+/** @file
+Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
+
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "HiiDatabase.h"
+extern HII_DATABASE_PRIVATE_DATA mPrivate;
+
+/**
+ Calculate the number of Unicode characters of the incoming Configuration string,
+ not including NULL terminator.
+
+ This is a internal function.
+
+ @param String String in <MultiConfigRequest> or
+ <MultiConfigResp> format.
+
+ @return The number of Unicode characters.
+
+**/
+UINTN
+CalculateConfigStringLen (
+ IN EFI_STRING String
+ )
+{
+ EFI_STRING TmpPtr;
+
+ //
+ // "GUID=" should be the first element of incoming string.
+ //
+ ASSERT (String != NULL);
+ ASSERT (StrnCmp (String, L"GUID=", StrLen (L"GUID=")) == 0);
+
+ //
+ // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
+ // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
+ //
+ TmpPtr = StrStr (String, L"&GUID=");
+ if (TmpPtr == NULL) {
+ return StrLen (String);
+ }
+
+ return (TmpPtr - String);
+}
+
+/**
+ Convert the hex UNICODE %02x encoding of a UEFI device path to binary
+ from <PathHdr> of <ConfigHdr>.
+
+ This is a internal function.
+
+ @param String UEFI configuration string
+ @param DevicePathData Binary of a UEFI device path.
+
+ @retval EFI_NOT_FOUND The device path is not invalid.
+ @retval EFI_INVALID_PARAMETER Any 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.
+
+**/
+EFI_STATUS
+GetDevicePath (
+ IN EFI_STRING String,
+ OUT UINT8 **DevicePathData
+ )
+{
+ UINTN Length;
+ EFI_STRING PathHdr;
+ UINT8 *DevicePathBuffer;
+ CHAR16 TemStr[2];
+ UINTN Index;
+ UINT8 DigitUint8;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ if ((String == NULL) || (DevicePathData == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Find the 'PATH=' of <PathHdr> and skip it.
+ //
+ for ( ; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++) {
+ }
+
+ if (*String == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // 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++) {
+ }
+
+ //
+ // Check DevicePath Length
+ //
+ if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // 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_NOT_FOUND;
+ }
+
+ DevicePath = NextDevicePathNode (DevicePath);
+ }
+
+ //
+ // return the device path
+ //
+ *DevicePathData = DevicePathBuffer;
+ return EFI_SUCCESS;
+}
+
+/**
+ Converts the unicode character of the string from uppercase to lowercase.
+ This is a internal function.
+
+ @param ConfigString String to be converted
+
+**/
+VOID
+EFIAPI
+HiiToLower (
+ 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;
+}
+
+/**
+ Generate a sub string then output it.
+
+ This is a internal function.
+
+ @param String A constant string which is the prefix of the to be
+ generated string, e.g. GUID=
+
+ @param BufferLen The length of the Buffer in bytes.
+
+ @param Buffer Points to a buffer which will be converted to be the
+ content of the generated string.
+
+ @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
+ UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
+ if 3, the buffer contains other data.
+
+ @param SubStr Points to the output string. It's caller's
+ responsibility to free this buffer.
+
+
+**/
+VOID
+GenerateSubStr (
+ IN CONST EFI_STRING String,
+ IN UINTN BufferLen,
+ IN VOID *Buffer,
+ IN UINT8 Flag,
+ OUT EFI_STRING *SubStr
+ )
+{
+ UINTN Length;
+ EFI_STRING Str;
+ EFI_STRING StringHeader;
+ CHAR16 *TemString;
+ CHAR16 *TemName;
+ UINT8 *TemBuffer;
+ UINTN Index;
+
+ ASSERT (String != NULL && SubStr != NULL);
+
+ if (Buffer == NULL) {
+ *SubStr = AllocateCopyPool (StrSize (String), String);
+ ASSERT (*SubStr != NULL);
+ return;
+ }
+
+ //
+ // Header + Data + '&' + '\0'
+ //
+ Length = StrLen (String) + BufferLen * 2 + 1 + 1;
+ Str = AllocateZeroPool (Length * sizeof (CHAR16));
+ ASSERT (Str != NULL);
+
+ StrCpyS (Str, Length, String);
+
+ StringHeader = Str + StrLen (String);
+ TemString = (CHAR16 *)StringHeader;
+
+ switch (Flag) {
+ case 1:
+ //
+ // Convert Buffer to Hex String in reverse order
+ //
+ TemBuffer = ((UINT8 *)Buffer);
+ for (Index = 0; Index < BufferLen; Index++, TemBuffer++) {
+ UnicodeValueToStringS (
+ TemString,
+ sizeof (CHAR16) * (Length - StrnLenS (Str, Length)),
+ PREFIX_ZERO | RADIX_HEX,
+ *TemBuffer,
+ 2
+ );
+ TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length));
+ }
+
+ break;
+ case 2:
+ //
+ // Check buffer is enough
+ //
+ TemName = (CHAR16 *)Buffer;
+ ASSERT ((BufferLen * 2 + 1) >= (StrLen (TemName) * 4 + 1));
+ //
+ // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
+ //
+ for ( ; *TemName != L'\0'; TemName++) {
+ UnicodeValueToStringS (
+ TemString,
+ sizeof (CHAR16) * (Length - StrnLenS (Str, Length)),
+ PREFIX_ZERO | RADIX_HEX,
+ *TemName,
+ 4
+ );
+ TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length));
+ }
+
+ break;
+ case 3:
+ //
+ // Convert Buffer to Hex String
+ //
+ TemBuffer = ((UINT8 *)Buffer) + BufferLen - 1;
+ for (Index = 0; Index < BufferLen; Index++, TemBuffer--) {
+ UnicodeValueToStringS (
+ TemString,
+ sizeof (CHAR16) * (Length - StrnLenS (Str, Length)),
+ PREFIX_ZERO | RADIX_HEX,
+ *TemBuffer,
+ 2
+ );
+ TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length));
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ //
+ // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
+ //
+ StrCatS (Str, Length, L"&");
+ HiiToLower (Str);
+
+ *SubStr = Str;
+}
+
+/**
+ Retrieve the <ConfigBody> from String then output it.
+
+ This is a internal function.
+
+ @param String A sub string of a configuration string in
+ <MultiConfigAltResp> format.
+ @param ConfigBody Points to the output string. It's caller's
+ responsibility to free this buffer.
+
+ @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
+ @retval EFI_SUCCESS All existing storage is exported.
+
+**/
+EFI_STATUS
+OutputConfigBody (
+ IN EFI_STRING String,
+ OUT EFI_STRING *ConfigBody
+ )
+{
+ EFI_STRING TmpPtr;
+ EFI_STRING Result;
+ UINTN Length;
+
+ if ((String == NULL) || (ConfigBody == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // The setting information should start OFFSET, not ALTCFG.
+ //
+ if (StrnCmp (String, L"&ALTCFG=", StrLen (L"&ALTCFG=")) == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TmpPtr = StrStr (String, L"GUID=");
+ if (TmpPtr == NULL) {
+ //
+ // It is the last <ConfigResp> of the incoming configuration string.
+ //
+ Result = AllocateCopyPool (StrSize (String), String);
+ if (Result == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ } else {
+ *ConfigBody = Result;
+ return EFI_SUCCESS;
+ }
+ }
+
+ Length = TmpPtr - String;
+ if (Length == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ Result = AllocateCopyPool (Length * sizeof (CHAR16), String);
+ if (Result == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *(Result + Length - 1) = 0;
+ *ConfigBody = Result;
+ return EFI_SUCCESS;
+}
+
+/**
+ Append a string to a multi-string format.
+
+ This is a internal function.
+
+ @param MultiString String in <MultiConfigRequest>,
+ <MultiConfigAltResp>, or <MultiConfigResp>. On
+ input, the buffer length of this string is
+ MAX_STRING_LENGTH. On output, the buffer length
+ might be updated.
+ @param AppendString NULL-terminated Unicode string.
+
+ @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
+ @retval EFI_SUCCESS AppendString is append to the end of MultiString
+
+**/
+EFI_STATUS
+AppendToMultiString (
+ IN OUT EFI_STRING *MultiString,
+ IN EFI_STRING AppendString
+ )
+{
+ UINTN AppendStringSize;
+ UINTN MultiStringSize;
+ UINTN MaxLen;
+
+ if ((MultiString == NULL) || (*MultiString == NULL) || (AppendString == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AppendStringSize = StrSize (AppendString);
+ MultiStringSize = StrSize (*MultiString);
+ MaxLen = MAX_STRING_LENGTH / sizeof (CHAR16);
+
+ //
+ // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
+ //
+ if ((MultiStringSize + AppendStringSize > MAX_STRING_LENGTH) ||
+ (MultiStringSize > MAX_STRING_LENGTH))
+ {
+ *MultiString = (EFI_STRING)ReallocatePool (
+ MultiStringSize,
+ MultiStringSize + AppendStringSize,
+ (VOID *)(*MultiString)
+ );
+ MaxLen = (MultiStringSize + AppendStringSize) / sizeof (CHAR16);
+ ASSERT (*MultiString != NULL);
+ }
+
+ //
+ // Append the incoming string
+ //
+ StrCatS (*MultiString, MaxLen, AppendString);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
+ or WIDTH or VALUE.
+ <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
+
+ This is a internal function.
+
+ @param StringPtr String in <BlockConfig> format and points to the
+ first character of <Number>.
+ @param Number The output value. Caller takes the responsibility
+ to free memory.
+ @param Len Length of the <Number>, in characters.
+
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary
+ structures.
+ @retval EFI_SUCCESS Value of <Number> is outputted in Number
+ successfully.
+
+**/
+EFI_STATUS
+GetValueOfNumber (
+ IN EFI_STRING StringPtr,
+ OUT UINT8 **Number,
+ OUT UINTN *Len
+ )
+{
+ EFI_STRING TmpPtr;
+ UINTN Length;
+ EFI_STRING Str;
+ UINT8 *Buf;
+ EFI_STATUS Status;
+ UINT8 DigitUint8;
+ UINTN Index;
+ CHAR16 TemStr[2];
+
+ if ((StringPtr == NULL) || (*StringPtr == L'\0') || (Number == NULL) || (Len == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Buf = NULL;
+
+ TmpPtr = StringPtr;
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {
+ StringPtr++;
+ }
+
+ *Len = StringPtr - TmpPtr;
+ Length = *Len + 1;
+
+ Str = (EFI_STRING)AllocateZeroPool (Length * sizeof (CHAR16));
+ if (Str == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));
+ *(Str + *Len) = L'\0';
+
+ Length = (Length + 1) / 2;
+ Buf = (UINT8 *)AllocateZeroPool (Length);
+ if (Buf == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ Length = *Len;
+ ZeroMem (TemStr, sizeof (TemStr));
+ for (Index = 0; Index < Length; Index++) {
+ TemStr[0] = Str[Length - Index - 1];
+ DigitUint8 = (UINT8)StrHexToUint64 (TemStr);
+ if ((Index & 1) == 0) {
+ Buf[Index/2] = DigitUint8;
+ } else {
+ Buf[Index/2] = (UINT8)((DigitUint8 << 4) + Buf[Index/2]);
+ }
+ }
+
+ *Number = Buf;
+ Status = EFI_SUCCESS;
+
+Exit:
+ if (Str != NULL) {
+ FreePool (Str);
+ }
+
+ return Status;
+}
+
+/**
+ To find the BlockName in the string with same value.
+
+ @param String Pointer to a Null-terminated Unicode string.
+ @param BlockName Pointer to a Null-terminated Unicode string to search for.
+ @param Buffer Pointer to the value correspond to the BlockName.
+ @param Found The Block whether has been found.
+ @param BufferLen The length of the buffer.
+
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
+ @retval EFI_SUCCESS The function finishes successfully.
+
+**/
+EFI_STATUS
+FindSameBlockElement (
+ IN EFI_STRING String,
+ IN EFI_STRING BlockName,
+ IN UINT8 *Buffer,
+ OUT BOOLEAN *Found,
+ IN UINTN BufferLen
+ )
+{
+ EFI_STRING BlockPtr;
+ UINTN Length;
+ UINT8 *TempBuffer;
+ EFI_STATUS Status;
+
+ TempBuffer = NULL;
+ *Found = FALSE;
+ BlockPtr = StrStr (String, BlockName);
+
+ while (BlockPtr != NULL) {
+ BlockPtr += StrLen (BlockName);
+ Status = GetValueOfNumber (BlockPtr, &TempBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ASSERT (TempBuffer != NULL);
+ if ((BufferLen == Length) && (0 == CompareMem (Buffer, TempBuffer, Length))) {
+ *Found = TRUE;
+ FreePool (TempBuffer);
+ TempBuffer = NULL;
+ return EFI_SUCCESS;
+ } else {
+ FreePool (TempBuffer);
+ TempBuffer = NULL;
+ BlockPtr = StrStr (BlockPtr + 1, BlockName);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
+ in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
+
+ @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
+ <MultiConfigAltResp> format. The default value
+ string may contain more than one ConfigAltResp
+ string for the different varstore buffer.
+ @param ConfigAltResp Pointer to a null-terminated Unicode string in
+ <ConfigAltResp> format.
+ @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
+ @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
+
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
+ @retval EFI_SUCCESS The function finishes successfully.
+
+**/
+EFI_STATUS
+CompareBlockElementDefault (
+ IN EFI_STRING DefaultAltCfgResp,
+ IN OUT EFI_STRING *ConfigAltResp,
+ IN EFI_STRING AltConfigHdr,
+ IN OUT BOOLEAN *ConfigAltRespChanged
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING BlockPtr;
+ EFI_STRING BlockPtrStart;
+ EFI_STRING StringPtr;
+ EFI_STRING AppendString;
+ EFI_STRING AltConfigHdrPtr;
+ UINT8 *TempBuffer;
+ UINTN OffsetLength;
+ UINTN AppendSize;
+ UINTN TotalSize;
+ BOOLEAN FoundOffset;
+
+ AppendString = NULL;
+ TempBuffer = NULL;
+ //
+ // Make BlockPtr point to the first <BlockConfig> with AltConfigHdr in DefaultAltCfgResp.
+ //
+ AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
+ ASSERT (AltConfigHdrPtr != NULL);
+ BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET=");
+ //
+ // Make StringPtr point to the AltConfigHdr in ConfigAltResp.
+ //
+ StringPtr = StrStr (*ConfigAltResp, AltConfigHdr);
+ ASSERT (StringPtr != NULL);
+
+ while (BlockPtr != NULL) {
+ //
+ // Find the "&OFFSET=<Number>" block and get the value of the Number with AltConfigHdr in DefaultAltCfgResp.
+ //
+ BlockPtrStart = BlockPtr;
+ BlockPtr += StrLen (L"&OFFSET=");
+ Status = GetValueOfNumber (BlockPtr, &TempBuffer, &OffsetLength);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ //
+ // To find the same "&OFFSET=<Number>" block in ConfigAltResp.
+ //
+ Status = FindSameBlockElement (StringPtr, L"&OFFSET=", TempBuffer, &FoundOffset, OffsetLength);
+ if (TempBuffer != NULL) {
+ FreePool (TempBuffer);
+ TempBuffer = NULL;
+ }
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ if (!FoundOffset) {
+ //
+ // Don't find the same "&OFFSET=<Number>" block in ConfigAltResp.
+ // Calculate the size of <BlockConfig>.
+ // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number>.
+ //
+ BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET=");
+ if (BlockPtr != NULL) {
+ AppendSize = (BlockPtr - BlockPtrStart) * sizeof (CHAR16);
+ } else {
+ AppendSize = StrSize (BlockPtrStart);
+ }
+
+ //
+ // Copy the <BlockConfig> to AppendString.
+ //
+ if (AppendString == NULL) {
+ AppendString = (EFI_STRING)AllocateZeroPool (AppendSize + sizeof (CHAR16));
+ StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, BlockPtrStart, AppendSize / sizeof (CHAR16));
+ } else {
+ TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16);
+ AppendString = (EFI_STRING)ReallocatePool (
+ StrSize (AppendString),
+ TotalSize,
+ AppendString
+ );
+ if (AppendString == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ StrnCatS (AppendString, TotalSize / sizeof (CHAR16), BlockPtrStart, AppendSize / sizeof (CHAR16));
+ }
+ } else {
+ //
+ // To find next "&OFFSET=<Number>" block with AltConfigHdr in DefaultAltCfgResp.
+ //
+ BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET=");
+ }
+ }
+
+ if (AppendString != NULL) {
+ //
+ // Reallocate ConfigAltResp to copy the AppendString.
+ //
+ TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16);
+ *ConfigAltResp = (EFI_STRING)ReallocatePool (
+ StrSize (*ConfigAltResp),
+ TotalSize,
+ *ConfigAltResp
+ );
+ if (*ConfigAltResp == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString);
+ *ConfigAltRespChanged = TRUE;
+ }
+
+ Status = EFI_SUCCESS;
+
+Exit:
+ if (AppendString != NULL) {
+ FreePool (AppendString);
+ }
+
+ return Status;
+}
+
+/**
+ Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
+ in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
+
+ @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
+ <MultiConfigAltResp> format. The default value
+ string may contain more than one ConfigAltResp
+ string for the different varstore buffer.
+ @param ConfigAltResp Pointer to a null-terminated Unicode string in
+ <ConfigAltResp> format.
+ @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
+ @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
+
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
+ @retval EFI_SUCCESS The function finishes successfully.
+
+**/
+EFI_STATUS
+CompareNameElementDefault (
+ IN EFI_STRING DefaultAltCfgResp,
+ IN OUT EFI_STRING *ConfigAltResp,
+ IN EFI_STRING AltConfigHdr,
+ IN OUT BOOLEAN *ConfigAltRespChanged
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING NvConfigPtr;
+ EFI_STRING NvConfigStart;
+ EFI_STRING NvConfigValuePtr;
+ EFI_STRING StringPtr;
+ EFI_STRING NvConfigExist;
+ EFI_STRING AppendString;
+ CHAR16 TempChar;
+ UINTN AppendSize;
+ UINTN TotalSize;
+
+ AppendString = NULL;
+ NvConfigExist = NULL;
+ //
+ // Make NvConfigPtr point to the first <NvConfig> with AltConfigHdr in DefaultAltCfgResp.
+ //
+ NvConfigPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
+ ASSERT (NvConfigPtr != NULL);
+ NvConfigPtr = StrStr (NvConfigPtr + StrLen (AltConfigHdr), L"&");
+ //
+ // Make StringPtr point to the first <NvConfig> with AltConfigHdr in ConfigAltResp.
+ //
+ StringPtr = StrStr (*ConfigAltResp, AltConfigHdr);
+ ASSERT (StringPtr != NULL);
+ StringPtr = StrStr (StringPtr + StrLen (AltConfigHdr), L"&");
+ ASSERT (StringPtr != NULL);
+
+ while (NvConfigPtr != NULL) {
+ //
+ // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number>.
+ // Get the <Label> with AltConfigHdr in DefaultAltCfgResp.
+ //
+ NvConfigStart = NvConfigPtr;
+ NvConfigValuePtr = StrStr (NvConfigPtr + 1, L"=");
+ ASSERT (NvConfigValuePtr != NULL);
+ TempChar = *NvConfigValuePtr;
+ *NvConfigValuePtr = L'\0';
+ //
+ // Get the <Label> with AltConfigHdr in ConfigAltResp.
+ //
+ NvConfigExist = StrStr (StringPtr, NvConfigPtr);
+ if (NvConfigExist == NULL) {
+ //
+ // Don't find same <Label> in ConfigAltResp.
+ // Calculate the size of <NvConfig>.
+ //
+ *NvConfigValuePtr = TempChar;
+ NvConfigPtr = StrStr (NvConfigPtr + 1, L"&");
+ if (NvConfigPtr != NULL) {
+ AppendSize = (NvConfigPtr - NvConfigStart) * sizeof (CHAR16);
+ } else {
+ AppendSize = StrSize (NvConfigStart);
+ }
+
+ //
+ // Copy the <NvConfig> to AppendString.
+ //
+ if (AppendString == NULL) {
+ AppendString = (EFI_STRING)AllocateZeroPool (AppendSize + sizeof (CHAR16));
+ StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, NvConfigStart, AppendSize / sizeof (CHAR16));
+ } else {
+ TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16);
+ AppendString = (EFI_STRING)ReallocatePool (
+ StrSize (AppendString),
+ TotalSize,
+ AppendString
+ );
+ if (AppendString == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ StrnCatS (AppendString, TotalSize / sizeof (CHAR16), NvConfigStart, AppendSize / sizeof (CHAR16));
+ }
+ } else {
+ //
+ // To find next <Label> in DefaultAltCfgResp.
+ //
+ *NvConfigValuePtr = TempChar;
+ NvConfigPtr = StrStr (NvConfigPtr + 1, L"&");
+ }
+ }
+
+ if (AppendString != NULL) {
+ //
+ // Reallocate ConfigAltResp to copy the AppendString.
+ //
+ TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16);
+ *ConfigAltResp = (EFI_STRING)ReallocatePool (
+ StrSize (*ConfigAltResp),
+ StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16),
+ *ConfigAltResp
+ );
+ if (*ConfigAltResp == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString);
+ *ConfigAltRespChanged = TRUE;
+ }
+
+ Status = EFI_SUCCESS;
+
+Exit:
+ if (AppendString != NULL) {
+ FreePool (AppendString);
+ }
+
+ return Status;
+}
+
+/**
+ Compare the <AltResp> in AltCfgResp and DefaultAltCfgResp, if the <AltResp>
+ in DefaultAltCfgResp but not in AltCfgResp,add it to the AltCfgResp.
+
+ @param AltCfgResp Pointer to a null-terminated Unicode string in
+ <ConfigAltResp> format.
+ @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
+ <MultiConfigAltResp> format. The default value
+ string may contain more than one ConfigAltResp
+ string for the different varstore buffer.
+ @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
+
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary
+ structures.
+ @retval EFI_SUCCESS The function finishes successfully.
+
+**/
+EFI_STATUS
+CompareAndMergeDefaultString (
+ IN OUT EFI_STRING *AltCfgResp,
+ IN EFI_STRING DefaultAltCfgResp,
+ IN EFI_STRING AltConfigHdr
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING AltCfgRespBackup;
+ EFI_STRING AltConfigHdrPtr;
+ EFI_STRING AltConfigHdrPtrNext;
+ EFI_STRING ConfigAltResp;
+ EFI_STRING StringPtr;
+ EFI_STRING StringPtrNext;
+ EFI_STRING BlockPtr;
+ UINTN ReallocateSize;
+ CHAR16 TempChar;
+ CHAR16 TempCharA;
+ BOOLEAN ConfigAltRespChanged;
+
+ Status = EFI_OUT_OF_RESOURCES;
+ BlockPtr = NULL;
+ AltConfigHdrPtrNext = NULL;
+ StringPtrNext = NULL;
+ ConfigAltResp = NULL;
+ AltCfgRespBackup = NULL;
+ TempChar = L'\0';
+ TempCharA = L'\0';
+ ConfigAltRespChanged = FALSE;
+
+ //
+ // To find the <AltResp> with AltConfigHdr in DefaultAltCfgResp, ignore other <AltResp> which follow it.
+ //
+ AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
+ ASSERT (AltConfigHdrPtr != NULL);
+ AltConfigHdrPtrNext = StrStr (AltConfigHdrPtr + 1, L"&GUID");
+ if (AltConfigHdrPtrNext != NULL) {
+ TempChar = *AltConfigHdrPtrNext;
+ *AltConfigHdrPtrNext = L'\0';
+ }
+
+ //
+ // To find the <AltResp> with AltConfigHdr in AltCfgResp, ignore other <AltResp> which follow it.
+ //
+ StringPtr = StrStr (*AltCfgResp, AltConfigHdr);
+ ASSERT (StringPtr != NULL);
+ StringPtrNext = StrStr (StringPtr + 1, L"&GUID");
+ if (StringPtrNext != NULL) {
+ TempCharA = *StringPtrNext;
+ *StringPtrNext = L'\0';
+ }
+
+ //
+ // Copy the content of <ConfigAltResp> which contain current AltConfigHdr in AltCfgResp.
+ //
+ ConfigAltResp = AllocateCopyPool (StrSize (*AltCfgResp), *AltCfgResp);
+ if (ConfigAltResp == NULL) {
+ goto Exit;
+ }
+
+ //
+ // To find the <ConfigBody> with AltConfigHdr in DefaultAltCfgResp.
+ //
+ BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET=");
+ if (BlockPtr != NULL) {
+ //
+ // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number> style.
+ // Call function CompareBlockElementDefault to compare the <BlockConfig> in DefaultAltCfgResp and ConfigAltResp.
+ // The ConfigAltResp which may contain the new <BlockConfig> get from DefaultAltCfgResp.
+ //
+ Status = CompareBlockElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ } else {
+ //
+ // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number> style.
+ // Call function CompareNameElementDefault to compare the <NvConfig> in DefaultAltCfgResp and ConfigAltResp.
+ // The ConfigAltResp which may contain the new <NvConfig> get from DefaultAltCfgResp.
+ //
+ Status = CompareNameElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ }
+
+ //
+ // Restore the AltCfgResp.
+ //
+ if (StringPtrNext != NULL) {
+ *StringPtrNext = TempCharA;
+ }
+
+ //
+ // If the ConfigAltResp has no change,no need to update the content in AltCfgResp.
+ //
+ if (!ConfigAltRespChanged) {
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+
+ //
+ // ConfigAltResp has been changed, need to update the content in AltCfgResp.
+ //
+ if (StringPtrNext != NULL) {
+ ReallocateSize = StrSize (ConfigAltResp) + StrSize (StringPtrNext) + sizeof (CHAR16);
+ } else {
+ ReallocateSize = StrSize (ConfigAltResp) + sizeof (CHAR16);
+ }
+
+ AltCfgRespBackup = (EFI_STRING)AllocateZeroPool (ReallocateSize);
+ if (AltCfgRespBackup == NULL) {
+ goto Exit;
+ }
+
+ StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), ConfigAltResp);
+ if (StringPtrNext != NULL) {
+ StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), StringPtrNext);
+ }
+
+ FreePool (*AltCfgResp);
+ *AltCfgResp = AltCfgRespBackup;
+
+ Status = EFI_SUCCESS;
+
+Exit:
+ if (ConfigAltResp != NULL) {
+ FreePool (ConfigAltResp);
+ }
+
+ //
+ // Restore the DefaultAltCfgResp.
+ //
+ if ( AltConfigHdrPtrNext != NULL) {
+ *AltConfigHdrPtrNext = TempChar;
+ AltConfigHdrPtrNext = NULL;
+ }
+
+ return Status;
+}
+
+/**
+ This function merges DefaultAltCfgResp string into AltCfgResp string for
+ the missing AltCfgId in AltCfgResq.
+
+ @param AltCfgResp Pointer to a null-terminated Unicode string in
+ <ConfigAltResp> format. The default value string
+ will be merged into it.
+ @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
+ <MultiConfigAltResp> format. The default value
+ string may contain more than one ConfigAltResp
+ string for the different varstore buffer.
+
+ @retval EFI_SUCCESS The merged string returns.
+ @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
+**/
+EFI_STATUS
+EFIAPI
+MergeDefaultString (
+ IN OUT EFI_STRING *AltCfgResp,
+ IN EFI_STRING DefaultAltCfgResp
+ )
+{
+ EFI_STRING StringPtrDefault;
+ EFI_STRING StringPtrEnd;
+ CHAR16 TempChar;
+ EFI_STRING StringPtr;
+ EFI_STRING AltConfigHdr;
+ UINTN HeaderLength;
+ UINTN SizeAltCfgResp;
+ UINTN MaxLen;
+ UINTN TotalSize;
+
+ if (*AltCfgResp == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get the request ConfigHdr
+ //
+ SizeAltCfgResp = 0;
+ StringPtr = *AltCfgResp;
+
+ //
+ // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
+ //
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
+ StringPtr++;
+ }
+
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
+ StringPtr++;
+ }
+
+ if (*StringPtr == L'\0') {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ StringPtr += StrLen (L"&PATH=");
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {
+ StringPtr++;
+ }
+
+ HeaderLength = StringPtr - *AltCfgResp;
+
+ //
+ // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
+ // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
+ //
+ MaxLen = 1 + HeaderLength + 8 + 4 + 1;
+ AltConfigHdr = AllocateZeroPool (MaxLen * sizeof (CHAR16));
+ if (AltConfigHdr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StrCpyS (AltConfigHdr, MaxLen, L"&");
+ StrnCatS (AltConfigHdr, MaxLen, *AltCfgResp, HeaderLength);
+ StrCatS (AltConfigHdr, MaxLen, L"&ALTCFG=");
+ HeaderLength = StrLen (AltConfigHdr);
+
+ StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);
+ while (StringPtrDefault != NULL) {
+ //
+ // Get AltCfg Name
+ //
+ StrnCatS (AltConfigHdr, MaxLen, StringPtrDefault + HeaderLength, 4);
+ StringPtr = StrStr (*AltCfgResp, AltConfigHdr);
+
+ //
+ // Append the found default value string to the input AltCfgResp
+ //
+ if (StringPtr == NULL) {
+ StringPtrEnd = StrStr (StringPtrDefault + 1, L"&GUID");
+ SizeAltCfgResp = StrSize (*AltCfgResp);
+ if (StringPtrEnd == NULL) {
+ //
+ // No more default string is found.
+ //
+ TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);
+ *AltCfgResp = (EFI_STRING)ReallocatePool (
+ SizeAltCfgResp,
+ TotalSize,
+ (VOID *)(*AltCfgResp)
+ );
+ if (*AltCfgResp == NULL) {
+ FreePool (AltConfigHdr);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);
+ break;
+ } else {
+ TempChar = *StringPtrEnd;
+ *StringPtrEnd = L'\0';
+ TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);
+ *AltCfgResp = (EFI_STRING)ReallocatePool (
+ SizeAltCfgResp,
+ TotalSize,
+ (VOID *)(*AltCfgResp)
+ );
+ if (*AltCfgResp == NULL) {
+ FreePool (AltConfigHdr);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);
+ *StringPtrEnd = TempChar;
+ }
+ } else {
+ //
+ // The AltCfgResp contains <AltCfgResp>.
+ // If the <ConfigElement> in <AltCfgResp> in the DefaultAltCfgResp but not in the
+ // related <AltCfgResp> in AltCfgResp, merge it to AltCfgResp. else no need to merge.
+ //
+ CompareAndMergeDefaultString (AltCfgResp, DefaultAltCfgResp, AltConfigHdr);
+ }
+
+ //
+ // Find next AltCfg String
+ //
+ *(AltConfigHdr + HeaderLength) = L'\0';
+ StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr);
+ }
+
+ FreePool (AltConfigHdr);
+ return EFI_SUCCESS;
+}
+
+/**
+ This function inserts new DefaultValueData into the BlockData DefaultValue array.
+
+ @param BlockData The BlockData is updated to add new default value.
+ @param DefaultValueData The DefaultValue is added.
+
+**/
+VOID
+InsertDefaultValue (
+ IN IFR_BLOCK_DATA *BlockData,
+ IN IFR_DEFAULT_DATA *DefaultValueData
+ )
+{
+ LIST_ENTRY *Link;
+ IFR_DEFAULT_DATA *DefaultValueArray;
+ LIST_ENTRY *DefaultLink;
+
+ DefaultLink = &BlockData->DefaultValueEntry;
+
+ for (Link = DefaultLink->ForwardLink; Link != DefaultLink; Link = Link->ForwardLink) {
+ DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
+ if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {
+ //
+ // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
+ // When default types are DEFAULT_VALUE_FROM_OTHER_DEFAULT, the default value can be overrode.
+ //
+ if ((DefaultValueData->Type > DefaultValueArray->Type) || ((DefaultValueData->Type == DefaultValueArray->Type) && (DefaultValueData->Type == DefaultValueFromOtherDefault))) {
+ //
+ // Update the default value array in BlockData.
+ //
+ CopyMem (&DefaultValueArray->Value, &DefaultValueData->Value, sizeof (EFI_IFR_TYPE_VALUE));
+ DefaultValueArray->Type = DefaultValueData->Type;
+ DefaultValueArray->Cleaned = DefaultValueData->Cleaned;
+ }
+
+ return;
+ }
+ }
+
+ //
+ // Insert new default value data in tail.
+ //
+ DefaultValueArray = AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
+ ASSERT (DefaultValueArray != NULL);
+ CopyMem (DefaultValueArray, DefaultValueData, sizeof (IFR_DEFAULT_DATA));
+ InsertTailList (Link, &DefaultValueArray->Entry);
+}
+
+/**
+ This function inserts new BlockData into the block link
+
+ @param BlockLink The list entry points to block array.
+ @param BlockData The point to BlockData is added.
+
+**/
+VOID
+InsertBlockData (
+ IN LIST_ENTRY *BlockLink,
+ IN IFR_BLOCK_DATA **BlockData
+ )
+{
+ LIST_ENTRY *Link;
+ IFR_BLOCK_DATA *BlockArray;
+ IFR_BLOCK_DATA *BlockSingleData;
+
+ BlockSingleData = *BlockData;
+
+ if (BlockSingleData->Name != NULL) {
+ InsertTailList (BlockLink, &BlockSingleData->Entry);
+ return;
+ }
+
+ //
+ // Insert block data in its Offset and Width order.
+ //
+ for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
+ BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
+ if (BlockArray->Offset == BlockSingleData->Offset) {
+ if ((BlockArray->Width > BlockSingleData->Width) || (BlockSingleData->IsBitVar && (BlockArray->Width == BlockSingleData->Width))) {
+ //
+ // Insert this block data in the front of block array
+ //
+ InsertTailList (Link, &BlockSingleData->Entry);
+ return;
+ }
+
+ if ((!BlockSingleData->IsBitVar) && (BlockArray->Width == BlockSingleData->Width)) {
+ //
+ // The same block array has been added.
+ //
+ if (BlockSingleData != BlockArray) {
+ FreePool (BlockSingleData);
+ *BlockData = BlockArray;
+ }
+
+ return;
+ }
+ } else if (BlockArray->Offset > BlockSingleData->Offset) {
+ //
+ // Insert new block data in the front of block array
+ //
+ InsertTailList (Link, &BlockSingleData->Entry);
+ return;
+ }
+ }
+
+ //
+ // Add new block data into the tail.
+ //
+ InsertTailList (Link, &BlockSingleData->Entry);
+}
+
+/**
+ Retrieves a pointer to the a Null-terminated ASCII string containing the list
+ of languages that an HII handle in the HII Database supports. The returned
+ string is allocated using AllocatePool(). The caller is responsible for freeing
+ the returned string using FreePool(). The format of the returned string follows
+ the language format assumed the HII Database.
+
+ If HiiHandle is NULL, then ASSERT().
+
+ @param[in] HiiHandle A handle that was previously registered in the HII Database.
+
+ @retval NULL HiiHandle is not registered in the HII database
+ @retval NULL There are not enough resources available to retrieve the supported
+ languages.
+ @retval NULL The list of supported languages could not be retrieved.
+ @retval Other A pointer to the Null-terminated ASCII string of supported languages.
+
+**/
+CHAR8 *
+GetSupportedLanguages (
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ EFI_STATUS Status;
+ UINTN LanguageSize;
+ CHAR8 TempSupportedLanguages;
+ CHAR8 *SupportedLanguages;
+
+ ASSERT (HiiHandle != NULL);
+
+ //
+ // Retrieve the size required for the supported languages buffer.
+ //
+ LanguageSize = 0;
+ Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, &TempSupportedLanguages, &LanguageSize);
+
+ //
+ // If GetLanguages() returns EFI_SUCCESS for a zero size,
+ // then there are no supported languages registered for HiiHandle. If GetLanguages()
+ // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
+ // in the HII Database
+ //
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ //
+ // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
+ //
+ return NULL;
+ }
+
+ //
+ // Allocate the supported languages buffer.
+ //
+ SupportedLanguages = AllocateZeroPool (LanguageSize);
+ if (SupportedLanguages == NULL) {
+ //
+ // Return NULL if allocation fails.
+ //
+ return NULL;
+ }
+
+ //
+ // Retrieve the supported languages string
+ //
+ Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, SupportedLanguages, &LanguageSize);
+ if (EFI_ERROR (Status)) {
+ //
+ // Free the buffer and return NULL if the supported languages can not be retrieved.
+ //
+ FreePool (SupportedLanguages);
+ return NULL;
+ }
+
+ //
+ // Return the Null-terminated ASCII string of supported languages
+ //
+ return SupportedLanguages;
+}
+
+/**
+ Retrieves a string from a string package.
+
+ If HiiHandle is NULL, then ASSERT().
+ If StringId is 0, then ASSET.
+
+ @param[in] HiiHandle A handle that was previously registered in the HII Database.
+ @param[in] StringId The identifier of the string to retrieved from the string
+ package associated with HiiHandle.
+
+ @retval NULL The string specified by StringId is not present in the string package.
+ @retval Other The string was returned.
+
+**/
+EFI_STRING
+InternalGetString (
+ IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_STRING_ID StringId
+ )
+{
+ EFI_STATUS Status;
+ UINTN StringSize;
+ CHAR16 TempString;
+ EFI_STRING String;
+ CHAR8 *SupportedLanguages;
+ CHAR8 *PlatformLanguage;
+ CHAR8 *BestLanguage;
+ CHAR8 *Language;
+
+ ASSERT (HiiHandle != NULL);
+ ASSERT (StringId != 0);
+
+ //
+ // Initialize all allocated buffers to NULL
+ //
+ SupportedLanguages = NULL;
+ PlatformLanguage = NULL;
+ BestLanguage = NULL;
+ String = NULL;
+ Language = "";
+
+ //
+ // Get the languages that the package specified by HiiHandle supports
+ //
+ SupportedLanguages = GetSupportedLanguages (HiiHandle);
+ if (SupportedLanguages == NULL) {
+ goto Error;
+ }
+
+ //
+ // Get the current platform language setting
+ //
+ GetEfiGlobalVariable2 (L"PlatformLang", (VOID **)&PlatformLanguage, NULL);
+
+ //
+ // Get the best matching language from SupportedLanguages
+ //
+ BestLanguage = GetBestLanguage (
+ SupportedLanguages,
+ FALSE, // RFC 4646 mode
+ Language, // Highest priority
+ PlatformLanguage != NULL ? PlatformLanguage : "", // Next highest priority
+ SupportedLanguages, // Lowest priority
+ NULL
+ );
+ if (BestLanguage == NULL) {
+ goto Error;
+ }
+
+ //
+ // Retrieve the size of the string in the string package for the BestLanguage
+ //
+ StringSize = 0;
+ Status = mPrivate.HiiString.GetString (
+ &mPrivate.HiiString,
+ BestLanguage,
+ HiiHandle,
+ StringId,
+ &TempString,
+ &StringSize,
+ NULL
+ );
+ //
+ // If GetString() returns EFI_SUCCESS for a zero size,
+ // then there are no supported languages registered for HiiHandle. If GetString()
+ // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
+ // in the HII Database
+ //
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ goto Error;
+ }
+
+ //
+ // Allocate a buffer for the return string
+ //
+ String = AllocateZeroPool (StringSize);
+ if (String == NULL) {
+ goto Error;
+ }
+
+ //
+ // Retrieve the string from the string package
+ //
+ Status = mPrivate.HiiString.GetString (
+ &mPrivate.HiiString,
+ BestLanguage,
+ HiiHandle,
+ StringId,
+ String,
+ &StringSize,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Free the buffer and return NULL if the supported languages can not be retrieved.
+ //
+ FreePool (String);
+ String = NULL;
+ }
+
+Error:
+ //
+ // Free allocated buffers
+ //
+ if (SupportedLanguages != NULL) {
+ FreePool (SupportedLanguages);
+ }
+
+ if (PlatformLanguage != NULL) {
+ FreePool (PlatformLanguage);
+ }
+
+ if (BestLanguage != NULL) {
+ FreePool (BestLanguage);
+ }
+
+ //
+ // Return the Null-terminated Unicode string
+ //
+ return String;
+}
+
+/**
+ This function checks VarOffset and VarWidth is in the block range.
+
+ @param RequestBlockArray The block array is to be checked.
+ @param VarOffset Offset of var to the structure
+ @param VarWidth Width of var.
+ @param IsNameValueType Whether this varstore is name/value varstore or not.
+ @param HiiHandle Hii handle for this hii package.
+
+ @retval TRUE This Var is in the block range.
+ @retval FALSE This Var is not in the block range.
+**/
+BOOLEAN
+BlockArrayCheck (
+ IN IFR_BLOCK_DATA *RequestBlockArray,
+ IN UINT16 VarOffset,
+ IN UINT16 VarWidth,
+ IN BOOLEAN IsNameValueType,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ LIST_ENTRY *Link;
+ IFR_BLOCK_DATA *BlockData;
+ EFI_STRING Name;
+
+ //
+ // No Request Block array, all vars are got.
+ //
+ if (RequestBlockArray == NULL) {
+ return TRUE;
+ }
+
+ //
+ // Check the input var is in the request block range.
+ //
+ for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
+
+ if (IsNameValueType) {
+ Name = InternalGetString (HiiHandle, VarOffset);
+ ASSERT (Name != NULL);
+
+ if (StrnCmp (BlockData->Name, Name, StrLen (Name)) == 0) {
+ FreePool (Name);
+ return TRUE;
+ }
+
+ FreePool (Name);
+ } else {
+ if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Get form package data from data base.
+
+ @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
+ @param HiiFormPackage The buffer saves the package data.
+ @param PackageSize The buffer size of the package data.
+
+**/
+EFI_STATUS
+GetFormPackageData (
+ IN HII_DATABASE_RECORD *DataBaseRecord,
+ IN OUT UINT8 **HiiFormPackage,
+ OUT UINTN *PackageSize
+ )
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ UINTN ResultSize;
+
+ if ((DataBaseRecord == NULL) || (HiiFormPackage == NULL) || (PackageSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Size = 0;
+ ResultSize = 0;
+ //
+ // 0. Get Hii Form Package by HiiHandle
+ //
+ Status = ExportFormPackages (
+ &mPrivate,
+ DataBaseRecord->Handle,
+ DataBaseRecord->PackageList,
+ 0,
+ Size,
+ HiiFormPackage,
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ (*HiiFormPackage) = AllocatePool (ResultSize);
+ if (*HiiFormPackage == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ return Status;
+ }
+
+ //
+ // Get HiiFormPackage by HiiHandle
+ //
+ Size = ResultSize;
+ ResultSize = 0;
+ Status = ExportFormPackages (
+ &mPrivate,
+ DataBaseRecord->Handle,
+ DataBaseRecord->PackageList,
+ 0,
+ Size,
+ *HiiFormPackage,
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (*HiiFormPackage);
+ }
+
+ *PackageSize = Size;
+
+ return Status;
+}
+
+/**
+ This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
+
+ @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
+ @param ConfigHdr Request string ConfigHdr. If it is NULL,
+ the first found varstore will be as ConfigHdr.
+ @param IsEfiVarstore Whether the request storage type is efi varstore type.
+ @param EfiVarStore The efi varstore info which will return.
+**/
+EFI_STATUS
+GetVarStoreType (
+ IN HII_DATABASE_RECORD *DataBaseRecord,
+ IN EFI_STRING ConfigHdr,
+ OUT BOOLEAN *IsEfiVarstore,
+ OUT EFI_IFR_VARSTORE_EFI **EfiVarStore
+ )
+{
+ EFI_STATUS Status;
+ UINTN IfrOffset;
+ UINTN PackageOffset;
+ EFI_IFR_OP_HEADER *IfrOpHdr;
+ CHAR16 *VarStoreName;
+ UINTN NameSize;
+ EFI_STRING GuidStr;
+ EFI_STRING NameStr;
+ EFI_STRING TempStr;
+ UINTN LengthString;
+ UINT8 *HiiFormPackage;
+ UINTN PackageSize;
+ EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
+ EFI_HII_PACKAGE_HEADER *PackageHeader;
+
+ HiiFormPackage = NULL;
+ LengthString = 0;
+ Status = EFI_SUCCESS;
+ GuidStr = NULL;
+ NameStr = NULL;
+ TempStr = NULL;
+ *IsEfiVarstore = FALSE;
+
+ Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
+ PackageOffset = IfrOffset;
+ PackageHeader = (EFI_HII_PACKAGE_HEADER *)HiiFormPackage;
+
+ while (IfrOffset < PackageSize) {
+ //
+ // More than one form packages exist.
+ //
+ if (PackageOffset >= PackageHeader->Length) {
+ //
+ // Process the new form package.
+ //
+ PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
+ IfrOffset += PackageOffset;
+ PackageHeader = (EFI_HII_PACKAGE_HEADER *)(HiiFormPackage + IfrOffset);
+ }
+
+ IfrOpHdr = (EFI_IFR_OP_HEADER *)(HiiFormPackage + IfrOffset);
+ IfrOffset += IfrOpHdr->Length;
+ PackageOffset += IfrOpHdr->Length;
+
+ if (IfrOpHdr->OpCode == EFI_IFR_VARSTORE_EFI_OP ) {
+ IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *)IfrOpHdr;
+ //
+ // If the length is small than the structure, this is from old efi
+ // varstore definition. Old efi varstore get config directly from
+ // GetVariable function.
+ //
+ if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
+ continue;
+ }
+
+ NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
+ VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
+ if (VarStoreName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);
+
+ GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)&IfrEfiVarStore->Guid, 1, &GuidStr);
+ GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *)VarStoreName, 2, &NameStr);
+ LengthString = StrLen (GuidStr);
+ LengthString = LengthString + StrLen (NameStr) + 1;
+ TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
+ if (TempStr == NULL) {
+ FreePool (GuidStr);
+ FreePool (NameStr);
+ FreePool (VarStoreName);
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ StrCpyS (TempStr, LengthString, GuidStr);
+ StrCatS (TempStr, LengthString, NameStr);
+ if ((ConfigHdr == NULL) || (StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0)) {
+ *EfiVarStore = (EFI_IFR_VARSTORE_EFI *)AllocateZeroPool (IfrOpHdr->Length);
+ if (*EfiVarStore == NULL) {
+ FreePool (VarStoreName);
+ FreePool (GuidStr);
+ FreePool (NameStr);
+ FreePool (TempStr);
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ *IsEfiVarstore = TRUE;
+ CopyMem (*EfiVarStore, IfrEfiVarStore, IfrOpHdr->Length);
+ }
+
+ //
+ // Free allocated temp string.
+ //
+ FreePool (VarStoreName);
+ FreePool (GuidStr);
+ FreePool (NameStr);
+ FreePool (TempStr);
+
+ //
+ // Already found the varstore, break;
+ //
+ if (*IsEfiVarstore) {
+ break;
+ }
+ }
+ }
+
+Done:
+ if (HiiFormPackage != NULL) {
+ FreePool (HiiFormPackage);
+ }
+
+ return Status;
+}
+
+/**
+ Check whether the ConfigRequest string has the request elements.
+ For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
+ For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
+
+ @param ConfigRequest The input config request string.
+
+ @retval TRUE The input include config request elements.
+ @retval FALSE The input string not includes.
+
+**/
+BOOLEAN
+GetElementsFromRequest (
+ IN EFI_STRING ConfigRequest
+ )
+{
+ EFI_STRING TmpRequest;
+
+ TmpRequest = StrStr (ConfigRequest, L"PATH=");
+ ASSERT (TmpRequest != NULL);
+
+ if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Check whether the this varstore is the request varstore.
+
+ @param VarstoreGuid Varstore guid.
+ @param Name Varstore name.
+ @param ConfigHdr Current configRequest info.
+
+ @retval TRUE This varstore is the request one.
+ @retval FALSE This varstore is not the request one.
+
+**/
+BOOLEAN
+IsThisVarstore (
+ IN EFI_GUID *VarstoreGuid,
+ IN CHAR16 *Name,
+ IN CHAR16 *ConfigHdr
+ )
+{
+ EFI_STRING GuidStr;
+ EFI_STRING NameStr;
+ EFI_STRING TempStr;
+ UINTN LengthString;
+ BOOLEAN RetVal;
+
+ RetVal = FALSE;
+ GuidStr = NULL;
+ TempStr = NULL;
+
+ //
+ // If ConfigHdr has name field and varstore not has name, return FALSE.
+ //
+ if ((Name == NULL) && (ConfigHdr != NULL) && (StrStr (ConfigHdr, L"NAME=&") == NULL)) {
+ return FALSE;
+ }
+
+ GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)VarstoreGuid, 1, &GuidStr);
+ if (Name != NULL) {
+ GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *)Name, 2, &NameStr);
+ } else {
+ GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
+ }
+
+ LengthString = StrLen (GuidStr);
+ LengthString = LengthString + StrLen (NameStr) + 1;
+ TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
+ if (TempStr == NULL) {
+ goto Done;
+ }
+
+ StrCpyS (TempStr, LengthString, GuidStr);
+ StrCatS (TempStr, LengthString, NameStr);
+
+ if ((ConfigHdr == NULL) || (StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0)) {
+ RetVal = TRUE;
+ }
+
+Done:
+ if (GuidStr != NULL) {
+ FreePool (GuidStr);
+ }
+
+ if (NameStr != NULL) {
+ FreePool (NameStr);
+ }
+
+ if (TempStr != NULL) {
+ FreePool (TempStr);
+ }
+
+ return RetVal;
+}
+
+/**
+ This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
+
+ @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
+ @param ConfigHdr Request string ConfigHdr. If it is NULL,
+ the first found varstore will be as ConfigHdr.
+ @retval TRUE This hii package is the request one.
+ @retval FALSE This hii package is not the request one.
+**/
+BOOLEAN
+IsThisPackageList (
+ IN HII_DATABASE_RECORD *DataBaseRecord,
+ IN EFI_STRING ConfigHdr
+ )
+{
+ EFI_STATUS Status;
+ UINTN IfrOffset;
+ UINTN PackageOffset;
+ EFI_IFR_OP_HEADER *IfrOpHdr;
+ CHAR16 *VarStoreName;
+ UINTN NameSize;
+ UINT8 *HiiFormPackage;
+ UINTN PackageSize;
+ EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
+ EFI_HII_PACKAGE_HEADER *PackageHeader;
+ EFI_IFR_VARSTORE *IfrVarStore;
+ EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
+ BOOLEAN FindVarstore;
+
+ HiiFormPackage = NULL;
+ VarStoreName = NULL;
+ Status = EFI_SUCCESS;
+ FindVarstore = FALSE;
+
+ Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
+ PackageOffset = IfrOffset;
+ PackageHeader = (EFI_HII_PACKAGE_HEADER *)HiiFormPackage;
+
+ while (IfrOffset < PackageSize) {
+ //
+ // More than one form packages exist.
+ //
+ if (PackageOffset >= PackageHeader->Length) {
+ //
+ // Process the new form package.
+ //
+ PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
+ IfrOffset += PackageOffset;
+ PackageHeader = (EFI_HII_PACKAGE_HEADER *)(HiiFormPackage + IfrOffset);
+ }
+
+ IfrOpHdr = (EFI_IFR_OP_HEADER *)(HiiFormPackage + IfrOffset);
+ IfrOffset += IfrOpHdr->Length;
+ PackageOffset += IfrOpHdr->Length;
+
+ switch (IfrOpHdr->OpCode) {
+ case EFI_IFR_VARSTORE_OP:
+ IfrVarStore = (EFI_IFR_VARSTORE *)IfrOpHdr;
+
+ NameSize = AsciiStrSize ((CHAR8 *)IfrVarStore->Name);
+ VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
+ if (VarStoreName == NULL) {
+ goto Done;
+ }
+
+ AsciiStrToUnicodeStrS ((CHAR8 *)IfrVarStore->Name, VarStoreName, NameSize);
+
+ if (IsThisVarstore ((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
+ FindVarstore = TRUE;
+ goto Done;
+ } else {
+ FreePool (VarStoreName);
+ VarStoreName = NULL;
+ }
+
+ break;
+
+ case EFI_IFR_VARSTORE_EFI_OP:
+ IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *)IfrOpHdr;
+ NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
+ VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
+ if (VarStoreName == NULL) {
+ goto Done;
+ }
+
+ AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);
+
+ if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
+ FindVarstore = TRUE;
+ goto Done;
+ } else {
+ FreePool (VarStoreName);
+ VarStoreName = NULL;
+ }
+
+ break;
+
+ case EFI_IFR_VARSTORE_NAME_VALUE_OP:
+ IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *)IfrOpHdr;
+
+ if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
+ FindVarstore = TRUE;
+ goto Done;
+ }
+
+ break;
+
+ case EFI_IFR_FORM_OP:
+ case EFI_IFR_FORM_MAP_OP:
+ //
+ // No matched varstore is found and directly return.
+ //
+ goto Done;
+
+ default:
+ break;
+ }
+ }
+
+Done:
+ if (HiiFormPackage != NULL) {
+ FreePool (HiiFormPackage);
+ }
+
+ if (VarStoreName != NULL) {
+ FreePool (VarStoreName);
+ }
+
+ return FindVarstore;
+}
+
+/**
+ Check whether the this op code is required.
+
+ @param RequestBlockArray The array includes all the request info or NULL.
+ @param HiiHandle The hii handle for this form package.
+ @param VarStorageData The varstore data structure.
+ @param IfrOpHdr Ifr opcode header for this opcode.
+ @param VarWidth The buffer width for this opcode.
+ @param ReturnData The data block added for this opcode.
+ @param IsBitVar Whether the the opcode refers to bit storage.
+
+ @retval EFI_SUCCESS This opcode is required.
+ @retval EFI_NOT_FOUND This opcode is not required.
+ @retval Others Contain some error.
+
+**/
+EFI_STATUS
+IsThisOpcodeRequired (
+ IN IFR_BLOCK_DATA *RequestBlockArray,
+ IN EFI_HII_HANDLE HiiHandle,
+ IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
+ IN EFI_IFR_OP_HEADER *IfrOpHdr,
+ IN UINT16 VarWidth,
+ OUT IFR_BLOCK_DATA **ReturnData,
+ IN BOOLEAN IsBitVar
+ )
+{
+ IFR_BLOCK_DATA *BlockData;
+ UINT16 VarOffset;
+ EFI_STRING_ID NameId;
+ EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;
+ UINT16 BitOffset;
+ UINT16 BitWidth;
+ UINT16 TotalBits;
+
+ NameId = 0;
+ VarOffset = 0;
+ BitOffset = 0;
+ BitWidth = 0;
+ IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)((CHAR8 *)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER));
+
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ NameId = IfrQuestionHdr->VarStoreInfo.VarName;
+
+ //
+ // Check whether this question is in requested block array.
+ //
+ if (!BlockArrayCheck (RequestBlockArray, NameId, 0, TRUE, HiiHandle)) {
+ //
+ // This question is not in the requested string. Skip it.
+ //
+ return EFI_NOT_FOUND;
+ }
+ } else {
+ //
+ // Get the byte offset/with and bit offset/width
+ //
+ if (IsBitVar) {
+ BitOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
+ BitWidth = VarWidth;
+ VarOffset = BitOffset / 8;
+ //
+ // Use current bit width and the bit width before current bit (with same byte offset) to calculate the byte width.
+ //
+ TotalBits = BitOffset % 8 + BitWidth;
+ VarWidth = (TotalBits % 8 == 0 ? TotalBits / 8 : TotalBits / 8 + 1);
+ } else {
+ VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
+ BitWidth = VarWidth;
+ BitOffset = VarOffset * 8;
+ }
+
+ //
+ // Check whether this question is in requested block array.
+ //
+ if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth, FALSE, HiiHandle)) {
+ //
+ // This question is not in the requested string. Skip it.
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Check this var question is in the var storage
+ //
+ if (((VarOffset + VarWidth) > VarStorageData->Size)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ BlockData = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
+ if (BlockData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ BlockData->Name = InternalGetString (HiiHandle, NameId);
+ } else {
+ BlockData->Offset = VarOffset;
+ }
+
+ BlockData->Width = VarWidth;
+ BlockData->QuestionId = IfrQuestionHdr->QuestionId;
+ BlockData->OpCode = IfrOpHdr->OpCode;
+ BlockData->Scope = IfrOpHdr->Scope;
+ BlockData->IsBitVar = IsBitVar;
+ BlockData->BitOffset = BitOffset;
+ BlockData->BitWidth = BitWidth;
+ InitializeListHead (&BlockData->DefaultValueEntry);
+ //
+ // Add Block Data into VarStorageData BlockEntry
+ //
+ InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
+ *ReturnData = BlockData;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function parses Form Package to get the block array and the default
+ value array according to the request ConfigHdr.
+
+ @param HiiHandle Hii Handle for this hii package.
+ @param Package Pointer to the form package data.
+ @param PackageLength Length of the package.
+ @param ConfigHdr Request string ConfigHdr. If it is NULL,
+ the first found varstore will be as ConfigHdr.
+ @param RequestBlockArray The block array is retrieved from the request string.
+ @param VarStorageData VarStorage structure contains the got block and default value.
+ @param DefaultIdArray Point to the got default id and default name array.
+
+ @retval EFI_SUCCESS The block array and the default value array are got.
+ @retval EFI_INVALID_PARAMETER The varstore definition in the different form packages
+ are conflicted.
+ @retval EFI_OUT_OF_RESOURCES No enough memory.
+**/
+EFI_STATUS
+EFIAPI
+ParseIfrData (
+ IN EFI_HII_HANDLE HiiHandle,
+ IN UINT8 *Package,
+ IN UINT32 PackageLength,
+ IN EFI_STRING ConfigHdr,
+ IN IFR_BLOCK_DATA *RequestBlockArray,
+ IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
+ OUT IFR_DEFAULT_DATA *DefaultIdArray
+ )
+{
+ EFI_STATUS Status;
+ UINTN IfrOffset;
+ UINTN PackageOffset;
+ EFI_IFR_VARSTORE *IfrVarStore;
+ EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
+ EFI_IFR_VARSTORE_EFI *IfrEfiVarStoreTmp;
+ EFI_IFR_OP_HEADER *IfrOpHdr;
+ EFI_IFR_ONE_OF *IfrOneOf;
+ EFI_IFR_REF4 *IfrRef;
+ EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
+ EFI_IFR_DEFAULT *IfrDefault;
+ EFI_IFR_ORDERED_LIST *IfrOrderedList;
+ EFI_IFR_CHECKBOX *IfrCheckBox;
+ EFI_IFR_PASSWORD *IfrPassword;
+ EFI_IFR_STRING *IfrString;
+ EFI_IFR_DATE *IfrDate;
+ EFI_IFR_TIME *IfrTime;
+ IFR_DEFAULT_DATA DefaultData;
+ IFR_DEFAULT_DATA *DefaultDataPtr;
+ IFR_BLOCK_DATA *BlockData;
+ CHAR16 *VarStoreName;
+ UINTN NameSize;
+ UINTN NvDefaultStoreSize;
+ UINT16 VarWidth;
+ UINT16 VarDefaultId;
+ BOOLEAN FirstOneOfOption;
+ BOOLEAN FirstOrderedList;
+ LIST_ENTRY *LinkData;
+ LIST_ENTRY *LinkDefault;
+ EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
+ EFI_HII_PACKAGE_HEADER *PackageHeader;
+ EFI_VARSTORE_ID VarStoreId;
+ UINT16 SmallestDefaultId;
+ BOOLEAN SmallestIdFromFlag;
+ BOOLEAN FromOtherDefaultOpcode;
+ BOOLEAN QuestionReferBitField;
+
+ Status = EFI_SUCCESS;
+ BlockData = NULL;
+ DefaultDataPtr = NULL;
+ FirstOneOfOption = FALSE;
+ VarStoreId = 0;
+ FirstOrderedList = FALSE;
+ VarStoreName = NULL;
+ ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));
+ SmallestDefaultId = 0xFFFF;
+ FromOtherDefaultOpcode = FALSE;
+ QuestionReferBitField = FALSE;
+ IfrEfiVarStoreTmp = NULL;
+
+ //
+ // Go through the form package to parse OpCode one by one.
+ //
+ PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
+ PackageHeader = (EFI_HII_PACKAGE_HEADER *)Package;
+ IfrOffset = PackageOffset;
+ while (IfrOffset < PackageLength) {
+ //
+ // More than one form package found.
+ //
+ if (PackageOffset >= PackageHeader->Length) {
+ //
+ // Already found varstore for this request, break;
+ //
+ if (VarStoreId != 0) {
+ VarStoreId = 0;
+ }
+
+ //
+ // Get next package header info.
+ //
+ IfrOffset += sizeof (EFI_HII_PACKAGE_HEADER);
+ PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
+ PackageHeader = (EFI_HII_PACKAGE_HEADER *)(Package + IfrOffset);
+ }
+
+ IfrOpHdr = (EFI_IFR_OP_HEADER *)(Package + IfrOffset);
+ switch (IfrOpHdr->OpCode) {
+ case EFI_IFR_VARSTORE_OP:
+ //
+ // VarStore is found. Don't need to search any more.
+ //
+ if (VarStoreId != 0) {
+ break;
+ }
+
+ IfrVarStore = (EFI_IFR_VARSTORE *)IfrOpHdr;
+
+ NameSize = AsciiStrSize ((CHAR8 *)IfrVarStore->Name);
+ VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
+ if (VarStoreName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ AsciiStrToUnicodeStrS ((CHAR8 *)IfrVarStore->Name, VarStoreName, NameSize);
+
+ if (IsThisVarstore ((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
+ //
+ // Find the matched VarStore
+ //
+ CopyGuid (&VarStorageData->Guid, (EFI_GUID *)(VOID *)&IfrVarStore->Guid);
+ VarStorageData->Size = IfrVarStore->Size;
+ VarStorageData->Name = VarStoreName;
+ VarStorageData->Type = EFI_HII_VARSTORE_BUFFER;
+ VarStoreId = IfrVarStore->VarStoreId;
+ } else {
+ FreePool (VarStoreName);
+ VarStoreName = NULL;
+ }
+
+ break;
+
+ case EFI_IFR_VARSTORE_EFI_OP:
+ //
+ // VarStore is found. Don't need to search any more.
+ //
+ if (VarStoreId != 0) {
+ break;
+ }
+
+ IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *)IfrOpHdr;
+
+ //
+ // If the length is small than the structure, this is from old efi
+ // varstore definition. Old efi varstore get config directly from
+ // GetVariable function.
+ //
+ if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
+ break;
+ }
+
+ NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
+ VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
+ if (VarStoreName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);
+ if (IfrEfiVarStoreTmp != NULL) {
+ FreePool (IfrEfiVarStoreTmp);
+ }
+
+ IfrEfiVarStoreTmp = AllocatePool (IfrEfiVarStore->Header.Length + AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name));
+ if (IfrEfiVarStoreTmp == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ CopyMem (IfrEfiVarStoreTmp, IfrEfiVarStore, IfrEfiVarStore->Header.Length);
+ AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, (CHAR16 *)&(IfrEfiVarStoreTmp->Name[0]), AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
+
+ if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
+ //
+ // Find the matched VarStore
+ //
+ CopyGuid (&VarStorageData->Guid, (EFI_GUID *)(VOID *)&IfrEfiVarStore->Guid);
+ VarStorageData->Size = IfrEfiVarStore->Size;
+ VarStorageData->Name = VarStoreName;
+ VarStorageData->Type = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;
+ VarStoreId = IfrEfiVarStore->VarStoreId;
+ } else {
+ FreePool (VarStoreName);
+ VarStoreName = NULL;
+ }
+
+ break;
+
+ case EFI_IFR_VARSTORE_NAME_VALUE_OP:
+ //
+ // VarStore is found. Don't need to search any more.
+ //
+ if (VarStoreId != 0) {
+ break;
+ }
+
+ IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *)IfrOpHdr;
+
+ if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
+ //
+ // Find the matched VarStore
+ //
+ CopyGuid (&VarStorageData->Guid, (EFI_GUID *)(VOID *)&IfrNameValueVarStore->Guid);
+ VarStorageData->Type = EFI_HII_VARSTORE_NAME_VALUE;
+ VarStoreId = IfrNameValueVarStore->VarStoreId;
+ }
+
+ break;
+
+ case EFI_IFR_DEFAULTSTORE_OP:
+ //
+ // Add new the map between default id and default name.
+ //
+ DefaultDataPtr = (IFR_DEFAULT_DATA *)AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
+ if (DefaultDataPtr == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ DefaultDataPtr->DefaultId = ((EFI_IFR_DEFAULTSTORE *)IfrOpHdr)->DefaultId;
+ InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);
+ DefaultDataPtr = NULL;
+ break;
+
+ case EFI_IFR_FORM_OP:
+ case EFI_IFR_FORM_MAP_OP:
+ //
+ // No matched varstore is found and directly return.
+ //
+ if ( VarStoreId == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ break;
+
+ case EFI_IFR_REF_OP:
+ //
+ // Ref question is not in IFR Form. This IFR form is not valid.
+ //
+ if ( VarStoreId == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Check whether this question is for the requested varstore.
+ //
+ IfrRef = (EFI_IFR_REF4 *)IfrOpHdr;
+ if (IfrRef->Question.VarStoreId != VarStoreId) {
+ break;
+ }
+
+ VarWidth = (UINT16)(sizeof (EFI_HII_REF));
+
+ //
+ // The BlockData may allocate by other opcode,need to clean.
+ //
+ if (BlockData != NULL) {
+ BlockData = NULL;
+ }
+
+ Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // The opcode is not required,exit and parse other opcode.
+ //
+ break;
+ }
+
+ goto Done;
+ }
+
+ break;
+
+ case EFI_IFR_ONE_OF_OP:
+ case EFI_IFR_NUMERIC_OP:
+ //
+ // Numeric and OneOf has the same opcode structure.
+ //
+
+ //
+ // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
+ //
+ if (VarStoreId == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Check whether this question is for the requested varstore.
+ //
+ IfrOneOf = (EFI_IFR_ONE_OF *)IfrOpHdr;
+ if (IfrOneOf->Question.VarStoreId != VarStoreId) {
+ break;
+ }
+
+ if (QuestionReferBitField) {
+ VarWidth = IfrOneOf->Flags & EDKII_IFR_NUMERIC_SIZE_BIT;
+ } else {
+ VarWidth = (UINT16)(1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
+ }
+
+ //
+ // The BlockData may allocate by other opcode,need to clean.
+ //
+ if (BlockData != NULL) {
+ BlockData = NULL;
+ }
+
+ Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, QuestionReferBitField);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // The opcode is not required,exit and parse other opcode.
+ //
+ break;
+ }
+
+ goto Done;
+ }
+
+ //
+ // when go to there,BlockData can't be NULLL.
+ //
+ ASSERT (BlockData != NULL);
+
+ if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {
+ //
+ // Set this flag to TRUE for the first oneof option.
+ //
+ FirstOneOfOption = TRUE;
+ } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {
+ //
+ // Numeric minimum value will be used as default value when no default is specified.
+ //
+ DefaultData.Type = DefaultValueFromDefault;
+ if (QuestionReferBitField) {
+ //
+ // Since default value in bit field was stored as UINT32 type.
+ //
+ CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));
+ } else {
+ switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {
+ case EFI_IFR_NUMERIC_SIZE_1:
+ DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_2:
+ CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_4:
+ CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_8:
+ CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+ }
+
+ //
+ // Set default value base on the DefaultId list get from IFR data.
+ //
+ NvDefaultStoreSize = PcdGetSize (PcdNvStoreDefaultValueBuffer);
+ for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
+ DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
+ DefaultData.DefaultId = DefaultDataPtr->DefaultId;
+ if (NvDefaultStoreSize > sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) {
+ FindQuestionDefaultSetting (DefaultData.DefaultId, IfrEfiVarStoreTmp, &(IfrOneOf->Question), &DefaultData.Value, VarWidth, QuestionReferBitField);
+ }
+
+ InsertDefaultValue (BlockData, &DefaultData);
+ }
+ }
+
+ break;
+
+ case EFI_IFR_ORDERED_LIST_OP:
+ //
+ // offset by question header
+ // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
+ //
+
+ FirstOrderedList = TRUE;
+ //
+ // OrderedList question is not in IFR Form. This IFR form is not valid.
+ //
+ if (VarStoreId == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Check whether this question is for the requested varstore.
+ //
+ IfrOrderedList = (EFI_IFR_ORDERED_LIST *)IfrOpHdr;
+ if (IfrOrderedList->Question.VarStoreId != VarStoreId) {
+ BlockData = NULL;
+ break;
+ }
+
+ VarWidth = IfrOrderedList->MaxContainers;
+
+ //
+ // The BlockData may allocate by other opcode,need to clean.
+ //
+ if (BlockData != NULL) {
+ BlockData = NULL;
+ }
+
+ Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // The opcode is not required,exit and parse other opcode.
+ //
+ break;
+ }
+
+ goto Done;
+ }
+
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ //
+ // EFI_IFR_DEFAULT_OP
+ // offset by question header
+ // width is 1 sizeof (BOOLEAN)
+ // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
+ // value by DefaultOption
+ // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
+ //
+
+ //
+ // CheckBox question is not in IFR Form. This IFR form is not valid.
+ //
+ if (VarStoreId == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Check whether this question is for the requested varstore.
+ //
+ IfrCheckBox = (EFI_IFR_CHECKBOX *)IfrOpHdr;
+ if (IfrCheckBox->Question.VarStoreId != VarStoreId) {
+ break;
+ }
+
+ VarWidth = (UINT16)sizeof (BOOLEAN);
+
+ //
+ // The BlockData may allocate by other opcode,need to clean.
+ //
+ if (BlockData != NULL) {
+ BlockData = NULL;
+ }
+
+ if (QuestionReferBitField) {
+ VarWidth = 1;
+ }
+
+ Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, QuestionReferBitField);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // The opcode is not required,exit and parse other opcode.
+ //
+ break;
+ }
+
+ goto Done;
+ }
+
+ //
+ // when go to there,BlockData can't be NULLL.
+ //
+ ASSERT (BlockData != NULL);
+
+ SmallestIdFromFlag = FALSE;
+
+ //
+ // Add default value for standard ID by CheckBox Flag
+ //
+ VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
+ //
+ // Prepare new DefaultValue
+ //
+ DefaultData.DefaultId = VarDefaultId;
+ if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {
+ //
+ // When flag is set, default value is TRUE.
+ //
+ DefaultData.Type = DefaultValueFromFlag;
+ if (QuestionReferBitField) {
+ DefaultData.Value.u32 = TRUE;
+ } else {
+ DefaultData.Value.b = TRUE;
+ }
+
+ InsertDefaultValue (BlockData, &DefaultData);
+
+ if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {
+ //
+ // Record the SmallestDefaultId and update the SmallestIdFromFlag.
+ //
+ SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
+ SmallestIdFromFlag = TRUE;
+ }
+ }
+
+ //
+ // Add default value for Manufacture ID by CheckBox Flag
+ //
+ VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
+ //
+ // Prepare new DefaultValue
+ //
+ DefaultData.DefaultId = VarDefaultId;
+ if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {
+ //
+ // When flag is set, default value is TRUE.
+ //
+ DefaultData.Type = DefaultValueFromFlag;
+ if (QuestionReferBitField) {
+ DefaultData.Value.u32 = TRUE;
+ } else {
+ DefaultData.Value.b = TRUE;
+ }
+
+ InsertDefaultValue (BlockData, &DefaultData);
+
+ if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+ //
+ // Record the SmallestDefaultId and update the SmallestIdFromFlag.
+ //
+ SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
+ SmallestIdFromFlag = TRUE;
+ }
+ }
+
+ if (SmallestIdFromFlag) {
+ //
+ // When smallest default Id is given by the flag of CheckBox, set default value with TRUE for other default Id in the DefaultId list.
+ //
+ DefaultData.Type = DefaultValueFromOtherDefault;
+ if (QuestionReferBitField) {
+ DefaultData.Value.u32 = TRUE;
+ } else {
+ DefaultData.Value.b = TRUE;
+ }
+
+ //
+ // Set default value for all the default id in the DefaultId list.
+ //
+ for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
+ DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
+ DefaultData.DefaultId = DefaultDataPtr->DefaultId;
+ InsertDefaultValue (BlockData, &DefaultData);
+ }
+ } else {
+ //
+ // When flag is not set, default value is FASLE.
+ //
+ DefaultData.Type = DefaultValueFromDefault;
+ if (QuestionReferBitField) {
+ DefaultData.Value.u32 = FALSE;
+ } else {
+ DefaultData.Value.b = FALSE;
+ }
+
+ //
+ // Set default value for all the default id in the DefaultId list.
+ //
+ for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
+ DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
+ DefaultData.DefaultId = DefaultDataPtr->DefaultId;
+ InsertDefaultValue (BlockData, &DefaultData);
+ }
+ }
+
+ break;
+
+ case EFI_IFR_DATE_OP:
+ //
+ // offset by question header
+ // width MaxSize * sizeof (CHAR16)
+ // no default value, only block array
+ //
+
+ //
+ // Date question is not in IFR Form. This IFR form is not valid.
+ //
+ if (VarStoreId == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Check whether this question is for the requested varstore.
+ //
+ IfrDate = (EFI_IFR_DATE *)IfrOpHdr;
+ if (IfrDate->Question.VarStoreId != VarStoreId) {
+ break;
+ }
+
+ //
+ // The BlockData may allocate by other opcode,need to clean.
+ //
+ if (BlockData != NULL) {
+ BlockData = NULL;
+ }
+
+ VarWidth = (UINT16)sizeof (EFI_HII_DATE);
+ Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // The opcode is not required,exit and parse other opcode.
+ //
+ break;
+ }
+
+ goto Done;
+ }
+
+ break;
+
+ case EFI_IFR_TIME_OP:
+ //
+ // offset by question header
+ // width MaxSize * sizeof (CHAR16)
+ // no default value, only block array
+ //
+
+ //
+ // Time question is not in IFR Form. This IFR form is not valid.
+ //
+ if (VarStoreId == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Check whether this question is for the requested varstore.
+ //
+ IfrTime = (EFI_IFR_TIME *)IfrOpHdr;
+ if (IfrTime->Question.VarStoreId != VarStoreId) {
+ break;
+ }
+
+ //
+ // The BlockData may allocate by other opcode,need to clean.
+ //
+ if (BlockData != NULL) {
+ BlockData = NULL;
+ }
+
+ VarWidth = (UINT16)sizeof (EFI_HII_TIME);
+ Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // The opcode is not required,exit and parse other opcode.
+ //
+ break;
+ }
+
+ goto Done;
+ }
+
+ break;
+
+ case EFI_IFR_STRING_OP:
+ //
+ // offset by question header
+ // width MaxSize * sizeof (CHAR16)
+ // no default value, only block array
+ //
+
+ //
+ // String question is not in IFR Form. This IFR form is not valid.
+ //
+ if (VarStoreId == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Check whether this question is for the requested varstore.
+ //
+ IfrString = (EFI_IFR_STRING *)IfrOpHdr;
+ if (IfrString->Question.VarStoreId != VarStoreId) {
+ break;
+ }
+
+ //
+ // The BlockData may allocate by other opcode,need to clean.
+ //
+ if (BlockData != NULL) {
+ BlockData = NULL;
+ }
+
+ VarWidth = (UINT16)(IfrString->MaxSize * sizeof (UINT16));
+ Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // The opcode is not required,exit and parse other opcode.
+ //
+ break;
+ }
+
+ goto Done;
+ }
+
+ break;
+
+ case EFI_IFR_PASSWORD_OP:
+ //
+ // offset by question header
+ // width MaxSize * sizeof (CHAR16)
+ // no default value, only block array
+ //
+
+ //
+ // Password question is not in IFR Form. This IFR form is not valid.
+ //
+ if (VarStoreId == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Check whether this question is for the requested varstore.
+ //
+ IfrPassword = (EFI_IFR_PASSWORD *)IfrOpHdr;
+ if (IfrPassword->Question.VarStoreId != VarStoreId) {
+ break;
+ }
+
+ //
+ // The BlockData may allocate by other opcode,need to clean.
+ //
+ if (BlockData != NULL) {
+ BlockData = NULL;
+ }
+
+ VarWidth = (UINT16)(IfrPassword->MaxSize * sizeof (UINT16));
+ Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // The opcode is not required,exit and parse other opcode.
+ //
+ break;
+ }
+
+ goto Done;
+ }
+
+ //
+ // No default value for string.
+ //
+ BlockData = NULL;
+ break;
+
+ case EFI_IFR_ONE_OF_OPTION_OP:
+ //
+ // No matched block data is ignored.
+ //
+ if ((BlockData == NULL) || (BlockData->Scope == 0)) {
+ break;
+ }
+
+ IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *)IfrOpHdr;
+ if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
+ if (!FirstOrderedList) {
+ break;
+ }
+
+ //
+ // Get ordered list option data type.
+ //
+ if ((IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8) || (IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN)) {
+ VarWidth = 1;
+ } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
+ VarWidth = 2;
+ } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
+ VarWidth = 4;
+ } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
+ VarWidth = 8;
+ } else {
+ //
+ // Invalid ordered list option data type.
+ //
+ Status = EFI_INVALID_PARAMETER;
+ if (BlockData->Name != NULL) {
+ FreePool (BlockData->Name);
+ }
+
+ FreePool (BlockData);
+ goto Done;
+ }
+
+ //
+ // Calculate Ordered list QuestionId width.
+ //
+ BlockData->Width = (UINT16)(BlockData->Width * VarWidth);
+ //
+ // Check whether this question is in requested block array.
+ //
+ if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, (BOOLEAN)(BlockData->Name != NULL), HiiHandle)) {
+ //
+ // This question is not in the requested string. Skip it.
+ //
+ if (BlockData->Name != NULL) {
+ FreePool (BlockData->Name);
+ }
+
+ FreePool (BlockData);
+ BlockData = NULL;
+ break;
+ }
+
+ //
+ // Check this var question is in the var storage
+ //
+ if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {
+ Status = EFI_INVALID_PARAMETER;
+ FreePool (BlockData);
+ goto Done;
+ }
+
+ //
+ // Add Block Data into VarStorageData BlockEntry
+ //
+ InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
+
+ FirstOrderedList = FALSE;
+
+ break;
+ }
+
+ //
+ // 1. Set default value for OneOf option when flag field has default attribute.
+ // And set the default value with the smallest default id for other default id in the DefaultId list.
+ //
+ if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||
+ ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG))
+ {
+ //
+ // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
+ // The first oneof option value will be used as default value when no default value is specified.
+ //
+ FirstOneOfOption = FALSE;
+
+ SmallestIdFromFlag = FALSE;
+
+ // Prepare new DefaultValue
+ //
+ DefaultData.Type = DefaultValueFromFlag;
+ CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
+ if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {
+ DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
+ InsertDefaultValue (BlockData, &DefaultData);
+ if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {
+ //
+ // Record the SmallestDefaultId and update the SmallestIdFromFlag.
+ //
+ SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
+ SmallestIdFromFlag = TRUE;
+ }
+ }
+
+ if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {
+ DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
+ InsertDefaultValue (BlockData, &DefaultData);
+ if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+ //
+ // Record the SmallestDefaultId and update the SmallestIdFromFlag.
+ //
+ SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
+ SmallestIdFromFlag = TRUE;
+ }
+ }
+
+ if (SmallestIdFromFlag) {
+ //
+ // When smallest default Id is given by the flag of oneofOption, set this option value for other default Id in the DefaultId list.
+ //
+ DefaultData.Type = DefaultValueFromOtherDefault;
+ //
+ // Set default value for other default id in the DefaultId list.
+ //
+ for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
+ DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
+ DefaultData.DefaultId = DefaultDataPtr->DefaultId;
+ InsertDefaultValue (BlockData, &DefaultData);
+ }
+ }
+ }
+
+ //
+ // 2. Set as the default value when this is the first option.
+ // The first oneof option value will be used as default value when no default value is specified.
+ //
+ if (FirstOneOfOption) {
+ // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
+ FirstOneOfOption = FALSE;
+
+ //
+ // Prepare new DefaultValue
+ //
+ DefaultData.Type = DefaultValueFromDefault;
+ CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
+ for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
+ DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
+ DefaultData.DefaultId = DefaultDataPtr->DefaultId;
+ InsertDefaultValue (BlockData, &DefaultData);
+ }
+ }
+
+ break;
+
+ case EFI_IFR_DEFAULT_OP:
+ //
+ // Update Current BlockData to the default value.
+ //
+ if ((BlockData == NULL) || (BlockData->Scope == 0)) {
+ //
+ // No matched block data is ignored.
+ //
+ break;
+ }
+
+ //
+ // Get the DefaultId
+ //
+ IfrDefault = (EFI_IFR_DEFAULT *)IfrOpHdr;
+ VarDefaultId = IfrDefault->DefaultId;
+ //
+ // Prepare new DefaultValue
+ //
+ DefaultData.Type = DefaultValueFromOpcode;
+ DefaultData.DefaultId = VarDefaultId;
+ if (QuestionReferBitField) {
+ CopyMem (&DefaultData.Value.u32, &IfrDefault->Value.u32, sizeof (UINT32));
+ } else {
+ CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));
+ }
+
+ // If the value field is expression, set the cleaned flag.
+ if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {
+ DefaultData.Cleaned = TRUE;
+ }
+
+ //
+ // Add DefaultValue into current BlockData
+ //
+ InsertDefaultValue (BlockData, &DefaultData);
+
+ //
+ // Set default value for other default id in the DefaultId list.
+ // when SmallestDefaultId == VarDefaultId means there are two defaults with same default Id.
+ // If the two defaults are both from default opcode, use the first default as the default value of other default Id.
+ // If one from flag and the other form default opcode, use the default opcode value as the default value of other default Id.
+ //
+ if ((SmallestDefaultId > VarDefaultId) || ((SmallestDefaultId == VarDefaultId) && !FromOtherDefaultOpcode)) {
+ FromOtherDefaultOpcode = TRUE;
+ SmallestDefaultId = VarDefaultId;
+ for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
+ DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
+ if (DefaultDataPtr->DefaultId != DefaultData.DefaultId) {
+ DefaultData.Type = DefaultValueFromOtherDefault;
+ DefaultData.DefaultId = DefaultDataPtr->DefaultId;
+ InsertDefaultValue (BlockData, &DefaultData);
+ }
+ }
+ }
+
+ //
+ // After insert the default value, reset the cleaned value for next
+ // time used. If not set here, need to set the value before every time.
+ // use it.
+ //
+ DefaultData.Cleaned = FALSE;
+ break;
+
+ case EFI_IFR_END_OP:
+ //
+ // End Opcode is for Var question.
+ //
+ QuestionReferBitField = FALSE;
+ if (BlockData != NULL) {
+ if (BlockData->Scope > 0) {
+ BlockData->Scope--;
+ }
+
+ if (BlockData->Scope == 0) {
+ BlockData = NULL;
+ //
+ // when finishing parsing a question, clean the SmallestDefaultId and GetDefaultFromDefaultOpcode.
+ //
+ SmallestDefaultId = 0xFFFF;
+ FromOtherDefaultOpcode = FALSE;
+ }
+ }
+
+ break;
+
+ case EFI_IFR_GUID_OP:
+ if (CompareGuid ((EFI_GUID *)((UINT8 *)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {
+ QuestionReferBitField = TRUE;
+ }
+
+ break;
+
+ default:
+ if (BlockData != NULL) {
+ if (BlockData->Scope > 0) {
+ BlockData->Scope = (UINT8)(BlockData->Scope + IfrOpHdr->Scope);
+ }
+
+ if (BlockData->Scope == 0) {
+ BlockData = NULL;
+ }
+ }
+
+ break;
+ }
+
+ IfrOffset += IfrOpHdr->Length;
+ PackageOffset += IfrOpHdr->Length;
+ }
+
+ //
+ // if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
+ // so set the Status to EFI_SUCCESS.
+ //
+ if (Status == EFI_NOT_FOUND) {
+ Status = EFI_SUCCESS;
+ }
+
+Done:
+ for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
+ BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
+ for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {
+ DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
+ LinkDefault = LinkDefault->ForwardLink;
+ if (DefaultDataPtr->Cleaned == TRUE) {
+ RemoveEntryList (&DefaultDataPtr->Entry);
+ FreePool (DefaultDataPtr);
+ }
+ }
+ }
+
+ if (IfrEfiVarStoreTmp != NULL) {
+ FreePool (IfrEfiVarStoreTmp);
+ }
+
+ return Status;
+}
+
+/**
+ parse the configrequest string, get the elements.
+
+ @param ConfigRequest The input configrequest string.
+ @param Progress Return the progress data.
+
+ @retval Block data pointer.
+**/
+IFR_BLOCK_DATA *
+GetBlockElement (
+ IN EFI_STRING ConfigRequest,
+ OUT EFI_STRING *Progress
+ )
+{
+ EFI_STRING StringPtr;
+ IFR_BLOCK_DATA *BlockData;
+ IFR_BLOCK_DATA *RequestBlockArray;
+ EFI_STATUS Status;
+ UINT8 *TmpBuffer;
+ UINT16 Offset;
+ UINT16 Width;
+ LIST_ENTRY *Link;
+ IFR_BLOCK_DATA *NextBlockData;
+ UINTN Length;
+
+ TmpBuffer = NULL;
+
+ //
+ // Init RequestBlockArray
+ //
+ RequestBlockArray = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
+ if (RequestBlockArray == NULL) {
+ goto Done;
+ }
+
+ InitializeListHead (&RequestBlockArray->Entry);
+
+ //
+ // Get the request Block array from the request string
+ // Offset and Width
+ //
+
+ //
+ // Parse each <RequestElement> if exists
+ // Only <BlockName> format is supported by this help function.
+ // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
+ //
+ StringPtr = ConfigRequest;
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
+ //
+ // Skip the OFFSET string
+ //
+ *Progress = StringPtr;
+ StringPtr += StrLen (L"&OFFSET=");
+ //
+ // Get Offset
+ //
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Offset = 0;
+ CopyMem (
+ &Offset,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
+ );
+ FreePool (TmpBuffer);
+
+ StringPtr += Length;
+ if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
+ goto Done;
+ }
+
+ StringPtr += StrLen (L"&WIDTH=");
+
+ //
+ // Get Width
+ //
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Width = 0;
+ CopyMem (
+ &Width,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
+ );
+ FreePool (TmpBuffer);
+
+ StringPtr += Length;
+ if ((*StringPtr != 0) && (*StringPtr != L'&')) {
+ goto Done;
+ }
+
+ //
+ // Set Block Data
+ //
+ BlockData = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
+ if (BlockData == NULL) {
+ goto Done;
+ }
+
+ BlockData->Offset = Offset;
+ BlockData->Width = Width;
+ InsertBlockData (&RequestBlockArray->Entry, &BlockData);
+
+ //
+ // Skip &VALUE string if &VALUE does exists.
+ //
+ if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {
+ StringPtr += StrLen (L"&VALUE=");
+
+ //
+ // Get Value
+ //
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ FreePool (TmpBuffer);
+ StringPtr += Length;
+ if ((*StringPtr != 0) && (*StringPtr != L'&')) {
+ goto Done;
+ }
+ }
+
+ //
+ // If '\0', parsing is finished.
+ //
+ if (*StringPtr == 0) {
+ break;
+ }
+ }
+
+ //
+ // Merge the requested block data.
+ //
+ Link = RequestBlockArray->Entry.ForwardLink;
+ while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
+ NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
+ if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
+ if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
+ BlockData->Width = (UINT16)(NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);
+ }
+
+ RemoveEntryList (Link->ForwardLink);
+ FreePool (NextBlockData);
+ continue;
+ }
+
+ Link = Link->ForwardLink;
+ }
+
+ return RequestBlockArray;
+
+Done:
+ if (RequestBlockArray != NULL) {
+ //
+ // Free Link Array RequestBlockArray
+ //
+ while (!IsListEmpty (&RequestBlockArray->Entry)) {
+ BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
+ RemoveEntryList (&BlockData->Entry);
+ FreePool (BlockData);
+ }
+
+ FreePool (RequestBlockArray);
+ }
+
+ return NULL;
+}
+
+/**
+ parse the configrequest string, get the elements.
+
+ @param ConfigRequest The input config request string.
+ @param Progress Return the progress data.
+
+ @retval return data block array.
+**/
+IFR_BLOCK_DATA *
+GetNameElement (
+ IN EFI_STRING ConfigRequest,
+ OUT EFI_STRING *Progress
+ )
+{
+ EFI_STRING StringPtr;
+ EFI_STRING NextTag;
+ IFR_BLOCK_DATA *BlockData;
+ IFR_BLOCK_DATA *RequestBlockArray;
+ BOOLEAN HasValue;
+
+ StringPtr = ConfigRequest;
+
+ //
+ // Init RequestBlockArray
+ //
+ RequestBlockArray = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
+ if (RequestBlockArray == NULL) {
+ goto Done;
+ }
+
+ InitializeListHead (&RequestBlockArray->Entry);
+
+ //
+ // Get the request Block array from the request string
+ //
+
+ //
+ // Parse each <RequestElement> if exists
+ // Only <BlockName> format is supported by this help function.
+ // <BlockName> ::= &'Name***=***
+ //
+ while (StringPtr != NULL && *StringPtr == L'&') {
+ *Progress = StringPtr;
+ //
+ // Skip the L"&" string
+ //
+ StringPtr += 1;
+
+ HasValue = FALSE;
+ if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {
+ *NextTag = L'\0';
+ HasValue = TRUE;
+ } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {
+ *NextTag = L'\0';
+ }
+
+ //
+ // Set Block Data
+ //
+ BlockData = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
+ if (BlockData == NULL) {
+ goto Done;
+ }
+
+ //
+ // Get Name
+ //
+ BlockData->Name = AllocateCopyPool (StrSize (StringPtr), StringPtr);
+ InsertBlockData (&RequestBlockArray->Entry, &BlockData);
+
+ if (HasValue) {
+ //
+ // If has value, skip the value.
+ //
+ StringPtr = NextTag + 1;
+ *NextTag = L'=';
+ StringPtr = StrStr (StringPtr, L"&");
+ } else if (NextTag != NULL) {
+ //
+ // restore the '&' text.
+ //
+ StringPtr = NextTag;
+ *NextTag = L'&';
+ }
+ }
+
+ return RequestBlockArray;
+
+Done:
+ if (RequestBlockArray != NULL) {
+ //
+ // Free Link Array RequestBlockArray
+ //
+ while (!IsListEmpty (&RequestBlockArray->Entry)) {
+ BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
+ RemoveEntryList (&BlockData->Entry);
+ if (BlockData->Name != NULL) {
+ FreePool (BlockData->Name);
+ }
+
+ FreePool (BlockData);
+ }
+
+ FreePool (RequestBlockArray);
+ }
+
+ return NULL;
+}
+
+/**
+ Generate ConfigRequest string base on the varstore info.
+
+ @param ConfigHdr The config header for this varstore.
+ @param VarStorageData The varstore info.
+ @param Status Return Status.
+ @param ConfigRequest The ConfigRequest info may be return.
+
+ @retval TRUE Need to continue
+ @retval Others NO need to continue or error occur.
+**/
+BOOLEAN
+GenerateConfigRequest (
+ IN CHAR16 *ConfigHdr,
+ IN IFR_VARSTORAGE_DATA *VarStorageData,
+ OUT EFI_STATUS *Status,
+ IN OUT EFI_STRING *ConfigRequest
+ )
+{
+ BOOLEAN DataExist;
+ UINTN Length;
+ LIST_ENTRY *Link;
+ CHAR16 *FullConfigRequest;
+ CHAR16 *StringPtr;
+ IFR_BLOCK_DATA *BlockData;
+
+ //
+ // Append VarStorageData BlockEntry into *Request string
+ // Now support only one varstore in a form package.
+ //
+
+ //
+ // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
+ // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
+ //
+
+ //
+ // Compute the length of the entire request starting with <ConfigHdr> and a
+ // Null-terminator
+ //
+ DataExist = FALSE;
+ Length = StrLen (ConfigHdr) + 1;
+
+ for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
+ DataExist = TRUE;
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ //
+ // Add <BlockName> length for each Name
+ //
+ // <BlockName> ::= &Name1&Name2&...
+ // |1| StrLen(Name1)
+ //
+ Length = Length + (1 + StrLen (BlockData->Name));
+ } else {
+ //
+ // Add <BlockName> length for each Offset/Width pair
+ //
+ // <BlockName> ::= &OFFSET=1234&WIDTH=1234
+ // | 8 | 4 | 7 | 4 |
+ //
+ Length = Length + (8 + 4 + 7 + 4);
+ }
+ }
+
+ //
+ // No any request block data is found. The request string can't be constructed.
+ //
+ if (!DataExist) {
+ *Status = EFI_SUCCESS;
+ return FALSE;
+ }
+
+ //
+ // Allocate buffer for the entire <ConfigRequest>
+ //
+ FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));
+ if (FullConfigRequest == NULL) {
+ *Status = EFI_OUT_OF_RESOURCES;
+ return FALSE;
+ }
+
+ StringPtr = FullConfigRequest;
+
+ //
+ // Start with <ConfigHdr>
+ //
+ StrCpyS (StringPtr, Length, ConfigHdr);
+ StringPtr += StrLen (StringPtr);
+
+ //
+ // Loop through all the Offset/Width pairs and append them to ConfigRequest
+ //
+ for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ //
+ // Append &Name1\0
+ //
+ UnicodeSPrint (
+ StringPtr,
+ (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),
+ L"&%s",
+ BlockData->Name
+ );
+ } else {
+ //
+ // Append &OFFSET=XXXX&WIDTH=YYYY\0
+ //
+ UnicodeSPrint (
+ StringPtr,
+ (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
+ L"&OFFSET=%04X&WIDTH=%04X",
+ BlockData->Offset,
+ BlockData->Width
+ );
+ }
+
+ StringPtr += StrLen (StringPtr);
+ }
+
+ //
+ // Set to the got full request string.
+ //
+ HiiToLower (FullConfigRequest);
+
+ if (*ConfigRequest != NULL) {
+ FreePool (*ConfigRequest);
+ }
+
+ *ConfigRequest = FullConfigRequest;
+
+ return TRUE;
+}
+
+/**
+ Generate ConfigRequest Header base on the varstore info.
+
+ @param VarStorageData The varstore info.
+ @param DevicePath Device path for this varstore.
+ @param ConfigHdr The config header for this varstore.
+
+ @retval EFI_SUCCESS Generate the header success.
+ @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
+**/
+EFI_STATUS
+GenerateHdr (
+ IN IFR_VARSTORAGE_DATA *VarStorageData,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT EFI_STRING *ConfigHdr
+ )
+{
+ EFI_STRING GuidStr;
+ EFI_STRING NameStr;
+ EFI_STRING PathStr;
+ UINTN Length;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ NameStr = NULL;
+ GuidStr = NULL;
+ PathStr = NULL;
+
+ //
+ // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
+ //
+ GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)&VarStorageData->Guid, 1, &GuidStr);
+ if (VarStorageData->Name != NULL) {
+ GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *)VarStorageData->Name, 2, &NameStr);
+ } else {
+ GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
+ }
+
+ GenerateSubStr (
+ L"PATH=",
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DevicePath),
+ (VOID *)DevicePath,
+ 1,
+ &PathStr
+ );
+ Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;
+ if (VarStorageData->Name == NULL) {
+ Length += 1;
+ }
+
+ *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));
+ if (*ConfigHdr == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ StrCpyS (*ConfigHdr, Length, GuidStr);
+ StrCatS (*ConfigHdr, Length, NameStr);
+ if (VarStorageData->Name == NULL) {
+ StrCatS (*ConfigHdr, Length, L"&");
+ }
+
+ StrCatS (*ConfigHdr, Length, PathStr);
+
+ //
+ // Remove the last character L'&'
+ //
+ *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';
+
+Done:
+ if (GuidStr != NULL) {
+ FreePool (GuidStr);
+ }
+
+ if (NameStr != NULL) {
+ FreePool (NameStr);
+ }
+
+ if (PathStr != NULL) {
+ FreePool (PathStr);
+ }
+
+ return Status;
+}
+
+/**
+ Update the default value in the block data which is used as bit var store.
+
+ For example:
+ A question value saved in a bit fied: bitoffset = 1; bitwidth = 2;default value = 1.
+ And corresponding block data info: offset==0; width==1;currently the default value
+ is saved as 1.Actually the default value 1 need to be set to bit field 1, so the
+ default value of this block data shuold be:2.
+
+ typedef struct {
+ UINT8 Bit1 : 1; //
+ UINT8 Bit2 : 2; // Question saved in Bit2,so originalBlock info: offset = 0; width = 1;(byte level) defaul = 1.
+ // (default value record for the bit field)
+ ......
+ }ExampleData;
+
+ After function UpdateDefaultValue,the Block info is: offset = 0; width = 1;(byte level) default = 2.
+ (default value record for the Block)
+
+ UpdateDefaultValue function update default value of bit var block based on the bit field info in the block.
+
+ @param BlockLink The Link of the block data.
+
+**/
+VOID
+UpdateDefaultValue (
+ IN LIST_ENTRY *BlockLink
+ )
+{
+ LIST_ENTRY *Link;
+ LIST_ENTRY *ListEntry;
+ LIST_ENTRY *LinkDefault;
+ IFR_BLOCK_DATA *BlockData;
+ IFR_DEFAULT_DATA *DefaultValueData;
+ UINTN StartBit;
+ UINTN EndBit;
+ UINT32 BitFieldDefaultValue;
+
+ for ( Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
+ if (!BlockData->IsBitVar) {
+ continue;
+ }
+
+ ListEntry = &BlockData->DefaultValueEntry;
+ //
+ // Update the default value in the block data with all existing default id.
+ //
+ for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
+ //
+ // Get the default data, and the value of the default data is for some field in the block.
+ // Note: Default value for bit field question is stored as UINT32.
+ //
+ DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
+ BitFieldDefaultValue = DefaultValueData->Value.u32;
+
+ StartBit = BlockData->BitOffset % 8;
+ EndBit = StartBit + BlockData->BitWidth - 1;
+
+ //
+ // Set the bit field default value to related bit filed, then we will got the new default vaule for the block data.
+ //
+ DefaultValueData->Value.u32 = BitFieldWrite32 (0, StartBit, EndBit, BitFieldDefaultValue);
+ }
+ }
+}
+
+/**
+Merge the default value in two block datas which have overlap region.
+
+For bit fields, their related block data may have overlap region, such as:
+
+typedef struct {
+ UINT16 Bit1 : 6; // Question1 refer Bit1, Block1: offset = 0; width = 1;(byte level) default = 1
+ UINT16 Bit2 : 5; // Question2 refer Bit2, Block2: offset = 0; width = 2;(byte level) default = 5
+ // (default value record for the bit field)
+ ......
+}ExampleData;
+
+After function UpdateDefaultValue:
+Block1: offset = 0; width = 1;(byte level) default = 1
+Block2: offset = 0; width = 2;(byte level) default = 320 (5 * (2 << 6))
+(default value record for block)
+
+After function MergeBlockDefaultValue:
+Block1: offset = 0; width = 1;(byte level) default = 65
+Block2: offset = 0; width = 2;(byte level) default = 321
+(Block1 and Block2 has overlap region, merge the overlap value to Block1 and Blcok2)
+
+Block1 and Block2 have overlap byte region, but currntly the default value of Block1 only contains
+value of Bit1 (low 6 bits),the default value of Block2 only contains the value of Bit2 (middle 5 bits).
+
+This fuction merge the default value of these two blocks, and make the default value of block1
+also contain the value of lower 2 bits of the Bit2. And make the default value of Block2 also
+contain the default value of Bit1.
+
+We can get the total value of the whole block that just cover these two blocks(in this case is:
+block: offset =0; width =2;) then the value of block2 is same as block, the value of block1 is
+the first byte value of block.
+
+@param FirstBlock Point to the block date whose default value need to be merged.
+@param SecondBlock Point to the block date whose default value need to be merged.
+
+**/
+VOID
+MergeBlockDefaultValue (
+ IN OUT IFR_BLOCK_DATA *FirstBlock,
+ IN OUT IFR_BLOCK_DATA *SecondBlock
+ )
+{
+ LIST_ENTRY *FirstListEntry;
+ LIST_ENTRY *SecondListEntry;
+ LIST_ENTRY *FirstDefaultLink;
+ LIST_ENTRY *SecondDefaultLink;
+ IFR_DEFAULT_DATA *FirstDefaultValueData;
+ IFR_DEFAULT_DATA *SecondDefaultValueData;
+ UINT32 *FirstDefaultValue;
+ UINT32 *SecondDefaultValue;
+ UINT64 TotalValue;
+ UINT64 ShiftedValue;
+ UINT16 OffsetShift;
+
+ FirstListEntry = &FirstBlock->DefaultValueEntry;
+ for (FirstDefaultLink = FirstListEntry->ForwardLink; FirstDefaultLink != FirstListEntry; FirstDefaultLink = FirstDefaultLink->ForwardLink) {
+ FirstDefaultValueData = BASE_CR (FirstDefaultLink, IFR_DEFAULT_DATA, Entry);
+ SecondListEntry = &SecondBlock->DefaultValueEntry;
+ for (SecondDefaultLink = SecondListEntry->ForwardLink; SecondDefaultLink != SecondListEntry; SecondDefaultLink = SecondDefaultLink->ForwardLink) {
+ SecondDefaultValueData = BASE_CR (SecondDefaultLink, IFR_DEFAULT_DATA, Entry);
+ if (FirstDefaultValueData->DefaultId != SecondDefaultValueData->DefaultId) {
+ continue;
+ }
+
+ //
+ // Find default value with same default id in the two blocks.
+ // Note: Default value for bit field question is stored as UINT32 type.
+ //
+ FirstDefaultValue = &FirstDefaultValueData->Value.u32;
+ SecondDefaultValue = &SecondDefaultValueData->Value.u32;
+ //
+ // 1. Get the default value of the whole blcok that can just cover FirstBlock and SecondBlock.
+ // 2. Get the default value of FirstBlock and SecondBlock form the value of whole block based
+ // on the offset and width of FirstBlock and SecondBlock.
+ //
+ if (FirstBlock->Offset > SecondBlock->Offset) {
+ OffsetShift = FirstBlock->Offset - SecondBlock->Offset;
+ ShiftedValue = LShiftU64 ((UINT64)(*FirstDefaultValue), OffsetShift * 8);
+ TotalValue = ShiftedValue | (UINT64)(*SecondDefaultValue);
+ *SecondDefaultValue = (UINT32)BitFieldRead64 (TotalValue, 0, SecondBlock->Width * 8 -1);
+ *FirstDefaultValue = (UINT32)BitFieldRead64 (TotalValue, OffsetShift * 8, OffsetShift * 8 + FirstBlock->Width *8 -1);
+ } else {
+ OffsetShift = SecondBlock->Offset -FirstBlock->Offset;
+ ShiftedValue = LShiftU64 ((UINT64)(*SecondDefaultValue), OffsetShift * 8);
+ TotalValue = ShiftedValue | (UINT64)(*FirstDefaultValue);
+ *FirstDefaultValue = (UINT32)BitFieldRead64 (TotalValue, 0, FirstBlock->Width * 8 -1);
+ *SecondDefaultValue = (UINT32)BitFieldRead64 (TotalValue, OffsetShift * 8, OffsetShift * 8 + SecondBlock->Width *8 -1);
+ }
+ }
+ }
+}
+
+/**
+
+Update the default value in the block data which used as Bit VarStore
+
+@param BlockLink The Link of the block data.
+
+**/
+VOID
+UpdateBlockDataArray (
+ IN LIST_ENTRY *BlockLink
+ )
+{
+ LIST_ENTRY *Link;
+ LIST_ENTRY *TempLink;
+ IFR_BLOCK_DATA *BlockData;
+ IFR_BLOCK_DATA *NextBlockData;
+
+ //
+ // 1. Update default value in BitVar block data.
+ // Sine some block datas are used as BitVarStore, then the default value recored in the block
+ // is for related bit field in the block. so we need to set the default value to the related bit
+ // fields in the block data if the block data is used as bit varstore, then the default value of
+ // the block will be updated.
+ //
+ UpdateDefaultValue (BlockLink);
+
+ //
+ // 2.Update default value for overlap BitVar blcok datas.
+ // For block datas have overlap region, we need to merge the default value in different blocks.
+ //
+ for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
+ if (!BlockData->IsBitVar) {
+ continue;
+ }
+
+ for (TempLink = Link->ForwardLink; TempLink != BlockLink; TempLink = TempLink->ForwardLink) {
+ NextBlockData = BASE_CR (TempLink, IFR_BLOCK_DATA, Entry);
+ if (!NextBlockData->IsBitVar || (NextBlockData->Offset >= BlockData->Offset + BlockData->Width) || (BlockData->Offset >= NextBlockData->Offset + NextBlockData->Width)) {
+ continue;
+ }
+
+ //
+ // Find two blocks are used as bit VarStore and have overlap region, so need to merge default value of these two blocks.
+ //
+ MergeBlockDefaultValue (BlockData, NextBlockData);
+ }
+ }
+}
+
+/**
+ Generate ConfigAltResp string base on the varstore info.
+
+ @param HiiHandle Hii Handle for this hii package.
+ @param ConfigHdr The config header for this varstore.
+ @param VarStorageData The varstore info.
+ @param DefaultIdArray The Default id array.
+ @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
+
+ @retval TRUE Need to continue
+ @retval Others NO need to continue or error occur.
+**/
+EFI_STATUS
+GenerateAltConfigResp (
+ IN EFI_HII_HANDLE HiiHandle,
+ IN CHAR16 *ConfigHdr,
+ IN IFR_VARSTORAGE_DATA *VarStorageData,
+ IN IFR_DEFAULT_DATA *DefaultIdArray,
+ IN OUT EFI_STRING *DefaultAltCfgResp
+ )
+{
+ BOOLEAN DataExist;
+ UINTN Length;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *LinkData;
+ LIST_ENTRY *LinkDefault;
+ LIST_ENTRY *ListEntry;
+ CHAR16 *StringPtr;
+ IFR_BLOCK_DATA *BlockData;
+ IFR_DEFAULT_DATA *DefaultId;
+ IFR_DEFAULT_DATA *DefaultValueData;
+ UINTN Width;
+ UINT8 *TmpBuffer;
+ CHAR16 *DefaultString;
+ UINTN StrSize;
+
+ BlockData = NULL;
+ DataExist = FALSE;
+ DefaultString = NULL;
+ //
+ // Add length for <ConfigHdr> + '\0'
+ //
+ Length = StrLen (ConfigHdr) + 1;
+
+ UpdateBlockDataArray (&VarStorageData->BlockEntry);
+
+ for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
+ DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
+ //
+ // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
+ // |1| StrLen (ConfigHdr) | 8 | 4 |
+ //
+ Length += (1 + StrLen (ConfigHdr) + 8 + 4);
+
+ for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
+ BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
+ ListEntry = &BlockData->DefaultValueEntry;
+ for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
+ DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
+ if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
+ continue;
+ }
+
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ //
+ // Add length for "&Name1=zzzzzzzzzzzz"
+ // |1|Name|1|Value|
+ //
+ Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);
+ } else {
+ //
+ // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
+ // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
+ //
+ Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);
+ }
+
+ DataExist = TRUE;
+ }
+ }
+ }
+
+ //
+ // No default value is found. The default string doesn't exist.
+ //
+ if (!DataExist) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Allocate buffer for the entire <DefaultAltCfgResp>
+ //
+ *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
+ if (*DefaultAltCfgResp == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StringPtr = *DefaultAltCfgResp;
+
+ //
+ // Start with <ConfigHdr>
+ //
+ StrCpyS (StringPtr, Length, ConfigHdr);
+ StringPtr += StrLen (StringPtr);
+
+ for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
+ DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
+ //
+ // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
+ // |1| StrLen (ConfigHdr) | 8 | 4 |
+ //
+ UnicodeSPrint (
+ StringPtr,
+ (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
+ L"&%s&ALTCFG=%04X",
+ ConfigHdr,
+ DefaultId->DefaultId
+ );
+ StringPtr += StrLen (StringPtr);
+
+ for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
+ BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
+ ListEntry = &BlockData->DefaultValueEntry;
+ for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
+ DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
+ if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
+ continue;
+ }
+
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ UnicodeSPrint (
+ StringPtr,
+ (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16),
+ L"&%s=",
+ BlockData->Name
+ );
+ StringPtr += StrLen (StringPtr);
+ } else {
+ //
+ // Add <BlockConfig>
+ // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
+ //
+ UnicodeSPrint (
+ StringPtr,
+ (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),
+ L"&OFFSET=%04X&WIDTH=%04X&VALUE=",
+ BlockData->Offset,
+ BlockData->Width
+ );
+ StringPtr += StrLen (StringPtr);
+ }
+
+ Width = BlockData->Width;
+ //
+ // Convert Value to a hex string in "%x" format
+ // NOTE: This is in the opposite byte that GUID and PATH use
+ //
+ if (BlockData->OpCode == EFI_IFR_STRING_OP) {
+ DefaultString = InternalGetString (HiiHandle, DefaultValueData->Value.string);
+ TmpBuffer = AllocateZeroPool (Width);
+ ASSERT (TmpBuffer != NULL);
+ if (DefaultString != NULL) {
+ StrSize = StrLen (DefaultString)* sizeof (CHAR16);
+ if (StrSize > Width) {
+ StrSize = Width;
+ }
+
+ CopyMem (TmpBuffer, (UINT8 *)DefaultString, StrSize);
+ }
+ } else {
+ TmpBuffer = (UINT8 *)&(DefaultValueData->Value);
+ }
+
+ for ( ; Width > 0 && (TmpBuffer != NULL); Width--) {
+ UnicodeValueToStringS (
+ StringPtr,
+ Length * sizeof (CHAR16) - ((UINTN)StringPtr - (UINTN)*DefaultAltCfgResp),
+ PREFIX_ZERO | RADIX_HEX,
+ TmpBuffer[Width - 1],
+ 2
+ );
+ StringPtr += StrnLenS (StringPtr, Length - ((UINTN)StringPtr - (UINTN)*DefaultAltCfgResp) / sizeof (CHAR16));
+ }
+
+ if (DefaultString != NULL) {
+ FreePool (DefaultString);
+ DefaultString = NULL;
+ }
+
+ if ((BlockData->OpCode == EFI_IFR_STRING_OP) && (TmpBuffer != NULL)) {
+ FreePool (TmpBuffer);
+ TmpBuffer = NULL;
+ }
+ }
+ }
+ }
+
+ HiiToLower (*DefaultAltCfgResp);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function gets the full request string and full default value string by
+ parsing IFR data in HII form packages.
+
+ When Request points to NULL string, the request string and default value string
+ for each varstore in form package will return.
+
+ @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
+ @param DevicePath Device Path which Hii Config Access Protocol is registered.
+ @param Request Pointer to a null-terminated Unicode string in
+ <ConfigRequest> format. When it doesn't contain
+ any RequestElement, it will be updated to return
+ the full RequestElement retrieved from IFR data.
+ If it points to NULL, the request string for the first
+ varstore in form package will be merged into a
+ <MultiConfigRequest> format string and return.
+ @param AltCfgResp Pointer to a null-terminated Unicode string in
+ <ConfigAltResp> format. When the pointer is to NULL,
+ the full default value string retrieved from IFR data
+ will return. When the pinter is to a string, the
+ full default value string retrieved from IFR data
+ will be merged into the input string and return.
+ When Request points to NULL, the default value string
+ for each varstore in form package will be merged into
+ a <MultiConfigAltResp> format string and return.
+ @param PointerProgress Optional parameter, it can be NULL.
+ When it is not NULL, if Request is NULL, it returns NULL.
+ On return, points to a character in the Request
+ string. Points to the string's null terminator if
+ 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.
+ @retval EFI_SUCCESS The Results string is set to the full request string.
+ And AltCfgResp contains all default value string.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
+ @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
+ can't be found in Form package.
+ @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
+ @retval EFI_INVALID_PARAMETER Request points to NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+GetFullStringFromHiiFormPackages (
+ IN HII_DATABASE_RECORD *DataBaseRecord,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN OUT EFI_STRING *Request,
+ IN OUT EFI_STRING *AltCfgResp,
+ OUT EFI_STRING *PointerProgress OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *HiiFormPackage;
+ UINTN PackageSize;
+ IFR_BLOCK_DATA *RequestBlockArray;
+ IFR_BLOCK_DATA *BlockData;
+ IFR_DEFAULT_DATA *DefaultValueData;
+ IFR_DEFAULT_DATA *DefaultId;
+ IFR_DEFAULT_DATA *DefaultIdArray;
+ IFR_VARSTORAGE_DATA *VarStorageData;
+ EFI_STRING DefaultAltCfgResp;
+ EFI_STRING ConfigHdr;
+ EFI_STRING StringPtr;
+ EFI_STRING Progress;
+
+ if ((DataBaseRecord == NULL) || (DevicePath == NULL) || (Request == NULL) || (AltCfgResp == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Initialize the local variables.
+ //
+ RequestBlockArray = NULL;
+ DefaultIdArray = NULL;
+ VarStorageData = NULL;
+ DefaultAltCfgResp = NULL;
+ ConfigHdr = NULL;
+ HiiFormPackage = NULL;
+ PackageSize = 0;
+ Progress = *Request;
+
+ Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // 1. Get the request block array by Request String when Request string contains the block array.
+ //
+ StringPtr = NULL;
+ if (*Request != NULL) {
+ StringPtr = *Request;
+ //
+ // Jump <ConfigHdr>
+ //
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ StringPtr += StrLen (L"GUID=");
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
+ StringPtr++;
+ }
+
+ if (*StringPtr == L'\0') {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ StringPtr += StrLen (L"&NAME=");
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
+ StringPtr++;
+ }
+
+ if (*StringPtr == L'\0') {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ StringPtr += StrLen (L"&PATH=");
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {
+ StringPtr++;
+ }
+
+ if (*StringPtr == L'\0') {
+ //
+ // No request block is found.
+ //
+ StringPtr = NULL;
+ }
+ }
+
+ //
+ // If StringPtr != NULL, get the request elements.
+ //
+ if (StringPtr != NULL) {
+ if (StrStr (StringPtr, L"&OFFSET=") != NULL) {
+ RequestBlockArray = GetBlockElement (StringPtr, &Progress);
+ } else {
+ RequestBlockArray = GetNameElement (StringPtr, &Progress);
+ }
+
+ if (RequestBlockArray == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+ }
+
+ //
+ // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
+ //
+ DefaultIdArray = (IFR_DEFAULT_DATA *)AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
+ if (DefaultIdArray == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ InitializeListHead (&DefaultIdArray->Entry);
+
+ //
+ // Initialize VarStorageData to store the var store Block and Default value information.
+ //
+ VarStorageData = (IFR_VARSTORAGE_DATA *)AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));
+ if (VarStorageData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ InitializeListHead (&VarStorageData->Entry);
+ InitializeListHead (&VarStorageData->BlockEntry);
+
+ //
+ // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
+ //
+
+ //
+ // Parse the opcode in form package to get the default setting.
+ //
+ Status = ParseIfrData (
+ DataBaseRecord->Handle,
+ HiiFormPackage,
+ (UINT32)PackageSize,
+ *Request,
+ RequestBlockArray,
+ VarStorageData,
+ DefaultIdArray
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // No requested varstore in IFR data and directly return
+ //
+ if ((VarStorageData->Type == 0) && (VarStorageData->Name == NULL)) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ //
+ // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
+ //
+ Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (RequestBlockArray == NULL) {
+ if (!GenerateConfigRequest (ConfigHdr, VarStorageData, &Status, Request)) {
+ goto Done;
+ }
+ }
+
+ //
+ // 4. Construct Default Value string in AltResp according to request element.
+ // Go through all VarStorageData Entry and get the DefaultId array for each one
+ // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
+ //
+ Status = GenerateAltConfigResp (DataBaseRecord->Handle, ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // 5. Merge string into the input AltCfgResp if the input *AltCfgResp is not NULL.
+ //
+ if ((*AltCfgResp != NULL) && (DefaultAltCfgResp != NULL)) {
+ Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);
+ FreePool (DefaultAltCfgResp);
+ } else if (*AltCfgResp == NULL) {
+ *AltCfgResp = DefaultAltCfgResp;
+ }
+
+Done:
+ if (RequestBlockArray != NULL) {
+ //
+ // Free Link Array RequestBlockArray
+ //
+ while (!IsListEmpty (&RequestBlockArray->Entry)) {
+ BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
+ RemoveEntryList (&BlockData->Entry);
+ if (BlockData->Name != NULL) {
+ FreePool (BlockData->Name);
+ }
+
+ FreePool (BlockData);
+ }
+
+ FreePool (RequestBlockArray);
+ }
+
+ if (VarStorageData != NULL) {
+ //
+ // Free link array VarStorageData
+ //
+ while (!IsListEmpty (&VarStorageData->BlockEntry)) {
+ BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);
+ RemoveEntryList (&BlockData->Entry);
+ if (BlockData->Name != NULL) {
+ FreePool (BlockData->Name);
+ }
+
+ //
+ // Free default value link array
+ //
+ while (!IsListEmpty (&BlockData->DefaultValueEntry)) {
+ DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);
+ RemoveEntryList (&DefaultValueData->Entry);
+ FreePool (DefaultValueData);
+ }
+
+ FreePool (BlockData);
+ }
+
+ if (VarStorageData->Name != NULL) {
+ FreePool (VarStorageData->Name);
+ VarStorageData->Name = NULL;
+ }
+
+ FreePool (VarStorageData);
+ }
+
+ if (DefaultIdArray != NULL) {
+ //
+ // Free DefaultId Array
+ //
+ while (!IsListEmpty (&DefaultIdArray->Entry)) {
+ DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);
+ RemoveEntryList (&DefaultId->Entry);
+ FreePool (DefaultId);
+ }
+
+ FreePool (DefaultIdArray);
+ }
+
+ //
+ // Free the allocated string
+ //
+ if (ConfigHdr != NULL) {
+ FreePool (ConfigHdr);
+ }
+
+ //
+ // Free Package data
+ //
+ if (HiiFormPackage != NULL) {
+ FreePool (HiiFormPackage);
+ }
+
+ if (PointerProgress != NULL) {
+ if (*Request == NULL) {
+ *PointerProgress = NULL;
+ } else if (EFI_ERROR (Status)) {
+ *PointerProgress = *Request;
+ } else {
+ *PointerProgress = *Request + StrLen (*Request);
+ }
+ }
+
+ return Status;
+}
+
+/**
+ This function gets the full request resp string by
+ parsing IFR data in HII form packages.
+
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+ instance.
+ @param EfiVarStoreInfo The efi varstore info which is save in the EFI
+ varstore data structure.
+ @param Request Pointer to a null-terminated Unicode string in
+ <ConfigRequest> format.
+ @param RequestResp Pointer to a null-terminated Unicode string in
+ <ConfigResp> format.
+ @param AccessProgress On return, points to a character in the Request
+ string. Points to the string's null terminator if
+ 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.
+
+ @retval EFI_SUCCESS The Results string is set to the full request string.
+ And AltCfgResp contains all default value string.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
+ @retval EFI_INVALID_PARAMETER Request points to NULL.
+
+**/
+EFI_STATUS
+GetConfigRespFromEfiVarStore (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
+ IN EFI_STRING Request,
+ OUT EFI_STRING *RequestResp,
+ OUT EFI_STRING *AccessProgress
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING VarStoreName;
+ UINTN NameSize;
+ UINT8 *VarStore;
+ UINTN BufferSize;
+
+ Status = EFI_SUCCESS;
+ BufferSize = 0;
+ VarStore = NULL;
+ VarStoreName = NULL;
+ *AccessProgress = Request;
+
+ NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);
+ VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
+ if (VarStoreName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ AsciiStrToUnicodeStrS ((CHAR8 *)EfiVarStoreInfo->Name, VarStoreName, NameSize);
+
+ Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ goto Done;
+ }
+
+ VarStore = AllocateZeroPool (BufferSize);
+ ASSERT (VarStore != NULL);
+ Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = HiiBlockToConfig (This, Request, VarStore, BufferSize, RequestResp, AccessProgress);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+Done:
+ if (VarStoreName != NULL) {
+ FreePool (VarStoreName);
+ }
+
+ if (VarStore != NULL) {
+ FreePool (VarStore);
+ }
+
+ return Status;
+}
+
+/**
+ This function route the full request resp string for efi varstore.
+
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+ instance.
+ @param EfiVarStoreInfo The efi varstore info which is save in the EFI
+ varstore data structure.
+ @param RequestResp Pointer to a null-terminated Unicode string in
+ <ConfigResp> format.
+ @param Result Pointer to a null-terminated Unicode string in
+ <ConfigResp> format.
+
+ @retval EFI_SUCCESS The Results string is set to the full request string.
+ And AltCfgResp contains all default value string.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
+ @retval EFI_INVALID_PARAMETER Request points to NULL.
+
+**/
+EFI_STATUS
+RouteConfigRespForEfiVarStore (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
+ IN EFI_STRING RequestResp,
+ OUT EFI_STRING *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING VarStoreName;
+ UINTN NameSize;
+ UINT8 *VarStore;
+ UINTN BufferSize;
+ UINTN BlockSize;
+
+ Status = EFI_SUCCESS;
+ BufferSize = 0;
+ VarStore = NULL;
+ VarStoreName = NULL;
+ *Result = RequestResp;
+
+ NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);
+ VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
+ if (VarStoreName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ AsciiStrToUnicodeStrS ((CHAR8 *)EfiVarStoreInfo->Name, VarStoreName, NameSize);
+
+ Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ DEBUG ((DEBUG_ERROR, "The variable does not exist!"));
+ goto Done;
+ }
+
+ BlockSize = BufferSize;
+ VarStore = AllocateZeroPool (BufferSize);
+ ASSERT (VarStore != NULL);
+ Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = HiiConfigToBlock (This, RequestResp, VarStore, &BlockSize, Result);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);
+ if (EFI_ERROR (Status)) {
+ *Result = RequestResp;
+ goto Done;
+ }
+
+Done:
+ if (VarStoreName != NULL) {
+ FreePool (VarStoreName);
+ }
+
+ if (VarStore != NULL) {
+ FreePool (VarStore);
+ }
+
+ return Status;
+}
+
+/**
+ Validate the config request elements.
+
+ @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
+ without configHdr field.
+
+ @retval CHAR16 * THE first Name/value pair not correct.
+ @retval NULL Success parse the name/value pair
+**/
+CHAR16 *
+OffsetWidthValidate (
+ CHAR16 *ConfigElements
+ )
+{
+ CHAR16 *StringPtr;
+ CHAR16 *RetVal;
+
+ StringPtr = ConfigElements;
+
+ while (1) {
+ RetVal = StringPtr;
+ if (StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
+ return RetVal;
+ }
+
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
+ StringPtr++;
+ }
+
+ if (*StringPtr == L'\0') {
+ return RetVal;
+ }
+
+ StringPtr += StrLen (L"&WIDTH=");
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
+ StringPtr++;
+ }
+
+ if (*StringPtr == L'\0') {
+ return NULL;
+ }
+ }
+}
+
+/**
+ Validate the config request elements.
+
+ @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
+ without configHdr field.
+
+ @retval CHAR16 * THE first Name/value pair not correct.
+ @retval NULL Success parse the name/value pair
+
+**/
+CHAR16 *
+NameValueValidate (
+ CHAR16 *ConfigElements
+ )
+{
+ CHAR16 *StringPtr;
+ CHAR16 *RetVal;
+
+ StringPtr = ConfigElements;
+
+ while (1) {
+ RetVal = StringPtr;
+ if (*StringPtr != L'&') {
+ return RetVal;
+ }
+
+ StringPtr += 1;
+
+ StringPtr = StrStr (StringPtr, L"&");
+
+ if (StringPtr == NULL) {
+ return NULL;
+ }
+ }
+}
+
+/**
+ Validate the config request string.
+
+ @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
+
+ @retval CHAR16 * THE first element not correct.
+ @retval NULL Success parse the name/value pair
+
+**/
+CHAR16 *
+ConfigRequestValidate (
+ CHAR16 *ConfigRequest
+ )
+{
+ BOOLEAN HasNameField;
+ CHAR16 *StringPtr;
+
+ HasNameField = TRUE;
+ StringPtr = ConfigRequest;
+
+ //
+ // Check <ConfigHdr>
+ //
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
+ return ConfigRequest;
+ }
+
+ StringPtr += StrLen (L"GUID=");
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
+ StringPtr++;
+ }
+
+ if (*StringPtr == L'\0') {
+ return ConfigRequest;
+ }
+
+ StringPtr += StrLen (L"&NAME=");
+ if (*StringPtr == L'&') {
+ HasNameField = FALSE;
+ }
+
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
+ StringPtr++;
+ }
+
+ if (*StringPtr == L'\0') {
+ return ConfigRequest;
+ }
+
+ StringPtr += StrLen (L"&PATH=");
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {
+ StringPtr++;
+ }
+
+ if (*StringPtr == L'\0') {
+ return NULL;
+ }
+
+ if (HasNameField) {
+ //
+ // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
+ //
+ return OffsetWidthValidate (StringPtr);
+ } else {
+ //
+ // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
+ //
+ return NameValueValidate (StringPtr);
+ }
+}
+
+/**
+ This function allows a caller to extract the current configuration
+ for one or more named elements from one or more drivers.
+
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+ instance.
+ @param Request A null-terminated Unicode string in
+ <MultiConfigRequest> format.
+ @param Progress On return, points to a character in the Request
+ string. Points to the string's null terminator if
+ 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 Results Null-terminated Unicode string in
+ <MultiConfigAltResp> format which has all values
+ filled in for the names in the Request string.
+ String to be allocated by the called function.
+
+ @retval EFI_SUCCESS The Results string is filled with the values
+ corresponding to all requested names.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
+ results that must be stored awaiting possible
+ future protocols.
+ @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
+ Progress set to the "G" in "GUID" of the routing
+ header that doesn't match. Note: There is no
+ requirement that all routing data be validated
+ before any configuration extraction.
+ @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
+ parameter would result in this type of error. The
+ Progress parameter is set to NULL.
+ @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
+ before the error or the beginning of the string.
+ @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
+ Configuration Access Protocol returned
+ EFI_INVALID_PARAMETER. Progress set to most recent
+ & before the error or the beginning of the string.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiConfigRoutingExtractConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_STRING StringPtr;
+ EFI_STRING ConfigRequest;
+ UINTN Length;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *Database;
+ UINT8 *DevicePathPkg;
+ UINT8 *CurrentDevicePath;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+ EFI_STRING AccessProgress;
+ EFI_STRING AccessResults;
+ EFI_STRING AccessProgressBackup;
+ EFI_STRING AccessResultsBackup;
+ EFI_STRING DefaultResults;
+ BOOLEAN FirstElement;
+ BOOLEAN IfrDataParsedFlag;
+ BOOLEAN IsEfiVarStore;
+ EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
+ EFI_STRING ErrorPtr;
+ UINTN DevicePathSize;
+ UINTN ConigStringSize;
+ UINTN ConigStringSizeNewsize;
+ EFI_STRING ConfigStringPtr;
+
+ if ((This == NULL) || (Progress == NULL) || (Results == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Request == NULL) {
+ *Progress = NULL;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ StringPtr = Request;
+ *Progress = StringPtr;
+ DefaultResults = NULL;
+ ConfigRequest = NULL;
+ Status = EFI_SUCCESS;
+ AccessResults = NULL;
+ AccessProgress = NULL;
+ AccessResultsBackup = NULL;
+ AccessProgressBackup = NULL;
+ DevicePath = NULL;
+ IfrDataParsedFlag = FALSE;
+ IsEfiVarStore = FALSE;
+ EfiVarStoreInfo = NULL;
+
+ //
+ // The first element of <MultiConfigRequest> should be
+ // <GuidHdr>, which is in 'GUID='<Guid> syntax.
+ //
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FirstElement = TRUE;
+
+ //
+ // Allocate a fix length of memory to store Results. Reallocate memory for
+ // Results if this fix length is insufficient.
+ //
+ *Results = (EFI_STRING)AllocateZeroPool (MAX_STRING_LENGTH);
+ if (*Results == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
+ //
+ // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
+ // or most recent & before the error.
+ //
+ if (StringPtr == Request) {
+ *Progress = StringPtr;
+ } else {
+ *Progress = StringPtr - 1;
+ }
+
+ //
+ // Process each <ConfigRequest> of <MultiConfigRequest>
+ //
+ Length = CalculateConfigStringLen (StringPtr);
+ ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
+ if (ConfigRequest == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ *(ConfigRequest + Length) = 0;
+
+ //
+ // Get the UEFI device path
+ //
+ Status = GetDevicePath (ConfigRequest, (UINT8 **)&DevicePath);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Find driver which matches the routing data.
+ //
+ DriverHandle = NULL;
+ HiiHandle = NULL;
+ Database = NULL;
+ for (Link = Private->DatabaseList.ForwardLink;
+ Link != &Private->DatabaseList;
+ Link = Link->ForwardLink
+ )
+ {
+ Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
+ CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
+ DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath);
+ if ((CompareMem (DevicePath, CurrentDevicePath, DevicePathSize) == 0) && IsThisPackageList (Database, ConfigRequest)) {
+ DriverHandle = Database->DriverHandle;
+ HiiHandle = Database->Handle;
+ break;
+ }
+ }
+ }
+
+ //
+ // Try to find driver handle by device path.
+ //
+ if (DriverHandle == NULL) {
+ TempDevicePath = DevicePath;
+ Status = gBS->LocateDevicePath (
+ &gEfiDevicePathProtocolGuid,
+ &TempDevicePath,
+ &DriverHandle
+ );
+ if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
+ //
+ // Routing data does not match any known driver.
+ // Set Progress to the 'G' in "GUID" of the routing header.
+ //
+ *Progress = StringPtr;
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ }
+
+ //
+ // Validate ConfigRequest String.
+ //
+ ErrorPtr = ConfigRequestValidate (ConfigRequest);
+ if (ErrorPtr != NULL) {
+ *Progress = StrStr (StringPtr, ErrorPtr);
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Check whether ConfigRequest contains request string.
+ //
+ IfrDataParsedFlag = FALSE;
+ if ((HiiHandle != NULL) && !GetElementsFromRequest (ConfigRequest)) {
+ //
+ // Get the full request string from IFR when HiiPackage is registered to HiiHandle
+ //
+ IfrDataParsedFlag = TRUE;
+ Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);
+ if (EFI_ERROR (Status)) {
+ //
+ // AccessProgress indicates the parsing progress on <ConfigRequest>.
+ // Map it to the progress on <MultiConfigRequest> then return it.
+ //
+ ASSERT (AccessProgress != NULL);
+ *Progress = StrStr (StringPtr, AccessProgress);
+ goto Done;
+ }
+
+ //
+ // Not any request block is found.
+ //
+ if (!GetElementsFromRequest (ConfigRequest)) {
+ AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
+ goto NextConfigString;
+ }
+ }
+
+ //
+ // Check whether this ConfigRequest is search from Efi varstore type storage.
+ //
+ Status = GetVarStoreType (Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (IsEfiVarStore) {
+ //
+ // Call the GetVariable function to extract settings.
+ //
+ Status = GetConfigRespFromEfiVarStore (This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);
+ FreePool (EfiVarStoreInfo);
+ if (EFI_ERROR (Status)) {
+ //
+ // AccessProgress indicates the parsing progress on <ConfigRequest>.
+ // Map it to the progress on <MultiConfigRequest> then return it.
+ //
+ *Progress = StrStr (StringPtr, AccessProgress);
+ goto Done;
+ }
+
+ //
+ // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
+ //
+ Status = gBS->HandleProtocol (
+ DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ (VOID **)&ConfigAccess
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // The driver has EfiVarStore, may not install ConfigAccess protocol.
+ // So ignore the error status in this case.
+ //
+ Status = EFI_SUCCESS;
+ } else {
+ Status = ConfigAccess->ExtractConfig (
+ ConfigAccess,
+ ConfigRequest,
+ &AccessProgressBackup,
+ &AccessResultsBackup
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Merge the AltCfgResp in AccessResultsBackup to AccessResults
+ //
+ if ((AccessResultsBackup != NULL) && (StrStr (AccessResultsBackup, L"&ALTCFG=") != NULL)) {
+ ConigStringSize = StrSize (AccessResults);
+ ConfigStringPtr = StrStr (AccessResultsBackup, L"&GUID=");
+ ConigStringSizeNewsize = StrSize (ConfigStringPtr) + ConigStringSize + sizeof (CHAR16);
+ AccessResults = (EFI_STRING)ReallocatePool (
+ ConigStringSize,
+ ConigStringSizeNewsize,
+ AccessResults
+ );
+ StrCatS (AccessResults, ConigStringSizeNewsize / sizeof (CHAR16), ConfigStringPtr);
+ }
+ } else {
+ //
+ // In the ExtractConfig function of some driver may not support EfiVarStore,
+ // may return error status, just ignore the error status in this case.
+ //
+ Status = EFI_SUCCESS;
+ }
+
+ if (AccessResultsBackup != NULL) {
+ FreePool (AccessResultsBackup);
+ AccessResultsBackup = NULL;
+ }
+ }
+ } else {
+ //
+ // Call corresponding ConfigAccess protocol to extract settings
+ //
+ Status = gBS->HandleProtocol (
+ DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ (VOID **)&ConfigAccess
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = ConfigAccess->ExtractConfig (
+ ConfigAccess,
+ ConfigRequest,
+ &AccessProgress,
+ &AccessResults
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // AccessProgress indicates the parsing progress on <ConfigRequest>.
+ // Map it to the progress on <MultiConfigRequest> then return it.
+ //
+ *Progress = StrStr (StringPtr, AccessProgress);
+ goto Done;
+ }
+
+ //
+ // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
+ // which separates the first <ConfigAltResp> and the following ones.
+ //
+ ASSERT (*AccessProgress == 0);
+
+ //
+ // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
+ //
+ if (!IfrDataParsedFlag && (HiiHandle != NULL)) {
+ Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ FreePool (DevicePath);
+ DevicePath = NULL;
+
+ if (DefaultResults != NULL) {
+ Status = MergeDefaultString (&AccessResults, DefaultResults);
+ ASSERT_EFI_ERROR (Status);
+ FreePool (DefaultResults);
+ DefaultResults = NULL;
+ }
+
+NextConfigString:
+ if (!FirstElement) {
+ Status = AppendToMultiString (Results, L"&");
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = AppendToMultiString (Results, AccessResults);
+ ASSERT_EFI_ERROR (Status);
+
+ FirstElement = FALSE;
+
+ FreePool (AccessResults);
+ AccessResults = NULL;
+ FreePool (ConfigRequest);
+ ConfigRequest = NULL;
+
+ //
+ // Go to next <ConfigRequest> (skip '&').
+ //
+ StringPtr += Length;
+ if (*StringPtr == 0) {
+ *Progress = StringPtr;
+ break;
+ }
+
+ StringPtr++;
+ }
+
+Done:
+ if (EFI_ERROR (Status)) {
+ FreePool (*Results);
+ *Results = NULL;
+ }
+
+ if (ConfigRequest != NULL) {
+ FreePool (ConfigRequest);
+ }
+
+ if (AccessResults != NULL) {
+ FreePool (AccessResults);
+ }
+
+ if (DefaultResults != NULL) {
+ FreePool (DefaultResults);
+ }
+
+ if (DevicePath != NULL) {
+ FreePool (DevicePath);
+ }
+
+ return Status;
+}
+
+/**
+ This function allows the caller to request the current configuration for the
+ entirety of the current HII database and returns the data in a
+ null-terminated Unicode string.
+
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+ instance.
+ @param Results Null-terminated Unicode string in
+ <MultiConfigAltResp> format which has all values
+ filled in for the entirety of the current HII
+ database. String to be allocated by the called
+ function. De-allocation is up to the caller.
+
+ @retval EFI_SUCCESS The Results string is filled with the values
+ corresponding to all requested names.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
+ results that must be stored awaiting possible
+ future protocols.
+ @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
+ parameter would result in this type of error.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiConfigRoutingExportConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ OUT EFI_STRING *Results
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+ EFI_STRING AccessResults;
+ EFI_STRING Progress;
+ EFI_STRING StringPtr;
+ EFI_STRING ConfigRequest;
+ UINTN Index;
+ EFI_HANDLE *ConfigAccessHandles;
+ UINTN NumberConfigAccessHandles;
+ BOOLEAN FirstElement;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_STRING DefaultResults;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *Database;
+ UINT8 *DevicePathPkg;
+ UINT8 *CurrentDevicePath;
+ BOOLEAN IfrDataParsedFlag;
+
+ if ((This == NULL) || (Results == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Allocate a fix length of memory to store Results. Reallocate memory for
+ // Results if this fix length is insufficient.
+ //
+ *Results = (EFI_STRING)AllocateZeroPool (MAX_STRING_LENGTH);
+ if (*Results == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NumberConfigAccessHandles = 0;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiHiiConfigAccessProtocolGuid,
+ NULL,
+ &NumberConfigAccessHandles,
+ &ConfigAccessHandles
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FirstElement = TRUE;
+
+ for (Index = 0; Index < NumberConfigAccessHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ ConfigAccessHandles[Index],
+ &gEfiHiiConfigAccessProtocolGuid,
+ (VOID **)&ConfigAccess
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Get DevicePath and HiiHandle for this ConfigAccess driver handle
+ //
+ IfrDataParsedFlag = FALSE;
+ Progress = NULL;
+ HiiHandle = NULL;
+ DefaultResults = NULL;
+ Database = NULL;
+ ConfigRequest = NULL;
+ DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);
+ if (DevicePath != NULL) {
+ for (Link = Private->DatabaseList.ForwardLink;
+ Link != &Private->DatabaseList;
+ Link = Link->ForwardLink
+ )
+ {
+ Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
+ CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
+ if (CompareMem (
+ DevicePath,
+ CurrentDevicePath,
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath)
+ ) == 0)
+ {
+ HiiHandle = Database->Handle;
+ break;
+ }
+ }
+ }
+ }
+
+ Status = ConfigAccess->ExtractConfig (
+ ConfigAccess,
+ NULL,
+ &Progress,
+ &AccessResults
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
+ //
+ if ((HiiHandle != NULL) && (DevicePath != NULL)) {
+ IfrDataParsedFlag = TRUE;
+ Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
+ //
+ // Get the full request string to get the Current setting again.
+ //
+ if (!EFI_ERROR (Status) && (ConfigRequest != NULL)) {
+ Status = ConfigAccess->ExtractConfig (
+ ConfigAccess,
+ ConfigRequest,
+ &Progress,
+ &AccessResults
+ );
+ FreePool (ConfigRequest);
+ } else {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ }
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
+ //
+ if (!IfrDataParsedFlag && (HiiHandle != NULL) && (DevicePath != NULL)) {
+ StringPtr = StrStr (AccessResults, L"&GUID=");
+ if (StringPtr != NULL) {
+ *StringPtr = 0;
+ }
+
+ if (GetElementsFromRequest (AccessResults)) {
+ Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (StringPtr != NULL) {
+ *StringPtr = L'&';
+ }
+ }
+
+ //
+ // Merge the default sting from IFR code into the got setting from driver.
+ //
+ if (DefaultResults != NULL) {
+ Status = MergeDefaultString (&AccessResults, DefaultResults);
+ ASSERT_EFI_ERROR (Status);
+ FreePool (DefaultResults);
+ DefaultResults = NULL;
+ }
+
+ //
+ // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
+ // which separates the first <ConfigAltResp> and the following ones.
+ //
+ if (!FirstElement) {
+ Status = AppendToMultiString (Results, L"&");
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = AppendToMultiString (Results, AccessResults);
+ ASSERT_EFI_ERROR (Status);
+
+ FirstElement = FALSE;
+
+ FreePool (AccessResults);
+ AccessResults = NULL;
+ }
+ }
+
+ FreePool (ConfigAccessHandles);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function processes the results of processing forms and routes it to the
+ appropriate handlers or storage.
+
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+ instance.
+ @param Configuration A null-terminated Unicode string in
+ <MulltiConfigResp> format.
+ @param Progress A pointer to a string filled in with the offset of
+ 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) or the
+ terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The results have been distributed or are awaiting
+ distribution.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
+ results that must be stored awaiting possible
+ future protocols.
+ @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
+ would result in this type of error.
+ @retval EFI_NOT_FOUND Target for the specified routing data was not
+ found.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiConfigRoutingRouteConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_STRING StringPtr;
+ EFI_STRING ConfigResp;
+ UINTN Length;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *Database;
+ UINT8 *DevicePathPkg;
+ UINT8 *CurrentDevicePath;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+ EFI_STRING AccessProgress;
+ EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
+ BOOLEAN IsEfiVarstore;
+ UINTN DevicePathSize;
+
+ if ((This == NULL) || (Progress == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Configuration == NULL) {
+ *Progress = NULL;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ StringPtr = Configuration;
+ *Progress = StringPtr;
+ Database = NULL;
+ AccessProgress = NULL;
+ EfiVarStoreInfo = NULL;
+ IsEfiVarstore = FALSE;
+
+ //
+ // The first element of <MultiConfigResp> should be
+ // <GuidHdr>, which is in 'GUID='<Guid> syntax.
+ //
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
+ //
+ // If parsing error, set Progress to the beginning of the <MultiConfigResp>
+ // or most recent & before the error.
+ //
+ if (StringPtr == Configuration) {
+ *Progress = StringPtr;
+ } else {
+ *Progress = StringPtr - 1;
+ }
+
+ //
+ // Process each <ConfigResp> of <MultiConfigResp>
+ //
+ Length = CalculateConfigStringLen (StringPtr);
+ ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
+ if (ConfigResp == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Append '\0' to the end of ConfigRequest
+ //
+ *(ConfigResp + Length) = 0;
+
+ //
+ // Get the UEFI device path
+ //
+ Status = GetDevicePath (ConfigResp, (UINT8 **)&DevicePath);
+ if (EFI_ERROR (Status)) {
+ FreePool (ConfigResp);
+ return Status;
+ }
+
+ //
+ // Find driver which matches the routing data.
+ //
+ DriverHandle = NULL;
+ for (Link = Private->DatabaseList.ForwardLink;
+ Link != &Private->DatabaseList;
+ Link = Link->ForwardLink
+ )
+ {
+ Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+
+ if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
+ CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
+ DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath);
+ if ((CompareMem (DevicePath, CurrentDevicePath, DevicePathSize) == 0) && IsThisPackageList (Database, ConfigResp)) {
+ DriverHandle = Database->DriverHandle;
+ break;
+ }
+ }
+ }
+
+ //
+ // Try to find driver handle by device path.
+ //
+ if (DriverHandle == NULL) {
+ TempDevicePath = DevicePath;
+ Status = gBS->LocateDevicePath (
+ &gEfiDevicePathProtocolGuid,
+ &TempDevicePath,
+ &DriverHandle
+ );
+ if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
+ //
+ // Routing data does not match any known driver.
+ // Set Progress to the 'G' in "GUID" of the routing header.
+ //
+ FreePool (DevicePath);
+ *Progress = StringPtr;
+ FreePool (ConfigResp);
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ FreePool (DevicePath);
+
+ //
+ // Check whether this ConfigRequest is search from Efi varstore type storage.
+ //
+ Status = GetVarStoreType (Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (IsEfiVarstore) {
+ //
+ // Call the SetVariable function to route settings.
+ //
+ Status = RouteConfigRespForEfiVarStore (This, EfiVarStoreInfo, ConfigResp, &AccessProgress);
+ FreePool (EfiVarStoreInfo);
+ } else {
+ //
+ // Call corresponding ConfigAccess protocol to route settings
+ //
+ Status = gBS->HandleProtocol (
+ DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ (VOID **)&ConfigAccess
+ );
+ if (EFI_ERROR (Status)) {
+ *Progress = StringPtr;
+ FreePool (ConfigResp);
+ return EFI_NOT_FOUND;
+ }
+
+ Status = ConfigAccess->RouteConfig (
+ ConfigAccess,
+ ConfigResp,
+ &AccessProgress
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ ASSERT (AccessProgress != NULL);
+ //
+ // AccessProgress indicates the parsing progress on <ConfigResp>.
+ // Map it to the progress on <MultiConfigResp> then return it.
+ //
+ *Progress = StrStr (StringPtr, AccessProgress);
+
+ FreePool (ConfigResp);
+ return Status;
+ }
+
+ FreePool (ConfigResp);
+ ConfigResp = NULL;
+
+ //
+ // Go to next <ConfigResp> (skip '&').
+ //
+ StringPtr += Length;
+ if (*StringPtr == 0) {
+ *Progress = StringPtr;
+ break;
+ }
+
+ StringPtr++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This helper function is to be called by drivers to map configuration data
+ stored in byte array ("block") formats such as UEFI Variables into current
+ configuration strings.
+
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+ instance.
+ @param ConfigRequest A null-terminated Unicode string in
+ <ConfigRequest> format.
+ @param Block Array of bytes defining the block's configuration.
+ @param BlockSize Length in bytes of Block.
+ @param Config Filled-in configuration string. String allocated
+ by the function. Returned only if call is
+ successful. It is <ConfigResp> string format.
+ @param Progress A pointer to a string filled in with the offset of
+ 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) or
+ the terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The request succeeded. Progress points to the null
+ terminator at the end of the ConfigRequest
+ string.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
+ points to the first character of ConfigRequest.
+ @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
+ Block parameter would result in this type of
+ error. Progress points to the first character of
+ ConfigRequest.
+ @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
+ @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
+ Block is left updated and Progress points at
+ the "&" preceding the first non-<BlockName>.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiBlockToConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING ConfigRequest,
+ IN CONST UINT8 *Block,
+ IN CONST UINTN BlockSize,
+ OUT EFI_STRING *Config,
+ OUT EFI_STRING *Progress
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_STRING StringPtr;
+ UINTN Length;
+ EFI_STATUS Status;
+ EFI_STRING TmpPtr;
+ UINT8 *TmpBuffer;
+ UINTN Offset;
+ UINTN Width;
+ UINT8 *Value;
+ EFI_STRING ValueStr;
+ EFI_STRING ConfigElement;
+ UINTN Index;
+ UINT8 *TemBuffer;
+ CHAR16 *TemString;
+
+ TmpBuffer = NULL;
+
+ if ((This == NULL) || (Progress == NULL) || (Config == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Block == NULL) || (ConfigRequest == NULL)) {
+ *Progress = ConfigRequest;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ ASSERT (Private != NULL);
+
+ StringPtr = ConfigRequest;
+ ValueStr = NULL;
+ Value = NULL;
+ ConfigElement = NULL;
+
+ //
+ // Allocate a fix length of memory to store Results. Reallocate memory for
+ // Results if this fix length is insufficient.
+ //
+ *Config = (EFI_STRING)AllocateZeroPool (MAX_STRING_LENGTH);
+ if (*Config == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Jump <ConfigHdr>
+ //
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
+ *Progress = StringPtr;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
+ StringPtr++;
+ }
+
+ if (*StringPtr == 0) {
+ *Progress = StringPtr - 1;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ while (*StringPtr != L'&' && *StringPtr != 0) {
+ StringPtr++;
+ }
+
+ if (*StringPtr == 0) {
+ *Progress = StringPtr;
+
+ AppendToMultiString (Config, ConfigRequest);
+ HiiToLower (*Config);
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Skip '&'
+ //
+ StringPtr++;
+
+ //
+ // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
+ //
+ TemString = AllocateCopyPool (sizeof (CHAR16) * (StringPtr - ConfigRequest + 1), ConfigRequest);
+ if (TemString == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ TemString[StringPtr - ConfigRequest] = '\0';
+ AppendToMultiString (Config, TemString);
+ FreePool (TemString);
+
+ //
+ // Parse each <RequestElement> if exists
+ // Only <BlockName> format is supported by this help function.
+ // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
+ //
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
+ //
+ // Back up the header of one <BlockName>
+ //
+ TmpPtr = StringPtr;
+
+ StringPtr += StrLen (L"OFFSET=");
+ //
+ // Get Offset
+ //
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ *Progress = TmpPtr - 1;
+ goto Exit;
+ }
+
+ Offset = 0;
+ CopyMem (
+ &Offset,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
+ );
+ FreePool (TmpBuffer);
+
+ StringPtr += Length;
+ if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
+ *Progress = TmpPtr - 1;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ StringPtr += StrLen (L"&WIDTH=");
+
+ //
+ // Get Width
+ //
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ *Progress = TmpPtr - 1;
+ goto Exit;
+ }
+
+ Width = 0;
+ CopyMem (
+ &Width,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
+ );
+ FreePool (TmpBuffer);
+
+ StringPtr += Length;
+ if ((*StringPtr != 0) && (*StringPtr != L'&')) {
+ *Progress = TmpPtr - 1;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ //
+ // Calculate Value and convert it to hex string.
+ //
+ if (Offset + Width > BlockSize) {
+ *Progress = StringPtr;
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Value = (UINT8 *)AllocateZeroPool (Width);
+ if (Value == NULL) {
+ *Progress = ConfigRequest;
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ CopyMem (Value, (UINT8 *)Block + Offset, Width);
+
+ Length = Width * 2 + 1;
+ ValueStr = (EFI_STRING)AllocateZeroPool (Length * sizeof (CHAR16));
+ if (ValueStr == NULL) {
+ *Progress = ConfigRequest;
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ TemString = ValueStr;
+ TemBuffer = Value + Width - 1;
+ for (Index = 0; Index < Width; Index++, TemBuffer--) {
+ UnicodeValueToStringS (
+ TemString,
+ Length * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ValueStr),
+ PREFIX_ZERO | RADIX_HEX,
+ *TemBuffer,
+ 2
+ );
+ TemString += StrnLenS (TemString, Length - ((UINTN)TemString - (UINTN)ValueStr) / sizeof (CHAR16));
+ }
+
+ FreePool (Value);
+ Value = NULL;
+
+ //
+ // Build a ConfigElement
+ //
+ Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");
+ ConfigElement = (EFI_STRING)AllocateZeroPool (Length * sizeof (CHAR16));
+ if (ConfigElement == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));
+ if (*StringPtr == 0) {
+ *(ConfigElement + (StringPtr - TmpPtr)) = L'&';
+ }
+
+ *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;
+ StrCatS (ConfigElement, Length, L"VALUE=");
+ StrCatS (ConfigElement, Length, ValueStr);
+
+ AppendToMultiString (Config, ConfigElement);
+
+ FreePool (ConfigElement);
+ FreePool (ValueStr);
+ ConfigElement = NULL;
+ ValueStr = NULL;
+
+ //
+ // If '\0', parsing is finished. Otherwise skip '&' to continue
+ //
+ if (*StringPtr == 0) {
+ break;
+ }
+
+ AppendToMultiString (Config, L"&");
+ StringPtr++;
+ }
+
+ if (*StringPtr != 0) {
+ *Progress = StringPtr - 1;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ HiiToLower (*Config);
+ *Progress = StringPtr;
+ return EFI_SUCCESS;
+
+Exit:
+ if (*Config != NULL) {
+ FreePool (*Config);
+ *Config = NULL;
+ }
+
+ if (ValueStr != NULL) {
+ FreePool (ValueStr);
+ }
+
+ if (Value != NULL) {
+ FreePool (Value);
+ }
+
+ if (ConfigElement != NULL) {
+ FreePool (ConfigElement);
+ }
+
+ return Status;
+}
+
+/**
+ This helper function is to be called by drivers to map configuration strings
+ to configurations stored in byte array ("block") formats such as UEFI Variables.
+
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+ instance.
+ @param ConfigResp A null-terminated Unicode string in <ConfigResp>
+ format.
+ @param Block A possibly null array of bytes representing the
+ current block. Only bytes referenced in the
+ ConfigResp string in the block are modified. If
+ this parameter is null or if the *BlockSize
+ parameter is (on input) shorter than required by
+ the Configuration string, only the BlockSize
+ parameter is updated and an appropriate status
+ (see below) is returned.
+ @param BlockSize The length of the Block in units of UINT8. On
+ input, this is the size of the Block. On output,
+ if successful, contains the largest index of the
+ modified byte in the Block, or the required buffer
+ size if the Block is not large enough.
+ @param Progress On return, points to an element of the ConfigResp
+ string filled in with the offset of 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) or the
+ terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The request succeeded. Progress points to the null
+ terminator at the end of the ConfigResp string.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
+ points to the first character of ConfigResp.
+ @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
+ Block parameter would result in this type of
+ error. Progress points to the first character of
+ ConfigResp.
+ @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
+ value pair. Block is left updated and
+ Progress points at the '&' preceding the first
+ non-<BlockName>.
+ @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
+ BlockSize is updated with the required buffer size.
+ @retval EFI_NOT_FOUND Target for the specified routing data was not found.
+ Progress points to the "G" in "GUID" of the errant
+ routing data.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiConfigToBlock (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING ConfigResp,
+ IN OUT UINT8 *Block,
+ IN OUT UINTN *BlockSize,
+ OUT EFI_STRING *Progress
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_STRING StringPtr;
+ EFI_STRING TmpPtr;
+ UINTN Length;
+ EFI_STATUS Status;
+ UINT8 *TmpBuffer;
+ UINTN Offset;
+ UINTN Width;
+ UINT8 *Value;
+ UINTN BufferSize;
+ UINTN MaxBlockSize;
+
+ TmpBuffer = NULL;
+
+ if ((This == NULL) || (BlockSize == NULL) || (Progress == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Progress = ConfigResp;
+ if (ConfigResp == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ ASSERT (Private != NULL);
+
+ StringPtr = ConfigResp;
+ BufferSize = *BlockSize;
+ Value = NULL;
+ MaxBlockSize = 0;
+
+ //
+ // Jump <ConfigHdr>
+ //
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
+ *Progress = StringPtr;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
+ StringPtr++;
+ }
+
+ if (*StringPtr == 0) {
+ *Progress = StringPtr;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ while (*StringPtr != L'&' && *StringPtr != 0) {
+ StringPtr++;
+ }
+
+ if (*StringPtr == 0) {
+ *Progress = StringPtr;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ //
+ // Parse each <ConfigElement> if exists
+ // Only '&'<BlockConfig> format is supported by this help function.
+ // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
+ //
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
+ TmpPtr = StringPtr;
+ StringPtr += StrLen (L"&OFFSET=");
+ //
+ // Get Offset
+ //
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ *Progress = TmpPtr;
+ goto Exit;
+ }
+
+ Offset = 0;
+ CopyMem (
+ &Offset,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
+ );
+ FreePool (TmpBuffer);
+
+ StringPtr += Length;
+ if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
+ *Progress = TmpPtr;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ StringPtr += StrLen (L"&WIDTH=");
+
+ //
+ // Get Width
+ //
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ *Progress = TmpPtr;
+ goto Exit;
+ }
+
+ Width = 0;
+ CopyMem (
+ &Width,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
+ );
+ FreePool (TmpBuffer);
+
+ StringPtr += Length;
+ if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
+ *Progress = TmpPtr;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ StringPtr += StrLen (L"&VALUE=");
+
+ //
+ // Get Value
+ //
+ Status = GetValueOfNumber (StringPtr, &Value, &Length);
+ if (EFI_ERROR (Status)) {
+ *Progress = TmpPtr;
+ goto Exit;
+ }
+
+ StringPtr += Length;
+ if ((*StringPtr != 0) && (*StringPtr != L'&')) {
+ *Progress = TmpPtr;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ //
+ // Update the Block with configuration info
+ //
+ if ((Block != NULL) && (Offset + Width <= BufferSize)) {
+ CopyMem (Block + Offset, Value, Width);
+ }
+
+ if (Offset + Width > MaxBlockSize) {
+ MaxBlockSize = Offset + Width;
+ }
+
+ FreePool (Value);
+ Value = NULL;
+
+ //
+ // If '\0', parsing is finished.
+ //
+ if (*StringPtr == 0) {
+ break;
+ }
+ }
+
+ //
+ // The input string is not ConfigResp format, return error.
+ //
+ if (*StringPtr != 0) {
+ *Progress = StringPtr;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ *Progress = StringPtr + StrLen (StringPtr);
+ *BlockSize = MaxBlockSize - 1;
+
+ if (MaxBlockSize > BufferSize) {
+ *BlockSize = MaxBlockSize;
+ if (Block != NULL) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ }
+
+ if (Block == NULL) {
+ *Progress = ConfigResp;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+
+Exit:
+
+ if (Value != NULL) {
+ FreePool (Value);
+ }
+
+ return Status;
+}
+
+/**
+ This helper function is to be called by drivers to extract portions of
+ a larger configuration string.
+
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+ instance.
+ @param Configuration A null-terminated Unicode string in
+ <MultiConfigAltResp> format.
+ @param Guid A pointer to the GUID value to search for in the
+ routing portion of the ConfigResp string when
+ retrieving the requested data. If Guid is NULL,
+ then all GUID values will be searched for.
+ @param Name A pointer to the NAME value to search for in the
+ routing portion of the ConfigResp string when
+ retrieving the requested data. If Name is NULL,
+ then all Name values will be searched for.
+ @param DevicePath A pointer to the PATH value to search for in the
+ routing portion of the ConfigResp string when
+ retrieving the requested data. If DevicePath is
+ NULL, then all DevicePath values will be searched
+ for.
+ @param AltCfgId A pointer to the ALTCFG value to search for in the
+ routing portion of the ConfigResp string when
+ retrieving the requested data. If this parameter
+ is NULL, then the current setting will be
+ retrieved.
+ @param AltCfgResp A pointer to a buffer which will be allocated by
+ the function which contains the retrieved string
+ as requested. This buffer is only allocated if
+ the call was successful. It is <ConfigResp> format.
+
+ @retval EFI_SUCCESS The request succeeded. The requested data was
+ extracted and placed in the newly allocated
+ AltCfgResp buffer.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
+ @retval EFI_INVALID_PARAMETER Any parameter is invalid.
+ @retval EFI_NOT_FOUND Target for the specified routing data was not
+ found.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetAltCfg (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ IN CONST EFI_GUID *Guid,
+ IN CONST EFI_STRING Name,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN CONST UINT16 *AltCfgId,
+ OUT EFI_STRING *AltCfgResp
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING StringPtr;
+ EFI_STRING HdrStart;
+ EFI_STRING HdrEnd;
+ EFI_STRING TmpPtr;
+ UINTN Length;
+ EFI_STRING GuidStr;
+ EFI_STRING NameStr;
+ EFI_STRING PathStr;
+ EFI_STRING AltIdStr;
+ EFI_STRING Result;
+ BOOLEAN GuidFlag;
+ BOOLEAN NameFlag;
+ BOOLEAN PathFlag;
+
+ HdrStart = NULL;
+ HdrEnd = NULL;
+ GuidStr = NULL;
+ NameStr = NULL;
+ PathStr = NULL;
+ AltIdStr = NULL;
+ Result = NULL;
+ GuidFlag = FALSE;
+ NameFlag = FALSE;
+ PathFlag = FALSE;
+
+ if ((This == NULL) || (Configuration == NULL) || (AltCfgResp == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ StringPtr = Configuration;
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Generate the sub string for later matching.
+ //
+ GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)Guid, 1, &GuidStr);
+ GenerateSubStr (
+ L"PATH=",
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DevicePath),
+ (VOID *)DevicePath,
+ 1,
+ &PathStr
+ );
+ if (AltCfgId != NULL) {
+ GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *)AltCfgId, 3, &AltIdStr);
+ }
+
+ if (Name != NULL) {
+ GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *)Name, 2, &NameStr);
+ } else {
+ GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
+ }
+
+ while (*StringPtr != 0) {
+ //
+ // Try to match the GUID
+ //
+ if (!GuidFlag) {
+ TmpPtr = StrStr (StringPtr, GuidStr);
+ if (TmpPtr == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+
+ HdrStart = TmpPtr;
+
+ //
+ // Jump to <NameHdr>
+ //
+ if (Guid != NULL) {
+ StringPtr = TmpPtr + StrLen (GuidStr);
+ } else {
+ StringPtr = StrStr (TmpPtr, L"NAME=");
+ if (StringPtr == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+ }
+
+ GuidFlag = TRUE;
+ }
+
+ //
+ // Try to match the NAME
+ //
+ if (GuidFlag && !NameFlag) {
+ if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {
+ GuidFlag = FALSE;
+ } else {
+ //
+ // Jump to <PathHdr>
+ //
+ if (Name != NULL) {
+ StringPtr += StrLen (NameStr);
+ } else {
+ StringPtr = StrStr (StringPtr, L"PATH=");
+ if (StringPtr == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+ }
+
+ NameFlag = TRUE;
+ }
+ }
+
+ //
+ // Try to match the DevicePath
+ //
+ if (GuidFlag && NameFlag && !PathFlag) {
+ if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {
+ GuidFlag = FALSE;
+ NameFlag = FALSE;
+ } else {
+ //
+ // Jump to '&' before <DescHdr> or <ConfigBody>
+ //
+ if (DevicePath != NULL) {
+ StringPtr += StrLen (PathStr);
+ } else {
+ StringPtr = StrStr (StringPtr, L"&");
+ if (StringPtr == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+
+ StringPtr++;
+ }
+
+ PathFlag = TRUE;
+ HdrEnd = StringPtr;
+ }
+ }
+
+ //
+ // Try to match the AltCfgId
+ //
+ if (GuidFlag && NameFlag && PathFlag) {
+ if (AltCfgId == NULL) {
+ //
+ // Return Current Setting when AltCfgId is NULL.
+ //
+ Status = OutputConfigBody (StringPtr, &Result);
+ goto Exit;
+ }
+
+ //
+ // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
+ //
+ if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {
+ GuidFlag = FALSE;
+ NameFlag = FALSE;
+ PathFlag = FALSE;
+ } else {
+ //
+ // Skip AltIdStr and &
+ //
+ StringPtr = StringPtr + StrLen (AltIdStr);
+ Status = OutputConfigBody (StringPtr, &Result);
+ goto Exit;
+ }
+ }
+ }
+
+ Status = EFI_NOT_FOUND;
+
+Exit:
+ *AltCfgResp = NULL;
+ if (!EFI_ERROR (Status) && (Result != NULL)) {
+ //
+ // Copy the <ConfigHdr> and <ConfigBody>
+ //
+ Length = HdrEnd - HdrStart + StrLen (Result) + 1;
+ *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
+ if (*AltCfgResp == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ StrnCpyS (*AltCfgResp, Length, HdrStart, HdrEnd - HdrStart);
+ StrCatS (*AltCfgResp, Length, Result);
+ Status = EFI_SUCCESS;
+ }
+ }
+
+ if (GuidStr != NULL) {
+ FreePool (GuidStr);
+ }
+
+ if (NameStr != NULL) {
+ FreePool (NameStr);
+ }
+
+ if (PathStr != NULL) {
+ FreePool (PathStr);
+ }
+
+ if (AltIdStr != NULL) {
+ FreePool (AltIdStr);
+ }
+
+ if (Result != NULL) {
+ FreePool (Result);
+ }
+
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
index 0b09c24d52..f506f8b415 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
@@ -1,4722 +1,4722 @@
-/** @file
-Implementation for EFI_HII_DATABASE_PROTOCOL.
-
-Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "HiiDatabase.h"
-
-#define BASE_NUMBER 10
-
-EFI_HII_PACKAGE_LIST_HEADER *gRTDatabaseInfoBuffer = NULL;
-EFI_STRING gRTConfigRespBuffer = NULL;
-UINTN gDatabaseInfoSize = 0;
-UINTN gConfigRespSize = 0;
-BOOLEAN gExportConfigResp = FALSE;
-UINTN gNvDefaultStoreSize = 0;
-SKU_ID gSkuId = 0xFFFFFFFFFFFFFFFF;
-LIST_ENTRY gVarStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gVarStorageList);
-
-//
-// HII database lock.
-//
-EFI_LOCK mHiiDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
-
-/**
- This function generates a HII_DATABASE_RECORD node and adds into hii database.
- This is a internal function.
-
- @param Private hii database private structure
- @param DatabaseNode HII_DATABASE_RECORD node which is used to store a
- package list
-
- @retval EFI_SUCCESS A database record is generated successfully.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
- database contents.
- @retval EFI_INVALID_PARAMETER Private is NULL or DatabaseRecord is NULL.
-
-**/
-EFI_STATUS
-GenerateHiiDatabaseRecord (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- OUT HII_DATABASE_RECORD **DatabaseNode
- )
-{
- HII_DATABASE_RECORD *DatabaseRecord;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
- HII_HANDLE *HiiHandle;
-
- if ((Private == NULL) || (DatabaseNode == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- DatabaseRecord = (HII_DATABASE_RECORD *)AllocateZeroPool (sizeof (HII_DATABASE_RECORD));
- if (DatabaseRecord == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- DatabaseRecord->Signature = HII_DATABASE_RECORD_SIGNATURE;
-
- DatabaseRecord->PackageList = AllocateZeroPool (sizeof (HII_DATABASE_PACKAGE_LIST_INSTANCE));
- if (DatabaseRecord->PackageList == NULL) {
- FreePool (DatabaseRecord);
- return EFI_OUT_OF_RESOURCES;
- }
-
- PackageList = DatabaseRecord->PackageList;
-
- InitializeListHead (&PackageList->GuidPkgHdr);
- InitializeListHead (&PackageList->FormPkgHdr);
- InitializeListHead (&PackageList->KeyboardLayoutHdr);
- InitializeListHead (&PackageList->StringPkgHdr);
- InitializeListHead (&PackageList->FontPkgHdr);
- InitializeListHead (&PackageList->SimpleFontPkgHdr);
- PackageList->ImagePkg = NULL;
- PackageList->DevicePathPkg = NULL;
-
- //
- // Create a new hii handle
- //
- HiiHandle = (HII_HANDLE *)AllocateZeroPool (sizeof (HII_HANDLE));
- if (HiiHandle == NULL) {
- FreePool (DatabaseRecord->PackageList);
- FreePool (DatabaseRecord);
- return EFI_OUT_OF_RESOURCES;
- }
-
- HiiHandle->Signature = HII_HANDLE_SIGNATURE;
- //
- // Backup the number of Hii handles
- //
- Private->HiiHandleCount++;
- HiiHandle->Key = (UINTN)Private->HiiHandleCount;
- //
- // Insert the handle to hii handle list of the whole database.
- //
- InsertTailList (&Private->HiiHandleList, &HiiHandle->Handle);
-
- DatabaseRecord->Handle = (EFI_HII_HANDLE)HiiHandle;
-
- //
- // Insert the Package List node to Package List link of the whole database.
- //
- InsertTailList (&Private->DatabaseList, &DatabaseRecord->DatabaseEntry);
-
- *DatabaseNode = DatabaseRecord;
-
- return EFI_SUCCESS;
-}
-
-/**
- This function checks whether a handle is a valid EFI_HII_HANDLE
- This is a internal function.
-
- @param Handle Pointer to a EFI_HII_HANDLE
-
- @retval TRUE Valid
- @retval FALSE Invalid
-
-**/
-BOOLEAN
-IsHiiHandleValid (
- EFI_HII_HANDLE Handle
- )
-{
- HII_HANDLE *HiiHandle;
-
- HiiHandle = (HII_HANDLE *)Handle;
-
- if (HiiHandle == NULL) {
- return FALSE;
- }
-
- if (HiiHandle->Signature != HII_HANDLE_SIGNATURE) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- This function invokes the matching registered function.
- This is a internal function.
-
- @param Private HII Database driver private structure.
- @param NotifyType The type of change concerning the database.
- @param PackageInstance Points to the package referred to by the
- notification.
- @param PackageType Package type
- @param Handle The handle of the package list which contains the
- specified package.
-
- @retval EFI_SUCCESS Already checked all registered function and
- invoked if matched.
- @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
-
-**/
-EFI_STATUS
-InvokeRegisteredFunction (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
- IN VOID *PackageInstance,
- IN UINT8 PackageType,
- IN EFI_HII_HANDLE Handle
- )
-{
- HII_DATABASE_NOTIFY *Notify;
- LIST_ENTRY *Link;
- EFI_HII_PACKAGE_HEADER *Package;
- UINT8 *Buffer;
- UINT32 BufferSize;
- UINT32 HeaderSize;
- UINT32 ImageBlockSize;
- UINT32 PaletteInfoSize;
-
- if ((Private == NULL) || ((NotifyType & 0xF) == 0) || (PackageInstance == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (!IsHiiHandleValid (Handle)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Buffer = NULL;
- Package = NULL;
-
- //
- // Convert the incoming package from hii database storage format to UEFI
- // storage format. e.g. HII_GUID_PACKAGE_INSTANCE to EFI_HII_GUID_PACKAGE_HDR.
- //
- switch (PackageType) {
- case EFI_HII_PACKAGE_TYPE_GUID:
- Package = (EFI_HII_PACKAGE_HEADER *)(((HII_GUID_PACKAGE_INSTANCE *)PackageInstance)->GuidPkg);
- break;
-
- case EFI_HII_PACKAGE_FORMS:
- BufferSize = ((HII_IFR_PACKAGE_INSTANCE *)PackageInstance)->FormPkgHdr.Length;
- Buffer = (UINT8 *)AllocateZeroPool (BufferSize);
- ASSERT (Buffer != NULL);
- CopyMem (
- Buffer,
- &((HII_IFR_PACKAGE_INSTANCE *)PackageInstance)->FormPkgHdr,
- sizeof (EFI_HII_PACKAGE_HEADER)
- );
- CopyMem (
- Buffer + sizeof (EFI_HII_PACKAGE_HEADER),
- ((HII_IFR_PACKAGE_INSTANCE *)PackageInstance)->IfrData,
- BufferSize - sizeof (EFI_HII_PACKAGE_HEADER)
- );
- Package = (EFI_HII_PACKAGE_HEADER *)Buffer;
- break;
-
- case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
- Package = (EFI_HII_PACKAGE_HEADER *)(((HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *)PackageInstance)->KeyboardPkg);
- break;
-
- case EFI_HII_PACKAGE_STRINGS:
- BufferSize = ((HII_STRING_PACKAGE_INSTANCE *)PackageInstance)->StringPkgHdr->Header.Length;
- HeaderSize = ((HII_STRING_PACKAGE_INSTANCE *)PackageInstance)->StringPkgHdr->HdrSize;
- Buffer = (UINT8 *)AllocateZeroPool (BufferSize);
- ASSERT (Buffer != NULL);
- CopyMem (
- Buffer,
- ((HII_STRING_PACKAGE_INSTANCE *)PackageInstance)->StringPkgHdr,
- HeaderSize
- );
- CopyMem (
- Buffer + HeaderSize,
- ((HII_STRING_PACKAGE_INSTANCE *)PackageInstance)->StringBlock,
- BufferSize - HeaderSize
- );
- Package = (EFI_HII_PACKAGE_HEADER *)Buffer;
- break;
-
- case EFI_HII_PACKAGE_FONTS:
- BufferSize = ((HII_FONT_PACKAGE_INSTANCE *)PackageInstance)->FontPkgHdr->Header.Length;
- HeaderSize = ((HII_FONT_PACKAGE_INSTANCE *)PackageInstance)->FontPkgHdr->HdrSize;
- Buffer = (UINT8 *)AllocateZeroPool (BufferSize);
- ASSERT (Buffer != NULL);
- CopyMem (
- Buffer,
- ((HII_FONT_PACKAGE_INSTANCE *)PackageInstance)->FontPkgHdr,
- HeaderSize
- );
- CopyMem (
- Buffer + HeaderSize,
- ((HII_FONT_PACKAGE_INSTANCE *)PackageInstance)->GlyphBlock,
- BufferSize - HeaderSize
- );
- Package = (EFI_HII_PACKAGE_HEADER *)Buffer;
- break;
-
- case EFI_HII_PACKAGE_IMAGES:
- BufferSize = ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->ImagePkgHdr.Header.Length;
- HeaderSize = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
- Buffer = (UINT8 *)AllocateZeroPool (BufferSize);
- ASSERT (Buffer != NULL);
-
- CopyMem (
- Buffer,
- &((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->ImagePkgHdr,
- HeaderSize
- );
- CopyMem (
- Buffer + sizeof (EFI_HII_PACKAGE_HEADER),
- &HeaderSize,
- sizeof (UINT32)
- );
-
- ImageBlockSize = ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->ImageBlockSize;
- if (ImageBlockSize != 0) {
- CopyMem (
- Buffer + HeaderSize,
- ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->ImageBlock,
- ImageBlockSize
- );
- }
-
- PaletteInfoSize = ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->PaletteInfoSize;
- if (PaletteInfoSize != 0) {
- CopyMem (
- Buffer + HeaderSize + ImageBlockSize,
- ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->PaletteBlock,
- PaletteInfoSize
- );
- HeaderSize += ImageBlockSize;
- CopyMem (
- Buffer + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT32),
- &HeaderSize,
- sizeof (UINT32)
- );
- }
-
- Package = (EFI_HII_PACKAGE_HEADER *)Buffer;
- break;
-
- case EFI_HII_PACKAGE_SIMPLE_FONTS:
- BufferSize = ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *)PackageInstance)->SimpleFontPkgHdr->Header.Length;
- Buffer = (UINT8 *)AllocateZeroPool (BufferSize);
- ASSERT (Buffer != NULL);
- CopyMem (
- Buffer,
- ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *)PackageInstance)->SimpleFontPkgHdr,
- BufferSize
- );
- Package = (EFI_HII_PACKAGE_HEADER *)Buffer;
- break;
-
- case EFI_HII_PACKAGE_DEVICE_PATH:
- Package = (EFI_HII_PACKAGE_HEADER *)PackageInstance;
- break;
-
- default:
- return EFI_INVALID_PARAMETER;
- }
-
- for (Link = Private->DatabaseNotifyList.ForwardLink;
- Link != &Private->DatabaseNotifyList;
- Link = Link->ForwardLink
- )
- {
- Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);
- if ((Notify->NotifyType == NotifyType) && (Notify->PackageType == PackageType)) {
- //
- // Check in case PackageGuid is not NULL when Package is GUID package
- //
- if (PackageType != EFI_HII_PACKAGE_TYPE_GUID) {
- Notify->PackageGuid = NULL;
- }
-
- //
- // Status of Registered Function is unknown so did not check it
- //
- Notify->PackageNotifyFn (
- Notify->PackageType,
- Notify->PackageGuid,
- Package,
- Handle,
- NotifyType
- );
- }
- }
-
- if (Buffer != NULL) {
- FreePool (Buffer);
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This function insert a GUID package to a package list node.
- This is a internal function.
-
- @param PackageHdr Pointer to a buffer stored with GUID package
- information.
- @param NotifyType The type of change concerning the database.
- @param PackageList Pointer to a package list which will be inserted
- to.
- @param Package Created GUID package
-
- @retval EFI_SUCCESS Guid Package is inserted successfully.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
- Guid package.
- @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
-
-**/
-EFI_STATUS
-InsertGuidPackage (
- IN VOID *PackageHdr,
- IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
- IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
- OUT HII_GUID_PACKAGE_INSTANCE **Package
- )
-{
- HII_GUID_PACKAGE_INSTANCE *GuidPackage;
- EFI_HII_PACKAGE_HEADER PackageHeader;
-
- if ((PackageHdr == NULL) || (PackageList == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
-
- //
- // Create a GUID package node
- //
- GuidPackage = (HII_GUID_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_GUID_PACKAGE_INSTANCE));
- if (GuidPackage == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- GuidPackage->GuidPkg = (UINT8 *)AllocateZeroPool (PackageHeader.Length);
- if (GuidPackage->GuidPkg == NULL) {
- FreePool (GuidPackage);
- return EFI_OUT_OF_RESOURCES;
- }
-
- GuidPackage->Signature = HII_GUID_PACKAGE_SIGNATURE;
- CopyMem (GuidPackage->GuidPkg, PackageHdr, PackageHeader.Length);
- InsertTailList (&PackageList->GuidPkgHdr, &GuidPackage->GuidEntry);
- *Package = GuidPackage;
-
- if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
- PackageList->PackageListHdr.PackageLength += PackageHeader.Length;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This function exports GUID packages to a buffer.
- This is a internal function.
-
- @param Private Hii database private structure.
- @param Handle Identification of a package list.
- @param PackageList Pointer to a package list which will be exported.
- @param UsedSize The length of buffer be used.
- @param BufferSize Length of the Buffer.
- @param Buffer Allocated space for storing exported data.
- @param ResultSize The size of the already exported content of this
- package list.
-
- @retval EFI_SUCCESS Guid Packages are exported successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
-
-**/
-EFI_STATUS
-ExportGuidPackages (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
- IN UINTN UsedSize,
- IN UINTN BufferSize,
- IN OUT VOID *Buffer,
- IN OUT UINTN *ResultSize
- )
-{
- HII_GUID_PACKAGE_INSTANCE *GuidPackage;
- LIST_ENTRY *Link;
- UINTN PackageLength;
- EFI_HII_PACKAGE_HEADER PackageHeader;
- EFI_STATUS Status;
-
- if ((PackageList == NULL) || (ResultSize == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((BufferSize > 0) && (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- PackageLength = 0;
- Status = EFI_SUCCESS;
-
- for (Link = PackageList->GuidPkgHdr.ForwardLink; Link != &PackageList->GuidPkgHdr; Link = Link->ForwardLink) {
- GuidPackage = CR (Link, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);
- CopyMem (&PackageHeader, GuidPackage->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));
- PackageLength += PackageHeader.Length;
- if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
- Status = InvokeRegisteredFunction (
- Private,
- EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
- (VOID *)GuidPackage,
- EFI_HII_PACKAGE_TYPE_GUID,
- Handle
- );
- ASSERT_EFI_ERROR (Status);
- CopyMem (Buffer, GuidPackage->GuidPkg, PackageHeader.Length);
- Buffer = (UINT8 *)Buffer + PackageHeader.Length;
- }
- }
-
- *ResultSize += PackageLength;
- return EFI_SUCCESS;
-}
-
-/**
- This function deletes all GUID packages from a package list node.
- This is a internal function.
-
- @param Private Hii database private data.
- @param Handle Handle of the package list which contains the to
- be removed GUID packages.
- @param PackageList Pointer to a package list that contains removing
- packages.
-
- @retval EFI_SUCCESS GUID Package(s) is deleted successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
-
-**/
-EFI_STATUS
-RemoveGuidPackages (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
- )
-{
- LIST_ENTRY *ListHead;
- HII_GUID_PACKAGE_INSTANCE *Package;
- EFI_STATUS Status;
- EFI_HII_PACKAGE_HEADER PackageHeader;
-
- ListHead = &PackageList->GuidPkgHdr;
-
- while (!IsListEmpty (ListHead)) {
- Package = CR (
- ListHead->ForwardLink,
- HII_GUID_PACKAGE_INSTANCE,
- GuidEntry,
- HII_GUID_PACKAGE_SIGNATURE
- );
- Status = InvokeRegisteredFunction (
- Private,
- EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
- (VOID *)Package,
- EFI_HII_PACKAGE_TYPE_GUID,
- Handle
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- RemoveEntryList (&Package->GuidEntry);
- CopyMem (&PackageHeader, Package->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));
- PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;
- FreePool (Package->GuidPkg);
- FreePool (Package);
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Check the input question related to EFI variable
-
- @param IfrQuestionHdr Point to Question header
- @param EfiVarStoreList Point to EFI VarStore List
- @param EfiVarStoreNumber The number of EFI VarStore
-
- @retval Index The index of the found EFI varstore in EFI varstore list
- EfiVarStoreNumber will return if no EFI varstore is found.
-**/
-UINTN
-IsEfiVarStoreQuestion (
- EFI_IFR_QUESTION_HEADER *IfrQuestionHdr,
- EFI_IFR_VARSTORE_EFI **EfiVarStoreList,
- UINTN EfiVarStoreNumber
- )
-{
- UINTN Index;
-
- for (Index = 0; Index < EfiVarStoreNumber; Index++) {
- if (IfrQuestionHdr->VarStoreId == EfiVarStoreList[Index]->VarStoreId) {
- return Index;
- }
- }
-
- return EfiVarStoreNumber;
-}
-
-/**
- Find the matched variable from the input variable storage.
-
- @param[in] VariableStorage Point to the variable storage header.
- @param[in] VarGuid A unique identifier for the variable.
- @param[in] VarAttribute The attributes bitmask for the variable.
- @param[in] VarName A Null-terminated ascii string that is the name of the variable.
-
- @return Pointer to the matched variable header or NULL if not found.
-**/
-VARIABLE_HEADER *
-FindVariableData (
- IN VARIABLE_STORE_HEADER *VariableStorage,
- IN EFI_GUID *VarGuid,
- IN UINT32 VarAttribute,
- IN CHAR16 *VarName
- )
-{
- VARIABLE_HEADER *VariableHeader;
- VARIABLE_HEADER *VariableEnd;
-
- VariableEnd = (VARIABLE_HEADER *)((UINT8 *)VariableStorage + VariableStorage->Size);
- VariableHeader = (VARIABLE_HEADER *)(VariableStorage + 1);
- VariableHeader = (VARIABLE_HEADER *)HEADER_ALIGN (VariableHeader);
- while (VariableHeader < VariableEnd) {
- if (CompareGuid (&VariableHeader->VendorGuid, VarGuid) &&
- (VariableHeader->Attributes == VarAttribute) &&
- (StrCmp (VarName, (CHAR16 *)(VariableHeader + 1)) == 0))
- {
- return VariableHeader;
- }
-
- VariableHeader = (VARIABLE_HEADER *)((UINT8 *)VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + VariableHeader->DataSize);
- VariableHeader = (VARIABLE_HEADER *)HEADER_ALIGN (VariableHeader);
- }
-
- return NULL;
-}
-
-/**
- Find question default value from PcdNvStoreDefaultValueBuffer
-
- @param DefaultId Default store ID
- @param EfiVarStore Point to EFI VarStore header
- @param IfrQuestionHdr Point to Question header
- @param ValueBuffer Point to Buffer includes the found default setting
- @param Width Width of the default value
- @param BitFieldQuestion Whether the Question is stored in Bit field.
-
- @retval EFI_SUCCESS Question default value is found.
- @retval EFI_NOT_FOUND Question default value is not found.
-**/
-EFI_STATUS
-FindQuestionDefaultSetting (
- IN UINT16 DefaultId,
- IN EFI_IFR_VARSTORE_EFI *EfiVarStore,
- IN EFI_IFR_QUESTION_HEADER *IfrQuestionHdr,
- OUT VOID *ValueBuffer,
- IN UINTN Width,
- IN BOOLEAN BitFieldQuestion
- )
-{
- VARIABLE_HEADER *VariableHeader;
- VARIABLE_STORE_HEADER *VariableStorage;
- LIST_ENTRY *Link;
- VARSTORAGE_DEFAULT_DATA *Entry;
- VARIABLE_STORE_HEADER *NvStoreBuffer;
- UINT8 *DataBuffer;
- UINT8 *BufferEnd;
- BOOLEAN IsFound;
- UINTN Index;
- UINT32 BufferValue;
- UINT32 BitFieldVal;
- UINTN BitOffset;
- UINTN ByteOffset;
- UINTN BitWidth;
- UINTN StartBit;
- UINTN EndBit;
- PCD_DEFAULT_DATA *DataHeader;
- PCD_DEFAULT_INFO *DefaultInfo;
- PCD_DATA_DELTA *DeltaData;
-
- if (gSkuId == 0xFFFFFFFFFFFFFFFF) {
- gSkuId = LibPcdGetSku ();
- }
-
- //
- // Find the DefaultId setting from the full DefaultSetting
- //
- VariableStorage = NULL;
- Link = gVarStorageList.ForwardLink;
- while (Link != &gVarStorageList) {
- Entry = BASE_CR (Link, VARSTORAGE_DEFAULT_DATA, Entry);
- if (Entry->DefaultId == DefaultId) {
- VariableStorage = Entry->VariableStorage;
- break;
- }
-
- Link = Link->ForwardLink;
- }
-
- if (Link == &gVarStorageList) {
- DataBuffer = (UINT8 *)PcdGetPtr (PcdNvStoreDefaultValueBuffer);
- gNvDefaultStoreSize = ((PCD_NV_STORE_DEFAULT_BUFFER_HEADER *)DataBuffer)->Length;
- //
- // The first section data includes NV storage default setting.
- //
- DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER));
- NvStoreBuffer = (VARIABLE_STORE_HEADER *)((UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize);
- VariableStorage = AllocatePool (NvStoreBuffer->Size);
- ASSERT (VariableStorage != NULL);
- CopyMem (VariableStorage, NvStoreBuffer, NvStoreBuffer->Size);
-
- //
- // Find the matched SkuId and DefaultId in the first section
- //
- IsFound = FALSE;
- DefaultInfo = &(DataHeader->DefaultInfo[0]);
- BufferEnd = (UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;
- while ((UINT8 *)DefaultInfo < BufferEnd) {
- if ((DefaultInfo->DefaultId == DefaultId) && (DefaultInfo->SkuId == gSkuId)) {
- IsFound = TRUE;
- break;
- }
-
- DefaultInfo++;
- }
-
- //
- // Find the matched SkuId and DefaultId in the remaining section
- //
- Index = sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER) + ((DataHeader->DataSize + 7) & (~7));
- DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + Index);
- while (!IsFound && Index < gNvDefaultStoreSize && DataHeader->DataSize != 0xFFFF) {
- DefaultInfo = &(DataHeader->DefaultInfo[0]);
- BufferEnd = (UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;
- while ((UINT8 *)DefaultInfo < BufferEnd) {
- if ((DefaultInfo->DefaultId == DefaultId) && (DefaultInfo->SkuId == gSkuId)) {
- IsFound = TRUE;
- break;
- }
-
- DefaultInfo++;
- }
-
- if (IsFound) {
- DeltaData = (PCD_DATA_DELTA *)BufferEnd;
- BufferEnd = (UINT8 *)DataHeader + DataHeader->DataSize;
- while ((UINT8 *)DeltaData < BufferEnd) {
- *((UINT8 *)VariableStorage + DeltaData->Offset) = (UINT8)DeltaData->Value;
- DeltaData++;
- }
-
- break;
- }
-
- Index = (Index + DataHeader->DataSize + 7) & (~7);
- DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + Index);
- }
-
- //
- // Cache the found result in VarStorageList
- //
- if (!IsFound) {
- FreePool (VariableStorage);
- VariableStorage = NULL;
- }
-
- Entry = AllocatePool (sizeof (VARSTORAGE_DEFAULT_DATA));
- if (Entry != NULL) {
- Entry->DefaultId = DefaultId;
- Entry->VariableStorage = VariableStorage;
- InsertTailList (&gVarStorageList, &Entry->Entry);
- } else if (VariableStorage != NULL) {
- FreePool (VariableStorage);
- VariableStorage = NULL;
- }
- }
-
- //
- // The matched variable storage is not found.
- //
- if (VariableStorage == NULL) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Find the question default value from the variable storage
- //
- VariableHeader = FindVariableData (VariableStorage, &EfiVarStore->Guid, EfiVarStore->Attributes, (CHAR16 *)EfiVarStore->Name);
- if (VariableHeader == NULL) {
- return EFI_NOT_FOUND;
- }
-
- StartBit = 0;
- EndBit = 0;
- ByteOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
- if (BitFieldQuestion) {
- BitOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
- ByteOffset = BitOffset / 8;
- BitWidth = Width;
- StartBit = BitOffset % 8;
- EndBit = StartBit + BitWidth - 1;
- Width = EndBit / 8 + 1;
- }
-
- if (VariableHeader->DataSize < ByteOffset + Width) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Copy the question value
- //
- if (ValueBuffer != NULL) {
- if (BitFieldQuestion) {
- CopyMem (&BufferValue, (UINT8 *)VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + ByteOffset, Width);
- BitFieldVal = BitFieldRead32 (BufferValue, StartBit, EndBit);
- CopyMem (ValueBuffer, &BitFieldVal, Width);
- } else {
- CopyMem (ValueBuffer, (UINT8 *)VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + IfrQuestionHdr->VarStoreInfo.VarOffset, Width);
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Update IFR default setting in Form Package.
-
- @param FormPackage Form Package to be updated
-
-**/
-VOID
-UpdateDefaultSettingInFormPackage (
- HII_IFR_PACKAGE_INSTANCE *FormPackage
- )
-{
- UINTN IfrOffset;
- UINTN PackageLength;
- EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
- EFI_IFR_OP_HEADER *IfrOpHdr;
- EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
- UINT8 IfrQuestionType;
- UINT8 IfrScope;
- EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;
- EFI_IFR_VARSTORE_EFI **EfiVarStoreList;
- UINTN EfiVarStoreMaxNum;
- UINTN EfiVarStoreNumber;
- UINT16 *DefaultIdList;
- UINTN DefaultIdNumber;
- UINTN DefaultIdMaxNum;
- UINTN Index;
- UINTN EfiVarStoreIndex;
- EFI_IFR_TYPE_VALUE IfrValue;
- EFI_IFR_TYPE_VALUE IfrManufactValue;
- BOOLEAN StandardDefaultIsSet;
- BOOLEAN ManufactDefaultIsSet;
- EFI_IFR_CHECKBOX *IfrCheckBox;
- EFI_STATUS Status;
- EFI_IFR_DEFAULT *IfrDefault;
- UINTN Width;
- EFI_IFR_QUESTION_HEADER VarStoreQuestionHeader;
- BOOLEAN QuestionReferBitField;
-
- //
- // If no default setting, do nothing
- //
- if (gNvDefaultStoreSize == 0) {
- gNvDefaultStoreSize = PcdGetSize (PcdNvStoreDefaultValueBuffer);
- }
-
- if (gNvDefaultStoreSize < sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) {
- return;
- }
-
- ZeroMem (&VarStoreQuestionHeader, sizeof (VarStoreQuestionHeader));
- PackageLength = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
- Width = 0;
- IfrOffset = 0;
- IfrScope = 0;
- IfrOpHdr = (EFI_IFR_OP_HEADER *)FormPackage->IfrData;
- IfrQuestionHdr = NULL;
- IfrQuestionType = 0;
- EfiVarStoreMaxNum = 0;
- EfiVarStoreNumber = 0;
- DefaultIdMaxNum = 0;
- DefaultIdNumber = 0;
- EfiVarStoreList = NULL;
- DefaultIdList = NULL;
- StandardDefaultIsSet = FALSE;
- ManufactDefaultIsSet = FALSE;
- QuestionReferBitField = FALSE;
-
- while (IfrOffset < PackageLength) {
- switch (IfrOpHdr->OpCode) {
- case EFI_IFR_VARSTORE_EFI_OP:
- if (EfiVarStoreNumber >= EfiVarStoreMaxNum) {
- //
- // Reallocate EFI VarStore Buffer
- //
- EfiVarStoreList = ReallocatePool (EfiVarStoreMaxNum * sizeof (UINTN), (EfiVarStoreMaxNum + BASE_NUMBER) * sizeof (UINTN), EfiVarStoreList);
- if (EfiVarStoreList == NULL) {
- goto Done;
- }
-
- EfiVarStoreMaxNum = EfiVarStoreMaxNum + BASE_NUMBER;
- }
-
- IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *)IfrOpHdr;
- //
- // Convert VarStore Name from ASCII string to Unicode string.
- //
- EfiVarStoreList[EfiVarStoreNumber] = AllocatePool (IfrEfiVarStore->Header.Length + AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name));
- if (EfiVarStoreList[EfiVarStoreNumber] == NULL) {
- break;
- }
-
- CopyMem (EfiVarStoreList[EfiVarStoreNumber], IfrEfiVarStore, IfrEfiVarStore->Header.Length);
- AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, (CHAR16 *)&(EfiVarStoreList[EfiVarStoreNumber]->Name[0]), AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
- Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_STANDARD, EfiVarStoreList[EfiVarStoreNumber], &VarStoreQuestionHeader, NULL, IfrEfiVarStore->Size, FALSE);
- if (!EFI_ERROR (Status)) {
- EfiVarStoreNumber++;
- } else {
- FreePool (EfiVarStoreList[EfiVarStoreNumber]);
- EfiVarStoreList[EfiVarStoreNumber] = NULL;
- }
-
- break;
- case EFI_IFR_DEFAULTSTORE_OP:
- if (DefaultIdNumber >= DefaultIdMaxNum) {
- //
- // Reallocate DefaultIdNumber
- //
- DefaultIdList = ReallocatePool (DefaultIdMaxNum * sizeof (UINT16), (DefaultIdMaxNum + BASE_NUMBER) * sizeof (UINT16), DefaultIdList);
- if (DefaultIdList == NULL) {
- goto Done;
- }
-
- DefaultIdMaxNum = DefaultIdMaxNum + BASE_NUMBER;
- }
-
- DefaultIdList[DefaultIdNumber++] = ((EFI_IFR_DEFAULTSTORE *)IfrOpHdr)->DefaultId;
- break;
- case EFI_IFR_FORM_OP:
- case EFI_IFR_FORM_MAP_OP:
- //
- // No EFI varstore is found and directly return.
- //
- if ((EfiVarStoreNumber == 0) || (DefaultIdNumber == 0)) {
- goto Done;
- }
-
- break;
- case EFI_IFR_CHECKBOX_OP:
- IfrScope = IfrOpHdr->Scope;
- IfrQuestionType = IfrOpHdr->OpCode;
- IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)(IfrOpHdr + 1);
- IfrCheckBox = (EFI_IFR_CHECKBOX *)IfrOpHdr;
- EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);
- Width = sizeof (BOOLEAN);
- if (EfiVarStoreIndex < EfiVarStoreNumber) {
- for (Index = 0; Index < DefaultIdNumber; Index++) {
- if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_STANDARD) {
- Status = FindQuestionDefaultSetting (DefaultIdList[Index], EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, sizeof (BOOLEAN), QuestionReferBitField);
- if (!EFI_ERROR (Status)) {
- if (IfrValue.b) {
- IfrCheckBox->Flags = IfrCheckBox->Flags | EFI_IFR_CHECKBOX_DEFAULT;
- } else {
- IfrCheckBox->Flags = IfrCheckBox->Flags & (~EFI_IFR_CHECKBOX_DEFAULT);
- }
- }
- } else if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
- Status = FindQuestionDefaultSetting (DefaultIdList[Index], EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, sizeof (BOOLEAN), QuestionReferBitField);
- if (!EFI_ERROR (Status)) {
- if (IfrValue.b) {
- IfrCheckBox->Flags = IfrCheckBox->Flags | EFI_IFR_CHECKBOX_DEFAULT_MFG;
- } else {
- IfrCheckBox->Flags = IfrCheckBox->Flags & (~EFI_IFR_CHECKBOX_DEFAULT_MFG);
- }
- }
- }
- }
- }
-
- break;
- case EFI_IFR_NUMERIC_OP:
- IfrScope = IfrOpHdr->Scope;
- IfrQuestionType = IfrOpHdr->OpCode;
- IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)(IfrOpHdr + 1);
- if (QuestionReferBitField) {
- Width = (UINTN)(((EFI_IFR_ONE_OF *)IfrOpHdr)->Flags & EDKII_IFR_NUMERIC_SIZE_BIT);
- } else {
- Width = (UINTN)((UINT32)1 << (((EFI_IFR_ONE_OF *)IfrOpHdr)->Flags & EFI_IFR_NUMERIC_SIZE));
- }
-
- break;
- case EFI_IFR_ONE_OF_OP:
- IfrScope = IfrOpHdr->Scope;
- IfrQuestionType = IfrOpHdr->OpCode;
- IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)(IfrOpHdr + 1);
- if (QuestionReferBitField) {
- Width = (UINTN)(((EFI_IFR_ONE_OF *)IfrOpHdr)->Flags & EDKII_IFR_NUMERIC_SIZE_BIT);
- } else {
- Width = (UINTN)((UINT32)1 << (((EFI_IFR_ONE_OF *)IfrOpHdr)->Flags & EFI_IFR_NUMERIC_SIZE));
- }
-
- EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);
- StandardDefaultIsSet = FALSE;
- ManufactDefaultIsSet = FALSE;
- //
- // Find Default and Manufacturing default for OneOf question
- //
- if (EfiVarStoreIndex < EfiVarStoreNumber) {
- for (Index = 0; Index < DefaultIdNumber; Index++) {
- if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_STANDARD) {
- Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_STANDARD, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, Width, QuestionReferBitField);
- if (!EFI_ERROR (Status)) {
- StandardDefaultIsSet = TRUE;
- }
- } else if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
- Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_MANUFACTURING, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrManufactValue, Width, QuestionReferBitField);
- if (!EFI_ERROR (Status)) {
- ManufactDefaultIsSet = TRUE;
- }
- }
- }
- }
-
- break;
- case EFI_IFR_ORDERED_LIST_OP:
- IfrScope = IfrOpHdr->Scope;
- IfrQuestionType = IfrOpHdr->OpCode;
- IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)(IfrOpHdr + 1);
- break;
- case EFI_IFR_ONE_OF_OPTION_OP:
- if ((IfrQuestionHdr != NULL) && (IfrScope > 0)) {
- IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *)IfrOpHdr;
- if (IfrQuestionType == EFI_IFR_ONE_OF_OP) {
- Width = (UINTN)((UINT32)1 << (IfrOneOfOption->Flags & EFI_IFR_NUMERIC_SIZE));
- if (StandardDefaultIsSet) {
- if (CompareMem (&IfrOneOfOption->Value, &IfrValue, Width) == 0) {
- IfrOneOfOption->Flags |= EFI_IFR_OPTION_DEFAULT;
- } else {
- IfrOneOfOption->Flags &= ~EFI_IFR_OPTION_DEFAULT;
- }
- }
-
- if (ManufactDefaultIsSet) {
- if (CompareMem (&IfrOneOfOption->Value, &IfrManufactValue, Width) == 0) {
- IfrOneOfOption->Flags |= EFI_IFR_OPTION_DEFAULT_MFG;
- } else {
- IfrOneOfOption->Flags &= ~EFI_IFR_OPTION_DEFAULT_MFG;
- }
- }
- }
- }
-
- break;
- case EFI_IFR_DEFAULT_OP:
- if ((IfrQuestionHdr != NULL) && (IfrScope > 0)) {
- IfrDefault = (EFI_IFR_DEFAULT *)IfrOpHdr;
- //
- // Collect default value width
- //
- if (!QuestionReferBitField) {
- Width = 0;
- if ((IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_8) || (IfrDefault->Type == EFI_IFR_TYPE_BOOLEAN)) {
- Width = 1;
- } else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
- Width = 2;
- } else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
- Width = 4;
- } else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
- Width = 8;
- } else if (IfrDefault->Type == EFI_IFR_TYPE_BUFFER) {
- Width = IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value);
- }
- }
-
- //
- // Update the default value
- //
- if (Width > 0) {
- EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);
- if (EfiVarStoreIndex < EfiVarStoreNumber) {
- Status = FindQuestionDefaultSetting (IfrDefault->DefaultId, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrDefault->Value, Width, QuestionReferBitField);
- }
- }
- }
-
- break;
- case EFI_IFR_END_OP:
- if (IfrQuestionHdr != NULL) {
- if (IfrScope > 0) {
- IfrScope--;
- }
-
- if (IfrScope == 0) {
- IfrQuestionHdr = NULL;
- QuestionReferBitField = FALSE;
- }
- }
-
- break;
- case EFI_IFR_GUID_OP:
- if (CompareGuid ((EFI_GUID *)((UINT8 *)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {
- QuestionReferBitField = TRUE;
- }
-
- break;
- default:
- break;
- }
-
- IfrOffset = IfrOffset + IfrOpHdr->Length;
- IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *)IfrOpHdr + IfrOpHdr->Length);
- if (IfrScope > 0) {
- IfrScope += IfrOpHdr->Scope;
- }
- }
-
-Done:
- if (EfiVarStoreList != NULL) {
- for (Index = 0; Index < EfiVarStoreNumber; Index++) {
- FreePool (EfiVarStoreList[Index]);
- }
- }
-
- return;
-}
-
-/**
- This function insert a Form package to a package list node.
- This is a internal function.
-
- @param PackageHdr Pointer to a buffer stored with Form package
- information.
- @param NotifyType The type of change concerning the database.
- @param PackageList Pointer to a package list which will be inserted
- to.
- @param Package Created Form package
-
- @retval EFI_SUCCESS Form Package is inserted successfully.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
- Form package.
- @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
-
-**/
-EFI_STATUS
-InsertFormPackage (
- IN VOID *PackageHdr,
- IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
- IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
- OUT HII_IFR_PACKAGE_INSTANCE **Package
- )
-{
- HII_IFR_PACKAGE_INSTANCE *FormPackage;
- EFI_HII_PACKAGE_HEADER PackageHeader;
-
- if ((PackageHdr == NULL) || (PackageList == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Get the length of the package, including package header itself
- //
- CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
-
- //
- // Create a Form package node
- //
- FormPackage = (HII_IFR_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_IFR_PACKAGE_INSTANCE));
- if (FormPackage == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- FormPackage->IfrData = (UINT8 *)AllocateZeroPool (PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER));
- if (FormPackage->IfrData == NULL) {
- FreePool (FormPackage);
- return EFI_OUT_OF_RESOURCES;
- }
-
- FormPackage->Signature = HII_IFR_PACKAGE_SIGNATURE;
- //
- // Copy Package Header
- //
- CopyMem (&FormPackage->FormPkgHdr, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
-
- //
- // Copy Ifr contents
- //
- CopyMem (
- FormPackage->IfrData,
- (UINT8 *)PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER),
- PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER)
- );
-
- InsertTailList (&PackageList->FormPkgHdr, &FormPackage->IfrEntry);
- *Package = FormPackage;
-
- //
- // Update FormPackage with the default setting
- //
- UpdateDefaultSettingInFormPackage (FormPackage);
-
- if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
- PackageList->PackageListHdr.PackageLength += FormPackage->FormPkgHdr.Length;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This function exports Form packages to a buffer.
- This is a internal function.
-
- @param Private Hii database private structure.
- @param Handle Identification of a package list.
- @param PackageList Pointer to a package list which will be exported.
- @param UsedSize The length of buffer be used.
- @param BufferSize Length of the Buffer.
- @param Buffer Allocated space for storing exported data.
- @param ResultSize The size of the already exported content of this
- package list.
-
- @retval EFI_SUCCESS Form Packages are exported successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
-
-**/
-EFI_STATUS
-ExportFormPackages (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
- IN UINTN UsedSize,
- IN UINTN BufferSize,
- IN OUT VOID *Buffer,
- IN OUT UINTN *ResultSize
- )
-{
- HII_IFR_PACKAGE_INSTANCE *FormPackage;
- UINTN PackageLength;
- LIST_ENTRY *Link;
- EFI_STATUS Status;
-
- if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((BufferSize > 0) && (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- PackageLength = 0;
- Status = EFI_SUCCESS;
-
- //
- // Export Form packages.
- //
- for (Link = PackageList->FormPkgHdr.ForwardLink; Link != &PackageList->FormPkgHdr; Link = Link->ForwardLink) {
- FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);
- PackageLength += FormPackage->FormPkgHdr.Length;
- if ((Buffer != NULL) && (PackageLength + *ResultSize + UsedSize <= BufferSize)) {
- //
- // Invoke registered notification if exists
- //
- Status = InvokeRegisteredFunction (
- Private,
- EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
- (VOID *)FormPackage,
- EFI_HII_PACKAGE_FORMS,
- Handle
- );
- ASSERT_EFI_ERROR (Status);
- //
- // Copy the Form package content.
- //
- CopyMem (Buffer, (VOID *)(&FormPackage->FormPkgHdr), sizeof (EFI_HII_PACKAGE_HEADER));
- Buffer = (UINT8 *)Buffer + sizeof (EFI_HII_PACKAGE_HEADER);
- CopyMem (
- Buffer,
- (VOID *)FormPackage->IfrData,
- FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER)
- );
- Buffer = (UINT8 *)Buffer + FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
- }
- }
-
- *ResultSize += PackageLength;
-
- return EFI_SUCCESS;
-}
-
-/**
- This function deletes all Form packages from a package list node.
- This is a internal function.
-
- @param Private Hii database private data.
- @param Handle Handle of the package list which contains the to
- be removed Form packages.
- @param PackageList Pointer to a package list that contains removing
- packages.
-
- @retval EFI_SUCCESS Form Package(s) is deleted successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
-
-**/
-EFI_STATUS
-RemoveFormPackages (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
- )
-{
- LIST_ENTRY *ListHead;
- HII_IFR_PACKAGE_INSTANCE *Package;
- EFI_STATUS Status;
-
- ListHead = &PackageList->FormPkgHdr;
-
- while (!IsListEmpty (ListHead)) {
- Package = CR (
- ListHead->ForwardLink,
- HII_IFR_PACKAGE_INSTANCE,
- IfrEntry,
- HII_IFR_PACKAGE_SIGNATURE
- );
- Status = InvokeRegisteredFunction (
- Private,
- EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
- (VOID *)Package,
- EFI_HII_PACKAGE_FORMS,
- Handle
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- RemoveEntryList (&Package->IfrEntry);
- PackageList->PackageListHdr.PackageLength -= Package->FormPkgHdr.Length;
- FreePool (Package->IfrData);
- FreePool (Package);
- //
- // If Hii runtime support feature is enabled,
- // will export Hii info for runtime use after ReadyToBoot event triggered.
- // If some driver add/update/remove packages from HiiDatabase after ReadyToBoot,
- // will need to export the content of HiiDatabase.
- // But if form packages removed, also need to export the ConfigResp string
- //
- if (gExportAfterReadyToBoot) {
- gExportConfigResp = TRUE;
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This function insert a String package to a package list node.
- This is a internal function.
-
- @param Private Hii database private structure.
- @param PackageHdr Pointer to a buffer stored with String package
- information.
- @param NotifyType The type of change concerning the database.
- @param PackageList Pointer to a package list which will be inserted
- to.
- @param Package Created String package
-
- @retval EFI_SUCCESS String Package is inserted successfully.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
- String package.
- @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
- @retval EFI_UNSUPPORTED A string package with the same language already
- exists in current package list.
-
-**/
-EFI_STATUS
-InsertStringPackage (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN VOID *PackageHdr,
- IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
- IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
- OUT HII_STRING_PACKAGE_INSTANCE **Package
- )
-{
- HII_STRING_PACKAGE_INSTANCE *StringPackage;
- UINT32 HeaderSize;
- EFI_STATUS Status;
- EFI_HII_PACKAGE_HEADER PackageHeader;
- CHAR8 *Language;
- UINT32 LanguageSize;
- LIST_ENTRY *Link;
-
- if ((Private == NULL) || (PackageHdr == NULL) || (PackageList == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
- return EFI_INVALID_PARAMETER;
- }
-
- CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
- CopyMem (&HeaderSize, (UINT8 *)PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));
-
- //
- // It is illegal to have two string packages with same language within one packagelist
- // since the stringid will be duplicate if so. Check it to avoid this potential issue.
- //
- LanguageSize = HeaderSize - sizeof (EFI_HII_STRING_PACKAGE_HDR) + sizeof (CHAR8);
- Language = (CHAR8 *)AllocateZeroPool (LanguageSize);
- if (Language == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- AsciiStrCpyS (Language, LanguageSize / sizeof (CHAR8), (CHAR8 *)PackageHdr + HeaderSize - LanguageSize);
- for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {
- StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
- if (HiiCompareLanguage (Language, StringPackage->StringPkgHdr->Language)) {
- FreePool (Language);
- return EFI_UNSUPPORTED;
- }
- }
-
- FreePool (Language);
-
- //
- // Create a String package node
- //
- StringPackage = (HII_STRING_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));
- if (StringPackage == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error;
- }
-
- StringPackage->StringPkgHdr = (EFI_HII_STRING_PACKAGE_HDR *)AllocateZeroPool (HeaderSize);
- if (StringPackage->StringPkgHdr == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error;
- }
-
- StringPackage->StringBlock = (UINT8 *)AllocateZeroPool (PackageHeader.Length - HeaderSize);
- if (StringPackage->StringBlock == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error;
- }
-
- StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;
- StringPackage->FontId = 0;
- InitializeListHead (&StringPackage->FontInfoList);
-
- //
- // Copy the String package header.
- //
- CopyMem (StringPackage->StringPkgHdr, PackageHdr, HeaderSize);
-
- //
- // Copy the String blocks
- //
- CopyMem (
- StringPackage->StringBlock,
- (UINT8 *)PackageHdr + HeaderSize,
- PackageHeader.Length - HeaderSize
- );
-
- //
- // Collect all font block info
- //
- Status = FindStringBlock (Private, StringPackage, (EFI_STRING_ID)(-1), NULL, NULL, NULL, &StringPackage->MaxStringId, NULL);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Insert to String package array
- //
- InsertTailList (&PackageList->StringPkgHdr, &StringPackage->StringEntry);
- *Package = StringPackage;
-
- if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
- PackageList->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;
- }
-
- return EFI_SUCCESS;
-
-Error:
-
- if (StringPackage != NULL) {
- if (StringPackage->StringBlock != NULL) {
- FreePool (StringPackage->StringBlock);
- }
-
- if (StringPackage->StringPkgHdr != NULL) {
- FreePool (StringPackage->StringPkgHdr);
- }
-
- FreePool (StringPackage);
- }
-
- return Status;
-}
-
-/**
- Adjust all string packages in a single package list to have the same max string ID.
-
- @param PackageList Pointer to a package list which will be adjusted.
-
- @retval EFI_SUCCESS Adjust all string packages successfully.
- @retval others Can't adjust string packages.
-
-**/
-EFI_STATUS
-AdjustStringPackage (
- IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
- )
-{
- LIST_ENTRY *Link;
- HII_STRING_PACKAGE_INSTANCE *StringPackage;
- UINT32 Skip2BlockSize;
- UINT32 OldBlockSize;
- UINT8 *StringBlock;
- UINT8 *BlockPtr;
- EFI_STRING_ID MaxStringId;
- UINT16 SkipCount;
-
- MaxStringId = 0;
- for (Link = PackageList->StringPkgHdr.ForwardLink;
- Link != &PackageList->StringPkgHdr;
- Link = Link->ForwardLink
- )
- {
- StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
- if (MaxStringId < StringPackage->MaxStringId) {
- MaxStringId = StringPackage->MaxStringId;
- }
- }
-
- for (Link = PackageList->StringPkgHdr.ForwardLink;
- Link != &PackageList->StringPkgHdr;
- Link = Link->ForwardLink
- )
- {
- StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
- if (StringPackage->MaxStringId < MaxStringId) {
- OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
- //
- // Create SKIP2 EFI_HII_SIBT_SKIP2_BLOCKs to reserve the missing string IDs.
- //
- SkipCount = (UINT16)(MaxStringId - StringPackage->MaxStringId);
- Skip2BlockSize = (UINT32)sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
-
- StringBlock = (UINT8 *)AllocateZeroPool (OldBlockSize + Skip2BlockSize);
- if (StringBlock == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Copy original string blocks, except the EFI_HII_SIBT_END.
- //
- CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
- //
- // Create SKIP2 EFI_HII_SIBT_SKIP2_BLOCK blocks
- //
- BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
- *BlockPtr = EFI_HII_SIBT_SKIP2;
- CopyMem (BlockPtr + 1, &SkipCount, sizeof (UINT16));
- BlockPtr += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
-
- //
- // Append a EFI_HII_SIBT_END block to the end.
- //
- *BlockPtr = EFI_HII_SIBT_END;
- FreePool (StringPackage->StringBlock);
- StringPackage->StringBlock = StringBlock;
- StringPackage->StringPkgHdr->Header.Length += Skip2BlockSize;
- PackageList->PackageListHdr.PackageLength += Skip2BlockSize;
- StringPackage->MaxStringId = MaxStringId;
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This function exports String packages to a buffer.
- This is a internal function.
-
- @param Private Hii database private structure.
- @param Handle Identification of a package list.
- @param PackageList Pointer to a package list which will be exported.
- @param UsedSize The length of buffer be used.
- @param BufferSize Length of the Buffer.
- @param Buffer Allocated space for storing exported data.
- @param ResultSize The size of the already exported content of this
- package list.
-
- @retval EFI_SUCCESS String Packages are exported successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
-
-**/
-EFI_STATUS
-ExportStringPackages (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
- IN UINTN UsedSize,
- IN UINTN BufferSize,
- IN OUT VOID *Buffer,
- IN OUT UINTN *ResultSize
- )
-{
- LIST_ENTRY *Link;
- UINTN PackageLength;
- EFI_STATUS Status;
- HII_STRING_PACKAGE_INSTANCE *StringPackage;
-
- if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((BufferSize > 0) && (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- PackageLength = 0;
- Status = EFI_SUCCESS;
-
- for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {
- StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
- PackageLength += StringPackage->StringPkgHdr->Header.Length;
- if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
- //
- // Invoke registered notification function with EXPORT_PACK notify type
- //
- Status = InvokeRegisteredFunction (
- Private,
- EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
- (VOID *)StringPackage,
- EFI_HII_PACKAGE_STRINGS,
- Handle
- );
- ASSERT_EFI_ERROR (Status);
- //
- // Copy String package header
- //
- CopyMem (Buffer, StringPackage->StringPkgHdr, StringPackage->StringPkgHdr->HdrSize);
- Buffer = (UINT8 *)Buffer + StringPackage->StringPkgHdr->HdrSize;
-
- //
- // Copy String blocks information
- //
- CopyMem (
- Buffer,
- StringPackage->StringBlock,
- StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize
- );
- Buffer = (UINT8 *)Buffer + StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
- }
- }
-
- *ResultSize += PackageLength;
- return EFI_SUCCESS;
-}
-
-/**
- This function deletes all String packages from a package list node.
- This is a internal function.
-
- @param Private Hii database private data.
- @param Handle Handle of the package list which contains the to
- be removed String packages.
- @param PackageList Pointer to a package list that contains removing
- packages.
-
- @retval EFI_SUCCESS String Package(s) is deleted successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
-
-**/
-EFI_STATUS
-RemoveStringPackages (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
- )
-{
- LIST_ENTRY *ListHead;
- HII_STRING_PACKAGE_INSTANCE *Package;
- HII_FONT_INFO *FontInfo;
- EFI_STATUS Status;
-
- ListHead = &PackageList->StringPkgHdr;
-
- while (!IsListEmpty (ListHead)) {
- Package = CR (
- ListHead->ForwardLink,
- HII_STRING_PACKAGE_INSTANCE,
- StringEntry,
- HII_STRING_PACKAGE_SIGNATURE
- );
- Status = InvokeRegisteredFunction (
- Private,
- EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
- (VOID *)Package,
- EFI_HII_PACKAGE_STRINGS,
- Handle
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- RemoveEntryList (&Package->StringEntry);
- PackageList->PackageListHdr.PackageLength -= Package->StringPkgHdr->Header.Length;
- FreePool (Package->StringBlock);
- FreePool (Package->StringPkgHdr);
- //
- // Delete font information
- //
- while (!IsListEmpty (&Package->FontInfoList)) {
- FontInfo = CR (
- Package->FontInfoList.ForwardLink,
- HII_FONT_INFO,
- Entry,
- HII_FONT_INFO_SIGNATURE
- );
- RemoveEntryList (&FontInfo->Entry);
- FreePool (FontInfo);
- }
-
- FreePool (Package);
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This function insert a Font package to a package list node.
- This is a internal function.
-
- @param Private Hii database private structure.
- @param PackageHdr Pointer to a buffer stored with Font package
- information.
- @param NotifyType The type of change concerning the database.
- @param PackageList Pointer to a package list which will be inserted
- to.
- @param Package Created Font package
-
- @retval EFI_SUCCESS Font Package is inserted successfully.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
- Font package.
- @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
- @retval EFI_UNSUPPORTED A font package with same EFI_FONT_INFO already
- exists in current hii database.
-
-**/
-EFI_STATUS
-InsertFontPackage (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN VOID *PackageHdr,
- IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
- IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
- OUT HII_FONT_PACKAGE_INSTANCE **Package
- )
-{
- HII_FONT_PACKAGE_INSTANCE *FontPackage;
- EFI_HII_FONT_PACKAGE_HDR *FontPkgHdr;
- UINT32 HeaderSize;
- EFI_STATUS Status;
- EFI_HII_PACKAGE_HEADER PackageHeader;
- EFI_FONT_INFO *FontInfo;
- UINT32 FontInfoSize;
- HII_GLOBAL_FONT_INFO *GlobalFont;
-
- if ((Private == NULL) || (PackageHdr == NULL) || (PackageList == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
- CopyMem (&HeaderSize, (UINT8 *)PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));
-
- FontInfo = NULL;
- FontPackage = NULL;
- GlobalFont = NULL;
-
- //
- // It is illegal to have two font packages with same EFI_FONT_INFO within hii
- // database. EFI_FONT_INFO (FontName, FontSize, FontStyle) describes font's
- // attributes and identify a font uniquely.
- //
- FontPkgHdr = (EFI_HII_FONT_PACKAGE_HDR *)AllocateZeroPool (HeaderSize);
- if (FontPkgHdr == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error;
- }
-
- CopyMem (FontPkgHdr, PackageHdr, HeaderSize);
-
- FontInfoSize = sizeof (EFI_FONT_INFO) + HeaderSize - sizeof (EFI_HII_FONT_PACKAGE_HDR);
- FontInfo = (EFI_FONT_INFO *)AllocateZeroPool (FontInfoSize);
- if (FontInfo == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error;
- }
-
- FontInfo->FontStyle = FontPkgHdr->FontStyle;
- FontInfo->FontSize = FontPkgHdr->Cell.Height;
- StrCpyS (FontInfo->FontName, (FontInfoSize - OFFSET_OF (EFI_FONT_INFO, FontName)) / sizeof (CHAR16), FontPkgHdr->FontFamily);
-
- if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, NULL)) {
- Status = EFI_UNSUPPORTED;
- goto Error;
- }
-
- //
- // Create a Font package node
- //
- FontPackage = (HII_FONT_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_FONT_PACKAGE_INSTANCE));
- if (FontPackage == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error;
- }
-
- FontPackage->Signature = HII_FONT_PACKAGE_SIGNATURE;
- FontPackage->FontPkgHdr = FontPkgHdr;
- InitializeListHead (&FontPackage->GlyphInfoList);
-
- FontPackage->GlyphBlock = (UINT8 *)AllocateZeroPool (PackageHeader.Length - HeaderSize);
- if (FontPackage->GlyphBlock == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error;
- }
-
- CopyMem (FontPackage->GlyphBlock, (UINT8 *)PackageHdr + HeaderSize, PackageHeader.Length - HeaderSize);
-
- //
- // Collect all default character cell information and backup in GlyphInfoList.
- //
- Status = FindGlyphBlock (FontPackage, (CHAR16)(-1), NULL, NULL, NULL);
- if (EFI_ERROR (Status)) {
- goto Error;
- }
-
- //
- // This font package describes an unique EFI_FONT_INFO. Backup it in global
- // font info list.
- //
- GlobalFont = (HII_GLOBAL_FONT_INFO *)AllocateZeroPool (sizeof (HII_GLOBAL_FONT_INFO));
- if (GlobalFont == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error;
- }
-
- GlobalFont->Signature = HII_GLOBAL_FONT_INFO_SIGNATURE;
- GlobalFont->FontPackage = FontPackage;
- GlobalFont->FontInfoSize = FontInfoSize;
- GlobalFont->FontInfo = FontInfo;
- InsertTailList (&Private->FontInfoList, &GlobalFont->Entry);
-
- //
- // Insert this font package to Font package array
- //
- InsertTailList (&PackageList->FontPkgHdr, &FontPackage->FontEntry);
- *Package = FontPackage;
-
- if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
- PackageList->PackageListHdr.PackageLength += FontPackage->FontPkgHdr->Header.Length;
- }
-
- return EFI_SUCCESS;
-
-Error:
-
- if (FontPkgHdr != NULL) {
- FreePool (FontPkgHdr);
- }
-
- if (FontInfo != NULL) {
- FreePool (FontInfo);
- }
-
- if (FontPackage != NULL) {
- if (FontPackage->GlyphBlock != NULL) {
- FreePool (FontPackage->GlyphBlock);
- }
-
- FreePool (FontPackage);
- }
-
- if (GlobalFont != NULL) {
- FreePool (GlobalFont);
- }
-
- return Status;
-}
-
-/**
- This function exports Font packages to a buffer.
- This is a internal function.
-
- @param Private Hii database private structure.
- @param Handle Identification of a package list.
- @param PackageList Pointer to a package list which will be exported.
- @param UsedSize The length of buffer be used.
- @param BufferSize Length of the Buffer.
- @param Buffer Allocated space for storing exported data.
- @param ResultSize The size of the already exported content of this
- package list.
-
- @retval EFI_SUCCESS Font Packages are exported successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
-
-**/
-EFI_STATUS
-ExportFontPackages (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
- IN UINTN UsedSize,
- IN UINTN BufferSize,
- IN OUT VOID *Buffer,
- IN OUT UINTN *ResultSize
- )
-{
- LIST_ENTRY *Link;
- UINTN PackageLength;
- EFI_STATUS Status;
- HII_FONT_PACKAGE_INSTANCE *Package;
-
- if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((BufferSize > 0) && (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- PackageLength = 0;
- Status = EFI_SUCCESS;
-
- for (Link = PackageList->FontPkgHdr.ForwardLink; Link != &PackageList->FontPkgHdr; Link = Link->ForwardLink) {
- Package = CR (Link, HII_FONT_PACKAGE_INSTANCE, FontEntry, HII_FONT_PACKAGE_SIGNATURE);
- PackageLength += Package->FontPkgHdr->Header.Length;
- if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
- //
- // Invoke registered notification function with EXPORT_PACK notify type
- //
- Status = InvokeRegisteredFunction (
- Private,
- EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
- (VOID *)Package,
- EFI_HII_PACKAGE_FONTS,
- Handle
- );
- ASSERT_EFI_ERROR (Status);
- //
- // Copy Font package header
- //
- CopyMem (Buffer, Package->FontPkgHdr, Package->FontPkgHdr->HdrSize);
- Buffer = (UINT8 *)Buffer + Package->FontPkgHdr->HdrSize;
-
- //
- // Copy Glyph blocks information
- //
- CopyMem (
- Buffer,
- Package->GlyphBlock,
- Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize
- );
- Buffer = (UINT8 *)Buffer + Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize;
- }
- }
-
- *ResultSize += PackageLength;
- return EFI_SUCCESS;
-}
-
-/**
- This function deletes all Font packages from a package list node.
- This is a internal function.
-
- @param Private Hii database private data.
- @param Handle Handle of the package list which contains the to
- be removed Font packages.
- @param PackageList Pointer to a package list that contains removing
- packages.
-
- @retval EFI_SUCCESS Font Package(s) is deleted successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
-
-**/
-EFI_STATUS
-RemoveFontPackages (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
- )
-{
- LIST_ENTRY *ListHead;
- HII_FONT_PACKAGE_INSTANCE *Package;
- EFI_STATUS Status;
- HII_GLYPH_INFO *GlyphInfo;
- LIST_ENTRY *Link;
- HII_GLOBAL_FONT_INFO *GlobalFont;
-
- ListHead = &PackageList->FontPkgHdr;
-
- while (!IsListEmpty (ListHead)) {
- Package = CR (
- ListHead->ForwardLink,
- HII_FONT_PACKAGE_INSTANCE,
- FontEntry,
- HII_FONT_PACKAGE_SIGNATURE
- );
- Status = InvokeRegisteredFunction (
- Private,
- EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
- (VOID *)Package,
- EFI_HII_PACKAGE_FONTS,
- Handle
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- RemoveEntryList (&Package->FontEntry);
- PackageList->PackageListHdr.PackageLength -= Package->FontPkgHdr->Header.Length;
-
- if (Package->GlyphBlock != NULL) {
- FreePool (Package->GlyphBlock);
- }
-
- FreePool (Package->FontPkgHdr);
- //
- // Delete default character cell information
- //
- while (!IsListEmpty (&Package->GlyphInfoList)) {
- GlyphInfo = CR (
- Package->GlyphInfoList.ForwardLink,
- HII_GLYPH_INFO,
- Entry,
- HII_GLYPH_INFO_SIGNATURE
- );
- RemoveEntryList (&GlyphInfo->Entry);
- FreePool (GlyphInfo);
- }
-
- //
- // Remove corresponding global font info
- //
- for (Link = Private->FontInfoList.ForwardLink; Link != &Private->FontInfoList; Link = Link->ForwardLink) {
- GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);
- if (GlobalFont->FontPackage == Package) {
- RemoveEntryList (&GlobalFont->Entry);
- FreePool (GlobalFont->FontInfo);
- FreePool (GlobalFont);
- break;
- }
- }
-
- FreePool (Package);
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This function insert a Image package to a package list node.
- This is a internal function.
-
- @param PackageHdr Pointer to a buffer stored with Image package
- information.
- @param NotifyType The type of change concerning the database.
- @param PackageList Pointer to a package list which will be inserted
- to.
- @param Package Created Image package
-
- @retval EFI_SUCCESS Image Package is inserted successfully.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
- Image package.
- @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
-
-**/
-EFI_STATUS
-InsertImagePackage (
- IN VOID *PackageHdr,
- IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
- IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
- OUT HII_IMAGE_PACKAGE_INSTANCE **Package
- )
-{
- HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
- UINT32 PaletteSize;
- UINT32 ImageSize;
- UINT16 Index;
- EFI_HII_IMAGE_PALETTE_INFO_HEADER *PaletteHdr;
- EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo;
- UINT32 PaletteInfoOffset;
- UINT32 ImageInfoOffset;
- UINT16 CurrentSize;
-
- if ((PackageHdr == NULL) || (PackageList == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Less than one image package is allowed in one package list.
- //
- if (PackageList->ImagePkg != NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Create a Image package node
- //
- ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));
- if (ImagePackage == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Copy the Image package header.
- //
- CopyMem (&ImagePackage->ImagePkgHdr, PackageHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));
-
- PaletteInfoOffset = ImagePackage->ImagePkgHdr.PaletteInfoOffset;
- ImageInfoOffset = ImagePackage->ImagePkgHdr.ImageInfoOffset;
-
- //
- // If PaletteInfoOffset is zero, there are no palettes in this image package.
- //
- PaletteSize = 0;
- ImagePackage->PaletteBlock = NULL;
- if (PaletteInfoOffset != 0) {
- PaletteHdr = (EFI_HII_IMAGE_PALETTE_INFO_HEADER *)((UINT8 *)PackageHdr + PaletteInfoOffset);
- PaletteSize = sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);
- PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *)((UINT8 *)PaletteHdr + PaletteSize);
-
- for (Index = 0; Index < PaletteHdr->PaletteCount; Index++) {
- CopyMem (&CurrentSize, PaletteInfo, sizeof (UINT16));
- CurrentSize += sizeof (UINT16);
- PaletteSize += (UINT32)CurrentSize;
- PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *)((UINT8 *)PaletteInfo + CurrentSize);
- }
-
- ImagePackage->PaletteBlock = (UINT8 *)AllocateZeroPool (PaletteSize);
- if (ImagePackage->PaletteBlock == NULL) {
- FreePool (ImagePackage);
- return EFI_OUT_OF_RESOURCES;
- }
-
- CopyMem (
- ImagePackage->PaletteBlock,
- (UINT8 *)PackageHdr + PaletteInfoOffset,
- PaletteSize
- );
- }
-
- //
- // If ImageInfoOffset is zero, there are no images in this package.
- //
- ImageSize = 0;
- ImagePackage->ImageBlock = NULL;
- if (ImageInfoOffset != 0) {
- ImageSize = ImagePackage->ImagePkgHdr.Header.Length -
- sizeof (EFI_HII_IMAGE_PACKAGE_HDR) - PaletteSize;
- ImagePackage->ImageBlock = AllocateZeroPool (ImageSize);
- if (ImagePackage->ImageBlock == NULL) {
- FreePool (ImagePackage->PaletteBlock);
- FreePool (ImagePackage);
- return EFI_OUT_OF_RESOURCES;
- }
-
- CopyMem (
- ImagePackage->ImageBlock,
- (UINT8 *)PackageHdr + ImageInfoOffset,
- ImageSize
- );
- }
-
- ImagePackage->ImageBlockSize = ImageSize;
- ImagePackage->PaletteInfoSize = PaletteSize;
- PackageList->ImagePkg = ImagePackage;
- *Package = ImagePackage;
-
- if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
- PackageList->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This function exports Image packages to a buffer.
- This is a internal function.
-
- @param Private Hii database private structure.
- @param Handle Identification of a package list.
- @param PackageList Pointer to a package list which will be exported.
- @param UsedSize The length of buffer be used.
- @param BufferSize Length of the Buffer.
- @param Buffer Allocated space for storing exported data.
- @param ResultSize The size of the already exported content of this
- package list.
-
- @retval EFI_SUCCESS Image Packages are exported successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
-
-**/
-EFI_STATUS
-ExportImagePackages (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
- IN UINTN UsedSize,
- IN UINTN BufferSize,
- IN OUT VOID *Buffer,
- IN OUT UINTN *ResultSize
- )
-{
- UINTN PackageLength;
- EFI_STATUS Status;
- HII_IMAGE_PACKAGE_INSTANCE *Package;
-
- if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((BufferSize > 0) && (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Package = PackageList->ImagePkg;
-
- if (Package == NULL) {
- return EFI_SUCCESS;
- }
-
- PackageLength = Package->ImagePkgHdr.Header.Length;
-
- if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
- //
- // Invoke registered notification function with EXPORT_PACK notify type
- //
- Status = InvokeRegisteredFunction (
- Private,
- EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
- (VOID *)Package,
- EFI_HII_PACKAGE_IMAGES,
- Handle
- );
- ASSERT_EFI_ERROR (Status);
- ASSERT (
- Package->ImagePkgHdr.Header.Length ==
- sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + Package->ImageBlockSize + Package->PaletteInfoSize
- );
- //
- // Copy Image package header,
- // then justify the offset for image info and palette info in the header.
- //
- CopyMem (Buffer, &Package->ImagePkgHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));
- Buffer = (UINT8 *)Buffer + sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
-
- //
- // Copy Image blocks information
- //
- if (Package->ImageBlockSize != 0) {
- CopyMem (Buffer, Package->ImageBlock, Package->ImageBlockSize);
- Buffer = (UINT8 *)Buffer + Package->ImageBlockSize;
- }
-
- //
- // Copy Palette information
- //
- if (Package->PaletteInfoSize != 0) {
- CopyMem (Buffer, Package->PaletteBlock, Package->PaletteInfoSize);
- Buffer = (UINT8 *)Buffer + Package->PaletteInfoSize;
- }
- }
-
- *ResultSize += PackageLength;
- return EFI_SUCCESS;
-}
-
-/**
- This function deletes Image package from a package list node.
- This is a internal function.
-
- @param Private Hii database private data.
- @param Handle Handle of the package list which contains the to
- be removed Image packages.
- @param PackageList Package List which contains the to be removed
- Image package.
-
- @retval EFI_SUCCESS Image Package(s) is deleted successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
-
-**/
-EFI_STATUS
-RemoveImagePackages (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
- )
-{
- HII_IMAGE_PACKAGE_INSTANCE *Package;
- EFI_STATUS Status;
-
- Package = PackageList->ImagePkg;
-
- //
- // Image package does not exist, return directly.
- //
- if (Package == NULL) {
- return EFI_SUCCESS;
- }
-
- Status = InvokeRegisteredFunction (
- Private,
- EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
- (VOID *)Package,
- EFI_HII_PACKAGE_IMAGES,
- Handle
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- PackageList->PackageListHdr.PackageLength -= Package->ImagePkgHdr.Header.Length;
-
- FreePool (Package->ImageBlock);
- if (Package->PaletteBlock != NULL) {
- FreePool (Package->PaletteBlock);
- }
-
- FreePool (Package);
-
- PackageList->ImagePkg = NULL;
-
- return EFI_SUCCESS;
-}
-
-/**
- This function insert a Simple Font package to a package list node.
- This is a internal function.
-
- @param PackageHdr Pointer to a buffer stored with Simple Font
- package information.
- @param NotifyType The type of change concerning the database.
- @param PackageList Pointer to a package list which will be inserted
- to.
- @param Package Created Simple Font package
-
- @retval EFI_SUCCESS Simple Font Package is inserted successfully.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
- Simple Font package.
- @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
-
-**/
-EFI_STATUS
-InsertSimpleFontPackage (
- IN VOID *PackageHdr,
- IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
- IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
- OUT HII_SIMPLE_FONT_PACKAGE_INSTANCE **Package
- )
-{
- HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;
- EFI_STATUS Status;
- EFI_HII_PACKAGE_HEADER Header;
-
- if ((PackageHdr == NULL) || (PackageList == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Create a Simple Font package node
- //
- SimpleFontPackage = AllocateZeroPool (sizeof (HII_SIMPLE_FONT_PACKAGE_INSTANCE));
- if (SimpleFontPackage == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error;
- }
-
- SimpleFontPackage->Signature = HII_S_FONT_PACKAGE_SIGNATURE;
-
- //
- // Copy the Simple Font package.
- //
- CopyMem (&Header, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
-
- SimpleFontPackage->SimpleFontPkgHdr = AllocateZeroPool (Header.Length);
- if (SimpleFontPackage->SimpleFontPkgHdr == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error;
- }
-
- CopyMem (SimpleFontPackage->SimpleFontPkgHdr, PackageHdr, Header.Length);
-
- //
- // Insert to Simple Font package array
- //
- InsertTailList (&PackageList->SimpleFontPkgHdr, &SimpleFontPackage->SimpleFontEntry);
- *Package = SimpleFontPackage;
-
- if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
- PackageList->PackageListHdr.PackageLength += Header.Length;
- }
-
- return EFI_SUCCESS;
-
-Error:
-
- if (SimpleFontPackage != NULL) {
- if (SimpleFontPackage->SimpleFontPkgHdr != NULL) {
- FreePool (SimpleFontPackage->SimpleFontPkgHdr);
- }
-
- FreePool (SimpleFontPackage);
- }
-
- return Status;
-}
-
-/**
- This function exports SimpleFont packages to a buffer.
- This is a internal function.
-
- @param Private Hii database private structure.
- @param Handle Identification of a package list.
- @param PackageList Pointer to a package list which will be exported.
- @param UsedSize The length of buffer be used.
- @param BufferSize Length of the Buffer.
- @param Buffer Allocated space for storing exported data.
- @param ResultSize The size of the already exported content of this
- package list.
-
- @retval EFI_SUCCESS SimpleFont Packages are exported successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
-
-**/
-EFI_STATUS
-ExportSimpleFontPackages (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
- IN UINTN UsedSize,
- IN UINTN BufferSize,
- IN OUT VOID *Buffer,
- IN OUT UINTN *ResultSize
- )
-{
- LIST_ENTRY *Link;
- UINTN PackageLength;
- EFI_STATUS Status;
- HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;
-
- if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((BufferSize > 0) && (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- PackageLength = 0;
- Status = EFI_SUCCESS;
-
- for (Link = PackageList->SimpleFontPkgHdr.ForwardLink; Link != &PackageList->SimpleFontPkgHdr; Link = Link->ForwardLink) {
- Package = CR (Link, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE);
- PackageLength += Package->SimpleFontPkgHdr->Header.Length;
- if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
- //
- // Invoke registered notification function with EXPORT_PACK notify type
- //
- Status = InvokeRegisteredFunction (
- Private,
- EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
- (VOID *)Package,
- EFI_HII_PACKAGE_SIMPLE_FONTS,
- Handle
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Copy SimpleFont package
- //
- CopyMem (Buffer, Package->SimpleFontPkgHdr, Package->SimpleFontPkgHdr->Header.Length);
- Buffer = (UINT8 *)Buffer + Package->SimpleFontPkgHdr->Header.Length;
- }
- }
-
- *ResultSize += PackageLength;
- return EFI_SUCCESS;
-}
-
-/**
- This function deletes all Simple Font packages from a package list node.
- This is a internal function.
-
- @param Private Hii database private data.
- @param Handle Handle of the package list which contains the to
- be removed Simple Font packages.
- @param PackageList Pointer to a package list that contains removing
- packages.
-
- @retval EFI_SUCCESS Simple Font Package(s) is deleted successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
-
-**/
-EFI_STATUS
-RemoveSimpleFontPackages (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
- )
-{
- LIST_ENTRY *ListHead;
- HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;
- EFI_STATUS Status;
-
- ListHead = &PackageList->SimpleFontPkgHdr;
-
- while (!IsListEmpty (ListHead)) {
- Package = CR (
- ListHead->ForwardLink,
- HII_SIMPLE_FONT_PACKAGE_INSTANCE,
- SimpleFontEntry,
- HII_S_FONT_PACKAGE_SIGNATURE
- );
- Status = InvokeRegisteredFunction (
- Private,
- EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
- (VOID *)Package,
- EFI_HII_PACKAGE_SIMPLE_FONTS,
- Handle
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- RemoveEntryList (&Package->SimpleFontEntry);
- PackageList->PackageListHdr.PackageLength -= Package->SimpleFontPkgHdr->Header.Length;
- FreePool (Package->SimpleFontPkgHdr);
- FreePool (Package);
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This function insert a Device path package to a package list node.
- This is a internal function.
-
- @param DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol
- instance
- @param NotifyType The type of change concerning the database.
- @param PackageList Pointer to a package list which will be inserted
- to.
-
- @retval EFI_SUCCESS Device path Package is inserted successfully.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
- Device path package.
- @retval EFI_INVALID_PARAMETER DevicePath is NULL or PackageList is NULL.
-
-**/
-EFI_STATUS
-InsertDevicePathPackage (
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
- IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
- )
-{
- UINT32 PackageLength;
- EFI_HII_PACKAGE_HEADER Header;
-
- if ((DevicePath == NULL) || (PackageList == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Less than one device path package is allowed in one package list.
- //
- if (PackageList->DevicePathPkg != NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- PackageLength = (UINT32)GetDevicePathSize (DevicePath) + sizeof (EFI_HII_PACKAGE_HEADER);
- PackageList->DevicePathPkg = (UINT8 *)AllocateZeroPool (PackageLength);
- if (PackageList->DevicePathPkg == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Header.Length = PackageLength;
- Header.Type = EFI_HII_PACKAGE_DEVICE_PATH;
- CopyMem (PackageList->DevicePathPkg, &Header, sizeof (EFI_HII_PACKAGE_HEADER));
- CopyMem (
- PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER),
- DevicePath,
- PackageLength - sizeof (EFI_HII_PACKAGE_HEADER)
- );
-
- //
- // Since Device Path package is created by NewPackageList, either NEW_PACK
- // or ADD_PACK should increase the length of package list.
- //
- PackageList->PackageListHdr.PackageLength += PackageLength;
- return EFI_SUCCESS;
-}
-
-/**
- This function exports device path package to a buffer.
- This is a internal function.
-
- @param Private Hii database private structure.
- @param Handle Identification of a package list.
- @param PackageList Pointer to a package list which will be exported.
- @param UsedSize The length of buffer be used.
- @param BufferSize Length of the Buffer.
- @param Buffer Allocated space for storing exported data.
- @param ResultSize The size of the already exported content of this
- package list.
-
- @retval EFI_SUCCESS Device path Package is exported successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
-
-**/
-EFI_STATUS
-ExportDevicePathPackage (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
- IN UINTN UsedSize,
- IN UINTN BufferSize,
- IN OUT VOID *Buffer,
- IN OUT UINTN *ResultSize
- )
-{
- EFI_STATUS Status;
- UINT8 *Package;
- EFI_HII_PACKAGE_HEADER Header;
-
- if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((BufferSize > 0) && (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Package = PackageList->DevicePathPkg;
-
- if (Package == NULL) {
- return EFI_SUCCESS;
- }
-
- CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));
-
- if (Header.Length + *ResultSize + UsedSize <= BufferSize) {
- //
- // Invoke registered notification function with EXPORT_PACK notify type
- //
- Status = InvokeRegisteredFunction (
- Private,
- EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
- (VOID *)Package,
- EFI_HII_PACKAGE_DEVICE_PATH,
- Handle
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Copy Device path package
- //
- CopyMem (Buffer, Package, Header.Length);
- }
-
- *ResultSize += Header.Length;
- return EFI_SUCCESS;
-}
-
-/**
- This function deletes Device Path package from a package list node.
- This is a internal function.
-
- @param Private Hii database private data.
- @param Handle Handle of the package list.
- @param PackageList Package List which contains the to be removed
- Device Path package.
-
- @retval EFI_SUCCESS Device Path Package is deleted successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
-
-**/
-EFI_STATUS
-RemoveDevicePathPackage (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
- )
-{
- EFI_STATUS Status;
- UINT8 *Package;
- EFI_HII_PACKAGE_HEADER Header;
-
- Package = PackageList->DevicePathPkg;
-
- //
- // No device path, return directly.
- //
- if (Package == NULL) {
- return EFI_SUCCESS;
- }
-
- Status = InvokeRegisteredFunction (
- Private,
- EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
- (VOID *)Package,
- EFI_HII_PACKAGE_DEVICE_PATH,
- Handle
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));
- PackageList->PackageListHdr.PackageLength -= Header.Length;
-
- FreePool (Package);
-
- PackageList->DevicePathPkg = NULL;
-
- return EFI_SUCCESS;
-}
-
-/**
- This function will insert a device path package to package list firstly then
- invoke notification functions if any.
- This is a internal function.
-
- @param Private Hii database private structure.
- @param NotifyType The type of change concerning the database.
- @param DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol
- instance
- @param DatabaseRecord Pointer to a database record contains a package
- list which will be inserted to.
-
- @retval EFI_SUCCESS Device path Package is inserted successfully.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
- Device path package.
- @retval EFI_INVALID_PARAMETER DevicePath is NULL or PackageList is NULL.
-
-**/
-EFI_STATUS
-AddDevicePathPackage (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- IN OUT HII_DATABASE_RECORD *DatabaseRecord
- )
-{
- EFI_STATUS Status;
-
- if (DevicePath == NULL) {
- return EFI_SUCCESS;
- }
-
- ASSERT (Private != NULL);
- ASSERT (DatabaseRecord != NULL);
-
- //
- // Create a device path package and insert to packagelist
- //
- Status = InsertDevicePathPackage (
- DevicePath,
- NotifyType,
- DatabaseRecord->PackageList
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- return InvokeRegisteredFunction (
- Private,
- NotifyType,
- (VOID *)DatabaseRecord->PackageList->DevicePathPkg,
- EFI_HII_PACKAGE_DEVICE_PATH,
- DatabaseRecord->Handle
- );
-}
-
-/**
- This function insert a Keyboard Layout package to a package list node.
- This is a internal function.
-
- @param PackageHdr Pointer to a buffer stored with Keyboard Layout
- package information.
- @param NotifyType The type of change concerning the database.
- @param PackageList Pointer to a package list which will be inserted
- to.
- @param Package Created Keyboard Layout package
-
- @retval EFI_SUCCESS Keyboard Layout Package is inserted successfully.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
- Keyboard Layout package.
- @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
-
-**/
-EFI_STATUS
-InsertKeyboardLayoutPackage (
- IN VOID *PackageHdr,
- IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
- IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
- OUT HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE **Package
- )
-{
- HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;
- EFI_HII_PACKAGE_HEADER PackageHeader;
- EFI_STATUS Status;
-
- if ((PackageHdr == NULL) || (PackageList == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
-
- //
- // Create a Keyboard Layout package node
- //
- KeyboardLayoutPackage = AllocateZeroPool (sizeof (HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE));
- if (KeyboardLayoutPackage == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error;
- }
-
- KeyboardLayoutPackage->Signature = HII_KB_LAYOUT_PACKAGE_SIGNATURE;
-
- KeyboardLayoutPackage->KeyboardPkg = (UINT8 *)AllocateZeroPool (PackageHeader.Length);
- if (KeyboardLayoutPackage->KeyboardPkg == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error;
- }
-
- CopyMem (KeyboardLayoutPackage->KeyboardPkg, PackageHdr, PackageHeader.Length);
- InsertTailList (&PackageList->KeyboardLayoutHdr, &KeyboardLayoutPackage->KeyboardEntry);
-
- *Package = KeyboardLayoutPackage;
-
- if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
- PackageList->PackageListHdr.PackageLength += PackageHeader.Length;
- }
-
- return EFI_SUCCESS;
-
-Error:
-
- if (KeyboardLayoutPackage != NULL) {
- if (KeyboardLayoutPackage->KeyboardPkg != NULL) {
- FreePool (KeyboardLayoutPackage->KeyboardPkg);
- }
-
- FreePool (KeyboardLayoutPackage);
- }
-
- return Status;
-}
-
-/**
- This function exports Keyboard Layout packages to a buffer.
- This is a internal function.
-
- @param Private Hii database private structure.
- @param Handle Identification of a package list.
- @param PackageList Pointer to a package list which will be exported.
- @param UsedSize The length of buffer be used.
- @param BufferSize Length of the Buffer.
- @param Buffer Allocated space for storing exported data.
- @param ResultSize The size of the already exported content of this
- package list.
-
- @retval EFI_SUCCESS Keyboard Layout Packages are exported
- successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
-
-**/
-EFI_STATUS
-ExportKeyboardLayoutPackages (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
- IN UINTN UsedSize,
- IN UINTN BufferSize,
- IN OUT VOID *Buffer,
- IN OUT UINTN *ResultSize
- )
-{
- LIST_ENTRY *Link;
- UINTN PackageLength;
- EFI_STATUS Status;
- HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
- EFI_HII_PACKAGE_HEADER PackageHeader;
-
- if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((BufferSize > 0) && (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- PackageLength = 0;
- Status = EFI_SUCCESS;
-
- for (Link = PackageList->KeyboardLayoutHdr.ForwardLink; Link != &PackageList->KeyboardLayoutHdr; Link = Link->ForwardLink) {
- Package = CR (Link, HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE, KeyboardEntry, HII_KB_LAYOUT_PACKAGE_SIGNATURE);
- CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));
- PackageLength += PackageHeader.Length;
- if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
- //
- // Invoke registered notification function with EXPORT_PACK notify type
- //
- Status = InvokeRegisteredFunction (
- Private,
- EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
- (EFI_HII_PACKAGE_HEADER *)Package,
- EFI_HII_PACKAGE_KEYBOARD_LAYOUT,
- Handle
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Copy Keyboard Layout package
- //
- CopyMem (Buffer, Package->KeyboardPkg, PackageHeader.Length);
- Buffer = (UINT8 *)Buffer + PackageHeader.Length;
- }
- }
-
- *ResultSize += PackageLength;
- return EFI_SUCCESS;
-}
-
-/**
- This function deletes all Keyboard Layout packages from a package list node.
- This is a internal function.
-
- @param Private Hii database private data.
- @param Handle Handle of the package list which contains the to
- be removed Keyboard Layout packages.
- @param PackageList Pointer to a package list that contains removing
- packages.
-
- @retval EFI_SUCCESS Keyboard Layout Package(s) is deleted
- successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
-
-**/
-EFI_STATUS
-RemoveKeyboardLayoutPackages (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
- )
-{
- LIST_ENTRY *ListHead;
- HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
- EFI_HII_PACKAGE_HEADER PackageHeader;
- EFI_STATUS Status;
-
- ListHead = &PackageList->KeyboardLayoutHdr;
-
- while (!IsListEmpty (ListHead)) {
- Package = CR (
- ListHead->ForwardLink,
- HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,
- KeyboardEntry,
- HII_KB_LAYOUT_PACKAGE_SIGNATURE
- );
- Status = InvokeRegisteredFunction (
- Private,
- EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
- (VOID *)Package,
- EFI_HII_PACKAGE_KEYBOARD_LAYOUT,
- Handle
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- RemoveEntryList (&Package->KeyboardEntry);
- CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));
- PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;
- FreePool (Package->KeyboardPkg);
- FreePool (Package);
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This function will insert a package list to hii database firstly then
- invoke notification functions if any. It is the worker function of
- HiiNewPackageList and HiiUpdatePackageList.
-
- This is a internal function.
-
- @param Private Hii database private structure.
- @param NotifyType The type of change concerning the database.
- @param PackageList Pointer to a package list.
- @param DatabaseRecord Pointer to a database record contains a package
- list instance which will be inserted to.
-
- @retval EFI_SUCCESS All incoming packages are inserted to current
- database.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
- Device path package.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
-
-**/
-EFI_STATUS
-AddPackages (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
- IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
- IN OUT HII_DATABASE_RECORD *DatabaseRecord
- )
-{
- EFI_STATUS Status;
- HII_GUID_PACKAGE_INSTANCE *GuidPackage;
- HII_IFR_PACKAGE_INSTANCE *FormPackage;
- HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;
- HII_STRING_PACKAGE_INSTANCE *StringPackage;
- HII_FONT_PACKAGE_INSTANCE *FontPackage;
- HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;
- HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
- EFI_HII_PACKAGE_HEADER *PackageHdrPtr;
- EFI_HII_PACKAGE_HEADER PackageHeader;
- UINT32 OldPackageListLen;
- BOOLEAN StringPkgIsAdd;
-
- //
- // Initialize Variables
- //
- StringPkgIsAdd = FALSE;
- FontPackage = NULL;
- StringPackage = NULL;
- GuidPackage = NULL;
- FormPackage = NULL;
- ImagePackage = NULL;
- SimpleFontPackage = NULL;
- KeyboardLayoutPackage = NULL;
-
- //
- // Process the package list header
- //
- OldPackageListLen = DatabaseRecord->PackageList->PackageListHdr.PackageLength;
- CopyMem (
- &DatabaseRecord->PackageList->PackageListHdr,
- (VOID *)PackageList,
- sizeof (EFI_HII_PACKAGE_LIST_HEADER)
- );
- if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
- DatabaseRecord->PackageList->PackageListHdr.PackageLength = OldPackageListLen;
- }
-
- PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *)((UINT8 *)PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));
- CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
-
- Status = EFI_SUCCESS;
-
- while (PackageHeader.Type != EFI_HII_PACKAGE_END) {
- switch (PackageHeader.Type) {
- case EFI_HII_PACKAGE_TYPE_GUID:
- Status = InsertGuidPackage (
- PackageHdrPtr,
- NotifyType,
- DatabaseRecord->PackageList,
- &GuidPackage
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = InvokeRegisteredFunction (
- Private,
- NotifyType,
- (VOID *)GuidPackage,
- (UINT8)(PackageHeader.Type),
- DatabaseRecord->Handle
- );
- break;
- case EFI_HII_PACKAGE_FORMS:
- Status = InsertFormPackage (
- PackageHdrPtr,
- NotifyType,
- DatabaseRecord->PackageList,
- &FormPackage
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = InvokeRegisteredFunction (
- Private,
- NotifyType,
- (VOID *)FormPackage,
- (UINT8)(PackageHeader.Type),
- DatabaseRecord->Handle
- );
- //
- // If Hii runtime support feature is enabled,
- // will export Hii info for runtime use after ReadyToBoot event triggered.
- // If some driver add/update/remove packages from HiiDatabase after ReadyToBoot,
- // will need to export the content of HiiDatabase.
- // But if form packages added/updated, also need to export the ConfigResp string.
- //
- if (gExportAfterReadyToBoot) {
- gExportConfigResp = TRUE;
- }
-
- break;
- case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
- Status = InsertKeyboardLayoutPackage (
- PackageHdrPtr,
- NotifyType,
- DatabaseRecord->PackageList,
- &KeyboardLayoutPackage
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = InvokeRegisteredFunction (
- Private,
- NotifyType,
- (VOID *)KeyboardLayoutPackage,
- (UINT8)(PackageHeader.Type),
- DatabaseRecord->Handle
- );
- break;
- case EFI_HII_PACKAGE_STRINGS:
- Status = InsertStringPackage (
- Private,
- PackageHdrPtr,
- NotifyType,
- DatabaseRecord->PackageList,
- &StringPackage
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- ASSERT (StringPackage != NULL);
- Status = InvokeRegisteredFunction (
- Private,
- NotifyType,
- (VOID *)StringPackage,
- (UINT8)(PackageHeader.Type),
- DatabaseRecord->Handle
- );
- StringPkgIsAdd = TRUE;
- break;
- case EFI_HII_PACKAGE_FONTS:
- Status = InsertFontPackage (
- Private,
- PackageHdrPtr,
- NotifyType,
- DatabaseRecord->PackageList,
- &FontPackage
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = InvokeRegisteredFunction (
- Private,
- NotifyType,
- (VOID *)FontPackage,
- (UINT8)(PackageHeader.Type),
- DatabaseRecord->Handle
- );
- break;
- case EFI_HII_PACKAGE_IMAGES:
- Status = InsertImagePackage (
- PackageHdrPtr,
- NotifyType,
- DatabaseRecord->PackageList,
- &ImagePackage
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = InvokeRegisteredFunction (
- Private,
- NotifyType,
- (VOID *)ImagePackage,
- (UINT8)(PackageHeader.Type),
- DatabaseRecord->Handle
- );
- break;
- case EFI_HII_PACKAGE_SIMPLE_FONTS:
- Status = InsertSimpleFontPackage (
- PackageHdrPtr,
- NotifyType,
- DatabaseRecord->PackageList,
- &SimpleFontPackage
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = InvokeRegisteredFunction (
- Private,
- NotifyType,
- (VOID *)SimpleFontPackage,
- (UINT8)(PackageHeader.Type),
- DatabaseRecord->Handle
- );
- break;
- case EFI_HII_PACKAGE_DEVICE_PATH:
- Status = AddDevicePathPackage (
- Private,
- NotifyType,
- (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)PackageHdrPtr + sizeof (EFI_HII_PACKAGE_HEADER)),
- DatabaseRecord
- );
- break;
- default:
- break;
- }
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // goto header of next package
- //
- PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *)((UINT8 *)PackageHdrPtr + PackageHeader.Length);
- CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
- }
-
- //
- // Adjust String Package to make sure all string packages have the same max string ID.
- //
- if (!EFI_ERROR (Status) && StringPkgIsAdd) {
- Status = AdjustStringPackage (DatabaseRecord->PackageList);
- }
-
- return Status;
-}
-
-/**
- This function exports a package list to a buffer. It is the worker function
- of HiiExportPackageList.
-
- This is a internal function.
-
- @param Private Hii database private structure.
- @param Handle Identification of a package list.
- @param PackageList Pointer to a package list which will be exported.
- @param UsedSize The length of buffer has been used by exporting
- package lists when Handle is NULL.
- @param BufferSize Length of the Buffer.
- @param Buffer Allocated space for storing exported data.
-
- @retval EFI_SUCCESS Keyboard Layout Packages are exported
- successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
-
-**/
-EFI_STATUS
-ExportPackageList (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
- IN OUT UINTN *UsedSize,
- IN UINTN BufferSize,
- OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer
- )
-{
- EFI_STATUS Status;
- UINTN ResultSize;
- EFI_HII_PACKAGE_HEADER EndofPackageList;
-
- ASSERT (Private != NULL && PackageList != NULL && UsedSize != NULL);
- ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
- ASSERT (IsHiiHandleValid (Handle));
-
- if ((BufferSize > 0) && (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Copy the package list header
- // ResultSize indicates the length of the exported bytes of this package list
- //
- ResultSize = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
- if (ResultSize + *UsedSize <= BufferSize) {
- CopyMem ((VOID *)Buffer, PackageList, ResultSize);
- }
-
- //
- // Copy the packages and invoke EXPORT_PACK notify functions if exists.
- //
- Status = ExportGuidPackages (
- Private,
- Handle,
- PackageList,
- *UsedSize,
- BufferSize,
- (VOID *)((UINT8 *)Buffer + ResultSize),
- &ResultSize
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = ExportFormPackages (
- Private,
- Handle,
- PackageList,
- *UsedSize,
- BufferSize,
- (VOID *)((UINT8 *)Buffer + ResultSize),
- &ResultSize
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = ExportKeyboardLayoutPackages (
- Private,
- Handle,
- PackageList,
- *UsedSize,
- BufferSize,
- (VOID *)((UINT8 *)Buffer + ResultSize),
- &ResultSize
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = ExportStringPackages (
- Private,
- Handle,
- PackageList,
- *UsedSize,
- BufferSize,
- (VOID *)((UINT8 *)Buffer + ResultSize),
- &ResultSize
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = ExportFontPackages (
- Private,
- Handle,
- PackageList,
- *UsedSize,
- BufferSize,
- (VOID *)((UINT8 *)Buffer + ResultSize),
- &ResultSize
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = ExportImagePackages (
- Private,
- Handle,
- PackageList,
- *UsedSize,
- BufferSize,
- (VOID *)((UINT8 *)Buffer + ResultSize),
- &ResultSize
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = ExportSimpleFontPackages (
- Private,
- Handle,
- PackageList,
- *UsedSize,
- BufferSize,
- (VOID *)((UINT8 *)Buffer + ResultSize),
- &ResultSize
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = ExportDevicePathPackage (
- Private,
- Handle,
- PackageList,
- *UsedSize,
- BufferSize,
- (VOID *)((UINT8 *)Buffer + ResultSize),
- &ResultSize
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Append the package list end.
- //
- EndofPackageList.Length = sizeof (EFI_HII_PACKAGE_HEADER);
- EndofPackageList.Type = EFI_HII_PACKAGE_END;
- if (ResultSize + *UsedSize + sizeof (EFI_HII_PACKAGE_HEADER) <= BufferSize) {
- CopyMem (
- (VOID *)((UINT8 *)Buffer + ResultSize),
- (VOID *)&EndofPackageList,
- sizeof (EFI_HII_PACKAGE_HEADER)
- );
- }
-
- *UsedSize += ResultSize + sizeof (EFI_HII_PACKAGE_HEADER);
-
- return EFI_SUCCESS;
-}
-
-/**
-This function mainly use to get and update ConfigResp string.
-
-@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
-
-@retval EFI_SUCCESS Get the information successfully.
-@retval EFI_OUT_OF_RESOURCES Not enough memory to store the Configuration Setting data.
-
-**/
-EFI_STATUS
-HiiGetConfigRespInfo (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This
- )
-{
- EFI_STATUS Status;
- HII_DATABASE_PRIVATE_DATA *Private;
- EFI_STRING ConfigAltResp;
- UINTN ConfigSize;
-
- ConfigAltResp = NULL;
- ConfigSize = 0;
-
- Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
-
- //
- // Get ConfigResp string
- //
- Status = HiiConfigRoutingExportConfig (&Private->ConfigRouting, &ConfigAltResp);
-
- if (!EFI_ERROR (Status)) {
- ConfigSize = StrSize (ConfigAltResp);
- if (ConfigSize > gConfigRespSize) {
- //
- // Do 25% overallocation to minimize the number of memory allocations after ReadyToBoot.
- // Since lots of allocation after ReadyToBoot may change memory map and cause S4 resume issue.
- //
- gConfigRespSize = ConfigSize + (ConfigSize >> 2);
- if (gRTConfigRespBuffer != NULL) {
- FreePool (gRTConfigRespBuffer);
- DEBUG ((DEBUG_WARN, "[HiiDatabase]: Memory allocation is required after ReadyToBoot, which may change memory map and cause S4 resume issue.\n"));
- }
-
- gRTConfigRespBuffer = (EFI_STRING)AllocateRuntimeZeroPool (gConfigRespSize);
- if (gRTConfigRespBuffer == NULL) {
- FreePool (ConfigAltResp);
- DEBUG ((DEBUG_ERROR, "[HiiDatabase]: No enough memory resource to store the ConfigResp string.\n"));
- //
- // Remove from the System Table when the configuration runtime buffer is freed.
- //
- gBS->InstallConfigurationTable (&gEfiHiiConfigRoutingProtocolGuid, NULL);
- return EFI_OUT_OF_RESOURCES;
- }
- } else {
- ZeroMem (gRTConfigRespBuffer, gConfigRespSize);
- }
-
- CopyMem (gRTConfigRespBuffer, ConfigAltResp, ConfigSize);
- gBS->InstallConfigurationTable (&gEfiHiiConfigRoutingProtocolGuid, gRTConfigRespBuffer);
- FreePool (ConfigAltResp);
- }
-
- return EFI_SUCCESS;
-}
-
-/**
-This is an internal function,mainly use to get HiiDatabase information.
-
-@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
-
-@retval EFI_SUCCESS Get the information successfully.
-@retval EFI_OUT_OF_RESOURCES Not enough memory to store the Hiidatabase data.
-
-**/
-EFI_STATUS
-HiiGetDatabaseInfo (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This
- )
-{
- EFI_STATUS Status;
- EFI_HII_PACKAGE_LIST_HEADER *DatabaseInfo;
- UINTN DatabaseInfoSize;
-
- DatabaseInfo = NULL;
- DatabaseInfoSize = 0;
-
- //
- // Get HiiDatabase information.
- //
- Status = HiiExportPackageLists (This, NULL, &DatabaseInfoSize, DatabaseInfo);
-
- ASSERT (Status == EFI_BUFFER_TOO_SMALL);
-
- if (DatabaseInfoSize > gDatabaseInfoSize ) {
- //
- // Do 25% overallocation to minimize the number of memory allocations after ReadyToBoot.
- // Since lots of allocation after ReadyToBoot may change memory map and cause S4 resume issue.
- //
- gDatabaseInfoSize = DatabaseInfoSize + (DatabaseInfoSize >> 2);
- if (gRTDatabaseInfoBuffer != NULL) {
- FreePool (gRTDatabaseInfoBuffer);
- DEBUG ((DEBUG_WARN, "[HiiDatabase]: Memory allocation is required after ReadyToBoot, which may change memory map and cause S4 resume issue.\n"));
- }
-
- gRTDatabaseInfoBuffer = AllocateRuntimeZeroPool (gDatabaseInfoSize);
- if (gRTDatabaseInfoBuffer == NULL) {
- DEBUG ((DEBUG_ERROR, "[HiiDatabase]: No enough memory resource to store the HiiDatabase info.\n"));
- //
- // Remove from the System Table when the configuration runtime buffer is freed.
- //
- gBS->InstallConfigurationTable (&gEfiHiiDatabaseProtocolGuid, NULL);
- return EFI_OUT_OF_RESOURCES;
- }
- } else {
- ZeroMem (gRTDatabaseInfoBuffer, gDatabaseInfoSize);
- }
-
- Status = HiiExportPackageLists (This, NULL, &DatabaseInfoSize, gRTDatabaseInfoBuffer);
- ASSERT_EFI_ERROR (Status);
- gBS->InstallConfigurationTable (&gEfiHiiDatabaseProtocolGuid, gRTDatabaseInfoBuffer);
-
- return EFI_SUCCESS;
-}
-
-/**
- This function adds the packages in the package list to the database and returns a handle. If there is a
- EFI_DEVICE_PATH_PROTOCOL associated with the DriverHandle, then this function will
- create a package of type EFI_PACKAGE_TYPE_DEVICE_PATH and add it to the package list.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER
- structure.
- @param DriverHandle Associate the package list with this EFI handle.
- If a NULL is specified, this data will not be associate
- with any drivers and cannot have a callback induced.
- @param Handle A pointer to the EFI_HII_HANDLE instance.
-
- @retval EFI_SUCCESS The package list associated with the Handle was
- added to the HII database.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
- database contents.
- @retval EFI_INVALID_PARAMETER PackageList is NULL or Handle is NULL.
- @retval EFI_INVALID_PARAMETER PackageListGuid already exists in database.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiNewPackageList (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
- IN CONST EFI_HANDLE DriverHandle OPTIONAL,
- OUT EFI_HII_HANDLE *Handle
- )
-{
- EFI_STATUS Status;
- HII_DATABASE_PRIVATE_DATA *Private;
- HII_DATABASE_RECORD *DatabaseRecord;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- LIST_ENTRY *Link;
- EFI_GUID PackageListGuid;
-
- if ((This == NULL) || (PackageList == NULL) || (Handle == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- CopyMem (&PackageListGuid, (VOID *)PackageList, sizeof (EFI_GUID));
-
- //
- // Check the Package list GUID to guarantee this GUID is unique in database.
- //
- for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
- DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- if (CompareGuid (
- &(DatabaseRecord->PackageList->PackageListHdr.PackageListGuid),
- &PackageListGuid
- ) &&
- (DatabaseRecord->DriverHandle == DriverHandle))
- {
- return EFI_INVALID_PARAMETER;
- }
- }
-
- EfiAcquireLock (&mHiiDatabaseLock);
-
- //
- // Build a PackageList node
- //
- Status = GenerateHiiDatabaseRecord (Private, &DatabaseRecord);
- if (EFI_ERROR (Status)) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return Status;
- }
-
- //
- // Fill in information of the created Package List node
- // according to incoming package list.
- //
- Status = AddPackages (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, PackageList, DatabaseRecord);
- if (EFI_ERROR (Status)) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return Status;
- }
-
- DatabaseRecord->DriverHandle = DriverHandle;
-
- //
- // Create a Device path package and add into the package list if exists.
- //
- Status = gBS->HandleProtocol (
- DriverHandle,
- &gEfiDevicePathProtocolGuid,
- (VOID **)&DevicePath
- );
- if (!EFI_ERROR (Status)) {
- Status = AddDevicePathPackage (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, DevicePath, DatabaseRecord);
- ASSERT_EFI_ERROR (Status);
- }
-
- *Handle = DatabaseRecord->Handle;
-
- //
- // Check whether need to get the Database info.
- // Only after ReadyToBoot, need to do the export.
- //
- if (gExportAfterReadyToBoot) {
- HiiGetDatabaseInfo (This);
- }
-
- EfiReleaseLock (&mHiiDatabaseLock);
-
- //
- // Notes:
- // HiiGetDatabaseInfo () will get the contents of HII data base,
- // belong to the atomic behavior of Hii Database update.
- // And since HiiGetConfigRespInfo () will get the configuration setting info from HII drivers
- // we can not think it belong to the atomic behavior of Hii Database update.
- // That's why EfiReleaseLock (&mHiiDatabaseLock) is callled before HiiGetConfigRespInfo ().
- //
-
- // Check whether need to get the configuration setting info from HII drivers.
- // When after ReadyToBoot and need to do the export for form package add.
- //
- if (gExportAfterReadyToBoot && gExportConfigResp) {
- HiiGetConfigRespInfo (This);
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This function removes the package list that is associated with Handle
- from the HII database. Before removing the package, any registered functions
- with the notification type REMOVE_PACK and the same package type will be called.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param Handle The handle that was registered to the data that is
- requested for removal.
-
- @retval EFI_SUCCESS The data associated with the Handle was removed
- from the HII database.
- @retval EFI_NOT_FOUND The specified handle is not in database.
- @retval EFI_INVALID_PARAMETER The Handle was not valid.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiRemovePackageList (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN EFI_HII_HANDLE Handle
- )
-{
- EFI_STATUS Status;
- HII_DATABASE_PRIVATE_DATA *Private;
- LIST_ENTRY *Link;
- HII_DATABASE_RECORD *Node;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
- HII_HANDLE *HiiHandle;
-
- if (This == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (!IsHiiHandleValid (Handle)) {
- return EFI_NOT_FOUND;
- }
-
- EfiAcquireLock (&mHiiDatabaseLock);
-
- Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
-
- //
- // Get the packagelist to be removed.
- //
- for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
- Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- if (Node->Handle == Handle) {
- PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList);
- ASSERT (PackageList != NULL);
-
- //
- // Call registered functions with REMOVE_PACK before removing packages
- // then remove them.
- //
- Status = RemoveGuidPackages (Private, Handle, PackageList);
- if (EFI_ERROR (Status)) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return Status;
- }
-
- Status = RemoveFormPackages (Private, Handle, PackageList);
- if (EFI_ERROR (Status)) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return Status;
- }
-
- Status = RemoveKeyboardLayoutPackages (Private, Handle, PackageList);
- if (EFI_ERROR (Status)) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return Status;
- }
-
- Status = RemoveStringPackages (Private, Handle, PackageList);
- if (EFI_ERROR (Status)) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return Status;
- }
-
- Status = RemoveFontPackages (Private, Handle, PackageList);
- if (EFI_ERROR (Status)) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return Status;
- }
-
- Status = RemoveImagePackages (Private, Handle, PackageList);
- if (EFI_ERROR (Status)) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return Status;
- }
-
- Status = RemoveSimpleFontPackages (Private, Handle, PackageList);
- if (EFI_ERROR (Status)) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return Status;
- }
-
- Status = RemoveDevicePathPackage (Private, Handle, PackageList);
- if (EFI_ERROR (Status)) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return Status;
- }
-
- //
- // Free resources of the package list
- //
- RemoveEntryList (&Node->DatabaseEntry);
-
- HiiHandle = (HII_HANDLE *)Handle;
- RemoveEntryList (&HiiHandle->Handle);
- Private->HiiHandleCount--;
- ASSERT (Private->HiiHandleCount >= 0);
-
- HiiHandle->Signature = 0;
- FreePool (HiiHandle);
- FreePool (Node->PackageList);
- FreePool (Node);
-
- //
- // Check whether need to get the Database info.
- // Only after ReadyToBoot, need to do the export.
- //
- if (gExportAfterReadyToBoot) {
- HiiGetDatabaseInfo (This);
- }
-
- EfiReleaseLock (&mHiiDatabaseLock);
-
- //
- // Notes:
- // HiiGetDatabaseInfo () will get the contents of HII data base,
- // belong to the atomic behavior of Hii Database update.
- // And since HiiGetConfigRespInfo () will get the configuration setting info from HII drivers
- // we can not think it belong to the atomic behavior of Hii Database update.
- // That's why EfiReleaseLock (&mHiiDatabaseLock) is callled before HiiGetConfigRespInfo ().
- //
-
- //
- // Check whether need to get the configuration setting info from HII drivers.
- // When after ReadyToBoot and need to do the export for form package remove.
- //
- if (gExportAfterReadyToBoot && gExportConfigResp) {
- HiiGetConfigRespInfo (This);
- }
-
- return EFI_SUCCESS;
- }
- }
-
- EfiReleaseLock (&mHiiDatabaseLock);
- return EFI_NOT_FOUND;
-}
-
-/**
- This function updates the existing package list (which has the specified Handle)
- in the HII databases, using the new package list specified by PackageList.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param Handle The handle that was registered to the data that is
- requested to be updated.
- @param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER
- package.
-
- @retval EFI_SUCCESS The HII database was successfully updated.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate enough memory for the updated
- database.
- @retval EFI_INVALID_PARAMETER PackageList was NULL.
- @retval EFI_NOT_FOUND The specified Handle is not in database.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiUpdatePackageList (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN EFI_HII_HANDLE Handle,
- IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList
- )
-{
- EFI_STATUS Status;
- HII_DATABASE_PRIVATE_DATA *Private;
- LIST_ENTRY *Link;
- HII_DATABASE_RECORD *Node;
- EFI_HII_PACKAGE_HEADER *PackageHdrPtr;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *OldPackageList;
- EFI_HII_PACKAGE_HEADER PackageHeader;
-
- if ((This == NULL) || (PackageList == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (!IsHiiHandleValid (Handle)) {
- return EFI_NOT_FOUND;
- }
-
- Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
-
- PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *)((UINT8 *)PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));
-
- Status = EFI_SUCCESS;
-
- EfiAcquireLock (&mHiiDatabaseLock);
- //
- // Get original packagelist to be updated
- //
- for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
- Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- if (Node->Handle == Handle) {
- OldPackageList = Node->PackageList;
- //
- // Remove the package if its type matches one of the package types which is
- // contained in the new package list.
- //
- CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
- while (PackageHeader.Type != EFI_HII_PACKAGE_END) {
- switch (PackageHeader.Type) {
- case EFI_HII_PACKAGE_TYPE_GUID:
- Status = RemoveGuidPackages (Private, Handle, OldPackageList);
- break;
- case EFI_HII_PACKAGE_FORMS:
- Status = RemoveFormPackages (Private, Handle, OldPackageList);
- break;
- case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
- Status = RemoveKeyboardLayoutPackages (Private, Handle, OldPackageList);
- break;
- case EFI_HII_PACKAGE_STRINGS:
- Status = RemoveStringPackages (Private, Handle, OldPackageList);
- break;
- case EFI_HII_PACKAGE_FONTS:
- Status = RemoveFontPackages (Private, Handle, OldPackageList);
- break;
- case EFI_HII_PACKAGE_IMAGES:
- Status = RemoveImagePackages (Private, Handle, OldPackageList);
- break;
- case EFI_HII_PACKAGE_SIMPLE_FONTS:
- Status = RemoveSimpleFontPackages (Private, Handle, OldPackageList);
- break;
- case EFI_HII_PACKAGE_DEVICE_PATH:
- Status = RemoveDevicePathPackage (Private, Handle, OldPackageList);
- break;
- }
-
- if (EFI_ERROR (Status)) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return Status;
- }
-
- PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *)((UINT8 *)PackageHdrPtr + PackageHeader.Length);
- CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
- }
-
- //
- // Add all of the packages within the new package list
- //
- Status = AddPackages (Private, EFI_HII_DATABASE_NOTIFY_ADD_PACK, PackageList, Node);
-
- //
- // Check whether need to get the Database info.
- // Only after ReadyToBoot, need to do the export.
- //
- if (gExportAfterReadyToBoot && (Status == EFI_SUCCESS)) {
- HiiGetDatabaseInfo (This);
- }
-
- EfiReleaseLock (&mHiiDatabaseLock);
-
- //
- // Notes:
- // HiiGetDatabaseInfo () will get the contents of HII data base,
- // belong to the atomic behavior of Hii Database update.
- // And since HiiGetConfigRespInfo () will get the configuration setting info from HII drivers
- // we can not think it belong to the atomic behavior of Hii Database update.
- // That's why EfiReleaseLock (&mHiiDatabaseLock) is callled before HiiGetConfigRespInfo ().
- //
-
- //
- // Check whether need to get the configuration setting info from HII drivers.
- // When after ReadyToBoot and need to do the export for form package update.
- //
- if (gExportAfterReadyToBoot && gExportConfigResp && (Status == EFI_SUCCESS)) {
- HiiGetConfigRespInfo (This);
- }
-
- return Status;
- }
- }
-
- EfiReleaseLock (&mHiiDatabaseLock);
- return EFI_NOT_FOUND;
-}
-
-/**
- This function returns a list of the package handles of the specified type
- that are currently active in the database. The pseudo-type
- EFI_HII_PACKAGE_TYPE_ALL will cause all package handles to be listed.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param PackageType Specifies the package type of the packages to list
- or EFI_HII_PACKAGE_TYPE_ALL for all packages to be
- listed.
- @param PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then
- this is the pointer to the GUID which must match
- the Guid field of EFI_HII_GUID_PACKAGE_GUID_HDR.
- Otherwise, it must be NULL.
- @param HandleBufferLength On input, a pointer to the length of the handle
- buffer. On output, the length of the handle
- buffer that is required for the handles found.
- @param Handle An array of EFI_HII_HANDLE instances returned.
-
- @retval EFI_SUCCESS The matching handles are outputted successfully.
- HandleBufferLength is updated with the actual length.
- @retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that
- Handle is too small to support the number of
- handles. HandleBufferLength is updated with a
- value that will enable the data to fit.
- @retval EFI_NOT_FOUND No matching handle could not be found in database.
- @retval EFI_INVALID_PARAMETER HandleBufferLength was NULL.
- @retval EFI_INVALID_PARAMETER The value referenced by HandleBufferLength was not
- zero and Handle was NULL.
- @retval EFI_INVALID_PARAMETER PackageType is not a EFI_HII_PACKAGE_TYPE_GUID but
- PackageGuid is not NULL, PackageType is a EFI_HII_
- PACKAGE_TYPE_GUID but PackageGuid is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiListPackageLists (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN UINT8 PackageType,
- IN CONST EFI_GUID *PackageGuid,
- IN OUT UINTN *HandleBufferLength,
- OUT EFI_HII_HANDLE *Handle
- )
-{
- HII_GUID_PACKAGE_INSTANCE *GuidPackage;
- HII_DATABASE_PRIVATE_DATA *Private;
- HII_DATABASE_RECORD *Node;
- LIST_ENTRY *Link;
- BOOLEAN Matched;
- HII_HANDLE **Result;
- UINTN ResultSize;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
- LIST_ENTRY *Link1;
-
- //
- // Check input parameters
- //
- if ((This == NULL) || (HandleBufferLength == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((*HandleBufferLength > 0) && (Handle == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (((PackageType == EFI_HII_PACKAGE_TYPE_GUID) && (PackageGuid == NULL)) ||
- ((PackageType != EFI_HII_PACKAGE_TYPE_GUID) && (PackageGuid != NULL)))
- {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- Matched = FALSE;
- Result = (HII_HANDLE **)Handle;
- ResultSize = 0;
-
- for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
- Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList);
- switch (PackageType) {
- case EFI_HII_PACKAGE_TYPE_GUID:
- for (Link1 = PackageList->GuidPkgHdr.ForwardLink; Link1 != &PackageList->GuidPkgHdr; Link1 = Link1->ForwardLink) {
- GuidPackage = CR (Link1, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);
- if (CompareGuid (
- (EFI_GUID *)PackageGuid,
- (EFI_GUID *)(GuidPackage->GuidPkg + sizeof (EFI_HII_PACKAGE_HEADER))
- ))
- {
- Matched = TRUE;
- break;
- }
- }
-
- break;
- case EFI_HII_PACKAGE_FORMS:
- if (!IsListEmpty (&PackageList->FormPkgHdr)) {
- Matched = TRUE;
- }
-
- break;
- case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
- if (!IsListEmpty (&PackageList->KeyboardLayoutHdr)) {
- Matched = TRUE;
- }
-
- break;
- case EFI_HII_PACKAGE_STRINGS:
- if (!IsListEmpty (&PackageList->StringPkgHdr)) {
- Matched = TRUE;
- }
-
- break;
- case EFI_HII_PACKAGE_FONTS:
- if (!IsListEmpty (&PackageList->FontPkgHdr)) {
- Matched = TRUE;
- }
-
- break;
- case EFI_HII_PACKAGE_IMAGES:
- if (PackageList->ImagePkg != NULL) {
- Matched = TRUE;
- }
-
- break;
- case EFI_HII_PACKAGE_SIMPLE_FONTS:
- if (!IsListEmpty (&PackageList->SimpleFontPkgHdr)) {
- Matched = TRUE;
- }
-
- break;
- case EFI_HII_PACKAGE_DEVICE_PATH:
- if (PackageList->DevicePathPkg != NULL) {
- Matched = TRUE;
- }
-
- break;
- //
- // Pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package handles
- // to be listed.
- //
- case EFI_HII_PACKAGE_TYPE_ALL:
- Matched = TRUE;
- break;
- default:
- break;
- }
-
- //
- // This active package list has the specified package type, list it.
- //
- if (Matched) {
- ResultSize += sizeof (EFI_HII_HANDLE);
- if (ResultSize <= *HandleBufferLength) {
- *Result++ = Node->Handle;
- }
- }
-
- Matched = FALSE;
- }
-
- if (ResultSize == 0) {
- return EFI_NOT_FOUND;
- }
-
- if (*HandleBufferLength < ResultSize) {
- *HandleBufferLength = ResultSize;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- *HandleBufferLength = ResultSize;
- return EFI_SUCCESS;
-}
-
-/**
- This function will export one or all package lists in the database to a buffer.
- For each package list exported, this function will call functions registered
- with EXPORT_PACK and then copy the package list to the buffer.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param Handle An EFI_HII_HANDLE that corresponds to the desired
- package list in the HII database to export or NULL
- to indicate all package lists should be exported.
- @param BufferSize On input, a pointer to the length of the buffer.
- On output, the length of the buffer that is
- required for the exported data.
- @param Buffer A pointer to a buffer that will contain the
- results of the export function.
-
- @retval EFI_SUCCESS Package exported.
- @retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that
- Handle is too small to support the number of
- handles. HandleBufferLength is updated with a
- value that will enable the data to fit.
- @retval EFI_NOT_FOUND The specified Handle could not be found in the
- current database.
- @retval EFI_INVALID_PARAMETER BufferSize was NULL.
- @retval EFI_INVALID_PARAMETER The value referenced by BufferSize was not zero
- and Buffer was NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiExportPackageLists (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN EFI_HII_HANDLE Handle,
- IN OUT UINTN *BufferSize,
- OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer
- )
-{
- LIST_ENTRY *Link;
- EFI_STATUS Status;
- HII_DATABASE_PRIVATE_DATA *Private;
- HII_DATABASE_RECORD *Node;
- UINTN UsedSize;
-
- if ((This == NULL) || (BufferSize == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((*BufferSize > 0) && (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((Handle != NULL) && (!IsHiiHandleValid (Handle))) {
- return EFI_NOT_FOUND;
- }
-
- Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- UsedSize = 0;
-
- for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
- Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- if (Handle == NULL) {
- //
- // Export all package lists in current hii database.
- //
- Status = ExportPackageList (
- Private,
- Node->Handle,
- (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList),
- &UsedSize,
- *BufferSize,
- (EFI_HII_PACKAGE_LIST_HEADER *)((UINT8 *)Buffer + UsedSize)
- );
- ASSERT_EFI_ERROR (Status);
- } else if ((Handle != NULL) && (Node->Handle == Handle)) {
- Status = ExportPackageList (
- Private,
- Handle,
- (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList),
- &UsedSize,
- *BufferSize,
- Buffer
- );
- ASSERT_EFI_ERROR (Status);
- if (*BufferSize < UsedSize) {
- *BufferSize = UsedSize;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- return EFI_SUCCESS;
- }
- }
-
- if ((Handle == NULL) && (UsedSize != 0)) {
- if (*BufferSize < UsedSize) {
- *BufferSize = UsedSize;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- return EFI_SUCCESS;
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- This function registers a function which will be called when specified actions related to packages of
- the specified type occur in the HII database. By registering a function, other HII-related drivers are
- notified when specific package types are added, removed or updated in the HII database.
- Each driver or application which registers a notification should use
- EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify() before exiting.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param PackageType Specifies the package type of the packages to list
- or EFI_HII_PACKAGE_TYPE_ALL for all packages to be
- listed.
- @param PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then
- this is the pointer to the GUID which must match
- the Guid field of
- EFI_HII_GUID_PACKAGE_GUID_HDR. Otherwise, it must
- be NULL.
- @param PackageNotifyFn Points to the function to be called when the event
- specified by
- NotificationType occurs.
- @param NotifyType Describes the types of notification which this
- function will be receiving.
- @param NotifyHandle Points to the unique handle assigned to the
- registered notification. Can be used in
- EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify()
- to stop notifications.
-
- @retval EFI_SUCCESS Notification registered successfully.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures
- @retval EFI_INVALID_PARAMETER NotifyHandle is NULL.
- @retval EFI_INVALID_PARAMETER PackageGuid is not NULL when PackageType is not
- EFI_HII_PACKAGE_TYPE_GUID.
- @retval EFI_INVALID_PARAMETER PackageGuid is NULL when PackageType is
- EFI_HII_PACKAGE_TYPE_GUID.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiRegisterPackageNotify (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN UINT8 PackageType,
- IN CONST EFI_GUID *PackageGuid,
- IN CONST EFI_HII_DATABASE_NOTIFY PackageNotifyFn,
- IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
- OUT EFI_HANDLE *NotifyHandle
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
- HII_DATABASE_NOTIFY *Notify;
- EFI_STATUS Status;
-
- if ((This == NULL) || (NotifyHandle == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (((PackageType == EFI_HII_PACKAGE_TYPE_GUID) && (PackageGuid == NULL)) ||
- ((PackageType != EFI_HII_PACKAGE_TYPE_GUID) && (PackageGuid != NULL)))
- {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
-
- //
- // Allocate a notification node
- //
- Notify = (HII_DATABASE_NOTIFY *)AllocateZeroPool (sizeof (HII_DATABASE_NOTIFY));
- if (Notify == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Generate a notify handle
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &Notify->NotifyHandle,
- &gEfiCallerIdGuid,
- NULL,
- NULL
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Fill in the information to the notification node
- //
- Notify->Signature = HII_DATABASE_NOTIFY_SIGNATURE;
- Notify->PackageType = PackageType;
- Notify->PackageGuid = (EFI_GUID *)PackageGuid;
- Notify->PackageNotifyFn = (EFI_HII_DATABASE_NOTIFY)PackageNotifyFn;
- Notify->NotifyType = NotifyType;
-
- InsertTailList (&Private->DatabaseNotifyList, &Notify->DatabaseNotifyEntry);
- *NotifyHandle = Notify->NotifyHandle;
-
- return EFI_SUCCESS;
-}
-
-/**
- Removes the specified HII database package-related notification.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param NotificationHandle The handle of the notification function being
- unregistered.
-
- @retval EFI_SUCCESS Notification is unregistered successfully.
- @retval EFI_INVALID_PARAMETER The Handle is invalid.
- @retval EFI_NOT_FOUND The incoming notification handle does not exist
- in current hii database.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiUnregisterPackageNotify (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN EFI_HANDLE NotificationHandle
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
- HII_DATABASE_NOTIFY *Notify;
- LIST_ENTRY *Link;
- EFI_STATUS Status;
-
- if (This == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (NotificationHandle == NULL) {
- return EFI_NOT_FOUND;
- }
-
- Status = gBS->OpenProtocol (
- NotificationHandle,
- &gEfiCallerIdGuid,
- NULL,
- NULL,
- NULL,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- return EFI_NOT_FOUND;
- }
-
- Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
-
- for (Link = Private->DatabaseNotifyList.ForwardLink; Link != &Private->DatabaseNotifyList; Link = Link->ForwardLink) {
- Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);
- if (Notify->NotifyHandle == NotificationHandle) {
- //
- // Remove the matching notification node
- //
- RemoveEntryList (&Notify->DatabaseNotifyEntry);
- Status = gBS->UninstallMultipleProtocolInterfaces (
- Notify->NotifyHandle,
- &gEfiCallerIdGuid,
- NULL,
- NULL
- );
- ASSERT_EFI_ERROR (Status);
- FreePool (Notify);
-
- return EFI_SUCCESS;
- }
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- This routine retrieves an array of GUID values for each keyboard layout that
- was previously registered in the system.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param KeyGuidBufferLength On input, a pointer to the length of the keyboard
- GUID buffer. On output, the length of the handle
- buffer that is required for the handles found.
- @param KeyGuidBuffer An array of keyboard layout GUID instances
- returned.
-
- @retval EFI_SUCCESS KeyGuidBuffer was updated successfully.
- @retval EFI_BUFFER_TOO_SMALL The KeyGuidBufferLength parameter indicates
- that KeyGuidBuffer is too small to support the
- number of GUIDs. KeyGuidBufferLength is
- updated with a value that will enable the data to
- fit.
- @retval EFI_INVALID_PARAMETER The KeyGuidBufferLength is NULL.
- @retval EFI_INVALID_PARAMETER The value referenced by KeyGuidBufferLength is not
- zero and KeyGuidBuffer is NULL.
- @retval EFI_NOT_FOUND There was no keyboard layout.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiFindKeyboardLayouts (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN OUT UINT16 *KeyGuidBufferLength,
- OUT EFI_GUID *KeyGuidBuffer
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
- HII_DATABASE_RECORD *Node;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
- LIST_ENTRY *Link;
- LIST_ENTRY *Link1;
- UINT16 ResultSize;
- UINTN Index;
- UINT16 LayoutCount;
- UINT16 LayoutLength;
- UINT8 *Layout;
- HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
-
- if ((This == NULL) || (KeyGuidBufferLength == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((*KeyGuidBufferLength > 0) && (KeyGuidBuffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- ResultSize = 0;
-
- //
- // Search all package lists in whole database to retrieve keyboard layout.
- //
- for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
- Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- PackageList = Node->PackageList;
- for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;
- Link1 != &PackageList->KeyboardLayoutHdr;
- Link1 = Link1->ForwardLink
- )
- {
- //
- // Find out all Keyboard Layout packages in this package list.
- //
- Package = CR (
- Link1,
- HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,
- KeyboardEntry,
- HII_KB_LAYOUT_PACKAGE_SIGNATURE
- );
- Layout = (UINT8 *)Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);
- CopyMem (
- &LayoutCount,
- (UINT8 *)Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER),
- sizeof (UINT16)
- );
- for (Index = 0; Index < LayoutCount; Index++) {
- ResultSize += sizeof (EFI_GUID);
- if (ResultSize <= *KeyGuidBufferLength) {
- CopyMem (KeyGuidBuffer + (ResultSize / sizeof (EFI_GUID) - 1), Layout + sizeof (UINT16), sizeof (EFI_GUID));
- CopyMem (&LayoutLength, Layout, sizeof (UINT16));
- Layout = Layout + LayoutLength;
- }
- }
- }
- }
-
- if (ResultSize == 0) {
- return EFI_NOT_FOUND;
- }
-
- if (*KeyGuidBufferLength < ResultSize) {
- *KeyGuidBufferLength = ResultSize;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- *KeyGuidBufferLength = ResultSize;
- return EFI_SUCCESS;
-}
-
-/**
- This routine retrieves the requested keyboard layout. The layout is a physical description of the keys
- on a keyboard and the character(s) that are associated with a particular set of key strokes.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param KeyGuid A pointer to the unique ID associated with a given
- keyboard layout. If KeyGuid is NULL then the
- current layout will be retrieved.
- @param KeyboardLayoutLength On input, a pointer to the length of the
- KeyboardLayout buffer. On output, the length of
- the data placed into KeyboardLayout.
- @param KeyboardLayout A pointer to a buffer containing the retrieved
- keyboard layout.
-
- @retval EFI_SUCCESS The keyboard layout was retrieved successfully.
- @retval EFI_NOT_FOUND The requested keyboard layout was not found.
- @retval EFI_INVALID_PARAMETER The KeyboardLayout or KeyboardLayoutLength was
- NULL.
- @retval EFI_BUFFER_TOO_SMALL The KeyboardLayoutLength parameter indicates
- that KeyboardLayout is too small to support the
- requested keyboard layout. KeyboardLayoutLength is
- updated with a value that will enable the
- data to fit.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetKeyboardLayout (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN CONST EFI_GUID *KeyGuid,
- IN OUT UINT16 *KeyboardLayoutLength,
- OUT EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
- HII_DATABASE_RECORD *Node;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
- LIST_ENTRY *Link;
- LIST_ENTRY *Link1;
- UINTN Index;
- UINT8 *Layout;
- UINT16 LayoutCount;
- UINT16 LayoutLength;
- HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
-
- if ((This == NULL) || (KeyboardLayoutLength == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((*KeyboardLayoutLength > 0) && (KeyboardLayout == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- //
- // Retrieve the current keyboard layout.
- //
- if (KeyGuid == NULL) {
- if (Private->CurrentLayout == NULL) {
- return EFI_NOT_FOUND;
- }
-
- CopyMem (&LayoutLength, Private->CurrentLayout, sizeof (UINT16));
- if (*KeyboardLayoutLength < LayoutLength) {
- *KeyboardLayoutLength = LayoutLength;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- CopyMem (KeyboardLayout, Private->CurrentLayout, LayoutLength);
- return EFI_SUCCESS;
- }
-
- for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
- Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList);
- for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;
- Link1 != &PackageList->KeyboardLayoutHdr;
- Link1 = Link1->ForwardLink
- )
- {
- Package = CR (
- Link1,
- HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,
- KeyboardEntry,
- HII_KB_LAYOUT_PACKAGE_SIGNATURE
- );
-
- Layout = (UINT8 *)Package->KeyboardPkg +
- sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);
- CopyMem (&LayoutCount, Layout - sizeof (UINT16), sizeof (UINT16));
- for (Index = 0; Index < LayoutCount; Index++) {
- CopyMem (&LayoutLength, Layout, sizeof (UINT16));
- if (CompareMem (Layout + sizeof (UINT16), KeyGuid, sizeof (EFI_GUID)) == 0) {
- if (LayoutLength <= *KeyboardLayoutLength) {
- CopyMem (KeyboardLayout, Layout, LayoutLength);
- return EFI_SUCCESS;
- } else {
- *KeyboardLayoutLength = LayoutLength;
- return EFI_BUFFER_TOO_SMALL;
- }
- }
-
- Layout = Layout + LayoutLength;
- }
- }
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- This routine sets the default keyboard layout to the one referenced by KeyGuid. When this routine
- is called, an event will be signaled of the EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID
- group type. This is so that agents which are sensitive to the current keyboard layout being changed
- can be notified of this change.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param KeyGuid A pointer to the unique ID associated with a given
- keyboard layout.
-
- @retval EFI_SUCCESS The current keyboard layout was successfully set.
- @retval EFI_NOT_FOUND The referenced keyboard layout was not found, so
- action was taken.
- @retval EFI_INVALID_PARAMETER The KeyGuid was NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiSetKeyboardLayout (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN CONST EFI_GUID *KeyGuid
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
- EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
- UINT16 KeyboardLayoutLength;
- EFI_STATUS Status;
-
- if ((This == NULL) || (KeyGuid == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
-
- //
- // The specified GUID equals the current keyboard layout GUID,
- // return directly.
- //
- if (CompareGuid (&Private->CurrentLayoutGuid, KeyGuid)) {
- return EFI_SUCCESS;
- }
-
- //
- // Try to find the incoming keyboard layout data in current database.
- //
- KeyboardLayoutLength = 0;
- KeyboardLayout = NULL;
- Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);
- if (Status != EFI_BUFFER_TOO_SMALL) {
- return Status;
- }
-
- KeyboardLayout = (EFI_HII_KEYBOARD_LAYOUT *)AllocateZeroPool (KeyboardLayoutLength);
- ASSERT (KeyboardLayout != NULL);
- Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);
- ASSERT_EFI_ERROR (Status);
-
- //
- // Backup current keyboard layout.
- //
- CopyMem (&Private->CurrentLayoutGuid, KeyGuid, sizeof (EFI_GUID));
- if (Private->CurrentLayout != NULL) {
- FreePool (Private->CurrentLayout);
- }
-
- Private->CurrentLayout = KeyboardLayout;
-
- //
- // Signal EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group to notify
- // current keyboard layout is changed.
- //
- Status = gBS->SignalEvent (gHiiKeyboardLayoutChanged);
- ASSERT_EFI_ERROR (Status);
-
- return EFI_SUCCESS;
-}
-
-/**
- Return the EFI handle associated with a package list.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param PackageListHandle An EFI_HII_HANDLE that corresponds to the desired
- package list in the HIIdatabase.
- @param DriverHandle On return, contains the EFI_HANDLE which was
- registered with the package list in
- NewPackageList().
-
- @retval EFI_SUCCESS The DriverHandle was returned successfully.
- @retval EFI_INVALID_PARAMETER The PackageListHandle was not valid or
- DriverHandle was NULL.
- @retval EFI_NOT_FOUND This PackageList handle can not be found in
- current database.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetPackageListHandle (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageListHandle,
- OUT EFI_HANDLE *DriverHandle
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
- HII_DATABASE_RECORD *Node;
- LIST_ENTRY *Link;
-
- if ((This == NULL) || (DriverHandle == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (!IsHiiHandleValid (PackageListHandle)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
-
- for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
- Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- if (Node->Handle == PackageListHandle) {
- *DriverHandle = Node->DriverHandle;
- return EFI_SUCCESS;
- }
- }
-
- return EFI_NOT_FOUND;
-}
+/** @file
+Implementation for EFI_HII_DATABASE_PROTOCOL.
+
+Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "HiiDatabase.h"
+
+#define BASE_NUMBER 10
+
+EFI_HII_PACKAGE_LIST_HEADER *gRTDatabaseInfoBuffer = NULL;
+EFI_STRING gRTConfigRespBuffer = NULL;
+UINTN gDatabaseInfoSize = 0;
+UINTN gConfigRespSize = 0;
+BOOLEAN gExportConfigResp = FALSE;
+UINTN gNvDefaultStoreSize = 0;
+SKU_ID gSkuId = 0xFFFFFFFFFFFFFFFF;
+LIST_ENTRY gVarStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gVarStorageList);
+
+//
+// HII database lock.
+//
+EFI_LOCK mHiiDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
+
+/**
+ This function generates a HII_DATABASE_RECORD node and adds into hii database.
+ This is a internal function.
+
+ @param Private hii database private structure
+ @param DatabaseNode HII_DATABASE_RECORD node which is used to store a
+ package list
+
+ @retval EFI_SUCCESS A database record is generated successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ database contents.
+ @retval EFI_INVALID_PARAMETER Private is NULL or DatabaseRecord is NULL.
+
+**/
+EFI_STATUS
+GenerateHiiDatabaseRecord (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ OUT HII_DATABASE_RECORD **DatabaseNode
+ )
+{
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
+ HII_HANDLE *HiiHandle;
+
+ if ((Private == NULL) || (DatabaseNode == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DatabaseRecord = (HII_DATABASE_RECORD *)AllocateZeroPool (sizeof (HII_DATABASE_RECORD));
+ if (DatabaseRecord == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DatabaseRecord->Signature = HII_DATABASE_RECORD_SIGNATURE;
+
+ DatabaseRecord->PackageList = AllocateZeroPool (sizeof (HII_DATABASE_PACKAGE_LIST_INSTANCE));
+ if (DatabaseRecord->PackageList == NULL) {
+ FreePool (DatabaseRecord);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ PackageList = DatabaseRecord->PackageList;
+
+ InitializeListHead (&PackageList->GuidPkgHdr);
+ InitializeListHead (&PackageList->FormPkgHdr);
+ InitializeListHead (&PackageList->KeyboardLayoutHdr);
+ InitializeListHead (&PackageList->StringPkgHdr);
+ InitializeListHead (&PackageList->FontPkgHdr);
+ InitializeListHead (&PackageList->SimpleFontPkgHdr);
+ PackageList->ImagePkg = NULL;
+ PackageList->DevicePathPkg = NULL;
+
+ //
+ // Create a new hii handle
+ //
+ HiiHandle = (HII_HANDLE *)AllocateZeroPool (sizeof (HII_HANDLE));
+ if (HiiHandle == NULL) {
+ FreePool (DatabaseRecord->PackageList);
+ FreePool (DatabaseRecord);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HiiHandle->Signature = HII_HANDLE_SIGNATURE;
+ //
+ // Backup the number of Hii handles
+ //
+ Private->HiiHandleCount++;
+ HiiHandle->Key = (UINTN)Private->HiiHandleCount;
+ //
+ // Insert the handle to hii handle list of the whole database.
+ //
+ InsertTailList (&Private->HiiHandleList, &HiiHandle->Handle);
+
+ DatabaseRecord->Handle = (EFI_HII_HANDLE)HiiHandle;
+
+ //
+ // Insert the Package List node to Package List link of the whole database.
+ //
+ InsertTailList (&Private->DatabaseList, &DatabaseRecord->DatabaseEntry);
+
+ *DatabaseNode = DatabaseRecord;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function checks whether a handle is a valid EFI_HII_HANDLE
+ This is a internal function.
+
+ @param Handle Pointer to a EFI_HII_HANDLE
+
+ @retval TRUE Valid
+ @retval FALSE Invalid
+
+**/
+BOOLEAN
+IsHiiHandleValid (
+ EFI_HII_HANDLE Handle
+ )
+{
+ HII_HANDLE *HiiHandle;
+
+ HiiHandle = (HII_HANDLE *)Handle;
+
+ if (HiiHandle == NULL) {
+ return FALSE;
+ }
+
+ if (HiiHandle->Signature != HII_HANDLE_SIGNATURE) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ This function invokes the matching registered function.
+ This is a internal function.
+
+ @param Private HII Database driver private structure.
+ @param NotifyType The type of change concerning the database.
+ @param PackageInstance Points to the package referred to by the
+ notification.
+ @param PackageType Package type
+ @param Handle The handle of the package list which contains the
+ specified package.
+
+ @retval EFI_SUCCESS Already checked all registered function and
+ invoked if matched.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+EFI_STATUS
+InvokeRegisteredFunction (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN VOID *PackageInstance,
+ IN UINT8 PackageType,
+ IN EFI_HII_HANDLE Handle
+ )
+{
+ HII_DATABASE_NOTIFY *Notify;
+ LIST_ENTRY *Link;
+ EFI_HII_PACKAGE_HEADER *Package;
+ UINT8 *Buffer;
+ UINT32 BufferSize;
+ UINT32 HeaderSize;
+ UINT32 ImageBlockSize;
+ UINT32 PaletteInfoSize;
+
+ if ((Private == NULL) || ((NotifyType & 0xF) == 0) || (PackageInstance == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (Handle)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Buffer = NULL;
+ Package = NULL;
+
+ //
+ // Convert the incoming package from hii database storage format to UEFI
+ // storage format. e.g. HII_GUID_PACKAGE_INSTANCE to EFI_HII_GUID_PACKAGE_HDR.
+ //
+ switch (PackageType) {
+ case EFI_HII_PACKAGE_TYPE_GUID:
+ Package = (EFI_HII_PACKAGE_HEADER *)(((HII_GUID_PACKAGE_INSTANCE *)PackageInstance)->GuidPkg);
+ break;
+
+ case EFI_HII_PACKAGE_FORMS:
+ BufferSize = ((HII_IFR_PACKAGE_INSTANCE *)PackageInstance)->FormPkgHdr.Length;
+ Buffer = (UINT8 *)AllocateZeroPool (BufferSize);
+ ASSERT (Buffer != NULL);
+ CopyMem (
+ Buffer,
+ &((HII_IFR_PACKAGE_INSTANCE *)PackageInstance)->FormPkgHdr,
+ sizeof (EFI_HII_PACKAGE_HEADER)
+ );
+ CopyMem (
+ Buffer + sizeof (EFI_HII_PACKAGE_HEADER),
+ ((HII_IFR_PACKAGE_INSTANCE *)PackageInstance)->IfrData,
+ BufferSize - sizeof (EFI_HII_PACKAGE_HEADER)
+ );
+ Package = (EFI_HII_PACKAGE_HEADER *)Buffer;
+ break;
+
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
+ Package = (EFI_HII_PACKAGE_HEADER *)(((HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *)PackageInstance)->KeyboardPkg);
+ break;
+
+ case EFI_HII_PACKAGE_STRINGS:
+ BufferSize = ((HII_STRING_PACKAGE_INSTANCE *)PackageInstance)->StringPkgHdr->Header.Length;
+ HeaderSize = ((HII_STRING_PACKAGE_INSTANCE *)PackageInstance)->StringPkgHdr->HdrSize;
+ Buffer = (UINT8 *)AllocateZeroPool (BufferSize);
+ ASSERT (Buffer != NULL);
+ CopyMem (
+ Buffer,
+ ((HII_STRING_PACKAGE_INSTANCE *)PackageInstance)->StringPkgHdr,
+ HeaderSize
+ );
+ CopyMem (
+ Buffer + HeaderSize,
+ ((HII_STRING_PACKAGE_INSTANCE *)PackageInstance)->StringBlock,
+ BufferSize - HeaderSize
+ );
+ Package = (EFI_HII_PACKAGE_HEADER *)Buffer;
+ break;
+
+ case EFI_HII_PACKAGE_FONTS:
+ BufferSize = ((HII_FONT_PACKAGE_INSTANCE *)PackageInstance)->FontPkgHdr->Header.Length;
+ HeaderSize = ((HII_FONT_PACKAGE_INSTANCE *)PackageInstance)->FontPkgHdr->HdrSize;
+ Buffer = (UINT8 *)AllocateZeroPool (BufferSize);
+ ASSERT (Buffer != NULL);
+ CopyMem (
+ Buffer,
+ ((HII_FONT_PACKAGE_INSTANCE *)PackageInstance)->FontPkgHdr,
+ HeaderSize
+ );
+ CopyMem (
+ Buffer + HeaderSize,
+ ((HII_FONT_PACKAGE_INSTANCE *)PackageInstance)->GlyphBlock,
+ BufferSize - HeaderSize
+ );
+ Package = (EFI_HII_PACKAGE_HEADER *)Buffer;
+ break;
+
+ case EFI_HII_PACKAGE_IMAGES:
+ BufferSize = ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->ImagePkgHdr.Header.Length;
+ HeaderSize = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
+ Buffer = (UINT8 *)AllocateZeroPool (BufferSize);
+ ASSERT (Buffer != NULL);
+
+ CopyMem (
+ Buffer,
+ &((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->ImagePkgHdr,
+ HeaderSize
+ );
+ CopyMem (
+ Buffer + sizeof (EFI_HII_PACKAGE_HEADER),
+ &HeaderSize,
+ sizeof (UINT32)
+ );
+
+ ImageBlockSize = ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->ImageBlockSize;
+ if (ImageBlockSize != 0) {
+ CopyMem (
+ Buffer + HeaderSize,
+ ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->ImageBlock,
+ ImageBlockSize
+ );
+ }
+
+ PaletteInfoSize = ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->PaletteInfoSize;
+ if (PaletteInfoSize != 0) {
+ CopyMem (
+ Buffer + HeaderSize + ImageBlockSize,
+ ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->PaletteBlock,
+ PaletteInfoSize
+ );
+ HeaderSize += ImageBlockSize;
+ CopyMem (
+ Buffer + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT32),
+ &HeaderSize,
+ sizeof (UINT32)
+ );
+ }
+
+ Package = (EFI_HII_PACKAGE_HEADER *)Buffer;
+ break;
+
+ case EFI_HII_PACKAGE_SIMPLE_FONTS:
+ BufferSize = ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *)PackageInstance)->SimpleFontPkgHdr->Header.Length;
+ Buffer = (UINT8 *)AllocateZeroPool (BufferSize);
+ ASSERT (Buffer != NULL);
+ CopyMem (
+ Buffer,
+ ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *)PackageInstance)->SimpleFontPkgHdr,
+ BufferSize
+ );
+ Package = (EFI_HII_PACKAGE_HEADER *)Buffer;
+ break;
+
+ case EFI_HII_PACKAGE_DEVICE_PATH:
+ Package = (EFI_HII_PACKAGE_HEADER *)PackageInstance;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Link = Private->DatabaseNotifyList.ForwardLink;
+ Link != &Private->DatabaseNotifyList;
+ Link = Link->ForwardLink
+ )
+ {
+ Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);
+ if ((Notify->NotifyType == NotifyType) && (Notify->PackageType == PackageType)) {
+ //
+ // Check in case PackageGuid is not NULL when Package is GUID package
+ //
+ if (PackageType != EFI_HII_PACKAGE_TYPE_GUID) {
+ Notify->PackageGuid = NULL;
+ }
+
+ //
+ // Status of Registered Function is unknown so did not check it
+ //
+ Notify->PackageNotifyFn (
+ Notify->PackageType,
+ Notify->PackageGuid,
+ Package,
+ Handle,
+ NotifyType
+ );
+ }
+ }
+
+ if (Buffer != NULL) {
+ FreePool (Buffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function insert a GUID package to a package list node.
+ This is a internal function.
+
+ @param PackageHdr Pointer to a buffer stored with GUID package
+ information.
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list which will be inserted
+ to.
+ @param Package Created GUID package
+
+ @retval EFI_SUCCESS Guid Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Guid package.
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
+
+**/
+EFI_STATUS
+InsertGuidPackage (
+ IN VOID *PackageHdr,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ OUT HII_GUID_PACKAGE_INSTANCE **Package
+ )
+{
+ HII_GUID_PACKAGE_INSTANCE *GuidPackage;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+
+ if ((PackageHdr == NULL) || (PackageList == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ //
+ // Create a GUID package node
+ //
+ GuidPackage = (HII_GUID_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_GUID_PACKAGE_INSTANCE));
+ if (GuidPackage == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ GuidPackage->GuidPkg = (UINT8 *)AllocateZeroPool (PackageHeader.Length);
+ if (GuidPackage->GuidPkg == NULL) {
+ FreePool (GuidPackage);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ GuidPackage->Signature = HII_GUID_PACKAGE_SIGNATURE;
+ CopyMem (GuidPackage->GuidPkg, PackageHdr, PackageHeader.Length);
+ InsertTailList (&PackageList->GuidPkgHdr, &GuidPackage->GuidEntry);
+ *Package = GuidPackage;
+
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
+ PackageList->PackageListHdr.PackageLength += PackageHeader.Length;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function exports GUID packages to a buffer.
+ This is a internal function.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer be used.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+ @param ResultSize The size of the already exported content of this
+ package list.
+
+ @retval EFI_SUCCESS Guid Packages are exported successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+EFI_STATUS
+ExportGuidPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN UINTN UsedSize,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *ResultSize
+ )
+{
+ HII_GUID_PACKAGE_INSTANCE *GuidPackage;
+ LIST_ENTRY *Link;
+ UINTN PackageLength;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+ EFI_STATUS Status;
+
+ if ((PackageList == NULL) || (ResultSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BufferSize > 0) && (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PackageLength = 0;
+ Status = EFI_SUCCESS;
+
+ for (Link = PackageList->GuidPkgHdr.ForwardLink; Link != &PackageList->GuidPkgHdr; Link = Link->ForwardLink) {
+ GuidPackage = CR (Link, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);
+ CopyMem (&PackageHeader, GuidPackage->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));
+ PackageLength += PackageHeader.Length;
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
+ (VOID *)GuidPackage,
+ EFI_HII_PACKAGE_TYPE_GUID,
+ Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+ CopyMem (Buffer, GuidPackage->GuidPkg, PackageHeader.Length);
+ Buffer = (UINT8 *)Buffer + PackageHeader.Length;
+ }
+ }
+
+ *ResultSize += PackageLength;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function deletes all GUID packages from a package list node.
+ This is a internal function.
+
+ @param Private Hii database private data.
+ @param Handle Handle of the package list which contains the to
+ be removed GUID packages.
+ @param PackageList Pointer to a package list that contains removing
+ packages.
+
+ @retval EFI_SUCCESS GUID Package(s) is deleted successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+EFI_STATUS
+RemoveGuidPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ LIST_ENTRY *ListHead;
+ HII_GUID_PACKAGE_INSTANCE *Package;
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+
+ ListHead = &PackageList->GuidPkgHdr;
+
+ while (!IsListEmpty (ListHead)) {
+ Package = CR (
+ ListHead->ForwardLink,
+ HII_GUID_PACKAGE_INSTANCE,
+ GuidEntry,
+ HII_GUID_PACKAGE_SIGNATURE
+ );
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ (VOID *)Package,
+ EFI_HII_PACKAGE_TYPE_GUID,
+ Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RemoveEntryList (&Package->GuidEntry);
+ CopyMem (&PackageHeader, Package->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));
+ PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;
+ FreePool (Package->GuidPkg);
+ FreePool (Package);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check the input question related to EFI variable
+
+ @param IfrQuestionHdr Point to Question header
+ @param EfiVarStoreList Point to EFI VarStore List
+ @param EfiVarStoreNumber The number of EFI VarStore
+
+ @retval Index The index of the found EFI varstore in EFI varstore list
+ EfiVarStoreNumber will return if no EFI varstore is found.
+**/
+UINTN
+IsEfiVarStoreQuestion (
+ EFI_IFR_QUESTION_HEADER *IfrQuestionHdr,
+ EFI_IFR_VARSTORE_EFI **EfiVarStoreList,
+ UINTN EfiVarStoreNumber
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < EfiVarStoreNumber; Index++) {
+ if (IfrQuestionHdr->VarStoreId == EfiVarStoreList[Index]->VarStoreId) {
+ return Index;
+ }
+ }
+
+ return EfiVarStoreNumber;
+}
+
+/**
+ Find the matched variable from the input variable storage.
+
+ @param[in] VariableStorage Point to the variable storage header.
+ @param[in] VarGuid A unique identifier for the variable.
+ @param[in] VarAttribute The attributes bitmask for the variable.
+ @param[in] VarName A Null-terminated ascii string that is the name of the variable.
+
+ @return Pointer to the matched variable header or NULL if not found.
+**/
+VARIABLE_HEADER *
+FindVariableData (
+ IN VARIABLE_STORE_HEADER *VariableStorage,
+ IN EFI_GUID *VarGuid,
+ IN UINT32 VarAttribute,
+ IN CHAR16 *VarName
+ )
+{
+ VARIABLE_HEADER *VariableHeader;
+ VARIABLE_HEADER *VariableEnd;
+
+ VariableEnd = (VARIABLE_HEADER *)((UINT8 *)VariableStorage + VariableStorage->Size);
+ VariableHeader = (VARIABLE_HEADER *)(VariableStorage + 1);
+ VariableHeader = (VARIABLE_HEADER *)HEADER_ALIGN (VariableHeader);
+ while (VariableHeader < VariableEnd) {
+ if (CompareGuid (&VariableHeader->VendorGuid, VarGuid) &&
+ (VariableHeader->Attributes == VarAttribute) &&
+ (StrCmp (VarName, (CHAR16 *)(VariableHeader + 1)) == 0))
+ {
+ return VariableHeader;
+ }
+
+ VariableHeader = (VARIABLE_HEADER *)((UINT8 *)VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + VariableHeader->DataSize);
+ VariableHeader = (VARIABLE_HEADER *)HEADER_ALIGN (VariableHeader);
+ }
+
+ return NULL;
+}
+
+/**
+ Find question default value from PcdNvStoreDefaultValueBuffer
+
+ @param DefaultId Default store ID
+ @param EfiVarStore Point to EFI VarStore header
+ @param IfrQuestionHdr Point to Question header
+ @param ValueBuffer Point to Buffer includes the found default setting
+ @param Width Width of the default value
+ @param BitFieldQuestion Whether the Question is stored in Bit field.
+
+ @retval EFI_SUCCESS Question default value is found.
+ @retval EFI_NOT_FOUND Question default value is not found.
+**/
+EFI_STATUS
+FindQuestionDefaultSetting (
+ IN UINT16 DefaultId,
+ IN EFI_IFR_VARSTORE_EFI *EfiVarStore,
+ IN EFI_IFR_QUESTION_HEADER *IfrQuestionHdr,
+ OUT VOID *ValueBuffer,
+ IN UINTN Width,
+ IN BOOLEAN BitFieldQuestion
+ )
+{
+ VARIABLE_HEADER *VariableHeader;
+ VARIABLE_STORE_HEADER *VariableStorage;
+ LIST_ENTRY *Link;
+ VARSTORAGE_DEFAULT_DATA *Entry;
+ VARIABLE_STORE_HEADER *NvStoreBuffer;
+ UINT8 *DataBuffer;
+ UINT8 *BufferEnd;
+ BOOLEAN IsFound;
+ UINTN Index;
+ UINT32 BufferValue;
+ UINT32 BitFieldVal;
+ UINTN BitOffset;
+ UINTN ByteOffset;
+ UINTN BitWidth;
+ UINTN StartBit;
+ UINTN EndBit;
+ PCD_DEFAULT_DATA *DataHeader;
+ PCD_DEFAULT_INFO *DefaultInfo;
+ PCD_DATA_DELTA *DeltaData;
+
+ if (gSkuId == 0xFFFFFFFFFFFFFFFF) {
+ gSkuId = LibPcdGetSku ();
+ }
+
+ //
+ // Find the DefaultId setting from the full DefaultSetting
+ //
+ VariableStorage = NULL;
+ Link = gVarStorageList.ForwardLink;
+ while (Link != &gVarStorageList) {
+ Entry = BASE_CR (Link, VARSTORAGE_DEFAULT_DATA, Entry);
+ if (Entry->DefaultId == DefaultId) {
+ VariableStorage = Entry->VariableStorage;
+ break;
+ }
+
+ Link = Link->ForwardLink;
+ }
+
+ if (Link == &gVarStorageList) {
+ DataBuffer = (UINT8 *)PcdGetPtr (PcdNvStoreDefaultValueBuffer);
+ gNvDefaultStoreSize = ((PCD_NV_STORE_DEFAULT_BUFFER_HEADER *)DataBuffer)->Length;
+ //
+ // The first section data includes NV storage default setting.
+ //
+ DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER));
+ NvStoreBuffer = (VARIABLE_STORE_HEADER *)((UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize);
+ VariableStorage = AllocatePool (NvStoreBuffer->Size);
+ ASSERT (VariableStorage != NULL);
+ CopyMem (VariableStorage, NvStoreBuffer, NvStoreBuffer->Size);
+
+ //
+ // Find the matched SkuId and DefaultId in the first section
+ //
+ IsFound = FALSE;
+ DefaultInfo = &(DataHeader->DefaultInfo[0]);
+ BufferEnd = (UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;
+ while ((UINT8 *)DefaultInfo < BufferEnd) {
+ if ((DefaultInfo->DefaultId == DefaultId) && (DefaultInfo->SkuId == gSkuId)) {
+ IsFound = TRUE;
+ break;
+ }
+
+ DefaultInfo++;
+ }
+
+ //
+ // Find the matched SkuId and DefaultId in the remaining section
+ //
+ Index = sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER) + ((DataHeader->DataSize + 7) & (~7));
+ DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + Index);
+ while (!IsFound && Index < gNvDefaultStoreSize && DataHeader->DataSize != 0xFFFF) {
+ DefaultInfo = &(DataHeader->DefaultInfo[0]);
+ BufferEnd = (UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;
+ while ((UINT8 *)DefaultInfo < BufferEnd) {
+ if ((DefaultInfo->DefaultId == DefaultId) && (DefaultInfo->SkuId == gSkuId)) {
+ IsFound = TRUE;
+ break;
+ }
+
+ DefaultInfo++;
+ }
+
+ if (IsFound) {
+ DeltaData = (PCD_DATA_DELTA *)BufferEnd;
+ BufferEnd = (UINT8 *)DataHeader + DataHeader->DataSize;
+ while ((UINT8 *)DeltaData < BufferEnd) {
+ *((UINT8 *)VariableStorage + DeltaData->Offset) = (UINT8)DeltaData->Value;
+ DeltaData++;
+ }
+
+ break;
+ }
+
+ Index = (Index + DataHeader->DataSize + 7) & (~7);
+ DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + Index);
+ }
+
+ //
+ // Cache the found result in VarStorageList
+ //
+ if (!IsFound) {
+ FreePool (VariableStorage);
+ VariableStorage = NULL;
+ }
+
+ Entry = AllocatePool (sizeof (VARSTORAGE_DEFAULT_DATA));
+ if (Entry != NULL) {
+ Entry->DefaultId = DefaultId;
+ Entry->VariableStorage = VariableStorage;
+ InsertTailList (&gVarStorageList, &Entry->Entry);
+ } else if (VariableStorage != NULL) {
+ FreePool (VariableStorage);
+ VariableStorage = NULL;
+ }
+ }
+
+ //
+ // The matched variable storage is not found.
+ //
+ if (VariableStorage == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Find the question default value from the variable storage
+ //
+ VariableHeader = FindVariableData (VariableStorage, &EfiVarStore->Guid, EfiVarStore->Attributes, (CHAR16 *)EfiVarStore->Name);
+ if (VariableHeader == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ StartBit = 0;
+ EndBit = 0;
+ ByteOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
+ if (BitFieldQuestion) {
+ BitOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
+ ByteOffset = BitOffset / 8;
+ BitWidth = Width;
+ StartBit = BitOffset % 8;
+ EndBit = StartBit + BitWidth - 1;
+ Width = EndBit / 8 + 1;
+ }
+
+ if (VariableHeader->DataSize < ByteOffset + Width) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Copy the question value
+ //
+ if (ValueBuffer != NULL) {
+ if (BitFieldQuestion) {
+ CopyMem (&BufferValue, (UINT8 *)VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + ByteOffset, Width);
+ BitFieldVal = BitFieldRead32 (BufferValue, StartBit, EndBit);
+ CopyMem (ValueBuffer, &BitFieldVal, Width);
+ } else {
+ CopyMem (ValueBuffer, (UINT8 *)VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + IfrQuestionHdr->VarStoreInfo.VarOffset, Width);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Update IFR default setting in Form Package.
+
+ @param FormPackage Form Package to be updated
+
+**/
+VOID
+UpdateDefaultSettingInFormPackage (
+ HII_IFR_PACKAGE_INSTANCE *FormPackage
+ )
+{
+ UINTN IfrOffset;
+ UINTN PackageLength;
+ EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
+ EFI_IFR_OP_HEADER *IfrOpHdr;
+ EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
+ UINT8 IfrQuestionType;
+ UINT8 IfrScope;
+ EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;
+ EFI_IFR_VARSTORE_EFI **EfiVarStoreList;
+ UINTN EfiVarStoreMaxNum;
+ UINTN EfiVarStoreNumber;
+ UINT16 *DefaultIdList;
+ UINTN DefaultIdNumber;
+ UINTN DefaultIdMaxNum;
+ UINTN Index;
+ UINTN EfiVarStoreIndex;
+ EFI_IFR_TYPE_VALUE IfrValue;
+ EFI_IFR_TYPE_VALUE IfrManufactValue;
+ BOOLEAN StandardDefaultIsSet;
+ BOOLEAN ManufactDefaultIsSet;
+ EFI_IFR_CHECKBOX *IfrCheckBox;
+ EFI_STATUS Status;
+ EFI_IFR_DEFAULT *IfrDefault;
+ UINTN Width;
+ EFI_IFR_QUESTION_HEADER VarStoreQuestionHeader;
+ BOOLEAN QuestionReferBitField;
+
+ //
+ // If no default setting, do nothing
+ //
+ if (gNvDefaultStoreSize == 0) {
+ gNvDefaultStoreSize = PcdGetSize (PcdNvStoreDefaultValueBuffer);
+ }
+
+ if (gNvDefaultStoreSize < sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) {
+ return;
+ }
+
+ ZeroMem (&VarStoreQuestionHeader, sizeof (VarStoreQuestionHeader));
+ PackageLength = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
+ Width = 0;
+ IfrOffset = 0;
+ IfrScope = 0;
+ IfrOpHdr = (EFI_IFR_OP_HEADER *)FormPackage->IfrData;
+ IfrQuestionHdr = NULL;
+ IfrQuestionType = 0;
+ EfiVarStoreMaxNum = 0;
+ EfiVarStoreNumber = 0;
+ DefaultIdMaxNum = 0;
+ DefaultIdNumber = 0;
+ EfiVarStoreList = NULL;
+ DefaultIdList = NULL;
+ StandardDefaultIsSet = FALSE;
+ ManufactDefaultIsSet = FALSE;
+ QuestionReferBitField = FALSE;
+
+ while (IfrOffset < PackageLength) {
+ switch (IfrOpHdr->OpCode) {
+ case EFI_IFR_VARSTORE_EFI_OP:
+ if (EfiVarStoreNumber >= EfiVarStoreMaxNum) {
+ //
+ // Reallocate EFI VarStore Buffer
+ //
+ EfiVarStoreList = ReallocatePool (EfiVarStoreMaxNum * sizeof (UINTN), (EfiVarStoreMaxNum + BASE_NUMBER) * sizeof (UINTN), EfiVarStoreList);
+ if (EfiVarStoreList == NULL) {
+ goto Done;
+ }
+
+ EfiVarStoreMaxNum = EfiVarStoreMaxNum + BASE_NUMBER;
+ }
+
+ IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *)IfrOpHdr;
+ //
+ // Convert VarStore Name from ASCII string to Unicode string.
+ //
+ EfiVarStoreList[EfiVarStoreNumber] = AllocatePool (IfrEfiVarStore->Header.Length + AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name));
+ if (EfiVarStoreList[EfiVarStoreNumber] == NULL) {
+ break;
+ }
+
+ CopyMem (EfiVarStoreList[EfiVarStoreNumber], IfrEfiVarStore, IfrEfiVarStore->Header.Length);
+ AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, (CHAR16 *)&(EfiVarStoreList[EfiVarStoreNumber]->Name[0]), AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
+ Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_STANDARD, EfiVarStoreList[EfiVarStoreNumber], &VarStoreQuestionHeader, NULL, IfrEfiVarStore->Size, FALSE);
+ if (!EFI_ERROR (Status)) {
+ EfiVarStoreNumber++;
+ } else {
+ FreePool (EfiVarStoreList[EfiVarStoreNumber]);
+ EfiVarStoreList[EfiVarStoreNumber] = NULL;
+ }
+
+ break;
+ case EFI_IFR_DEFAULTSTORE_OP:
+ if (DefaultIdNumber >= DefaultIdMaxNum) {
+ //
+ // Reallocate DefaultIdNumber
+ //
+ DefaultIdList = ReallocatePool (DefaultIdMaxNum * sizeof (UINT16), (DefaultIdMaxNum + BASE_NUMBER) * sizeof (UINT16), DefaultIdList);
+ if (DefaultIdList == NULL) {
+ goto Done;
+ }
+
+ DefaultIdMaxNum = DefaultIdMaxNum + BASE_NUMBER;
+ }
+
+ DefaultIdList[DefaultIdNumber++] = ((EFI_IFR_DEFAULTSTORE *)IfrOpHdr)->DefaultId;
+ break;
+ case EFI_IFR_FORM_OP:
+ case EFI_IFR_FORM_MAP_OP:
+ //
+ // No EFI varstore is found and directly return.
+ //
+ if ((EfiVarStoreNumber == 0) || (DefaultIdNumber == 0)) {
+ goto Done;
+ }
+
+ break;
+ case EFI_IFR_CHECKBOX_OP:
+ IfrScope = IfrOpHdr->Scope;
+ IfrQuestionType = IfrOpHdr->OpCode;
+ IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)(IfrOpHdr + 1);
+ IfrCheckBox = (EFI_IFR_CHECKBOX *)IfrOpHdr;
+ EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);
+ Width = sizeof (BOOLEAN);
+ if (EfiVarStoreIndex < EfiVarStoreNumber) {
+ for (Index = 0; Index < DefaultIdNumber; Index++) {
+ if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_STANDARD) {
+ Status = FindQuestionDefaultSetting (DefaultIdList[Index], EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, sizeof (BOOLEAN), QuestionReferBitField);
+ if (!EFI_ERROR (Status)) {
+ if (IfrValue.b) {
+ IfrCheckBox->Flags = IfrCheckBox->Flags | EFI_IFR_CHECKBOX_DEFAULT;
+ } else {
+ IfrCheckBox->Flags = IfrCheckBox->Flags & (~EFI_IFR_CHECKBOX_DEFAULT);
+ }
+ }
+ } else if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+ Status = FindQuestionDefaultSetting (DefaultIdList[Index], EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, sizeof (BOOLEAN), QuestionReferBitField);
+ if (!EFI_ERROR (Status)) {
+ if (IfrValue.b) {
+ IfrCheckBox->Flags = IfrCheckBox->Flags | EFI_IFR_CHECKBOX_DEFAULT_MFG;
+ } else {
+ IfrCheckBox->Flags = IfrCheckBox->Flags & (~EFI_IFR_CHECKBOX_DEFAULT_MFG);
+ }
+ }
+ }
+ }
+ }
+
+ break;
+ case EFI_IFR_NUMERIC_OP:
+ IfrScope = IfrOpHdr->Scope;
+ IfrQuestionType = IfrOpHdr->OpCode;
+ IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)(IfrOpHdr + 1);
+ if (QuestionReferBitField) {
+ Width = (UINTN)(((EFI_IFR_ONE_OF *)IfrOpHdr)->Flags & EDKII_IFR_NUMERIC_SIZE_BIT);
+ } else {
+ Width = (UINTN)((UINT32)1 << (((EFI_IFR_ONE_OF *)IfrOpHdr)->Flags & EFI_IFR_NUMERIC_SIZE));
+ }
+
+ break;
+ case EFI_IFR_ONE_OF_OP:
+ IfrScope = IfrOpHdr->Scope;
+ IfrQuestionType = IfrOpHdr->OpCode;
+ IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)(IfrOpHdr + 1);
+ if (QuestionReferBitField) {
+ Width = (UINTN)(((EFI_IFR_ONE_OF *)IfrOpHdr)->Flags & EDKII_IFR_NUMERIC_SIZE_BIT);
+ } else {
+ Width = (UINTN)((UINT32)1 << (((EFI_IFR_ONE_OF *)IfrOpHdr)->Flags & EFI_IFR_NUMERIC_SIZE));
+ }
+
+ EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);
+ StandardDefaultIsSet = FALSE;
+ ManufactDefaultIsSet = FALSE;
+ //
+ // Find Default and Manufacturing default for OneOf question
+ //
+ if (EfiVarStoreIndex < EfiVarStoreNumber) {
+ for (Index = 0; Index < DefaultIdNumber; Index++) {
+ if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_STANDARD) {
+ Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_STANDARD, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, Width, QuestionReferBitField);
+ if (!EFI_ERROR (Status)) {
+ StandardDefaultIsSet = TRUE;
+ }
+ } else if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+ Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_MANUFACTURING, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrManufactValue, Width, QuestionReferBitField);
+ if (!EFI_ERROR (Status)) {
+ ManufactDefaultIsSet = TRUE;
+ }
+ }
+ }
+ }
+
+ break;
+ case EFI_IFR_ORDERED_LIST_OP:
+ IfrScope = IfrOpHdr->Scope;
+ IfrQuestionType = IfrOpHdr->OpCode;
+ IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)(IfrOpHdr + 1);
+ break;
+ case EFI_IFR_ONE_OF_OPTION_OP:
+ if ((IfrQuestionHdr != NULL) && (IfrScope > 0)) {
+ IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *)IfrOpHdr;
+ if (IfrQuestionType == EFI_IFR_ONE_OF_OP) {
+ Width = (UINTN)((UINT32)1 << (IfrOneOfOption->Flags & EFI_IFR_NUMERIC_SIZE));
+ if (StandardDefaultIsSet) {
+ if (CompareMem (&IfrOneOfOption->Value, &IfrValue, Width) == 0) {
+ IfrOneOfOption->Flags |= EFI_IFR_OPTION_DEFAULT;
+ } else {
+ IfrOneOfOption->Flags &= ~EFI_IFR_OPTION_DEFAULT;
+ }
+ }
+
+ if (ManufactDefaultIsSet) {
+ if (CompareMem (&IfrOneOfOption->Value, &IfrManufactValue, Width) == 0) {
+ IfrOneOfOption->Flags |= EFI_IFR_OPTION_DEFAULT_MFG;
+ } else {
+ IfrOneOfOption->Flags &= ~EFI_IFR_OPTION_DEFAULT_MFG;
+ }
+ }
+ }
+ }
+
+ break;
+ case EFI_IFR_DEFAULT_OP:
+ if ((IfrQuestionHdr != NULL) && (IfrScope > 0)) {
+ IfrDefault = (EFI_IFR_DEFAULT *)IfrOpHdr;
+ //
+ // Collect default value width
+ //
+ if (!QuestionReferBitField) {
+ Width = 0;
+ if ((IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_8) || (IfrDefault->Type == EFI_IFR_TYPE_BOOLEAN)) {
+ Width = 1;
+ } else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
+ Width = 2;
+ } else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
+ Width = 4;
+ } else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
+ Width = 8;
+ } else if (IfrDefault->Type == EFI_IFR_TYPE_BUFFER) {
+ Width = IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value);
+ }
+ }
+
+ //
+ // Update the default value
+ //
+ if (Width > 0) {
+ EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);
+ if (EfiVarStoreIndex < EfiVarStoreNumber) {
+ Status = FindQuestionDefaultSetting (IfrDefault->DefaultId, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrDefault->Value, Width, QuestionReferBitField);
+ }
+ }
+ }
+
+ break;
+ case EFI_IFR_END_OP:
+ if (IfrQuestionHdr != NULL) {
+ if (IfrScope > 0) {
+ IfrScope--;
+ }
+
+ if (IfrScope == 0) {
+ IfrQuestionHdr = NULL;
+ QuestionReferBitField = FALSE;
+ }
+ }
+
+ break;
+ case EFI_IFR_GUID_OP:
+ if (CompareGuid ((EFI_GUID *)((UINT8 *)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {
+ QuestionReferBitField = TRUE;
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ IfrOffset = IfrOffset + IfrOpHdr->Length;
+ IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *)IfrOpHdr + IfrOpHdr->Length);
+ if (IfrScope > 0) {
+ IfrScope += IfrOpHdr->Scope;
+ }
+ }
+
+Done:
+ if (EfiVarStoreList != NULL) {
+ for (Index = 0; Index < EfiVarStoreNumber; Index++) {
+ FreePool (EfiVarStoreList[Index]);
+ }
+ }
+
+ return;
+}
+
+/**
+ This function insert a Form package to a package list node.
+ This is a internal function.
+
+ @param PackageHdr Pointer to a buffer stored with Form package
+ information.
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list which will be inserted
+ to.
+ @param Package Created Form package
+
+ @retval EFI_SUCCESS Form Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Form package.
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
+
+**/
+EFI_STATUS
+InsertFormPackage (
+ IN VOID *PackageHdr,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ OUT HII_IFR_PACKAGE_INSTANCE **Package
+ )
+{
+ HII_IFR_PACKAGE_INSTANCE *FormPackage;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+
+ if ((PackageHdr == NULL) || (PackageList == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get the length of the package, including package header itself
+ //
+ CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ //
+ // Create a Form package node
+ //
+ FormPackage = (HII_IFR_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_IFR_PACKAGE_INSTANCE));
+ if (FormPackage == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FormPackage->IfrData = (UINT8 *)AllocateZeroPool (PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER));
+ if (FormPackage->IfrData == NULL) {
+ FreePool (FormPackage);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FormPackage->Signature = HII_IFR_PACKAGE_SIGNATURE;
+ //
+ // Copy Package Header
+ //
+ CopyMem (&FormPackage->FormPkgHdr, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ //
+ // Copy Ifr contents
+ //
+ CopyMem (
+ FormPackage->IfrData,
+ (UINT8 *)PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER),
+ PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER)
+ );
+
+ InsertTailList (&PackageList->FormPkgHdr, &FormPackage->IfrEntry);
+ *Package = FormPackage;
+
+ //
+ // Update FormPackage with the default setting
+ //
+ UpdateDefaultSettingInFormPackage (FormPackage);
+
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
+ PackageList->PackageListHdr.PackageLength += FormPackage->FormPkgHdr.Length;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function exports Form packages to a buffer.
+ This is a internal function.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer be used.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+ @param ResultSize The size of the already exported content of this
+ package list.
+
+ @retval EFI_SUCCESS Form Packages are exported successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+EFI_STATUS
+ExportFormPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN UINTN UsedSize,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *ResultSize
+ )
+{
+ HII_IFR_PACKAGE_INSTANCE *FormPackage;
+ UINTN PackageLength;
+ LIST_ENTRY *Link;
+ EFI_STATUS Status;
+
+ if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BufferSize > 0) && (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PackageLength = 0;
+ Status = EFI_SUCCESS;
+
+ //
+ // Export Form packages.
+ //
+ for (Link = PackageList->FormPkgHdr.ForwardLink; Link != &PackageList->FormPkgHdr; Link = Link->ForwardLink) {
+ FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);
+ PackageLength += FormPackage->FormPkgHdr.Length;
+ if ((Buffer != NULL) && (PackageLength + *ResultSize + UsedSize <= BufferSize)) {
+ //
+ // Invoke registered notification if exists
+ //
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
+ (VOID *)FormPackage,
+ EFI_HII_PACKAGE_FORMS,
+ Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Copy the Form package content.
+ //
+ CopyMem (Buffer, (VOID *)(&FormPackage->FormPkgHdr), sizeof (EFI_HII_PACKAGE_HEADER));
+ Buffer = (UINT8 *)Buffer + sizeof (EFI_HII_PACKAGE_HEADER);
+ CopyMem (
+ Buffer,
+ (VOID *)FormPackage->IfrData,
+ FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER)
+ );
+ Buffer = (UINT8 *)Buffer + FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
+ }
+ }
+
+ *ResultSize += PackageLength;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function deletes all Form packages from a package list node.
+ This is a internal function.
+
+ @param Private Hii database private data.
+ @param Handle Handle of the package list which contains the to
+ be removed Form packages.
+ @param PackageList Pointer to a package list that contains removing
+ packages.
+
+ @retval EFI_SUCCESS Form Package(s) is deleted successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+EFI_STATUS
+RemoveFormPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ LIST_ENTRY *ListHead;
+ HII_IFR_PACKAGE_INSTANCE *Package;
+ EFI_STATUS Status;
+
+ ListHead = &PackageList->FormPkgHdr;
+
+ while (!IsListEmpty (ListHead)) {
+ Package = CR (
+ ListHead->ForwardLink,
+ HII_IFR_PACKAGE_INSTANCE,
+ IfrEntry,
+ HII_IFR_PACKAGE_SIGNATURE
+ );
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ (VOID *)Package,
+ EFI_HII_PACKAGE_FORMS,
+ Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RemoveEntryList (&Package->IfrEntry);
+ PackageList->PackageListHdr.PackageLength -= Package->FormPkgHdr.Length;
+ FreePool (Package->IfrData);
+ FreePool (Package);
+ //
+ // If Hii runtime support feature is enabled,
+ // will export Hii info for runtime use after ReadyToBoot event triggered.
+ // If some driver add/update/remove packages from HiiDatabase after ReadyToBoot,
+ // will need to export the content of HiiDatabase.
+ // But if form packages removed, also need to export the ConfigResp string
+ //
+ if (gExportAfterReadyToBoot) {
+ gExportConfigResp = TRUE;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function insert a String package to a package list node.
+ This is a internal function.
+
+ @param Private Hii database private structure.
+ @param PackageHdr Pointer to a buffer stored with String package
+ information.
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list which will be inserted
+ to.
+ @param Package Created String package
+
+ @retval EFI_SUCCESS String Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ String package.
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
+ @retval EFI_UNSUPPORTED A string package with the same language already
+ exists in current package list.
+
+**/
+EFI_STATUS
+InsertStringPackage (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN VOID *PackageHdr,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ OUT HII_STRING_PACKAGE_INSTANCE **Package
+ )
+{
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+ UINT32 HeaderSize;
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+ CHAR8 *Language;
+ UINT32 LanguageSize;
+ LIST_ENTRY *Link;
+
+ if ((Private == NULL) || (PackageHdr == NULL) || (PackageList == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
+ CopyMem (&HeaderSize, (UINT8 *)PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));
+
+ //
+ // It is illegal to have two string packages with same language within one packagelist
+ // since the stringid will be duplicate if so. Check it to avoid this potential issue.
+ //
+ LanguageSize = HeaderSize - sizeof (EFI_HII_STRING_PACKAGE_HDR) + sizeof (CHAR8);
+ Language = (CHAR8 *)AllocateZeroPool (LanguageSize);
+ if (Language == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ AsciiStrCpyS (Language, LanguageSize / sizeof (CHAR8), (CHAR8 *)PackageHdr + HeaderSize - LanguageSize);
+ for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ if (HiiCompareLanguage (Language, StringPackage->StringPkgHdr->Language)) {
+ FreePool (Language);
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ FreePool (Language);
+
+ //
+ // Create a String package node
+ //
+ StringPackage = (HII_STRING_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));
+ if (StringPackage == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ StringPackage->StringPkgHdr = (EFI_HII_STRING_PACKAGE_HDR *)AllocateZeroPool (HeaderSize);
+ if (StringPackage->StringPkgHdr == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ StringPackage->StringBlock = (UINT8 *)AllocateZeroPool (PackageHeader.Length - HeaderSize);
+ if (StringPackage->StringBlock == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;
+ StringPackage->FontId = 0;
+ InitializeListHead (&StringPackage->FontInfoList);
+
+ //
+ // Copy the String package header.
+ //
+ CopyMem (StringPackage->StringPkgHdr, PackageHdr, HeaderSize);
+
+ //
+ // Copy the String blocks
+ //
+ CopyMem (
+ StringPackage->StringBlock,
+ (UINT8 *)PackageHdr + HeaderSize,
+ PackageHeader.Length - HeaderSize
+ );
+
+ //
+ // Collect all font block info
+ //
+ Status = FindStringBlock (Private, StringPackage, (EFI_STRING_ID)(-1), NULL, NULL, NULL, &StringPackage->MaxStringId, NULL);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert to String package array
+ //
+ InsertTailList (&PackageList->StringPkgHdr, &StringPackage->StringEntry);
+ *Package = StringPackage;
+
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
+ PackageList->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;
+ }
+
+ return EFI_SUCCESS;
+
+Error:
+
+ if (StringPackage != NULL) {
+ if (StringPackage->StringBlock != NULL) {
+ FreePool (StringPackage->StringBlock);
+ }
+
+ if (StringPackage->StringPkgHdr != NULL) {
+ FreePool (StringPackage->StringPkgHdr);
+ }
+
+ FreePool (StringPackage);
+ }
+
+ return Status;
+}
+
+/**
+ Adjust all string packages in a single package list to have the same max string ID.
+
+ @param PackageList Pointer to a package list which will be adjusted.
+
+ @retval EFI_SUCCESS Adjust all string packages successfully.
+ @retval others Can't adjust string packages.
+
+**/
+EFI_STATUS
+AdjustStringPackage (
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ LIST_ENTRY *Link;
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+ UINT32 Skip2BlockSize;
+ UINT32 OldBlockSize;
+ UINT8 *StringBlock;
+ UINT8 *BlockPtr;
+ EFI_STRING_ID MaxStringId;
+ UINT16 SkipCount;
+
+ MaxStringId = 0;
+ for (Link = PackageList->StringPkgHdr.ForwardLink;
+ Link != &PackageList->StringPkgHdr;
+ Link = Link->ForwardLink
+ )
+ {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ if (MaxStringId < StringPackage->MaxStringId) {
+ MaxStringId = StringPackage->MaxStringId;
+ }
+ }
+
+ for (Link = PackageList->StringPkgHdr.ForwardLink;
+ Link != &PackageList->StringPkgHdr;
+ Link = Link->ForwardLink
+ )
+ {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ if (StringPackage->MaxStringId < MaxStringId) {
+ OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
+ //
+ // Create SKIP2 EFI_HII_SIBT_SKIP2_BLOCKs to reserve the missing string IDs.
+ //
+ SkipCount = (UINT16)(MaxStringId - StringPackage->MaxStringId);
+ Skip2BlockSize = (UINT32)sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
+
+ StringBlock = (UINT8 *)AllocateZeroPool (OldBlockSize + Skip2BlockSize);
+ if (StringBlock == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Copy original string blocks, except the EFI_HII_SIBT_END.
+ //
+ CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
+ //
+ // Create SKIP2 EFI_HII_SIBT_SKIP2_BLOCK blocks
+ //
+ BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
+ *BlockPtr = EFI_HII_SIBT_SKIP2;
+ CopyMem (BlockPtr + 1, &SkipCount, sizeof (UINT16));
+ BlockPtr += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
+
+ //
+ // Append a EFI_HII_SIBT_END block to the end.
+ //
+ *BlockPtr = EFI_HII_SIBT_END;
+ FreePool (StringPackage->StringBlock);
+ StringPackage->StringBlock = StringBlock;
+ StringPackage->StringPkgHdr->Header.Length += Skip2BlockSize;
+ PackageList->PackageListHdr.PackageLength += Skip2BlockSize;
+ StringPackage->MaxStringId = MaxStringId;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function exports String packages to a buffer.
+ This is a internal function.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer be used.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+ @param ResultSize The size of the already exported content of this
+ package list.
+
+ @retval EFI_SUCCESS String Packages are exported successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+EFI_STATUS
+ExportStringPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN UINTN UsedSize,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *ResultSize
+ )
+{
+ LIST_ENTRY *Link;
+ UINTN PackageLength;
+ EFI_STATUS Status;
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+
+ if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BufferSize > 0) && (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PackageLength = 0;
+ Status = EFI_SUCCESS;
+
+ for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ PackageLength += StringPackage->StringPkgHdr->Header.Length;
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
+ //
+ // Invoke registered notification function with EXPORT_PACK notify type
+ //
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
+ (VOID *)StringPackage,
+ EFI_HII_PACKAGE_STRINGS,
+ Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Copy String package header
+ //
+ CopyMem (Buffer, StringPackage->StringPkgHdr, StringPackage->StringPkgHdr->HdrSize);
+ Buffer = (UINT8 *)Buffer + StringPackage->StringPkgHdr->HdrSize;
+
+ //
+ // Copy String blocks information
+ //
+ CopyMem (
+ Buffer,
+ StringPackage->StringBlock,
+ StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize
+ );
+ Buffer = (UINT8 *)Buffer + StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
+ }
+ }
+
+ *ResultSize += PackageLength;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function deletes all String packages from a package list node.
+ This is a internal function.
+
+ @param Private Hii database private data.
+ @param Handle Handle of the package list which contains the to
+ be removed String packages.
+ @param PackageList Pointer to a package list that contains removing
+ packages.
+
+ @retval EFI_SUCCESS String Package(s) is deleted successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+EFI_STATUS
+RemoveStringPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ LIST_ENTRY *ListHead;
+ HII_STRING_PACKAGE_INSTANCE *Package;
+ HII_FONT_INFO *FontInfo;
+ EFI_STATUS Status;
+
+ ListHead = &PackageList->StringPkgHdr;
+
+ while (!IsListEmpty (ListHead)) {
+ Package = CR (
+ ListHead->ForwardLink,
+ HII_STRING_PACKAGE_INSTANCE,
+ StringEntry,
+ HII_STRING_PACKAGE_SIGNATURE
+ );
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ (VOID *)Package,
+ EFI_HII_PACKAGE_STRINGS,
+ Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RemoveEntryList (&Package->StringEntry);
+ PackageList->PackageListHdr.PackageLength -= Package->StringPkgHdr->Header.Length;
+ FreePool (Package->StringBlock);
+ FreePool (Package->StringPkgHdr);
+ //
+ // Delete font information
+ //
+ while (!IsListEmpty (&Package->FontInfoList)) {
+ FontInfo = CR (
+ Package->FontInfoList.ForwardLink,
+ HII_FONT_INFO,
+ Entry,
+ HII_FONT_INFO_SIGNATURE
+ );
+ RemoveEntryList (&FontInfo->Entry);
+ FreePool (FontInfo);
+ }
+
+ FreePool (Package);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function insert a Font package to a package list node.
+ This is a internal function.
+
+ @param Private Hii database private structure.
+ @param PackageHdr Pointer to a buffer stored with Font package
+ information.
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list which will be inserted
+ to.
+ @param Package Created Font package
+
+ @retval EFI_SUCCESS Font Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Font package.
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
+ @retval EFI_UNSUPPORTED A font package with same EFI_FONT_INFO already
+ exists in current hii database.
+
+**/
+EFI_STATUS
+InsertFontPackage (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN VOID *PackageHdr,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ OUT HII_FONT_PACKAGE_INSTANCE **Package
+ )
+{
+ HII_FONT_PACKAGE_INSTANCE *FontPackage;
+ EFI_HII_FONT_PACKAGE_HDR *FontPkgHdr;
+ UINT32 HeaderSize;
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+ EFI_FONT_INFO *FontInfo;
+ UINT32 FontInfoSize;
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+
+ if ((Private == NULL) || (PackageHdr == NULL) || (PackageList == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
+ CopyMem (&HeaderSize, (UINT8 *)PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));
+
+ FontInfo = NULL;
+ FontPackage = NULL;
+ GlobalFont = NULL;
+
+ //
+ // It is illegal to have two font packages with same EFI_FONT_INFO within hii
+ // database. EFI_FONT_INFO (FontName, FontSize, FontStyle) describes font's
+ // attributes and identify a font uniquely.
+ //
+ FontPkgHdr = (EFI_HII_FONT_PACKAGE_HDR *)AllocateZeroPool (HeaderSize);
+ if (FontPkgHdr == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ CopyMem (FontPkgHdr, PackageHdr, HeaderSize);
+
+ FontInfoSize = sizeof (EFI_FONT_INFO) + HeaderSize - sizeof (EFI_HII_FONT_PACKAGE_HDR);
+ FontInfo = (EFI_FONT_INFO *)AllocateZeroPool (FontInfoSize);
+ if (FontInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ FontInfo->FontStyle = FontPkgHdr->FontStyle;
+ FontInfo->FontSize = FontPkgHdr->Cell.Height;
+ StrCpyS (FontInfo->FontName, (FontInfoSize - OFFSET_OF (EFI_FONT_INFO, FontName)) / sizeof (CHAR16), FontPkgHdr->FontFamily);
+
+ if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, NULL)) {
+ Status = EFI_UNSUPPORTED;
+ goto Error;
+ }
+
+ //
+ // Create a Font package node
+ //
+ FontPackage = (HII_FONT_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_FONT_PACKAGE_INSTANCE));
+ if (FontPackage == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ FontPackage->Signature = HII_FONT_PACKAGE_SIGNATURE;
+ FontPackage->FontPkgHdr = FontPkgHdr;
+ InitializeListHead (&FontPackage->GlyphInfoList);
+
+ FontPackage->GlyphBlock = (UINT8 *)AllocateZeroPool (PackageHeader.Length - HeaderSize);
+ if (FontPackage->GlyphBlock == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ CopyMem (FontPackage->GlyphBlock, (UINT8 *)PackageHdr + HeaderSize, PackageHeader.Length - HeaderSize);
+
+ //
+ // Collect all default character cell information and backup in GlyphInfoList.
+ //
+ Status = FindGlyphBlock (FontPackage, (CHAR16)(-1), NULL, NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ //
+ // This font package describes an unique EFI_FONT_INFO. Backup it in global
+ // font info list.
+ //
+ GlobalFont = (HII_GLOBAL_FONT_INFO *)AllocateZeroPool (sizeof (HII_GLOBAL_FONT_INFO));
+ if (GlobalFont == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ GlobalFont->Signature = HII_GLOBAL_FONT_INFO_SIGNATURE;
+ GlobalFont->FontPackage = FontPackage;
+ GlobalFont->FontInfoSize = FontInfoSize;
+ GlobalFont->FontInfo = FontInfo;
+ InsertTailList (&Private->FontInfoList, &GlobalFont->Entry);
+
+ //
+ // Insert this font package to Font package array
+ //
+ InsertTailList (&PackageList->FontPkgHdr, &FontPackage->FontEntry);
+ *Package = FontPackage;
+
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
+ PackageList->PackageListHdr.PackageLength += FontPackage->FontPkgHdr->Header.Length;
+ }
+
+ return EFI_SUCCESS;
+
+Error:
+
+ if (FontPkgHdr != NULL) {
+ FreePool (FontPkgHdr);
+ }
+
+ if (FontInfo != NULL) {
+ FreePool (FontInfo);
+ }
+
+ if (FontPackage != NULL) {
+ if (FontPackage->GlyphBlock != NULL) {
+ FreePool (FontPackage->GlyphBlock);
+ }
+
+ FreePool (FontPackage);
+ }
+
+ if (GlobalFont != NULL) {
+ FreePool (GlobalFont);
+ }
+
+ return Status;
+}
+
+/**
+ This function exports Font packages to a buffer.
+ This is a internal function.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer be used.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+ @param ResultSize The size of the already exported content of this
+ package list.
+
+ @retval EFI_SUCCESS Font Packages are exported successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+EFI_STATUS
+ExportFontPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN UINTN UsedSize,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *ResultSize
+ )
+{
+ LIST_ENTRY *Link;
+ UINTN PackageLength;
+ EFI_STATUS Status;
+ HII_FONT_PACKAGE_INSTANCE *Package;
+
+ if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BufferSize > 0) && (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PackageLength = 0;
+ Status = EFI_SUCCESS;
+
+ for (Link = PackageList->FontPkgHdr.ForwardLink; Link != &PackageList->FontPkgHdr; Link = Link->ForwardLink) {
+ Package = CR (Link, HII_FONT_PACKAGE_INSTANCE, FontEntry, HII_FONT_PACKAGE_SIGNATURE);
+ PackageLength += Package->FontPkgHdr->Header.Length;
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
+ //
+ // Invoke registered notification function with EXPORT_PACK notify type
+ //
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
+ (VOID *)Package,
+ EFI_HII_PACKAGE_FONTS,
+ Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Copy Font package header
+ //
+ CopyMem (Buffer, Package->FontPkgHdr, Package->FontPkgHdr->HdrSize);
+ Buffer = (UINT8 *)Buffer + Package->FontPkgHdr->HdrSize;
+
+ //
+ // Copy Glyph blocks information
+ //
+ CopyMem (
+ Buffer,
+ Package->GlyphBlock,
+ Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize
+ );
+ Buffer = (UINT8 *)Buffer + Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize;
+ }
+ }
+
+ *ResultSize += PackageLength;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function deletes all Font packages from a package list node.
+ This is a internal function.
+
+ @param Private Hii database private data.
+ @param Handle Handle of the package list which contains the to
+ be removed Font packages.
+ @param PackageList Pointer to a package list that contains removing
+ packages.
+
+ @retval EFI_SUCCESS Font Package(s) is deleted successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+EFI_STATUS
+RemoveFontPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ LIST_ENTRY *ListHead;
+ HII_FONT_PACKAGE_INSTANCE *Package;
+ EFI_STATUS Status;
+ HII_GLYPH_INFO *GlyphInfo;
+ LIST_ENTRY *Link;
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+
+ ListHead = &PackageList->FontPkgHdr;
+
+ while (!IsListEmpty (ListHead)) {
+ Package = CR (
+ ListHead->ForwardLink,
+ HII_FONT_PACKAGE_INSTANCE,
+ FontEntry,
+ HII_FONT_PACKAGE_SIGNATURE
+ );
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ (VOID *)Package,
+ EFI_HII_PACKAGE_FONTS,
+ Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RemoveEntryList (&Package->FontEntry);
+ PackageList->PackageListHdr.PackageLength -= Package->FontPkgHdr->Header.Length;
+
+ if (Package->GlyphBlock != NULL) {
+ FreePool (Package->GlyphBlock);
+ }
+
+ FreePool (Package->FontPkgHdr);
+ //
+ // Delete default character cell information
+ //
+ while (!IsListEmpty (&Package->GlyphInfoList)) {
+ GlyphInfo = CR (
+ Package->GlyphInfoList.ForwardLink,
+ HII_GLYPH_INFO,
+ Entry,
+ HII_GLYPH_INFO_SIGNATURE
+ );
+ RemoveEntryList (&GlyphInfo->Entry);
+ FreePool (GlyphInfo);
+ }
+
+ //
+ // Remove corresponding global font info
+ //
+ for (Link = Private->FontInfoList.ForwardLink; Link != &Private->FontInfoList; Link = Link->ForwardLink) {
+ GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);
+ if (GlobalFont->FontPackage == Package) {
+ RemoveEntryList (&GlobalFont->Entry);
+ FreePool (GlobalFont->FontInfo);
+ FreePool (GlobalFont);
+ break;
+ }
+ }
+
+ FreePool (Package);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function insert a Image package to a package list node.
+ This is a internal function.
+
+ @param PackageHdr Pointer to a buffer stored with Image package
+ information.
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list which will be inserted
+ to.
+ @param Package Created Image package
+
+ @retval EFI_SUCCESS Image Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Image package.
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
+
+**/
+EFI_STATUS
+InsertImagePackage (
+ IN VOID *PackageHdr,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ OUT HII_IMAGE_PACKAGE_INSTANCE **Package
+ )
+{
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
+ UINT32 PaletteSize;
+ UINT32 ImageSize;
+ UINT16 Index;
+ EFI_HII_IMAGE_PALETTE_INFO_HEADER *PaletteHdr;
+ EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo;
+ UINT32 PaletteInfoOffset;
+ UINT32 ImageInfoOffset;
+ UINT16 CurrentSize;
+
+ if ((PackageHdr == NULL) || (PackageList == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Less than one image package is allowed in one package list.
+ //
+ if (PackageList->ImagePkg != NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Create a Image package node
+ //
+ ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));
+ if (ImagePackage == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Copy the Image package header.
+ //
+ CopyMem (&ImagePackage->ImagePkgHdr, PackageHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));
+
+ PaletteInfoOffset = ImagePackage->ImagePkgHdr.PaletteInfoOffset;
+ ImageInfoOffset = ImagePackage->ImagePkgHdr.ImageInfoOffset;
+
+ //
+ // If PaletteInfoOffset is zero, there are no palettes in this image package.
+ //
+ PaletteSize = 0;
+ ImagePackage->PaletteBlock = NULL;
+ if (PaletteInfoOffset != 0) {
+ PaletteHdr = (EFI_HII_IMAGE_PALETTE_INFO_HEADER *)((UINT8 *)PackageHdr + PaletteInfoOffset);
+ PaletteSize = sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);
+ PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *)((UINT8 *)PaletteHdr + PaletteSize);
+
+ for (Index = 0; Index < PaletteHdr->PaletteCount; Index++) {
+ CopyMem (&CurrentSize, PaletteInfo, sizeof (UINT16));
+ CurrentSize += sizeof (UINT16);
+ PaletteSize += (UINT32)CurrentSize;
+ PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *)((UINT8 *)PaletteInfo + CurrentSize);
+ }
+
+ ImagePackage->PaletteBlock = (UINT8 *)AllocateZeroPool (PaletteSize);
+ if (ImagePackage->PaletteBlock == NULL) {
+ FreePool (ImagePackage);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (
+ ImagePackage->PaletteBlock,
+ (UINT8 *)PackageHdr + PaletteInfoOffset,
+ PaletteSize
+ );
+ }
+
+ //
+ // If ImageInfoOffset is zero, there are no images in this package.
+ //
+ ImageSize = 0;
+ ImagePackage->ImageBlock = NULL;
+ if (ImageInfoOffset != 0) {
+ ImageSize = ImagePackage->ImagePkgHdr.Header.Length -
+ sizeof (EFI_HII_IMAGE_PACKAGE_HDR) - PaletteSize;
+ ImagePackage->ImageBlock = AllocateZeroPool (ImageSize);
+ if (ImagePackage->ImageBlock == NULL) {
+ FreePool (ImagePackage->PaletteBlock);
+ FreePool (ImagePackage);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (
+ ImagePackage->ImageBlock,
+ (UINT8 *)PackageHdr + ImageInfoOffset,
+ ImageSize
+ );
+ }
+
+ ImagePackage->ImageBlockSize = ImageSize;
+ ImagePackage->PaletteInfoSize = PaletteSize;
+ PackageList->ImagePkg = ImagePackage;
+ *Package = ImagePackage;
+
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
+ PackageList->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function exports Image packages to a buffer.
+ This is a internal function.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer be used.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+ @param ResultSize The size of the already exported content of this
+ package list.
+
+ @retval EFI_SUCCESS Image Packages are exported successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+EFI_STATUS
+ExportImagePackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN UINTN UsedSize,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *ResultSize
+ )
+{
+ UINTN PackageLength;
+ EFI_STATUS Status;
+ HII_IMAGE_PACKAGE_INSTANCE *Package;
+
+ if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BufferSize > 0) && (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Package = PackageList->ImagePkg;
+
+ if (Package == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ PackageLength = Package->ImagePkgHdr.Header.Length;
+
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
+ //
+ // Invoke registered notification function with EXPORT_PACK notify type
+ //
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
+ (VOID *)Package,
+ EFI_HII_PACKAGE_IMAGES,
+ Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (
+ Package->ImagePkgHdr.Header.Length ==
+ sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + Package->ImageBlockSize + Package->PaletteInfoSize
+ );
+ //
+ // Copy Image package header,
+ // then justify the offset for image info and palette info in the header.
+ //
+ CopyMem (Buffer, &Package->ImagePkgHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));
+ Buffer = (UINT8 *)Buffer + sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
+
+ //
+ // Copy Image blocks information
+ //
+ if (Package->ImageBlockSize != 0) {
+ CopyMem (Buffer, Package->ImageBlock, Package->ImageBlockSize);
+ Buffer = (UINT8 *)Buffer + Package->ImageBlockSize;
+ }
+
+ //
+ // Copy Palette information
+ //
+ if (Package->PaletteInfoSize != 0) {
+ CopyMem (Buffer, Package->PaletteBlock, Package->PaletteInfoSize);
+ Buffer = (UINT8 *)Buffer + Package->PaletteInfoSize;
+ }
+ }
+
+ *ResultSize += PackageLength;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function deletes Image package from a package list node.
+ This is a internal function.
+
+ @param Private Hii database private data.
+ @param Handle Handle of the package list which contains the to
+ be removed Image packages.
+ @param PackageList Package List which contains the to be removed
+ Image package.
+
+ @retval EFI_SUCCESS Image Package(s) is deleted successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+EFI_STATUS
+RemoveImagePackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ HII_IMAGE_PACKAGE_INSTANCE *Package;
+ EFI_STATUS Status;
+
+ Package = PackageList->ImagePkg;
+
+ //
+ // Image package does not exist, return directly.
+ //
+ if (Package == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ (VOID *)Package,
+ EFI_HII_PACKAGE_IMAGES,
+ Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PackageList->PackageListHdr.PackageLength -= Package->ImagePkgHdr.Header.Length;
+
+ FreePool (Package->ImageBlock);
+ if (Package->PaletteBlock != NULL) {
+ FreePool (Package->PaletteBlock);
+ }
+
+ FreePool (Package);
+
+ PackageList->ImagePkg = NULL;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function insert a Simple Font package to a package list node.
+ This is a internal function.
+
+ @param PackageHdr Pointer to a buffer stored with Simple Font
+ package information.
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list which will be inserted
+ to.
+ @param Package Created Simple Font package
+
+ @retval EFI_SUCCESS Simple Font Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Simple Font package.
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
+
+**/
+EFI_STATUS
+InsertSimpleFontPackage (
+ IN VOID *PackageHdr,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ OUT HII_SIMPLE_FONT_PACKAGE_INSTANCE **Package
+ )
+{
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_HEADER Header;
+
+ if ((PackageHdr == NULL) || (PackageList == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Create a Simple Font package node
+ //
+ SimpleFontPackage = AllocateZeroPool (sizeof (HII_SIMPLE_FONT_PACKAGE_INSTANCE));
+ if (SimpleFontPackage == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ SimpleFontPackage->Signature = HII_S_FONT_PACKAGE_SIGNATURE;
+
+ //
+ // Copy the Simple Font package.
+ //
+ CopyMem (&Header, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ SimpleFontPackage->SimpleFontPkgHdr = AllocateZeroPool (Header.Length);
+ if (SimpleFontPackage->SimpleFontPkgHdr == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ CopyMem (SimpleFontPackage->SimpleFontPkgHdr, PackageHdr, Header.Length);
+
+ //
+ // Insert to Simple Font package array
+ //
+ InsertTailList (&PackageList->SimpleFontPkgHdr, &SimpleFontPackage->SimpleFontEntry);
+ *Package = SimpleFontPackage;
+
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
+ PackageList->PackageListHdr.PackageLength += Header.Length;
+ }
+
+ return EFI_SUCCESS;
+
+Error:
+
+ if (SimpleFontPackage != NULL) {
+ if (SimpleFontPackage->SimpleFontPkgHdr != NULL) {
+ FreePool (SimpleFontPackage->SimpleFontPkgHdr);
+ }
+
+ FreePool (SimpleFontPackage);
+ }
+
+ return Status;
+}
+
+/**
+ This function exports SimpleFont packages to a buffer.
+ This is a internal function.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer be used.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+ @param ResultSize The size of the already exported content of this
+ package list.
+
+ @retval EFI_SUCCESS SimpleFont Packages are exported successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+EFI_STATUS
+ExportSimpleFontPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN UINTN UsedSize,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *ResultSize
+ )
+{
+ LIST_ENTRY *Link;
+ UINTN PackageLength;
+ EFI_STATUS Status;
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;
+
+ if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BufferSize > 0) && (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PackageLength = 0;
+ Status = EFI_SUCCESS;
+
+ for (Link = PackageList->SimpleFontPkgHdr.ForwardLink; Link != &PackageList->SimpleFontPkgHdr; Link = Link->ForwardLink) {
+ Package = CR (Link, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE);
+ PackageLength += Package->SimpleFontPkgHdr->Header.Length;
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
+ //
+ // Invoke registered notification function with EXPORT_PACK notify type
+ //
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
+ (VOID *)Package,
+ EFI_HII_PACKAGE_SIMPLE_FONTS,
+ Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Copy SimpleFont package
+ //
+ CopyMem (Buffer, Package->SimpleFontPkgHdr, Package->SimpleFontPkgHdr->Header.Length);
+ Buffer = (UINT8 *)Buffer + Package->SimpleFontPkgHdr->Header.Length;
+ }
+ }
+
+ *ResultSize += PackageLength;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function deletes all Simple Font packages from a package list node.
+ This is a internal function.
+
+ @param Private Hii database private data.
+ @param Handle Handle of the package list which contains the to
+ be removed Simple Font packages.
+ @param PackageList Pointer to a package list that contains removing
+ packages.
+
+ @retval EFI_SUCCESS Simple Font Package(s) is deleted successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+EFI_STATUS
+RemoveSimpleFontPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ LIST_ENTRY *ListHead;
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;
+ EFI_STATUS Status;
+
+ ListHead = &PackageList->SimpleFontPkgHdr;
+
+ while (!IsListEmpty (ListHead)) {
+ Package = CR (
+ ListHead->ForwardLink,
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE,
+ SimpleFontEntry,
+ HII_S_FONT_PACKAGE_SIGNATURE
+ );
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ (VOID *)Package,
+ EFI_HII_PACKAGE_SIMPLE_FONTS,
+ Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RemoveEntryList (&Package->SimpleFontEntry);
+ PackageList->PackageListHdr.PackageLength -= Package->SimpleFontPkgHdr->Header.Length;
+ FreePool (Package->SimpleFontPkgHdr);
+ FreePool (Package);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function insert a Device path package to a package list node.
+ This is a internal function.
+
+ @param DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol
+ instance
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list which will be inserted
+ to.
+
+ @retval EFI_SUCCESS Device path Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Device path package.
+ @retval EFI_INVALID_PARAMETER DevicePath is NULL or PackageList is NULL.
+
+**/
+EFI_STATUS
+InsertDevicePathPackage (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ UINT32 PackageLength;
+ EFI_HII_PACKAGE_HEADER Header;
+
+ if ((DevicePath == NULL) || (PackageList == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Less than one device path package is allowed in one package list.
+ //
+ if (PackageList->DevicePathPkg != NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PackageLength = (UINT32)GetDevicePathSize (DevicePath) + sizeof (EFI_HII_PACKAGE_HEADER);
+ PackageList->DevicePathPkg = (UINT8 *)AllocateZeroPool (PackageLength);
+ if (PackageList->DevicePathPkg == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Header.Length = PackageLength;
+ Header.Type = EFI_HII_PACKAGE_DEVICE_PATH;
+ CopyMem (PackageList->DevicePathPkg, &Header, sizeof (EFI_HII_PACKAGE_HEADER));
+ CopyMem (
+ PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER),
+ DevicePath,
+ PackageLength - sizeof (EFI_HII_PACKAGE_HEADER)
+ );
+
+ //
+ // Since Device Path package is created by NewPackageList, either NEW_PACK
+ // or ADD_PACK should increase the length of package list.
+ //
+ PackageList->PackageListHdr.PackageLength += PackageLength;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function exports device path package to a buffer.
+ This is a internal function.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer be used.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+ @param ResultSize The size of the already exported content of this
+ package list.
+
+ @retval EFI_SUCCESS Device path Package is exported successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+EFI_STATUS
+ExportDevicePathPackage (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN UINTN UsedSize,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *ResultSize
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *Package;
+ EFI_HII_PACKAGE_HEADER Header;
+
+ if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BufferSize > 0) && (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Package = PackageList->DevicePathPkg;
+
+ if (Package == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ if (Header.Length + *ResultSize + UsedSize <= BufferSize) {
+ //
+ // Invoke registered notification function with EXPORT_PACK notify type
+ //
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
+ (VOID *)Package,
+ EFI_HII_PACKAGE_DEVICE_PATH,
+ Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Copy Device path package
+ //
+ CopyMem (Buffer, Package, Header.Length);
+ }
+
+ *ResultSize += Header.Length;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function deletes Device Path package from a package list node.
+ This is a internal function.
+
+ @param Private Hii database private data.
+ @param Handle Handle of the package list.
+ @param PackageList Package List which contains the to be removed
+ Device Path package.
+
+ @retval EFI_SUCCESS Device Path Package is deleted successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+EFI_STATUS
+RemoveDevicePathPackage (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *Package;
+ EFI_HII_PACKAGE_HEADER Header;
+
+ Package = PackageList->DevicePathPkg;
+
+ //
+ // No device path, return directly.
+ //
+ if (Package == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ (VOID *)Package,
+ EFI_HII_PACKAGE_DEVICE_PATH,
+ Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+ PackageList->PackageListHdr.PackageLength -= Header.Length;
+
+ FreePool (Package);
+
+ PackageList->DevicePathPkg = NULL;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function will insert a device path package to package list firstly then
+ invoke notification functions if any.
+ This is a internal function.
+
+ @param Private Hii database private structure.
+ @param NotifyType The type of change concerning the database.
+ @param DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol
+ instance
+ @param DatabaseRecord Pointer to a database record contains a package
+ list which will be inserted to.
+
+ @retval EFI_SUCCESS Device path Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Device path package.
+ @retval EFI_INVALID_PARAMETER DevicePath is NULL or PackageList is NULL.
+
+**/
+EFI_STATUS
+AddDevicePathPackage (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN OUT HII_DATABASE_RECORD *DatabaseRecord
+ )
+{
+ EFI_STATUS Status;
+
+ if (DevicePath == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ ASSERT (Private != NULL);
+ ASSERT (DatabaseRecord != NULL);
+
+ //
+ // Create a device path package and insert to packagelist
+ //
+ Status = InsertDevicePathPackage (
+ DevicePath,
+ NotifyType,
+ DatabaseRecord->PackageList
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *)DatabaseRecord->PackageList->DevicePathPkg,
+ EFI_HII_PACKAGE_DEVICE_PATH,
+ DatabaseRecord->Handle
+ );
+}
+
+/**
+ This function insert a Keyboard Layout package to a package list node.
+ This is a internal function.
+
+ @param PackageHdr Pointer to a buffer stored with Keyboard Layout
+ package information.
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list which will be inserted
+ to.
+ @param Package Created Keyboard Layout package
+
+ @retval EFI_SUCCESS Keyboard Layout Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Keyboard Layout package.
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
+
+**/
+EFI_STATUS
+InsertKeyboardLayoutPackage (
+ IN VOID *PackageHdr,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ OUT HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE **Package
+ )
+{
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+ EFI_STATUS Status;
+
+ if ((PackageHdr == NULL) || (PackageList == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ //
+ // Create a Keyboard Layout package node
+ //
+ KeyboardLayoutPackage = AllocateZeroPool (sizeof (HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE));
+ if (KeyboardLayoutPackage == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ KeyboardLayoutPackage->Signature = HII_KB_LAYOUT_PACKAGE_SIGNATURE;
+
+ KeyboardLayoutPackage->KeyboardPkg = (UINT8 *)AllocateZeroPool (PackageHeader.Length);
+ if (KeyboardLayoutPackage->KeyboardPkg == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ CopyMem (KeyboardLayoutPackage->KeyboardPkg, PackageHdr, PackageHeader.Length);
+ InsertTailList (&PackageList->KeyboardLayoutHdr, &KeyboardLayoutPackage->KeyboardEntry);
+
+ *Package = KeyboardLayoutPackage;
+
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
+ PackageList->PackageListHdr.PackageLength += PackageHeader.Length;
+ }
+
+ return EFI_SUCCESS;
+
+Error:
+
+ if (KeyboardLayoutPackage != NULL) {
+ if (KeyboardLayoutPackage->KeyboardPkg != NULL) {
+ FreePool (KeyboardLayoutPackage->KeyboardPkg);
+ }
+
+ FreePool (KeyboardLayoutPackage);
+ }
+
+ return Status;
+}
+
+/**
+ This function exports Keyboard Layout packages to a buffer.
+ This is a internal function.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer be used.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+ @param ResultSize The size of the already exported content of this
+ package list.
+
+ @retval EFI_SUCCESS Keyboard Layout Packages are exported
+ successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+EFI_STATUS
+ExportKeyboardLayoutPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN UINTN UsedSize,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *ResultSize
+ )
+{
+ LIST_ENTRY *Link;
+ UINTN PackageLength;
+ EFI_STATUS Status;
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+
+ if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BufferSize > 0) && (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PackageLength = 0;
+ Status = EFI_SUCCESS;
+
+ for (Link = PackageList->KeyboardLayoutHdr.ForwardLink; Link != &PackageList->KeyboardLayoutHdr; Link = Link->ForwardLink) {
+ Package = CR (Link, HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE, KeyboardEntry, HII_KB_LAYOUT_PACKAGE_SIGNATURE);
+ CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));
+ PackageLength += PackageHeader.Length;
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
+ //
+ // Invoke registered notification function with EXPORT_PACK notify type
+ //
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
+ (EFI_HII_PACKAGE_HEADER *)Package,
+ EFI_HII_PACKAGE_KEYBOARD_LAYOUT,
+ Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Copy Keyboard Layout package
+ //
+ CopyMem (Buffer, Package->KeyboardPkg, PackageHeader.Length);
+ Buffer = (UINT8 *)Buffer + PackageHeader.Length;
+ }
+ }
+
+ *ResultSize += PackageLength;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function deletes all Keyboard Layout packages from a package list node.
+ This is a internal function.
+
+ @param Private Hii database private data.
+ @param Handle Handle of the package list which contains the to
+ be removed Keyboard Layout packages.
+ @param PackageList Pointer to a package list that contains removing
+ packages.
+
+ @retval EFI_SUCCESS Keyboard Layout Package(s) is deleted
+ successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+EFI_STATUS
+RemoveKeyboardLayoutPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ LIST_ENTRY *ListHead;
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+ EFI_STATUS Status;
+
+ ListHead = &PackageList->KeyboardLayoutHdr;
+
+ while (!IsListEmpty (ListHead)) {
+ Package = CR (
+ ListHead->ForwardLink,
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,
+ KeyboardEntry,
+ HII_KB_LAYOUT_PACKAGE_SIGNATURE
+ );
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ (VOID *)Package,
+ EFI_HII_PACKAGE_KEYBOARD_LAYOUT,
+ Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RemoveEntryList (&Package->KeyboardEntry);
+ CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));
+ PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;
+ FreePool (Package->KeyboardPkg);
+ FreePool (Package);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function will insert a package list to hii database firstly then
+ invoke notification functions if any. It is the worker function of
+ HiiNewPackageList and HiiUpdatePackageList.
+
+ This is a internal function.
+
+ @param Private Hii database private structure.
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list.
+ @param DatabaseRecord Pointer to a database record contains a package
+ list instance which will be inserted to.
+
+ @retval EFI_SUCCESS All incoming packages are inserted to current
+ database.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Device path package.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+EFI_STATUS
+AddPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
+ IN OUT HII_DATABASE_RECORD *DatabaseRecord
+ )
+{
+ EFI_STATUS Status;
+ HII_GUID_PACKAGE_INSTANCE *GuidPackage;
+ HII_IFR_PACKAGE_INSTANCE *FormPackage;
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+ HII_FONT_PACKAGE_INSTANCE *FontPackage;
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
+ EFI_HII_PACKAGE_HEADER *PackageHdrPtr;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+ UINT32 OldPackageListLen;
+ BOOLEAN StringPkgIsAdd;
+
+ //
+ // Initialize Variables
+ //
+ StringPkgIsAdd = FALSE;
+ FontPackage = NULL;
+ StringPackage = NULL;
+ GuidPackage = NULL;
+ FormPackage = NULL;
+ ImagePackage = NULL;
+ SimpleFontPackage = NULL;
+ KeyboardLayoutPackage = NULL;
+
+ //
+ // Process the package list header
+ //
+ OldPackageListLen = DatabaseRecord->PackageList->PackageListHdr.PackageLength;
+ CopyMem (
+ &DatabaseRecord->PackageList->PackageListHdr,
+ (VOID *)PackageList,
+ sizeof (EFI_HII_PACKAGE_LIST_HEADER)
+ );
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
+ DatabaseRecord->PackageList->PackageListHdr.PackageLength = OldPackageListLen;
+ }
+
+ PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *)((UINT8 *)PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));
+ CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ Status = EFI_SUCCESS;
+
+ while (PackageHeader.Type != EFI_HII_PACKAGE_END) {
+ switch (PackageHeader.Type) {
+ case EFI_HII_PACKAGE_TYPE_GUID:
+ Status = InsertGuidPackage (
+ PackageHdrPtr,
+ NotifyType,
+ DatabaseRecord->PackageList,
+ &GuidPackage
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *)GuidPackage,
+ (UINT8)(PackageHeader.Type),
+ DatabaseRecord->Handle
+ );
+ break;
+ case EFI_HII_PACKAGE_FORMS:
+ Status = InsertFormPackage (
+ PackageHdrPtr,
+ NotifyType,
+ DatabaseRecord->PackageList,
+ &FormPackage
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *)FormPackage,
+ (UINT8)(PackageHeader.Type),
+ DatabaseRecord->Handle
+ );
+ //
+ // If Hii runtime support feature is enabled,
+ // will export Hii info for runtime use after ReadyToBoot event triggered.
+ // If some driver add/update/remove packages from HiiDatabase after ReadyToBoot,
+ // will need to export the content of HiiDatabase.
+ // But if form packages added/updated, also need to export the ConfigResp string.
+ //
+ if (gExportAfterReadyToBoot) {
+ gExportConfigResp = TRUE;
+ }
+
+ break;
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
+ Status = InsertKeyboardLayoutPackage (
+ PackageHdrPtr,
+ NotifyType,
+ DatabaseRecord->PackageList,
+ &KeyboardLayoutPackage
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *)KeyboardLayoutPackage,
+ (UINT8)(PackageHeader.Type),
+ DatabaseRecord->Handle
+ );
+ break;
+ case EFI_HII_PACKAGE_STRINGS:
+ Status = InsertStringPackage (
+ Private,
+ PackageHdrPtr,
+ NotifyType,
+ DatabaseRecord->PackageList,
+ &StringPackage
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ASSERT (StringPackage != NULL);
+ Status = InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *)StringPackage,
+ (UINT8)(PackageHeader.Type),
+ DatabaseRecord->Handle
+ );
+ StringPkgIsAdd = TRUE;
+ break;
+ case EFI_HII_PACKAGE_FONTS:
+ Status = InsertFontPackage (
+ Private,
+ PackageHdrPtr,
+ NotifyType,
+ DatabaseRecord->PackageList,
+ &FontPackage
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *)FontPackage,
+ (UINT8)(PackageHeader.Type),
+ DatabaseRecord->Handle
+ );
+ break;
+ case EFI_HII_PACKAGE_IMAGES:
+ Status = InsertImagePackage (
+ PackageHdrPtr,
+ NotifyType,
+ DatabaseRecord->PackageList,
+ &ImagePackage
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *)ImagePackage,
+ (UINT8)(PackageHeader.Type),
+ DatabaseRecord->Handle
+ );
+ break;
+ case EFI_HII_PACKAGE_SIMPLE_FONTS:
+ Status = InsertSimpleFontPackage (
+ PackageHdrPtr,
+ NotifyType,
+ DatabaseRecord->PackageList,
+ &SimpleFontPackage
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *)SimpleFontPackage,
+ (UINT8)(PackageHeader.Type),
+ DatabaseRecord->Handle
+ );
+ break;
+ case EFI_HII_PACKAGE_DEVICE_PATH:
+ Status = AddDevicePathPackage (
+ Private,
+ NotifyType,
+ (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)PackageHdrPtr + sizeof (EFI_HII_PACKAGE_HEADER)),
+ DatabaseRecord
+ );
+ break;
+ default:
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // goto header of next package
+ //
+ PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *)((UINT8 *)PackageHdrPtr + PackageHeader.Length);
+ CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
+ }
+
+ //
+ // Adjust String Package to make sure all string packages have the same max string ID.
+ //
+ if (!EFI_ERROR (Status) && StringPkgIsAdd) {
+ Status = AdjustStringPackage (DatabaseRecord->PackageList);
+ }
+
+ return Status;
+}
+
+/**
+ This function exports a package list to a buffer. It is the worker function
+ of HiiExportPackageList.
+
+ This is a internal function.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer has been used by exporting
+ package lists when Handle is NULL.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+
+ @retval EFI_SUCCESS Keyboard Layout Packages are exported
+ successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+EFI_STATUS
+ExportPackageList (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN OUT UINTN *UsedSize,
+ IN UINTN BufferSize,
+ OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN ResultSize;
+ EFI_HII_PACKAGE_HEADER EndofPackageList;
+
+ ASSERT (Private != NULL && PackageList != NULL && UsedSize != NULL);
+ ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
+ ASSERT (IsHiiHandleValid (Handle));
+
+ if ((BufferSize > 0) && (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Copy the package list header
+ // ResultSize indicates the length of the exported bytes of this package list
+ //
+ ResultSize = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+ if (ResultSize + *UsedSize <= BufferSize) {
+ CopyMem ((VOID *)Buffer, PackageList, ResultSize);
+ }
+
+ //
+ // Copy the packages and invoke EXPORT_PACK notify functions if exists.
+ //
+ Status = ExportGuidPackages (
+ Private,
+ Handle,
+ PackageList,
+ *UsedSize,
+ BufferSize,
+ (VOID *)((UINT8 *)Buffer + ResultSize),
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = ExportFormPackages (
+ Private,
+ Handle,
+ PackageList,
+ *UsedSize,
+ BufferSize,
+ (VOID *)((UINT8 *)Buffer + ResultSize),
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = ExportKeyboardLayoutPackages (
+ Private,
+ Handle,
+ PackageList,
+ *UsedSize,
+ BufferSize,
+ (VOID *)((UINT8 *)Buffer + ResultSize),
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = ExportStringPackages (
+ Private,
+ Handle,
+ PackageList,
+ *UsedSize,
+ BufferSize,
+ (VOID *)((UINT8 *)Buffer + ResultSize),
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = ExportFontPackages (
+ Private,
+ Handle,
+ PackageList,
+ *UsedSize,
+ BufferSize,
+ (VOID *)((UINT8 *)Buffer + ResultSize),
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = ExportImagePackages (
+ Private,
+ Handle,
+ PackageList,
+ *UsedSize,
+ BufferSize,
+ (VOID *)((UINT8 *)Buffer + ResultSize),
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = ExportSimpleFontPackages (
+ Private,
+ Handle,
+ PackageList,
+ *UsedSize,
+ BufferSize,
+ (VOID *)((UINT8 *)Buffer + ResultSize),
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = ExportDevicePathPackage (
+ Private,
+ Handle,
+ PackageList,
+ *UsedSize,
+ BufferSize,
+ (VOID *)((UINT8 *)Buffer + ResultSize),
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Append the package list end.
+ //
+ EndofPackageList.Length = sizeof (EFI_HII_PACKAGE_HEADER);
+ EndofPackageList.Type = EFI_HII_PACKAGE_END;
+ if (ResultSize + *UsedSize + sizeof (EFI_HII_PACKAGE_HEADER) <= BufferSize) {
+ CopyMem (
+ (VOID *)((UINT8 *)Buffer + ResultSize),
+ (VOID *)&EndofPackageList,
+ sizeof (EFI_HII_PACKAGE_HEADER)
+ );
+ }
+
+ *UsedSize += ResultSize + sizeof (EFI_HII_PACKAGE_HEADER);
+
+ return EFI_SUCCESS;
+}
+
+/**
+This function mainly use to get and update ConfigResp string.
+
+@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
+
+@retval EFI_SUCCESS Get the information successfully.
+@retval EFI_OUT_OF_RESOURCES Not enough memory to store the Configuration Setting data.
+
+**/
+EFI_STATUS
+HiiGetConfigRespInfo (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_STRING ConfigAltResp;
+ UINTN ConfigSize;
+
+ ConfigAltResp = NULL;
+ ConfigSize = 0;
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Get ConfigResp string
+ //
+ Status = HiiConfigRoutingExportConfig (&Private->ConfigRouting, &ConfigAltResp);
+
+ if (!EFI_ERROR (Status)) {
+ ConfigSize = StrSize (ConfigAltResp);
+ if (ConfigSize > gConfigRespSize) {
+ //
+ // Do 25% overallocation to minimize the number of memory allocations after ReadyToBoot.
+ // Since lots of allocation after ReadyToBoot may change memory map and cause S4 resume issue.
+ //
+ gConfigRespSize = ConfigSize + (ConfigSize >> 2);
+ if (gRTConfigRespBuffer != NULL) {
+ FreePool (gRTConfigRespBuffer);
+ DEBUG ((DEBUG_WARN, "[HiiDatabase]: Memory allocation is required after ReadyToBoot, which may change memory map and cause S4 resume issue.\n"));
+ }
+
+ gRTConfigRespBuffer = (EFI_STRING)AllocateRuntimeZeroPool (gConfigRespSize);
+ if (gRTConfigRespBuffer == NULL) {
+ FreePool (ConfigAltResp);
+ DEBUG ((DEBUG_ERROR, "[HiiDatabase]: No enough memory resource to store the ConfigResp string.\n"));
+ //
+ // Remove from the System Table when the configuration runtime buffer is freed.
+ //
+ gBS->InstallConfigurationTable (&gEfiHiiConfigRoutingProtocolGuid, NULL);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ ZeroMem (gRTConfigRespBuffer, gConfigRespSize);
+ }
+
+ CopyMem (gRTConfigRespBuffer, ConfigAltResp, ConfigSize);
+ gBS->InstallConfigurationTable (&gEfiHiiConfigRoutingProtocolGuid, gRTConfigRespBuffer);
+ FreePool (ConfigAltResp);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+This is an internal function,mainly use to get HiiDatabase information.
+
+@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
+
+@retval EFI_SUCCESS Get the information successfully.
+@retval EFI_OUT_OF_RESOURCES Not enough memory to store the Hiidatabase data.
+
+**/
+EFI_STATUS
+HiiGetDatabaseInfo (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_LIST_HEADER *DatabaseInfo;
+ UINTN DatabaseInfoSize;
+
+ DatabaseInfo = NULL;
+ DatabaseInfoSize = 0;
+
+ //
+ // Get HiiDatabase information.
+ //
+ Status = HiiExportPackageLists (This, NULL, &DatabaseInfoSize, DatabaseInfo);
+
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+
+ if (DatabaseInfoSize > gDatabaseInfoSize ) {
+ //
+ // Do 25% overallocation to minimize the number of memory allocations after ReadyToBoot.
+ // Since lots of allocation after ReadyToBoot may change memory map and cause S4 resume issue.
+ //
+ gDatabaseInfoSize = DatabaseInfoSize + (DatabaseInfoSize >> 2);
+ if (gRTDatabaseInfoBuffer != NULL) {
+ FreePool (gRTDatabaseInfoBuffer);
+ DEBUG ((DEBUG_WARN, "[HiiDatabase]: Memory allocation is required after ReadyToBoot, which may change memory map and cause S4 resume issue.\n"));
+ }
+
+ gRTDatabaseInfoBuffer = AllocateRuntimeZeroPool (gDatabaseInfoSize);
+ if (gRTDatabaseInfoBuffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "[HiiDatabase]: No enough memory resource to store the HiiDatabase info.\n"));
+ //
+ // Remove from the System Table when the configuration runtime buffer is freed.
+ //
+ gBS->InstallConfigurationTable (&gEfiHiiDatabaseProtocolGuid, NULL);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ ZeroMem (gRTDatabaseInfoBuffer, gDatabaseInfoSize);
+ }
+
+ Status = HiiExportPackageLists (This, NULL, &DatabaseInfoSize, gRTDatabaseInfoBuffer);
+ ASSERT_EFI_ERROR (Status);
+ gBS->InstallConfigurationTable (&gEfiHiiDatabaseProtocolGuid, gRTDatabaseInfoBuffer);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function adds the packages in the package list to the database and returns a handle. If there is a
+ EFI_DEVICE_PATH_PROTOCOL associated with the DriverHandle, then this function will
+ create a package of type EFI_PACKAGE_TYPE_DEVICE_PATH and add it to the package list.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER
+ structure.
+ @param DriverHandle Associate the package list with this EFI handle.
+ If a NULL is specified, this data will not be associate
+ with any drivers and cannot have a callback induced.
+ @param Handle A pointer to the EFI_HII_HANDLE instance.
+
+ @retval EFI_SUCCESS The package list associated with the Handle was
+ added to the HII database.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ database contents.
+ @retval EFI_INVALID_PARAMETER PackageList is NULL or Handle is NULL.
+ @retval EFI_INVALID_PARAMETER PackageListGuid already exists in database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiNewPackageList (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
+ IN CONST EFI_HANDLE DriverHandle OPTIONAL,
+ OUT EFI_HII_HANDLE *Handle
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ LIST_ENTRY *Link;
+ EFI_GUID PackageListGuid;
+
+ if ((This == NULL) || (PackageList == NULL) || (Handle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ CopyMem (&PackageListGuid, (VOID *)PackageList, sizeof (EFI_GUID));
+
+ //
+ // Check the Package list GUID to guarantee this GUID is unique in database.
+ //
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (CompareGuid (
+ &(DatabaseRecord->PackageList->PackageListHdr.PackageListGuid),
+ &PackageListGuid
+ ) &&
+ (DatabaseRecord->DriverHandle == DriverHandle))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ EfiAcquireLock (&mHiiDatabaseLock);
+
+ //
+ // Build a PackageList node
+ //
+ Status = GenerateHiiDatabaseRecord (Private, &DatabaseRecord);
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return Status;
+ }
+
+ //
+ // Fill in information of the created Package List node
+ // according to incoming package list.
+ //
+ Status = AddPackages (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, PackageList, DatabaseRecord);
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return Status;
+ }
+
+ DatabaseRecord->DriverHandle = DriverHandle;
+
+ //
+ // Create a Device path package and add into the package list if exists.
+ //
+ Status = gBS->HandleProtocol (
+ DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **)&DevicePath
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = AddDevicePathPackage (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, DevicePath, DatabaseRecord);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ *Handle = DatabaseRecord->Handle;
+
+ //
+ // Check whether need to get the Database info.
+ // Only after ReadyToBoot, need to do the export.
+ //
+ if (gExportAfterReadyToBoot) {
+ HiiGetDatabaseInfo (This);
+ }
+
+ EfiReleaseLock (&mHiiDatabaseLock);
+
+ //
+ // Notes:
+ // HiiGetDatabaseInfo () will get the contents of HII data base,
+ // belong to the atomic behavior of Hii Database update.
+ // And since HiiGetConfigRespInfo () will get the configuration setting info from HII drivers
+ // we can not think it belong to the atomic behavior of Hii Database update.
+ // That's why EfiReleaseLock (&mHiiDatabaseLock) is callled before HiiGetConfigRespInfo ().
+ //
+
+ // Check whether need to get the configuration setting info from HII drivers.
+ // When after ReadyToBoot and need to do the export for form package add.
+ //
+ if (gExportAfterReadyToBoot && gExportConfigResp) {
+ HiiGetConfigRespInfo (This);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function removes the package list that is associated with Handle
+ from the HII database. Before removing the package, any registered functions
+ with the notification type REMOVE_PACK and the same package type will be called.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param Handle The handle that was registered to the data that is
+ requested for removal.
+
+ @retval EFI_SUCCESS The data associated with the Handle was removed
+ from the HII database.
+ @retval EFI_NOT_FOUND The specified handle is not in database.
+ @retval EFI_INVALID_PARAMETER The Handle was not valid.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiRemovePackageList (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *Node;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
+ HII_HANDLE *HiiHandle;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (Handle)) {
+ return EFI_NOT_FOUND;
+ }
+
+ EfiAcquireLock (&mHiiDatabaseLock);
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Get the packagelist to be removed.
+ //
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (Node->Handle == Handle) {
+ PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList);
+ ASSERT (PackageList != NULL);
+
+ //
+ // Call registered functions with REMOVE_PACK before removing packages
+ // then remove them.
+ //
+ Status = RemoveGuidPackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return Status;
+ }
+
+ Status = RemoveFormPackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return Status;
+ }
+
+ Status = RemoveKeyboardLayoutPackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return Status;
+ }
+
+ Status = RemoveStringPackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return Status;
+ }
+
+ Status = RemoveFontPackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return Status;
+ }
+
+ Status = RemoveImagePackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return Status;
+ }
+
+ Status = RemoveSimpleFontPackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return Status;
+ }
+
+ Status = RemoveDevicePathPackage (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return Status;
+ }
+
+ //
+ // Free resources of the package list
+ //
+ RemoveEntryList (&Node->DatabaseEntry);
+
+ HiiHandle = (HII_HANDLE *)Handle;
+ RemoveEntryList (&HiiHandle->Handle);
+ Private->HiiHandleCount--;
+ ASSERT (Private->HiiHandleCount >= 0);
+
+ HiiHandle->Signature = 0;
+ FreePool (HiiHandle);
+ FreePool (Node->PackageList);
+ FreePool (Node);
+
+ //
+ // Check whether need to get the Database info.
+ // Only after ReadyToBoot, need to do the export.
+ //
+ if (gExportAfterReadyToBoot) {
+ HiiGetDatabaseInfo (This);
+ }
+
+ EfiReleaseLock (&mHiiDatabaseLock);
+
+ //
+ // Notes:
+ // HiiGetDatabaseInfo () will get the contents of HII data base,
+ // belong to the atomic behavior of Hii Database update.
+ // And since HiiGetConfigRespInfo () will get the configuration setting info from HII drivers
+ // we can not think it belong to the atomic behavior of Hii Database update.
+ // That's why EfiReleaseLock (&mHiiDatabaseLock) is callled before HiiGetConfigRespInfo ().
+ //
+
+ //
+ // Check whether need to get the configuration setting info from HII drivers.
+ // When after ReadyToBoot and need to do the export for form package remove.
+ //
+ if (gExportAfterReadyToBoot && gExportConfigResp) {
+ HiiGetConfigRespInfo (This);
+ }
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_NOT_FOUND;
+}
+
+/**
+ This function updates the existing package list (which has the specified Handle)
+ in the HII databases, using the new package list specified by PackageList.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param Handle The handle that was registered to the data that is
+ requested to be updated.
+ @param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER
+ package.
+
+ @retval EFI_SUCCESS The HII database was successfully updated.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate enough memory for the updated
+ database.
+ @retval EFI_INVALID_PARAMETER PackageList was NULL.
+ @retval EFI_NOT_FOUND The specified Handle is not in database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiUpdatePackageList (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *Node;
+ EFI_HII_PACKAGE_HEADER *PackageHdrPtr;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *OldPackageList;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+
+ if ((This == NULL) || (PackageList == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (Handle)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *)((UINT8 *)PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));
+
+ Status = EFI_SUCCESS;
+
+ EfiAcquireLock (&mHiiDatabaseLock);
+ //
+ // Get original packagelist to be updated
+ //
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (Node->Handle == Handle) {
+ OldPackageList = Node->PackageList;
+ //
+ // Remove the package if its type matches one of the package types which is
+ // contained in the new package list.
+ //
+ CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
+ while (PackageHeader.Type != EFI_HII_PACKAGE_END) {
+ switch (PackageHeader.Type) {
+ case EFI_HII_PACKAGE_TYPE_GUID:
+ Status = RemoveGuidPackages (Private, Handle, OldPackageList);
+ break;
+ case EFI_HII_PACKAGE_FORMS:
+ Status = RemoveFormPackages (Private, Handle, OldPackageList);
+ break;
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
+ Status = RemoveKeyboardLayoutPackages (Private, Handle, OldPackageList);
+ break;
+ case EFI_HII_PACKAGE_STRINGS:
+ Status = RemoveStringPackages (Private, Handle, OldPackageList);
+ break;
+ case EFI_HII_PACKAGE_FONTS:
+ Status = RemoveFontPackages (Private, Handle, OldPackageList);
+ break;
+ case EFI_HII_PACKAGE_IMAGES:
+ Status = RemoveImagePackages (Private, Handle, OldPackageList);
+ break;
+ case EFI_HII_PACKAGE_SIMPLE_FONTS:
+ Status = RemoveSimpleFontPackages (Private, Handle, OldPackageList);
+ break;
+ case EFI_HII_PACKAGE_DEVICE_PATH:
+ Status = RemoveDevicePathPackage (Private, Handle, OldPackageList);
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return Status;
+ }
+
+ PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *)((UINT8 *)PackageHdrPtr + PackageHeader.Length);
+ CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
+ }
+
+ //
+ // Add all of the packages within the new package list
+ //
+ Status = AddPackages (Private, EFI_HII_DATABASE_NOTIFY_ADD_PACK, PackageList, Node);
+
+ //
+ // Check whether need to get the Database info.
+ // Only after ReadyToBoot, need to do the export.
+ //
+ if (gExportAfterReadyToBoot && (Status == EFI_SUCCESS)) {
+ HiiGetDatabaseInfo (This);
+ }
+
+ EfiReleaseLock (&mHiiDatabaseLock);
+
+ //
+ // Notes:
+ // HiiGetDatabaseInfo () will get the contents of HII data base,
+ // belong to the atomic behavior of Hii Database update.
+ // And since HiiGetConfigRespInfo () will get the configuration setting info from HII drivers
+ // we can not think it belong to the atomic behavior of Hii Database update.
+ // That's why EfiReleaseLock (&mHiiDatabaseLock) is callled before HiiGetConfigRespInfo ().
+ //
+
+ //
+ // Check whether need to get the configuration setting info from HII drivers.
+ // When after ReadyToBoot and need to do the export for form package update.
+ //
+ if (gExportAfterReadyToBoot && gExportConfigResp && (Status == EFI_SUCCESS)) {
+ HiiGetConfigRespInfo (This);
+ }
+
+ return Status;
+ }
+ }
+
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_NOT_FOUND;
+}
+
+/**
+ This function returns a list of the package handles of the specified type
+ that are currently active in the database. The pseudo-type
+ EFI_HII_PACKAGE_TYPE_ALL will cause all package handles to be listed.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param PackageType Specifies the package type of the packages to list
+ or EFI_HII_PACKAGE_TYPE_ALL for all packages to be
+ listed.
+ @param PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then
+ this is the pointer to the GUID which must match
+ the Guid field of EFI_HII_GUID_PACKAGE_GUID_HDR.
+ Otherwise, it must be NULL.
+ @param HandleBufferLength On input, a pointer to the length of the handle
+ buffer. On output, the length of the handle
+ buffer that is required for the handles found.
+ @param Handle An array of EFI_HII_HANDLE instances returned.
+
+ @retval EFI_SUCCESS The matching handles are outputted successfully.
+ HandleBufferLength is updated with the actual length.
+ @retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that
+ Handle is too small to support the number of
+ handles. HandleBufferLength is updated with a
+ value that will enable the data to fit.
+ @retval EFI_NOT_FOUND No matching handle could not be found in database.
+ @retval EFI_INVALID_PARAMETER HandleBufferLength was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by HandleBufferLength was not
+ zero and Handle was NULL.
+ @retval EFI_INVALID_PARAMETER PackageType is not a EFI_HII_PACKAGE_TYPE_GUID but
+ PackageGuid is not NULL, PackageType is a EFI_HII_
+ PACKAGE_TYPE_GUID but PackageGuid is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiListPackageLists (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN OUT UINTN *HandleBufferLength,
+ OUT EFI_HII_HANDLE *Handle
+ )
+{
+ HII_GUID_PACKAGE_INSTANCE *GuidPackage;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *Node;
+ LIST_ENTRY *Link;
+ BOOLEAN Matched;
+ HII_HANDLE **Result;
+ UINTN ResultSize;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
+ LIST_ENTRY *Link1;
+
+ //
+ // Check input parameters
+ //
+ if ((This == NULL) || (HandleBufferLength == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*HandleBufferLength > 0) && (Handle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((PackageType == EFI_HII_PACKAGE_TYPE_GUID) && (PackageGuid == NULL)) ||
+ ((PackageType != EFI_HII_PACKAGE_TYPE_GUID) && (PackageGuid != NULL)))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ Matched = FALSE;
+ Result = (HII_HANDLE **)Handle;
+ ResultSize = 0;
+
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList);
+ switch (PackageType) {
+ case EFI_HII_PACKAGE_TYPE_GUID:
+ for (Link1 = PackageList->GuidPkgHdr.ForwardLink; Link1 != &PackageList->GuidPkgHdr; Link1 = Link1->ForwardLink) {
+ GuidPackage = CR (Link1, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);
+ if (CompareGuid (
+ (EFI_GUID *)PackageGuid,
+ (EFI_GUID *)(GuidPackage->GuidPkg + sizeof (EFI_HII_PACKAGE_HEADER))
+ ))
+ {
+ Matched = TRUE;
+ break;
+ }
+ }
+
+ break;
+ case EFI_HII_PACKAGE_FORMS:
+ if (!IsListEmpty (&PackageList->FormPkgHdr)) {
+ Matched = TRUE;
+ }
+
+ break;
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
+ if (!IsListEmpty (&PackageList->KeyboardLayoutHdr)) {
+ Matched = TRUE;
+ }
+
+ break;
+ case EFI_HII_PACKAGE_STRINGS:
+ if (!IsListEmpty (&PackageList->StringPkgHdr)) {
+ Matched = TRUE;
+ }
+
+ break;
+ case EFI_HII_PACKAGE_FONTS:
+ if (!IsListEmpty (&PackageList->FontPkgHdr)) {
+ Matched = TRUE;
+ }
+
+ break;
+ case EFI_HII_PACKAGE_IMAGES:
+ if (PackageList->ImagePkg != NULL) {
+ Matched = TRUE;
+ }
+
+ break;
+ case EFI_HII_PACKAGE_SIMPLE_FONTS:
+ if (!IsListEmpty (&PackageList->SimpleFontPkgHdr)) {
+ Matched = TRUE;
+ }
+
+ break;
+ case EFI_HII_PACKAGE_DEVICE_PATH:
+ if (PackageList->DevicePathPkg != NULL) {
+ Matched = TRUE;
+ }
+
+ break;
+ //
+ // Pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package handles
+ // to be listed.
+ //
+ case EFI_HII_PACKAGE_TYPE_ALL:
+ Matched = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ //
+ // This active package list has the specified package type, list it.
+ //
+ if (Matched) {
+ ResultSize += sizeof (EFI_HII_HANDLE);
+ if (ResultSize <= *HandleBufferLength) {
+ *Result++ = Node->Handle;
+ }
+ }
+
+ Matched = FALSE;
+ }
+
+ if (ResultSize == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (*HandleBufferLength < ResultSize) {
+ *HandleBufferLength = ResultSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *HandleBufferLength = ResultSize;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function will export one or all package lists in the database to a buffer.
+ For each package list exported, this function will call functions registered
+ with EXPORT_PACK and then copy the package list to the buffer.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param Handle An EFI_HII_HANDLE that corresponds to the desired
+ package list in the HII database to export or NULL
+ to indicate all package lists should be exported.
+ @param BufferSize On input, a pointer to the length of the buffer.
+ On output, the length of the buffer that is
+ required for the exported data.
+ @param Buffer A pointer to a buffer that will contain the
+ results of the export function.
+
+ @retval EFI_SUCCESS Package exported.
+ @retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that
+ Handle is too small to support the number of
+ handles. HandleBufferLength is updated with a
+ value that will enable the data to fit.
+ @retval EFI_NOT_FOUND The specified Handle could not be found in the
+ current database.
+ @retval EFI_INVALID_PARAMETER BufferSize was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by BufferSize was not zero
+ and Buffer was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiExportPackageLists (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer
+ )
+{
+ LIST_ENTRY *Link;
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *Node;
+ UINTN UsedSize;
+
+ if ((This == NULL) || (BufferSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*BufferSize > 0) && (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Handle != NULL) && (!IsHiiHandleValid (Handle))) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ UsedSize = 0;
+
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (Handle == NULL) {
+ //
+ // Export all package lists in current hii database.
+ //
+ Status = ExportPackageList (
+ Private,
+ Node->Handle,
+ (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList),
+ &UsedSize,
+ *BufferSize,
+ (EFI_HII_PACKAGE_LIST_HEADER *)((UINT8 *)Buffer + UsedSize)
+ );
+ ASSERT_EFI_ERROR (Status);
+ } else if ((Handle != NULL) && (Node->Handle == Handle)) {
+ Status = ExportPackageList (
+ Private,
+ Handle,
+ (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList),
+ &UsedSize,
+ *BufferSize,
+ Buffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (*BufferSize < UsedSize) {
+ *BufferSize = UsedSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ if ((Handle == NULL) && (UsedSize != 0)) {
+ if (*BufferSize < UsedSize) {
+ *BufferSize = UsedSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ This function registers a function which will be called when specified actions related to packages of
+ the specified type occur in the HII database. By registering a function, other HII-related drivers are
+ notified when specific package types are added, removed or updated in the HII database.
+ Each driver or application which registers a notification should use
+ EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify() before exiting.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param PackageType Specifies the package type of the packages to list
+ or EFI_HII_PACKAGE_TYPE_ALL for all packages to be
+ listed.
+ @param PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then
+ this is the pointer to the GUID which must match
+ the Guid field of
+ EFI_HII_GUID_PACKAGE_GUID_HDR. Otherwise, it must
+ be NULL.
+ @param PackageNotifyFn Points to the function to be called when the event
+ specified by
+ NotificationType occurs.
+ @param NotifyType Describes the types of notification which this
+ function will be receiving.
+ @param NotifyHandle Points to the unique handle assigned to the
+ registered notification. Can be used in
+ EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify()
+ to stop notifications.
+
+ @retval EFI_SUCCESS Notification registered successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures
+ @retval EFI_INVALID_PARAMETER NotifyHandle is NULL.
+ @retval EFI_INVALID_PARAMETER PackageGuid is not NULL when PackageType is not
+ EFI_HII_PACKAGE_TYPE_GUID.
+ @retval EFI_INVALID_PARAMETER PackageGuid is NULL when PackageType is
+ EFI_HII_PACKAGE_TYPE_GUID.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiRegisterPackageNotify (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN CONST EFI_HII_DATABASE_NOTIFY PackageNotifyFn,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ OUT EFI_HANDLE *NotifyHandle
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_NOTIFY *Notify;
+ EFI_STATUS Status;
+
+ if ((This == NULL) || (NotifyHandle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((PackageType == EFI_HII_PACKAGE_TYPE_GUID) && (PackageGuid == NULL)) ||
+ ((PackageType != EFI_HII_PACKAGE_TYPE_GUID) && (PackageGuid != NULL)))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Allocate a notification node
+ //
+ Notify = (HII_DATABASE_NOTIFY *)AllocateZeroPool (sizeof (HII_DATABASE_NOTIFY));
+ if (Notify == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Generate a notify handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Notify->NotifyHandle,
+ &gEfiCallerIdGuid,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Fill in the information to the notification node
+ //
+ Notify->Signature = HII_DATABASE_NOTIFY_SIGNATURE;
+ Notify->PackageType = PackageType;
+ Notify->PackageGuid = (EFI_GUID *)PackageGuid;
+ Notify->PackageNotifyFn = (EFI_HII_DATABASE_NOTIFY)PackageNotifyFn;
+ Notify->NotifyType = NotifyType;
+
+ InsertTailList (&Private->DatabaseNotifyList, &Notify->DatabaseNotifyEntry);
+ *NotifyHandle = Notify->NotifyHandle;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Removes the specified HII database package-related notification.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param NotificationHandle The handle of the notification function being
+ unregistered.
+
+ @retval EFI_SUCCESS Notification is unregistered successfully.
+ @retval EFI_INVALID_PARAMETER The Handle is invalid.
+ @retval EFI_NOT_FOUND The incoming notification handle does not exist
+ in current hii database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiUnregisterPackageNotify (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HANDLE NotificationHandle
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_NOTIFY *Notify;
+ LIST_ENTRY *Link;
+ EFI_STATUS Status;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (NotificationHandle == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = gBS->OpenProtocol (
+ NotificationHandle,
+ &gEfiCallerIdGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ for (Link = Private->DatabaseNotifyList.ForwardLink; Link != &Private->DatabaseNotifyList; Link = Link->ForwardLink) {
+ Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);
+ if (Notify->NotifyHandle == NotificationHandle) {
+ //
+ // Remove the matching notification node
+ //
+ RemoveEntryList (&Notify->DatabaseNotifyEntry);
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Notify->NotifyHandle,
+ &gEfiCallerIdGuid,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ FreePool (Notify);
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ This routine retrieves an array of GUID values for each keyboard layout that
+ was previously registered in the system.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param KeyGuidBufferLength On input, a pointer to the length of the keyboard
+ GUID buffer. On output, the length of the handle
+ buffer that is required for the handles found.
+ @param KeyGuidBuffer An array of keyboard layout GUID instances
+ returned.
+
+ @retval EFI_SUCCESS KeyGuidBuffer was updated successfully.
+ @retval EFI_BUFFER_TOO_SMALL The KeyGuidBufferLength parameter indicates
+ that KeyGuidBuffer is too small to support the
+ number of GUIDs. KeyGuidBufferLength is
+ updated with a value that will enable the data to
+ fit.
+ @retval EFI_INVALID_PARAMETER The KeyGuidBufferLength is NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by KeyGuidBufferLength is not
+ zero and KeyGuidBuffer is NULL.
+ @retval EFI_NOT_FOUND There was no keyboard layout.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiFindKeyboardLayouts (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN OUT UINT16 *KeyGuidBufferLength,
+ OUT EFI_GUID *KeyGuidBuffer
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *Node;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *Link1;
+ UINT16 ResultSize;
+ UINTN Index;
+ UINT16 LayoutCount;
+ UINT16 LayoutLength;
+ UINT8 *Layout;
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
+
+ if ((This == NULL) || (KeyGuidBufferLength == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*KeyGuidBufferLength > 0) && (KeyGuidBuffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ ResultSize = 0;
+
+ //
+ // Search all package lists in whole database to retrieve keyboard layout.
+ //
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ PackageList = Node->PackageList;
+ for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;
+ Link1 != &PackageList->KeyboardLayoutHdr;
+ Link1 = Link1->ForwardLink
+ )
+ {
+ //
+ // Find out all Keyboard Layout packages in this package list.
+ //
+ Package = CR (
+ Link1,
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,
+ KeyboardEntry,
+ HII_KB_LAYOUT_PACKAGE_SIGNATURE
+ );
+ Layout = (UINT8 *)Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);
+ CopyMem (
+ &LayoutCount,
+ (UINT8 *)Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER),
+ sizeof (UINT16)
+ );
+ for (Index = 0; Index < LayoutCount; Index++) {
+ ResultSize += sizeof (EFI_GUID);
+ if (ResultSize <= *KeyGuidBufferLength) {
+ CopyMem (KeyGuidBuffer + (ResultSize / sizeof (EFI_GUID) - 1), Layout + sizeof (UINT16), sizeof (EFI_GUID));
+ CopyMem (&LayoutLength, Layout, sizeof (UINT16));
+ Layout = Layout + LayoutLength;
+ }
+ }
+ }
+ }
+
+ if (ResultSize == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (*KeyGuidBufferLength < ResultSize) {
+ *KeyGuidBufferLength = ResultSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *KeyGuidBufferLength = ResultSize;
+ return EFI_SUCCESS;
+}
+
+/**
+ This routine retrieves the requested keyboard layout. The layout is a physical description of the keys
+ on a keyboard and the character(s) that are associated with a particular set of key strokes.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param KeyGuid A pointer to the unique ID associated with a given
+ keyboard layout. If KeyGuid is NULL then the
+ current layout will be retrieved.
+ @param KeyboardLayoutLength On input, a pointer to the length of the
+ KeyboardLayout buffer. On output, the length of
+ the data placed into KeyboardLayout.
+ @param KeyboardLayout A pointer to a buffer containing the retrieved
+ keyboard layout.
+
+ @retval EFI_SUCCESS The keyboard layout was retrieved successfully.
+ @retval EFI_NOT_FOUND The requested keyboard layout was not found.
+ @retval EFI_INVALID_PARAMETER The KeyboardLayout or KeyboardLayoutLength was
+ NULL.
+ @retval EFI_BUFFER_TOO_SMALL The KeyboardLayoutLength parameter indicates
+ that KeyboardLayout is too small to support the
+ requested keyboard layout. KeyboardLayoutLength is
+ updated with a value that will enable the
+ data to fit.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetKeyboardLayout (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN CONST EFI_GUID *KeyGuid,
+ IN OUT UINT16 *KeyboardLayoutLength,
+ OUT EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *Node;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *Link1;
+ UINTN Index;
+ UINT8 *Layout;
+ UINT16 LayoutCount;
+ UINT16 LayoutLength;
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
+
+ if ((This == NULL) || (KeyboardLayoutLength == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*KeyboardLayoutLength > 0) && (KeyboardLayout == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ //
+ // Retrieve the current keyboard layout.
+ //
+ if (KeyGuid == NULL) {
+ if (Private->CurrentLayout == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ CopyMem (&LayoutLength, Private->CurrentLayout, sizeof (UINT16));
+ if (*KeyboardLayoutLength < LayoutLength) {
+ *KeyboardLayoutLength = LayoutLength;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ CopyMem (KeyboardLayout, Private->CurrentLayout, LayoutLength);
+ return EFI_SUCCESS;
+ }
+
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList);
+ for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;
+ Link1 != &PackageList->KeyboardLayoutHdr;
+ Link1 = Link1->ForwardLink
+ )
+ {
+ Package = CR (
+ Link1,
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,
+ KeyboardEntry,
+ HII_KB_LAYOUT_PACKAGE_SIGNATURE
+ );
+
+ Layout = (UINT8 *)Package->KeyboardPkg +
+ sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);
+ CopyMem (&LayoutCount, Layout - sizeof (UINT16), sizeof (UINT16));
+ for (Index = 0; Index < LayoutCount; Index++) {
+ CopyMem (&LayoutLength, Layout, sizeof (UINT16));
+ if (CompareMem (Layout + sizeof (UINT16), KeyGuid, sizeof (EFI_GUID)) == 0) {
+ if (LayoutLength <= *KeyboardLayoutLength) {
+ CopyMem (KeyboardLayout, Layout, LayoutLength);
+ return EFI_SUCCESS;
+ } else {
+ *KeyboardLayoutLength = LayoutLength;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ }
+
+ Layout = Layout + LayoutLength;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ This routine sets the default keyboard layout to the one referenced by KeyGuid. When this routine
+ is called, an event will be signaled of the EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID
+ group type. This is so that agents which are sensitive to the current keyboard layout being changed
+ can be notified of this change.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param KeyGuid A pointer to the unique ID associated with a given
+ keyboard layout.
+
+ @retval EFI_SUCCESS The current keyboard layout was successfully set.
+ @retval EFI_NOT_FOUND The referenced keyboard layout was not found, so
+ action was taken.
+ @retval EFI_INVALID_PARAMETER The KeyGuid was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiSetKeyboardLayout (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN CONST EFI_GUID *KeyGuid
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
+ UINT16 KeyboardLayoutLength;
+ EFI_STATUS Status;
+
+ if ((This == NULL) || (KeyGuid == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // The specified GUID equals the current keyboard layout GUID,
+ // return directly.
+ //
+ if (CompareGuid (&Private->CurrentLayoutGuid, KeyGuid)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Try to find the incoming keyboard layout data in current database.
+ //
+ KeyboardLayoutLength = 0;
+ KeyboardLayout = NULL;
+ Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ return Status;
+ }
+
+ KeyboardLayout = (EFI_HII_KEYBOARD_LAYOUT *)AllocateZeroPool (KeyboardLayoutLength);
+ ASSERT (KeyboardLayout != NULL);
+ Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Backup current keyboard layout.
+ //
+ CopyMem (&Private->CurrentLayoutGuid, KeyGuid, sizeof (EFI_GUID));
+ if (Private->CurrentLayout != NULL) {
+ FreePool (Private->CurrentLayout);
+ }
+
+ Private->CurrentLayout = KeyboardLayout;
+
+ //
+ // Signal EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group to notify
+ // current keyboard layout is changed.
+ //
+ Status = gBS->SignalEvent (gHiiKeyboardLayoutChanged);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the EFI handle associated with a package list.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param PackageListHandle An EFI_HII_HANDLE that corresponds to the desired
+ package list in the HIIdatabase.
+ @param DriverHandle On return, contains the EFI_HANDLE which was
+ registered with the package list in
+ NewPackageList().
+
+ @retval EFI_SUCCESS The DriverHandle was returned successfully.
+ @retval EFI_INVALID_PARAMETER The PackageListHandle was not valid or
+ DriverHandle was NULL.
+ @retval EFI_NOT_FOUND This PackageList handle can not be found in
+ current database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetPackageListHandle (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageListHandle,
+ OUT EFI_HANDLE *DriverHandle
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *Node;
+ LIST_ENTRY *Link;
+
+ if ((This == NULL) || (DriverHandle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageListHandle)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (Node->Handle == PackageListHandle) {
+ *DriverHandle = Node->DriverHandle;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c
index 8a0b12f72f..fc1fee17db 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c
@@ -1,3018 +1,3018 @@
-/** @file
-Implementation for EFI_HII_FONT_PROTOCOL.
-
-
-Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "HiiDatabase.h"
-
-EFI_GRAPHICS_OUTPUT_BLT_PIXEL mHiiEfiColors[16] = {
- //
- // B G R
- //
- { 0x00, 0x00, 0x00, 0x00 }, // BLACK
- { 0x98, 0x00, 0x00, 0x00 }, // BLUE
- { 0x00, 0x98, 0x00, 0x00 }, // GREEN
- { 0x98, 0x98, 0x00, 0x00 }, // CYAN
- { 0x00, 0x00, 0x98, 0x00 }, // RED
- { 0x98, 0x00, 0x98, 0x00 }, // MAGENTA
- { 0x00, 0x98, 0x98, 0x00 }, // BROWN
- { 0x98, 0x98, 0x98, 0x00 }, // LIGHTGRAY
- { 0x30, 0x30, 0x30, 0x00 }, // DARKGRAY - BRIGHT BLACK
- { 0xff, 0x00, 0x00, 0x00 }, // LIGHTBLUE
- { 0x00, 0xff, 0x00, 0x00 }, // LIGHTGREEN
- { 0xff, 0xff, 0x00, 0x00 }, // LIGHTCYAN
- { 0x00, 0x00, 0xff, 0x00 }, // LIGHTRED
- { 0xff, 0x00, 0xff, 0x00 }, // LIGHTMAGENTA
- { 0x00, 0xff, 0xff, 0x00 }, // YELLOW
- { 0xff, 0xff, 0xff, 0x00 }, // WHITE
-};
-
-/**
- Insert a character cell information to the list specified by GlyphInfoList.
-
- This is a internal function.
-
- @param CharValue Unicode character value, which identifies a glyph
- block.
- @param GlyphInfoList HII_GLYPH_INFO list head.
- @param Cell Incoming character cell information.
-
- @retval EFI_SUCCESS Cell information is added to the GlyphInfoList.
- @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
- task.
-
-**/
-EFI_STATUS
-NewCell (
- IN CHAR16 CharValue,
- IN LIST_ENTRY *GlyphInfoList,
- IN EFI_HII_GLYPH_INFO *Cell
- )
-{
- HII_GLYPH_INFO *GlyphInfo;
-
- ASSERT (Cell != NULL && GlyphInfoList != NULL);
-
- GlyphInfo = (HII_GLYPH_INFO *)AllocateZeroPool (sizeof (HII_GLYPH_INFO));
- if (GlyphInfo == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // GlyphInfoList stores a list of default character cell information, each is
- // identified by "CharId".
- //
- GlyphInfo->Signature = HII_GLYPH_INFO_SIGNATURE;
- GlyphInfo->CharId = CharValue;
- if (Cell->AdvanceX == 0) {
- Cell->AdvanceX = Cell->Width;
- }
-
- CopyMem (&GlyphInfo->Cell, Cell, sizeof (EFI_HII_GLYPH_INFO));
- InsertTailList (GlyphInfoList, &GlyphInfo->Entry);
-
- return EFI_SUCCESS;
-}
-
-/**
- Get a character cell information from the list specified by GlyphInfoList.
-
- This is a internal function.
-
- @param CharValue Unicode character value, which identifies a glyph
- block.
- @param GlyphInfoList HII_GLYPH_INFO list head.
- @param Cell Buffer which stores output character cell
- information.
-
- @retval EFI_SUCCESS Cell information is added to the GlyphInfoList.
- @retval EFI_NOT_FOUND The character info specified by CharValue does
- not exist.
-
-**/
-EFI_STATUS
-GetCell (
- IN CHAR16 CharValue,
- IN LIST_ENTRY *GlyphInfoList,
- OUT EFI_HII_GLYPH_INFO *Cell
- )
-{
- HII_GLYPH_INFO *GlyphInfo;
- LIST_ENTRY *Link;
-
- ASSERT (Cell != NULL && GlyphInfoList != NULL);
-
- //
- // Since the EFI_HII_GIBT_DEFAULTS block won't increment CharValueCurrent,
- // the value of "CharId" of a default character cell which is used for a
- // EFI_HII_GIBT_GLYPH_DEFAULT or EFI_HII_GIBT_GLYPHS_DEFAULT should be
- // less or equal to the value of "CharValueCurrent" of this default block.
- //
- // For instance, if the CharId of a GlyphInfoList is {1, 3, 7}, a default glyph
- // with CharValue equals "7" uses the GlyphInfo with CharId = 7;
- // a default glyph with CharValue equals "6" uses the GlyphInfo with CharId = 3.
- //
- for (Link = GlyphInfoList->BackLink; Link != GlyphInfoList; Link = Link->BackLink) {
- GlyphInfo = CR (Link, HII_GLYPH_INFO, Entry, HII_GLYPH_INFO_SIGNATURE);
- if (GlyphInfo->CharId <= CharValue) {
- CopyMem (Cell, &GlyphInfo->Cell, sizeof (EFI_HII_GLYPH_INFO));
- return EFI_SUCCESS;
- }
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- Convert the glyph for a single character into a bitmap.
-
- This is a internal function.
-
- @param Private HII database driver private data.
- @param Char Character to retrieve.
- @param StringInfo Points to the string font and color information
- or NULL if the string should use the default
- system font and color.
- @param GlyphBuffer Buffer to store the retrieved bitmap data.
- @param Cell Points to EFI_HII_GLYPH_INFO structure.
- @param Attributes If not NULL, output the glyph attributes if any.
-
- @retval EFI_SUCCESS Glyph bitmap outputted.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate the output buffer GlyphBuffer.
- @retval EFI_NOT_FOUND The glyph was unknown can not be found.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
-
-**/
-EFI_STATUS
-GetGlyphBuffer (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN CHAR16 Char,
- IN EFI_FONT_INFO *StringInfo,
- OUT UINT8 **GlyphBuffer,
- OUT EFI_HII_GLYPH_INFO *Cell,
- OUT UINT8 *Attributes OPTIONAL
- )
-{
- HII_DATABASE_RECORD *Node;
- LIST_ENTRY *Link;
- HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFont;
- LIST_ENTRY *Link1;
- UINT16 Index;
- EFI_NARROW_GLYPH Narrow;
- EFI_WIDE_GLYPH Wide;
- HII_GLOBAL_FONT_INFO *GlobalFont;
- UINTN HeaderSize;
- EFI_NARROW_GLYPH *NarrowPtr;
- EFI_WIDE_GLYPH *WidePtr;
-
- if ((GlyphBuffer == NULL) || (Cell == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((Private == NULL) || (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE)) {
- return EFI_INVALID_PARAMETER;
- }
-
- ZeroMem (Cell, sizeof (EFI_HII_GLYPH_INFO));
-
- //
- // If StringInfo is not NULL, it must point to an existing EFI_FONT_INFO rather
- // than system default font and color.
- // If NULL, try to find the character in simplified font packages since
- // default system font is the fixed font (narrow or wide glyph).
- //
- if (StringInfo != NULL) {
- if (!IsFontInfoExisted (Private, StringInfo, NULL, NULL, &GlobalFont)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Attributes != NULL) {
- *Attributes = PROPORTIONAL_GLYPH;
- }
-
- return FindGlyphBlock (GlobalFont->FontPackage, Char, GlyphBuffer, Cell, NULL);
- } else {
- HeaderSize = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR);
-
- for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
- Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- for (Link1 = Node->PackageList->SimpleFontPkgHdr.ForwardLink;
- Link1 != &Node->PackageList->SimpleFontPkgHdr;
- Link1 = Link1->ForwardLink
- )
- {
- SimpleFont = CR (Link1, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE);
- //
- // Search the narrow glyph array
- //
- NarrowPtr = (EFI_NARROW_GLYPH *)((UINT8 *)(SimpleFont->SimpleFontPkgHdr) + HeaderSize);
- for (Index = 0; Index < SimpleFont->SimpleFontPkgHdr->NumberOfNarrowGlyphs; Index++) {
- CopyMem (&Narrow, NarrowPtr + Index, sizeof (EFI_NARROW_GLYPH));
- if (Narrow.UnicodeWeight == Char) {
- *GlyphBuffer = (UINT8 *)AllocateZeroPool (EFI_GLYPH_HEIGHT);
- if (*GlyphBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Cell->Width = EFI_GLYPH_WIDTH;
- Cell->Height = EFI_GLYPH_HEIGHT;
- Cell->AdvanceX = Cell->Width;
- CopyMem (*GlyphBuffer, Narrow.GlyphCol1, Cell->Height);
- if (Attributes != NULL) {
- *Attributes = (UINT8)(Narrow.Attributes | NARROW_GLYPH);
- }
-
- return EFI_SUCCESS;
- }
- }
-
- //
- // Search the wide glyph array
- //
- WidePtr = (EFI_WIDE_GLYPH *)(NarrowPtr + SimpleFont->SimpleFontPkgHdr->NumberOfNarrowGlyphs);
- for (Index = 0; Index < SimpleFont->SimpleFontPkgHdr->NumberOfWideGlyphs; Index++) {
- CopyMem (&Wide, WidePtr + Index, sizeof (EFI_WIDE_GLYPH));
- if (Wide.UnicodeWeight == Char) {
- *GlyphBuffer = (UINT8 *)AllocateZeroPool (EFI_GLYPH_HEIGHT * 2);
- if (*GlyphBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Cell->Width = EFI_GLYPH_WIDTH * 2;
- Cell->Height = EFI_GLYPH_HEIGHT;
- Cell->AdvanceX = Cell->Width;
- CopyMem (*GlyphBuffer, Wide.GlyphCol1, EFI_GLYPH_HEIGHT);
- CopyMem (*GlyphBuffer + EFI_GLYPH_HEIGHT, Wide.GlyphCol2, EFI_GLYPH_HEIGHT);
- if (Attributes != NULL) {
- *Attributes = (UINT8)(Wide.Attributes | EFI_GLYPH_WIDE);
- }
-
- return EFI_SUCCESS;
- }
- }
- }
- }
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- Convert bitmap data of the glyph to blt structure.
-
- This is a internal function.
-
- @param GlyphBuffer Buffer points to bitmap data of glyph.
- @param Foreground The color of the "on" pixels in the glyph in the
- bitmap.
- @param Background The color of the "off" pixels in the glyph in the
- bitmap.
- @param ImageWidth Width of the whole image in pixels.
- @param RowWidth The width of the text on the line, in pixels.
- @param RowHeight The height of the line, in pixels.
- @param Transparent If TRUE, the Background color is ignored and all
- "off" pixels in the character's drawn will use the
- pixel value from BltBuffer.
- @param Origin On input, points to the origin of the to be
- displayed character, on output, points to the
- next glyph's origin.
-
-**/
-VOID
-NarrowGlyphToBlt (
- IN UINT8 *GlyphBuffer,
- IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
- IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
- IN UINT16 ImageWidth,
- IN UINTN RowWidth,
- IN UINTN RowHeight,
- IN BOOLEAN Transparent,
- IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
- )
-{
- UINT8 Xpos;
- UINT8 Ypos;
- UINT8 Height;
- UINT8 Width;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Buffer;
-
- ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL);
-
- Height = EFI_GLYPH_HEIGHT;
- Width = EFI_GLYPH_WIDTH;
-
- //
- // Move position to the left-top corner of char.
- //
- Buffer = *Origin - EFI_GLYPH_HEIGHT * ImageWidth;
-
- //
- // Char may be partially displayed when CLIP_X or CLIP_Y is not set.
- //
- if (RowHeight < Height) {
- Height = (UINT8)RowHeight;
- }
-
- if (RowWidth < Width) {
- Width = (UINT8)RowWidth;
- }
-
- for (Ypos = 0; Ypos < Height; Ypos++) {
- for (Xpos = 0; Xpos < Width; Xpos++) {
- if ((GlyphBuffer[Ypos] & (1 << (EFI_GLYPH_WIDTH - Xpos - 1))) != 0) {
- Buffer[Ypos * ImageWidth + Xpos] = Foreground;
- } else {
- if (!Transparent) {
- Buffer[Ypos * ImageWidth + Xpos] = Background;
- }
- }
- }
- }
-
- *Origin = *Origin + EFI_GLYPH_WIDTH;
-}
-
-/**
- Convert bitmap data of the glyph to blt structure.
-
- This is a internal function.
-
- @param GlyphBuffer Buffer points to bitmap data of glyph.
- @param Foreground The color of the "on" pixels in the glyph in the
- bitmap.
- @param Background The color of the "off" pixels in the glyph in the
- bitmap.
- @param ImageWidth Width of the whole image in pixels.
- @param BaseLine BaseLine in the line.
- @param RowWidth The width of the text on the line, in pixels.
- @param RowHeight The height of the line, in pixels.
- @param Transparent If TRUE, the Background color is ignored and all
- "off" pixels in the character's drawn will use the
- pixel value from BltBuffer.
- @param Cell Points to EFI_HII_GLYPH_INFO structure.
- @param Attributes The attribute of incoming glyph in GlyphBuffer.
- @param Origin On input, points to the origin of the to be
- displayed character, on output, points to the
- next glyph's origin.
-
-
-**/
-VOID
-GlyphToBlt (
- IN UINT8 *GlyphBuffer,
- IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
- IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
- IN UINT16 ImageWidth,
- IN UINT16 BaseLine,
- IN UINTN RowWidth,
- IN UINTN RowHeight,
- IN BOOLEAN Transparent,
- IN CONST EFI_HII_GLYPH_INFO *Cell,
- IN UINT8 Attributes,
- IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
- )
-{
- UINT16 Xpos;
- UINT16 Ypos;
- UINT8 Data;
- UINT16 Index;
- UINT16 YposOffset;
- UINTN OffsetY;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
-
- ASSERT (Origin != NULL && *Origin != NULL && Cell != NULL);
-
- //
- // Only adjust origin position if char has no bitmap.
- //
- if (GlyphBuffer == NULL) {
- *Origin = *Origin + Cell->AdvanceX;
- return;
- }
-
- //
- // Move position to the left-top corner of char.
- //
- BltBuffer = *Origin + Cell->OffsetX - (Cell->OffsetY + Cell->Height) * ImageWidth;
- YposOffset = (UINT16)(BaseLine - (Cell->OffsetY + Cell->Height));
-
- //
- // Since non-spacing key will be printed OR'd with the previous glyph, don't
- // write 0.
- //
- if ((Attributes & EFI_GLYPH_NON_SPACING) == EFI_GLYPH_NON_SPACING) {
- Transparent = TRUE;
- }
-
- //
- // The glyph's upper left hand corner pixel is the most significant bit of the
- // first bitmap byte.
- //
- for (Ypos = 0; Ypos < Cell->Height && (((UINT32)Ypos + YposOffset) < RowHeight); Ypos++) {
- OffsetY = BITMAP_LEN_1_BIT (Cell->Width, Ypos);
-
- //
- // All bits in these bytes are meaningful.
- //
- for (Xpos = 0; Xpos < Cell->Width / 8; Xpos++) {
- Data = *(GlyphBuffer + OffsetY + Xpos);
- for (Index = 0; Index < 8 && (((UINT32)Xpos * 8 + Index + Cell->OffsetX) < RowWidth); Index++) {
- if ((Data & (1 << (8 - Index - 1))) != 0) {
- BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Foreground;
- } else {
- if (!Transparent) {
- BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Background;
- }
- }
- }
- }
-
- if (Cell->Width % 8 != 0) {
- //
- // There are some padding bits in this byte. Ignore them.
- //
- Data = *(GlyphBuffer + OffsetY + Xpos);
- for (Index = 0; Index < Cell->Width % 8 && (((UINT32)Xpos * 8 + Index + Cell->OffsetX) < RowWidth); Index++) {
- if ((Data & (1 << (8 - Index - 1))) != 0) {
- BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Foreground;
- } else {
- if (!Transparent) {
- BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Background;
- }
- }
- }
- } // end of if (Width % 8...)
- } // end of for (Ypos=0...)
-
- *Origin = *Origin + Cell->AdvanceX;
-}
-
-/**
- Convert bitmap data of the glyph to blt structure.
-
- This is a internal function.
-
- @param GlyphBuffer Buffer points to bitmap data of glyph.
- @param Foreground The color of the "on" pixels in the glyph in the
- bitmap.
- @param Background The color of the "off" pixels in the glyph in the
- bitmap.
- @param ImageWidth Width of the whole image in pixels.
- @param BaseLine BaseLine in the line.
- @param RowWidth The width of the text on the line, in pixels.
- @param RowHeight The height of the line, in pixels.
- @param Transparent If TRUE, the Background color is ignored and all
- "off" pixels in the character's drawn will use the
- pixel value from BltBuffer.
- @param Cell Points to EFI_HII_GLYPH_INFO structure.
- @param Attributes The attribute of incoming glyph in GlyphBuffer.
- @param Origin On input, points to the origin of the to be
- displayed character, on output, points to the
- next glyph's origin.
-
- @return Points to the address of next origin node in BltBuffer.
-
-**/
-VOID
-GlyphToImage (
- IN UINT8 *GlyphBuffer,
- IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
- IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
- IN UINT16 ImageWidth,
- IN UINT16 BaseLine,
- IN UINTN RowWidth,
- IN UINTN RowHeight,
- IN BOOLEAN Transparent,
- IN CONST EFI_HII_GLYPH_INFO *Cell,
- IN UINT8 Attributes,
- IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
- )
-{
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Buffer;
-
- ASSERT (Origin != NULL && *Origin != NULL && Cell != NULL);
-
- Buffer = *Origin;
-
- if ((Attributes & EFI_GLYPH_NON_SPACING) == EFI_GLYPH_NON_SPACING) {
- //
- // This character is a non-spacing key, print it OR'd with the previous glyph.
- // without advancing cursor.
- //
- Buffer -= Cell->AdvanceX;
- GlyphToBlt (
- GlyphBuffer,
- Foreground,
- Background,
- ImageWidth,
- BaseLine,
- RowWidth,
- RowHeight,
- Transparent,
- Cell,
- Attributes,
- &Buffer
- );
- } else if ((Attributes & EFI_GLYPH_WIDE) == EFI_GLYPH_WIDE) {
- //
- // This character is wide glyph, i.e. 16 pixels * 19 pixels.
- // Draw it as two narrow glyphs.
- //
- NarrowGlyphToBlt (
- GlyphBuffer,
- Foreground,
- Background,
- ImageWidth,
- RowWidth,
- RowHeight,
- Transparent,
- Origin
- );
-
- NarrowGlyphToBlt (
- GlyphBuffer + EFI_GLYPH_HEIGHT,
- Foreground,
- Background,
- ImageWidth,
- RowWidth,
- RowHeight,
- Transparent,
- Origin
- );
- } else if ((Attributes & NARROW_GLYPH) == NARROW_GLYPH) {
- //
- // This character is narrow glyph, i.e. 8 pixels * 19 pixels.
- //
- NarrowGlyphToBlt (
- GlyphBuffer,
- Foreground,
- Background,
- ImageWidth,
- RowWidth,
- RowHeight,
- Transparent,
- Origin
- );
- } else if ((Attributes & PROPORTIONAL_GLYPH) == PROPORTIONAL_GLYPH) {
- //
- // This character is proportional glyph, i.e. Cell->Width * Cell->Height pixels.
- //
- GlyphToBlt (
- GlyphBuffer,
- Foreground,
- Background,
- ImageWidth,
- BaseLine,
- RowWidth,
- RowHeight,
- Transparent,
- Cell,
- Attributes,
- Origin
- );
- }
-}
-
-/**
- Write the output parameters of FindGlyphBlock().
-
- This is a internal function.
-
- @param BufferIn Buffer which stores the bitmap data of the found
- block.
- @param BufferLen Length of BufferIn.
- @param InputCell Buffer which stores cell information of the
- encoded bitmap.
- @param GlyphBuffer Output the corresponding bitmap data of the found
- block. It is the caller's responsibility to free
- this buffer.
- @param Cell Output cell information of the encoded bitmap.
- @param GlyphBufferLen If not NULL, output the length of GlyphBuffer.
-
- @retval EFI_SUCCESS The operation is performed successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
- @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
- task.
-
-**/
-EFI_STATUS
-WriteOutputParam (
- IN UINT8 *BufferIn,
- IN UINTN BufferLen,
- IN EFI_HII_GLYPH_INFO *InputCell,
- OUT UINT8 **GlyphBuffer OPTIONAL,
- OUT EFI_HII_GLYPH_INFO *Cell OPTIONAL,
- OUT UINTN *GlyphBufferLen OPTIONAL
- )
-{
- if ((BufferIn == NULL) || (InputCell == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Cell != NULL) {
- CopyMem (Cell, InputCell, sizeof (EFI_HII_GLYPH_INFO));
- }
-
- if ((GlyphBuffer != NULL) && (BufferLen > 0)) {
- *GlyphBuffer = (UINT8 *)AllocateZeroPool (BufferLen);
- if (*GlyphBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- CopyMem (*GlyphBuffer, BufferIn, BufferLen);
- }
-
- if (GlyphBufferLen != NULL) {
- *GlyphBufferLen = BufferLen;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Parse all glyph blocks to find a glyph block specified by CharValue.
- If CharValue = (CHAR16) (-1), collect all default character cell information
- within this font package and backup its information.
-
- @param FontPackage Hii string package instance.
- @param CharValue Unicode character value, which identifies a glyph
- block.
- @param GlyphBuffer Output the corresponding bitmap data of the found
- block. It is the caller's responsibility to free
- this buffer.
- @param Cell Output cell information of the encoded bitmap.
- @param GlyphBufferLen If not NULL, output the length of GlyphBuffer.
-
- @retval EFI_SUCCESS The bitmap data is retrieved successfully.
- @retval EFI_NOT_FOUND The specified CharValue does not exist in current
- database.
- @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
- task.
-
-**/
-EFI_STATUS
-FindGlyphBlock (
- IN HII_FONT_PACKAGE_INSTANCE *FontPackage,
- IN CHAR16 CharValue,
- OUT UINT8 **GlyphBuffer OPTIONAL,
- OUT EFI_HII_GLYPH_INFO *Cell OPTIONAL,
- OUT UINTN *GlyphBufferLen OPTIONAL
- )
-{
- EFI_STATUS Status;
- UINT8 *BlockPtr;
- UINT16 CharCurrent;
- UINT16 Length16;
- UINT32 Length32;
- EFI_HII_GIBT_GLYPHS_BLOCK Glyphs;
- UINTN BufferLen;
- UINT16 Index;
- EFI_HII_GLYPH_INFO DefaultCell;
- EFI_HII_GLYPH_INFO LocalCell;
- INT16 MinOffsetY;
- UINT16 BaseLine;
-
- ASSERT (FontPackage != NULL);
- ASSERT (FontPackage->Signature == HII_FONT_PACKAGE_SIGNATURE);
- BaseLine = 0;
- MinOffsetY = 0;
-
- if (CharValue == (CHAR16)(-1)) {
- //
- // Collect the cell information specified in font package fixed header.
- // Use CharValue =0 to represent this particular cell.
- //
- Status = NewCell (
- 0,
- &FontPackage->GlyphInfoList,
- (EFI_HII_GLYPH_INFO *)((UINT8 *)FontPackage->FontPkgHdr + 3 * sizeof (UINT32))
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- CopyMem (
- &LocalCell,
- (UINT8 *)FontPackage->FontPkgHdr + 3 * sizeof (UINT32),
- sizeof (EFI_HII_GLYPH_INFO)
- );
- }
-
- BlockPtr = FontPackage->GlyphBlock;
- CharCurrent = 1;
- BufferLen = 0;
-
- while (*BlockPtr != EFI_HII_GIBT_END) {
- switch (*BlockPtr) {
- case EFI_HII_GIBT_DEFAULTS:
- //
- // Collect all default character cell information specified by
- // EFI_HII_GIBT_DEFAULTS.
- //
- if (CharValue == (CHAR16)(-1)) {
- Status = NewCell (
- CharCurrent,
- &FontPackage->GlyphInfoList,
- (EFI_HII_GLYPH_INFO *)(BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK))
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- CopyMem (
- &LocalCell,
- BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),
- sizeof (EFI_HII_GLYPH_INFO)
- );
- if (BaseLine < LocalCell.Height + LocalCell.OffsetY) {
- BaseLine = (UINT16)(LocalCell.Height + LocalCell.OffsetY);
- }
-
- if (MinOffsetY > LocalCell.OffsetY) {
- MinOffsetY = LocalCell.OffsetY;
- }
- }
-
- BlockPtr += sizeof (EFI_HII_GIBT_DEFAULTS_BLOCK);
- break;
-
- case EFI_HII_GIBT_DUPLICATE:
- if (CharCurrent == CharValue) {
- CopyMem (&CharValue, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (CHAR16));
- CharCurrent = 1;
- BlockPtr = FontPackage->GlyphBlock;
- continue;
- }
-
- CharCurrent++;
- BlockPtr += sizeof (EFI_HII_GIBT_DUPLICATE_BLOCK);
- break;
-
- case EFI_HII_GIBT_EXT1:
- BlockPtr += *(UINT8 *)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8));
- break;
- case EFI_HII_GIBT_EXT2:
- CopyMem (
- &Length16,
- (UINT8 *)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8)),
- sizeof (UINT16)
- );
- BlockPtr += Length16;
- break;
- case EFI_HII_GIBT_EXT4:
- CopyMem (
- &Length32,
- (UINT8 *)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8)),
- sizeof (UINT32)
- );
- BlockPtr += Length32;
- break;
-
- case EFI_HII_GIBT_GLYPH:
- CopyMem (
- &LocalCell,
- BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),
- sizeof (EFI_HII_GLYPH_INFO)
- );
- if (CharValue == (CHAR16)(-1)) {
- if (BaseLine < LocalCell.Height + LocalCell.OffsetY) {
- BaseLine = (UINT16)(LocalCell.Height + LocalCell.OffsetY);
- }
-
- if (MinOffsetY > LocalCell.OffsetY) {
- MinOffsetY = LocalCell.OffsetY;
- }
- }
-
- BufferLen = BITMAP_LEN_1_BIT (LocalCell.Width, LocalCell.Height);
- if (CharCurrent == CharValue) {
- return WriteOutputParam (
- (UINT8 *)((UINTN)BlockPtr + sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8)),
- BufferLen,
- &LocalCell,
- GlyphBuffer,
- Cell,
- GlyphBufferLen
- );
- }
-
- CharCurrent++;
- BlockPtr += sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8) + BufferLen;
- break;
-
- case EFI_HII_GIBT_GLYPHS:
- BlockPtr += sizeof (EFI_HII_GLYPH_BLOCK);
- CopyMem (&Glyphs.Cell, BlockPtr, sizeof (EFI_HII_GLYPH_INFO));
- BlockPtr += sizeof (EFI_HII_GLYPH_INFO);
- CopyMem (&Glyphs.Count, BlockPtr, sizeof (UINT16));
- BlockPtr += sizeof (UINT16);
-
- if (CharValue == (CHAR16)(-1)) {
- if (BaseLine < Glyphs.Cell.Height + Glyphs.Cell.OffsetY) {
- BaseLine = (UINT16)(Glyphs.Cell.Height + Glyphs.Cell.OffsetY);
- }
-
- if (MinOffsetY > Glyphs.Cell.OffsetY) {
- MinOffsetY = Glyphs.Cell.OffsetY;
- }
- }
-
- BufferLen = BITMAP_LEN_1_BIT (Glyphs.Cell.Width, Glyphs.Cell.Height);
- for (Index = 0; Index < Glyphs.Count; Index++) {
- if (CharCurrent + Index == CharValue) {
- return WriteOutputParam (
- BlockPtr,
- BufferLen,
- &Glyphs.Cell,
- GlyphBuffer,
- Cell,
- GlyphBufferLen
- );
- }
-
- BlockPtr += BufferLen;
- }
-
- CharCurrent = (UINT16)(CharCurrent + Glyphs.Count);
- break;
-
- case EFI_HII_GIBT_GLYPH_DEFAULT:
- Status = GetCell (CharCurrent, &FontPackage->GlyphInfoList, &DefaultCell);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (CharValue == (CHAR16)(-1)) {
- if (BaseLine < DefaultCell.Height + DefaultCell.OffsetY) {
- BaseLine = (UINT16)(DefaultCell.Height + DefaultCell.OffsetY);
- }
-
- if (MinOffsetY > DefaultCell.OffsetY) {
- MinOffsetY = DefaultCell.OffsetY;
- }
- }
-
- BufferLen = BITMAP_LEN_1_BIT (DefaultCell.Width, DefaultCell.Height);
-
- if (CharCurrent == CharValue) {
- return WriteOutputParam (
- BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),
- BufferLen,
- &DefaultCell,
- GlyphBuffer,
- Cell,
- GlyphBufferLen
- );
- }
-
- CharCurrent++;
- BlockPtr += sizeof (EFI_HII_GLYPH_BLOCK) + BufferLen;
- break;
-
- case EFI_HII_GIBT_GLYPHS_DEFAULT:
- CopyMem (&Length16, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (UINT16));
- Status = GetCell (CharCurrent, &FontPackage->GlyphInfoList, &DefaultCell);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (CharValue == (CHAR16)(-1)) {
- if (BaseLine < DefaultCell.Height + DefaultCell.OffsetY) {
- BaseLine = (UINT16)(DefaultCell.Height + DefaultCell.OffsetY);
- }
-
- if (MinOffsetY > DefaultCell.OffsetY) {
- MinOffsetY = DefaultCell.OffsetY;
- }
- }
-
- BufferLen = BITMAP_LEN_1_BIT (DefaultCell.Width, DefaultCell.Height);
- BlockPtr += sizeof (EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK) - sizeof (UINT8);
- for (Index = 0; Index < Length16; Index++) {
- if (CharCurrent + Index == CharValue) {
- return WriteOutputParam (
- BlockPtr,
- BufferLen,
- &DefaultCell,
- GlyphBuffer,
- Cell,
- GlyphBufferLen
- );
- }
-
- BlockPtr += BufferLen;
- }
-
- CharCurrent = (UINT16)(CharCurrent + Length16);
- break;
-
- case EFI_HII_GIBT_SKIP1:
- CharCurrent = (UINT16)(CharCurrent + (UINT16)(*(BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK))));
- BlockPtr += sizeof (EFI_HII_GIBT_SKIP1_BLOCK);
- break;
- case EFI_HII_GIBT_SKIP2:
- CopyMem (&Length16, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (UINT16));
- CharCurrent = (UINT16)(CharCurrent + Length16);
- BlockPtr += sizeof (EFI_HII_GIBT_SKIP2_BLOCK);
- break;
- default:
- ASSERT (FALSE);
- break;
- }
-
- if (CharValue < CharCurrent) {
- return EFI_NOT_FOUND;
- }
- }
-
- if (CharValue == (CHAR16)(-1)) {
- FontPackage->BaseLine = BaseLine;
- FontPackage->Height = (UINT16)(BaseLine - MinOffsetY);
- return EFI_SUCCESS;
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- Copy a Font Name to a new created EFI_FONT_INFO structure.
-
- This is a internal function.
-
- @param FontName NULL-terminated string.
- @param FontInfo a new EFI_FONT_INFO which stores the FontName.
- It's caller's responsibility to free this buffer.
-
- @retval EFI_SUCCESS FontInfo is allocated and copied with FontName.
- @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
- task.
-
-**/
-EFI_STATUS
-SaveFontName (
- IN EFI_STRING FontName,
- OUT EFI_FONT_INFO **FontInfo
- )
-{
- UINTN FontInfoLen;
- UINTN NameSize;
-
- ASSERT (FontName != NULL && FontInfo != NULL);
-
- NameSize = StrSize (FontName);
- FontInfoLen = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + NameSize;
- *FontInfo = (EFI_FONT_INFO *)AllocateZeroPool (FontInfoLen);
- if (*FontInfo == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- StrCpyS ((*FontInfo)->FontName, NameSize / sizeof (CHAR16), FontName);
- return EFI_SUCCESS;
-}
-
-/**
- Retrieve system default font and color.
-
- @param Private HII database driver private data.
- @param FontInfo Points to system default font output-related
- information. It's caller's responsibility to free
- this buffer.
- @param FontInfoSize If not NULL, output the size of buffer FontInfo.
-
- @retval EFI_SUCCESS Cell information is added to the GlyphInfoList.
- @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
- task.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
-
-**/
-EFI_STATUS
-GetSystemFont (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- OUT EFI_FONT_DISPLAY_INFO **FontInfo,
- OUT UINTN *FontInfoSize OPTIONAL
- )
-{
- EFI_FONT_DISPLAY_INFO *Info;
- UINTN InfoSize;
- UINTN NameSize;
-
- if ((Private == NULL) || (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (FontInfo == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // The standard font always has the name "sysdefault".
- //
- NameSize = StrSize (L"sysdefault");
- InfoSize = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + NameSize;
- Info = (EFI_FONT_DISPLAY_INFO *)AllocateZeroPool (InfoSize);
- if (Info == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Info->ForegroundColor = mHiiEfiColors[Private->Attribute & 0x0f];
- ASSERT ((Private->Attribute >> 4) < 8);
- Info->BackgroundColor = mHiiEfiColors[Private->Attribute >> 4];
- Info->FontInfoMask = EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_SYS_STYLE;
- Info->FontInfo.FontStyle = 0;
- Info->FontInfo.FontSize = EFI_GLYPH_HEIGHT;
- StrCpyS (Info->FontInfo.FontName, NameSize / sizeof (CHAR16), L"sysdefault");
-
- *FontInfo = Info;
- if (FontInfoSize != NULL) {
- *FontInfoSize = InfoSize;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Check whether EFI_FONT_DISPLAY_INFO points to system default font and color or
- returns the system default according to the optional inputs.
-
- This is a internal function.
-
- @param Private HII database driver private data.
- @param StringInfo Points to the string output information,
- including the color and font.
- @param SystemInfo If not NULL, points to system default font and color.
-
- @param SystemInfoLen If not NULL, output the length of default system
- info.
-
- @retval TRUE Yes, it points to system default.
- @retval FALSE No.
-
-**/
-BOOLEAN
-IsSystemFontInfo (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_FONT_DISPLAY_INFO *StringInfo,
- OUT EFI_FONT_DISPLAY_INFO **SystemInfo OPTIONAL,
- OUT UINTN *SystemInfoLen OPTIONAL
- )
-{
- EFI_STATUS Status;
- EFI_FONT_DISPLAY_INFO *SystemDefault;
- UINTN DefaultLen;
- BOOLEAN Flag;
-
- ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
-
- if ((StringInfo == NULL) && (SystemInfo == NULL)) {
- return TRUE;
- }
-
- SystemDefault = NULL;
- DefaultLen = 0;
-
- Status = GetSystemFont (Private, &SystemDefault, &DefaultLen);
- ASSERT_EFI_ERROR (Status);
- ASSERT ((SystemDefault != NULL) && (DefaultLen != 0));
-
- //
- // Record the system default info.
- //
- if (SystemInfo != NULL) {
- *SystemInfo = SystemDefault;
- }
-
- if (SystemInfoLen != NULL) {
- *SystemInfoLen = DefaultLen;
- }
-
- if (StringInfo == NULL) {
- return TRUE;
- }
-
- Flag = FALSE;
- //
- // Check the FontInfoMask to see whether it is retrieving system info.
- //
- if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) == 0) {
- if (StrCmp (StringInfo->FontInfo.FontName, SystemDefault->FontInfo.FontName) != 0) {
- goto Exit;
- }
- }
-
- if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) == 0) {
- if (StringInfo->FontInfo.FontSize != SystemDefault->FontInfo.FontSize) {
- goto Exit;
- }
- }
-
- if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) == 0) {
- if (StringInfo->FontInfo.FontStyle != SystemDefault->FontInfo.FontStyle) {
- goto Exit;
- }
- }
-
- if ((StringInfo->FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) == 0) {
- if (CompareMem (
- &StringInfo->ForegroundColor,
- &SystemDefault->ForegroundColor,
- sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
- ) != 0)
- {
- goto Exit;
- }
- }
-
- if ((StringInfo->FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) == 0) {
- if (CompareMem (
- &StringInfo->BackgroundColor,
- &SystemDefault->BackgroundColor,
- sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
- ) != 0)
- {
- goto Exit;
- }
- }
-
- Flag = TRUE;
-
-Exit:
- if (SystemInfo == NULL) {
- if (SystemDefault != NULL) {
- FreePool (SystemDefault);
- }
- }
-
- return Flag;
-}
-
-/**
- This function checks whether EFI_FONT_INFO exists in current database. If
- FontInfoMask is specified, check what options can be used to make a match.
- Note that the masks relate to where the system default should be supplied
- are ignored by this function.
-
- @param Private Hii database private structure.
- @param FontInfo Points to EFI_FONT_INFO structure.
- @param FontInfoMask If not NULL, describes what options can be used
- to make a match between the font requested and
- the font available. The caller must guarantee
- this mask is valid.
- @param FontHandle On entry, Points to the font handle returned by a
- previous call to GetFontInfo() or NULL to start
- with the first font.
- @param GlobalFontInfo If not NULL, output the corresponding global font
- info.
-
- @retval TRUE Existed
- @retval FALSE Not existed
-
-**/
-BOOLEAN
-IsFontInfoExisted (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_FONT_INFO *FontInfo,
- IN EFI_FONT_INFO_MASK *FontInfoMask OPTIONAL,
- IN EFI_FONT_HANDLE FontHandle OPTIONAL,
- OUT HII_GLOBAL_FONT_INFO **GlobalFontInfo OPTIONAL
- )
-{
- HII_GLOBAL_FONT_INFO *GlobalFont;
- HII_GLOBAL_FONT_INFO *GlobalFontBackup1;
- HII_GLOBAL_FONT_INFO *GlobalFontBackup2;
- LIST_ENTRY *Link;
- EFI_FONT_INFO_MASK Mask;
- BOOLEAN Matched;
- BOOLEAN VagueMatched1;
- BOOLEAN VagueMatched2;
-
- ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
- ASSERT (FontInfo != NULL);
-
- //
- // Matched flag represents an exactly match; VagueMatched1 represents a RESIZE
- // or RESTYLE match; VagueMatched2 represents a RESIZE | RESTYLE match.
- //
- Matched = FALSE;
- VagueMatched1 = FALSE;
- VagueMatched2 = FALSE;
-
- Mask = 0;
- GlobalFontBackup1 = NULL;
- GlobalFontBackup2 = NULL;
-
- // The process of where the system default should be supplied instead of
- // the specified font info beyonds this function's scope.
- //
- if (FontInfoMask != NULL) {
- Mask = *FontInfoMask & (~SYS_FONT_INFO_MASK);
- }
-
- //
- // If not NULL, FontHandle points to the next node of the last searched font
- // node by previous call.
- //
- if (FontHandle == NULL) {
- Link = Private->FontInfoList.ForwardLink;
- } else {
- Link = (LIST_ENTRY *)FontHandle;
- }
-
- for ( ; Link != &Private->FontInfoList; Link = Link->ForwardLink) {
- GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);
- if (FontInfoMask == NULL) {
- if (CompareMem (GlobalFont->FontInfo, FontInfo, GlobalFont->FontInfoSize) == 0) {
- if (GlobalFontInfo != NULL) {
- *GlobalFontInfo = GlobalFont;
- }
-
- return TRUE;
- }
- } else {
- //
- // Check which options could be used to make a match.
- //
- switch (Mask) {
- case EFI_FONT_INFO_ANY_FONT:
- if ((GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) &&
- (GlobalFont->FontInfo->FontSize == FontInfo->FontSize))
- {
- Matched = TRUE;
- }
-
- break;
- case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE:
- if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
- Matched = TRUE;
- }
-
- break;
- case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE:
- if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
- Matched = TRUE;
- }
-
- break;
- case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_ANY_STYLE:
- Matched = TRUE;
- break;
- //
- // If EFI_FONT_INFO_RESTYLE is specified, then the system may attempt to
- // remove some of the specified styles to meet the style requested.
- //
- case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE:
- if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
- if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
- Matched = TRUE;
- } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
- VagueMatched1 = TRUE;
- GlobalFontBackup1 = GlobalFont;
- }
- }
-
- break;
- //
- // If EFI_FONT_INFO_RESIZE is specified, then the system may attempt to
- // stretch or shrink a font to meet the size requested.
- //
- case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESIZE:
- if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
- if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
- Matched = TRUE;
- } else {
- VagueMatched1 = TRUE;
- GlobalFontBackup1 = GlobalFont;
- }
- }
-
- break;
- case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_RESIZE:
- if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
- if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
- Matched = TRUE;
- } else {
- VagueMatched1 = TRUE;
- GlobalFontBackup1 = GlobalFont;
- }
- } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
- if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
- VagueMatched1 = TRUE;
- GlobalFontBackup1 = GlobalFont;
- } else {
- VagueMatched2 = TRUE;
- GlobalFontBackup2 = GlobalFont;
- }
- }
-
- break;
- case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE:
- if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
- Matched = TRUE;
- } else {
- VagueMatched1 = TRUE;
- GlobalFontBackup1 = GlobalFont;
- }
-
- break;
- case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE:
- if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
- Matched = TRUE;
- } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
- VagueMatched1 = TRUE;
- GlobalFontBackup1 = GlobalFont;
- }
-
- break;
- case EFI_FONT_INFO_ANY_STYLE:
- if ((CompareMem (
- GlobalFont->FontInfo->FontName,
- FontInfo->FontName,
- StrSize (FontInfo->FontName)
- ) == 0) &&
- (GlobalFont->FontInfo->FontSize == FontInfo->FontSize))
- {
- Matched = TRUE;
- }
-
- break;
- case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_ANY_SIZE:
- if (CompareMem (
- GlobalFont->FontInfo->FontName,
- FontInfo->FontName,
- StrSize (FontInfo->FontName)
- ) == 0)
- {
- Matched = TRUE;
- }
-
- break;
- case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE:
- if (CompareMem (
- GlobalFont->FontInfo->FontName,
- FontInfo->FontName,
- StrSize (FontInfo->FontName)
- ) == 0)
- {
- if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
- Matched = TRUE;
- } else {
- VagueMatched1 = TRUE;
- GlobalFontBackup1 = GlobalFont;
- }
- }
-
- break;
- case EFI_FONT_INFO_ANY_SIZE:
- if ((CompareMem (
- GlobalFont->FontInfo->FontName,
- FontInfo->FontName,
- StrSize (FontInfo->FontName)
- ) == 0) &&
- (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle))
- {
- Matched = TRUE;
- }
-
- break;
- case EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE:
- if (CompareMem (
- GlobalFont->FontInfo->FontName,
- FontInfo->FontName,
- StrSize (FontInfo->FontName)
- ) == 0)
- {
- if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
- Matched = TRUE;
- } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
- VagueMatched1 = TRUE;
- GlobalFontBackup1 = GlobalFont;
- }
- }
-
- break;
- case EFI_FONT_INFO_RESTYLE:
- if ((CompareMem (
- GlobalFont->FontInfo->FontName,
- FontInfo->FontName,
- StrSize (FontInfo->FontName)
- ) == 0) &&
- (GlobalFont->FontInfo->FontSize == FontInfo->FontSize))
- {
- if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
- Matched = TRUE;
- } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
- VagueMatched1 = TRUE;
- GlobalFontBackup1 = GlobalFont;
- }
- }
-
- break;
- case EFI_FONT_INFO_RESIZE:
- if ((CompareMem (
- GlobalFont->FontInfo->FontName,
- FontInfo->FontName,
- StrSize (FontInfo->FontName)
- ) == 0) &&
- (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle))
- {
- if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
- Matched = TRUE;
- } else {
- VagueMatched1 = TRUE;
- GlobalFontBackup1 = GlobalFont;
- }
- }
-
- break;
- case EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_RESTYLE:
- if (CompareMem (
- GlobalFont->FontInfo->FontName,
- FontInfo->FontName,
- StrSize (FontInfo->FontName)
- ) == 0)
- {
- if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
- if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
- Matched = TRUE;
- } else {
- VagueMatched1 = TRUE;
- GlobalFontBackup1 = GlobalFont;
- }
- } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
- if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
- VagueMatched1 = TRUE;
- GlobalFontBackup1 = GlobalFont;
- } else {
- VagueMatched2 = TRUE;
- GlobalFontBackup2 = GlobalFont;
- }
- }
- }
-
- break;
- default:
- break;
- }
-
- if (Matched) {
- if (GlobalFontInfo != NULL) {
- *GlobalFontInfo = GlobalFont;
- }
-
- return TRUE;
- }
- }
- }
-
- if (VagueMatched1) {
- if (GlobalFontInfo != NULL) {
- *GlobalFontInfo = GlobalFontBackup1;
- }
-
- return TRUE;
- } else if (VagueMatched2) {
- if (GlobalFontInfo != NULL) {
- *GlobalFontInfo = GlobalFontBackup2;
- }
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- Check whether the unicode represents a line break or not.
-
- This is a internal function. Please see Section 27.2.6 of the UEFI Specification
- for a description of the supported string format.
-
- @param Char Unicode character
-
- @retval 0 Yes, it forces a line break.
- @retval 1 Yes, it presents a line break opportunity
- @retval 2 Yes, it requires a line break happen before and after it.
- @retval -1 No, it is not a link break.
-
-**/
-INT8
-IsLineBreak (
- IN CHAR16 Char
- )
-{
- switch (Char) {
- //
- // Mandatory line break characters, which force a line-break
- //
- case 0x000A:
- case 0x000C:
- case 0x000D:
- case 0x2028:
- case 0x2029:
- return 0;
- //
- // Space characters, which is taken as a line-break opportunity
- //
- case 0x0020:
- case 0x1680:
- case 0x2000:
- case 0x2001:
- case 0x2002:
- case 0x2003:
- case 0x2004:
- case 0x2005:
- case 0x2006:
- case 0x2008:
- case 0x2009:
- case 0x200A:
- case 0x205F:
- //
- // In-Word Break Opportunities
- //
- case 0x200B:
- return 1;
- //
- // A space which is not a line-break opportunity
- //
- case 0x00A0:
- case 0x202F:
- //
- // A hyphen which is not a line-break opportunity
- //
- case 0x2011:
- return -1;
- //
- // Hyphen characters which describe line break opportunities after the character
- //
- case 0x058A:
- case 0x2010:
- case 0x2012:
- case 0x2013:
- case 0x0F0B:
- case 0x1361:
- case 0x17D5:
- return 1;
- //
- // A hyphen which describes line break opportunities before and after them, but not between a pair of them
- //
- case 0x2014:
- return 2;
- }
-
- return -1;
-}
-
-/**
- Renders a string to a bitmap or to the display.
-
- @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
- @param Flags Describes how the string is to be drawn.
- @param String Points to the null-terminated string to be
- displayed.
- @param StringInfo Points to the string output information,
- including the color and font. If NULL, then the
- string will be output in the default system font
- and color.
- @param Blt If this points to a non-NULL on entry, this
- points to the image, which is Width pixels wide
- and Height pixels high. The string will be drawn
- onto this image and
- EFI_HII_OUT_FLAG_CLIP is implied. If this points
- to a NULL on entry, then a buffer
- will be allocated to hold the generated image and
- the pointer updated on exit. It is the caller's
- responsibility to free this buffer.
- @param BltX Specifies the offset from the left and top edge
- of the image of the first character cell in the
- image.
- @param BltY Specifies the offset from the left and top edge
- of the image of the first character cell in the
- image.
- @param RowInfoArray If this is non-NULL on entry, then on exit, this
- will point to an allocated buffer containing
- row information and RowInfoArraySize will be
- updated to contain the number of elements.
- This array describes the characters which were at
- least partially drawn and the heights of the
- rows. It is the caller's responsibility to free
- this buffer.
- @param RowInfoArraySize If this is non-NULL on entry, then on exit it
- contains the number of elements in RowInfoArray.
- @param ColumnInfoArray If this is non-NULL, then on return it will be
- filled with the horizontal offset for each
- character in the string on the row where it is
- displayed. Non-printing characters will have
- the offset ~0. The caller is responsible to
- allocate a buffer large enough so that there
- is one entry for each character in the string,
- not including the null-terminator. It is possible
- when character display is normalized that some
- character cells overlap.
-
- @retval EFI_SUCCESS The string was successfully rendered.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for
- RowInfoArray or Blt.
- @retval EFI_INVALID_PARAMETER The String or Blt was NULL.
- @retval EFI_INVALID_PARAMETER Flags were invalid combination..
-
-**/
-EFI_STATUS
-EFIAPI
-HiiStringToImage (
- IN CONST EFI_HII_FONT_PROTOCOL *This,
- IN EFI_HII_OUT_FLAGS Flags,
- IN CONST EFI_STRING String,
- IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL,
- IN OUT EFI_IMAGE_OUTPUT **Blt,
- IN UINTN BltX,
- IN UINTN BltY,
- OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL,
- OUT UINTN *RowInfoArraySize OPTIONAL,
- OUT UINTN *ColumnInfoArray OPTIONAL
- )
-{
- EFI_STATUS Status;
- HII_DATABASE_PRIVATE_DATA *Private;
- UINT8 **GlyphBuf;
- EFI_HII_GLYPH_INFO *Cell;
- UINT8 *Attributes;
- EFI_IMAGE_OUTPUT *Image;
- EFI_STRING StringPtr;
- EFI_STRING StringTmp;
- EFI_HII_ROW_INFO *RowInfo;
- UINTN LineWidth;
- UINTN LineHeight;
- UINTN LineOffset;
- UINTN LastLineHeight;
- UINTN BaseLineOffset;
- UINT16 MaxRowNum;
- UINT16 RowIndex;
- UINTN Index;
- UINTN NextIndex;
- UINTN Index1;
- EFI_FONT_DISPLAY_INFO *StringInfoOut;
- EFI_FONT_DISPLAY_INFO *SystemDefault;
- EFI_FONT_HANDLE FontHandle;
- EFI_STRING StringIn;
- EFI_STRING StringIn2;
- UINT16 Height;
- UINT16 BaseLine;
- EFI_FONT_INFO *FontInfo;
- BOOLEAN SysFontFlag;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
- BOOLEAN Transparent;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BufferPtr;
- UINTN RowInfoSize;
- BOOLEAN LineBreak;
- UINTN StrLength;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *RowBufferPtr;
- HII_GLOBAL_FONT_INFO *GlobalFont;
- UINT32 PreInitBkgnd;
-
- //
- // Check incoming parameters.
- //
-
- if ((This == NULL) || (String == NULL) || (Blt == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (*Blt == NULL) {
- //
- // These two flag cannot be used if Blt is NULL upon entry.
- //
- if ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((Flags & EFI_HII_OUT_FLAG_CLIP) == EFI_HII_OUT_FLAG_CLIP) {
- return EFI_INVALID_PARAMETER;
- }
- }
-
- //
- // These two flags require that EFI_HII_OUT_FLAG_CLIP be also set.
- //
- if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) == EFI_HII_OUT_FLAG_CLIP_CLEAN_X) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLIP_CLEAN_Y)) == EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // This flag cannot be used with EFI_HII_OUT_FLAG_CLEAN_X.
- //
- if ((Flags & (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) == (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (*Blt == NULL) {
- //
- // Create a new bitmap and draw the string onto this image.
- //
- Image = AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
- if (Image == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Image->Width = 800;
- Image->Height = 600;
- Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height *sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
- if (Image->Image.Bitmap == NULL) {
- FreePool (Image);
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Other flags are not permitted when Blt is NULL.
- //
- Flags &= EFI_HII_OUT_FLAG_WRAP | EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_IGNORE_LINE_BREAK;
- *Blt = Image;
- }
-
- StrLength = StrLen (String);
- GlyphBuf = (UINT8 **)AllocateZeroPool (StrLength * sizeof (UINT8 *));
- ASSERT (GlyphBuf != NULL);
- Cell = (EFI_HII_GLYPH_INFO *)AllocateZeroPool (StrLength * sizeof (EFI_HII_GLYPH_INFO));
- ASSERT (Cell != NULL);
- Attributes = (UINT8 *)AllocateZeroPool (StrLength * sizeof (UINT8));
- ASSERT (Attributes != NULL);
-
- FontInfo = NULL;
- RowInfo = NULL;
- Status = EFI_SUCCESS;
- StringIn2 = NULL;
- SystemDefault = NULL;
- StringIn = NULL;
-
- //
- // Calculate the string output information, including specified color and font .
- // If StringInfo does not points to system font info, it must indicate an existing
- // EFI_FONT_INFO.
- //
- StringInfoOut = NULL;
- FontHandle = NULL;
- Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- SysFontFlag = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *)StringInfo, &SystemDefault, NULL);
-
- if (SysFontFlag) {
- ASSERT (SystemDefault != NULL);
- FontInfo = NULL;
- Height = SystemDefault->FontInfo.FontSize;
- BaseLine = SystemDefault->FontInfo.FontSize;
- Foreground = SystemDefault->ForegroundColor;
- Background = SystemDefault->BackgroundColor;
- } else {
- //
- // StringInfo must not be NULL if it is not system info.
- //
- ASSERT (StringInfo != NULL);
- Status = HiiGetFontInfo (This, &FontHandle, (EFI_FONT_DISPLAY_INFO *)StringInfo, &StringInfoOut, NULL);
- if (Status == EFI_NOT_FOUND) {
- //
- // The specified EFI_FONT_DISPLAY_INFO does not exist in current database.
- // Use the system font instead. Still use the color specified by StringInfo.
- //
- SysFontFlag = TRUE;
- FontInfo = NULL;
- Height = SystemDefault->FontInfo.FontSize;
- BaseLine = SystemDefault->FontInfo.FontSize;
- Foreground = ((EFI_FONT_DISPLAY_INFO *)StringInfo)->ForegroundColor;
- Background = ((EFI_FONT_DISPLAY_INFO *)StringInfo)->BackgroundColor;
- } else if (Status == EFI_SUCCESS) {
- FontInfo = &StringInfoOut->FontInfo;
- if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont)) {
- Height = GlobalFont->FontPackage->Height;
- BaseLine = GlobalFont->FontPackage->BaseLine;
- Foreground = StringInfoOut->ForegroundColor;
- Background = StringInfoOut->BackgroundColor;
- } else {
- goto Exit;
- }
- } else {
- goto Exit;
- }
- }
-
- //
- // Use the maximum height of font as the base line.
- // And, use the maximum height as line height.
- //
- LineHeight = Height;
- LastLineHeight = Height;
- BaseLineOffset = Height - BaseLine;
-
- //
- // Parse the string to be displayed to drop some ignored characters.
- //
-
- StringPtr = String;
-
- //
- // Ignore line-break characters only. Hyphens or dash character will be displayed
- // without line-break opportunity.
- //
- if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == EFI_HII_IGNORE_LINE_BREAK) {
- StringIn = AllocateZeroPool (StrSize (StringPtr));
- if (StringIn == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- StringTmp = StringIn;
- while (*StringPtr != 0) {
- if (IsLineBreak (*StringPtr) == 0) {
- StringPtr++;
- } else {
- *StringTmp++ = *StringPtr++;
- }
- }
-
- *StringTmp = 0;
- StringPtr = StringIn;
- }
-
- //
- // If EFI_HII_IGNORE_IF_NO_GLYPH is set, then characters which have no glyphs
- // are not drawn. Otherwise they are replaced with Unicode character 0xFFFD.
- //
- StringIn2 = AllocateZeroPool (StrSize (StringPtr));
- if (StringIn2 == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- Index = 0;
- StringTmp = StringIn2;
- StrLength = StrLen (StringPtr);
- while (*StringPtr != 0 && Index < StrLength) {
- if (IsLineBreak (*StringPtr) == 0) {
- *StringTmp++ = *StringPtr++;
- Index++;
- continue;
- }
-
- Status = GetGlyphBuffer (Private, *StringPtr, FontInfo, &GlyphBuf[Index], &Cell[Index], &Attributes[Index]);
- if (Status == EFI_NOT_FOUND) {
- if ((Flags & EFI_HII_IGNORE_IF_NO_GLYPH) == EFI_HII_IGNORE_IF_NO_GLYPH) {
- GlyphBuf[Index] = NULL;
- ZeroMem (&Cell[Index], sizeof (Cell[Index]));
- Status = EFI_SUCCESS;
- } else {
- //
- // Unicode 0xFFFD must exist in current hii database if this flag is not set.
- //
- Status = GetGlyphBuffer (
- Private,
- REPLACE_UNKNOWN_GLYPH,
- FontInfo,
- &GlyphBuf[Index],
- &Cell[Index],
- &Attributes[Index]
- );
- if (EFI_ERROR (Status)) {
- Status = EFI_INVALID_PARAMETER;
- }
- }
- }
-
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
-
- *StringTmp++ = *StringPtr++;
- Index++;
- }
-
- *StringTmp = 0;
- StringPtr = StringIn2;
-
- //
- // Draw the string according to the specified EFI_HII_OUT_FLAGS and Blt.
- // If Blt is not NULL, then EFI_HII_OUT_FLAG_CLIP is implied, render this string
- // to an existing image (bitmap or screen depending on flags) pointed by "*Blt".
- // Otherwise render this string to a new allocated image and output it.
- //
- Image = *Blt;
- BufferPtr = Image->Image.Bitmap + Image->Width * BltY + BltX;
- if (Image->Height < BltY) {
- //
- // the top edge of the image should be in Image resolution scope.
- //
- Status = EFI_INVALID_PARAMETER;
- goto Exit;
- }
-
- MaxRowNum = (UINT16)((Image->Height - BltY) / Height);
- if ((Image->Height - BltY) % Height != 0) {
- LastLineHeight = (Image->Height - BltY) % Height;
- MaxRowNum++;
- }
-
- RowInfo = (EFI_HII_ROW_INFO *)AllocateZeroPool (MaxRowNum * sizeof (EFI_HII_ROW_INFO));
- if (RowInfo == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- //
- // Format the glyph buffer according to flags.
- //
- Transparent = (BOOLEAN)((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT ? TRUE : FALSE);
-
- for (RowIndex = 0, Index = 0; RowIndex < MaxRowNum && StringPtr[Index] != 0; ) {
- LineWidth = 0;
- LineBreak = FALSE;
-
- //
- // Clip the final row if the row's bottom-most on pixel cannot fit when
- // EFI_HII_OUT_FLAG_CLEAN_Y is set.
- //
- if (RowIndex == MaxRowNum - 1) {
- if (((Flags & EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) == EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) && (LastLineHeight < LineHeight)) {
- //
- // Don't draw at all if the row's bottom-most on pixel cannot fit.
- //
- break;
- }
-
- LineHeight = LastLineHeight;
- }
-
- //
- // Calculate how many characters there are in a row.
- //
- RowInfo[RowIndex].StartIndex = Index;
-
- while (LineWidth + BltX < Image->Width && StringPtr[Index] != 0) {
- if (((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0) &&
- (IsLineBreak (StringPtr[Index]) == 0))
- {
- //
- // It forces a line break that ends this row.
- //
- Index++;
- LineBreak = TRUE;
- break;
- }
-
- //
- // If the glyph of the character is existing, then accumulate the actual printed width
- //
- LineWidth += (UINTN)Cell[Index].AdvanceX;
-
- Index++;
- }
-
- //
- // Record index of next char.
- //
- NextIndex = Index;
- //
- // Return to the previous char.
- //
- Index--;
- if (LineBreak && (Index > 0)) {
- //
- // Return the previous non line break char.
- //
- Index--;
- }
-
- //
- // If this character is the last character of a row, we need not
- // draw its (AdvanceX - Width - OffsetX) for next character.
- //
- LineWidth -= (Cell[Index].AdvanceX - Cell[Index].Width - Cell[Index].OffsetX);
-
- //
- // Clip the right-most character if cannot fit when EFI_HII_OUT_FLAG_CLEAN_X is set.
- //
- if ((LineWidth + BltX <= Image->Width) ||
- ((LineWidth + BltX > Image->Width) && ((Flags & EFI_HII_OUT_FLAG_CLIP_CLEAN_X) == 0)))
- {
- //
- // Record right-most character in RowInfo even if it is partially displayed.
- //
- RowInfo[RowIndex].EndIndex = Index;
- RowInfo[RowIndex].LineWidth = LineWidth;
- RowInfo[RowIndex].LineHeight = LineHeight;
- RowInfo[RowIndex].BaselineOffset = BaseLineOffset;
- } else {
- //
- // When EFI_HII_OUT_FLAG_CLEAN_X is set, it will not draw a character
- // if its right-most on pixel cannot fit.
- //
- if (Index > RowInfo[RowIndex].StartIndex) {
- //
- // Don't draw the last char on this row. And, don't draw the second last char (AdvanceX - Width - OffsetX).
- //
- LineWidth -= (Cell[Index].Width + Cell[Index].OffsetX);
- LineWidth -= (Cell[Index - 1].AdvanceX - Cell[Index - 1].Width - Cell[Index - 1].OffsetX);
- RowInfo[RowIndex].EndIndex = Index - 1;
- RowInfo[RowIndex].LineWidth = LineWidth;
- RowInfo[RowIndex].LineHeight = LineHeight;
- RowInfo[RowIndex].BaselineOffset = BaseLineOffset;
- } else {
- //
- // There is no enough column to draw any character, so set current line width to zero.
- // And go to draw Next line if LineBreak is set.
- //
- RowInfo[RowIndex].LineWidth = 0;
- goto NextLine;
- }
- }
-
- //
- // EFI_HII_OUT_FLAG_WRAP will wrap the text at the right-most line-break
- // opportunity prior to a character whose right-most extent would exceed Width.
- // Search the right-most line-break opportunity here.
- //
- if (((Flags & EFI_HII_OUT_FLAG_WRAP) == EFI_HII_OUT_FLAG_WRAP) &&
- ((RowInfo[RowIndex].LineWidth + BltX > Image->Width) || (StringPtr[NextIndex] != 0)) &&
- !LineBreak)
- {
- if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0) {
- LineWidth = RowInfo[RowIndex].LineWidth;
- for (Index1 = RowInfo[RowIndex].EndIndex; Index1 >= RowInfo[RowIndex].StartIndex; Index1--) {
- if (Index1 == RowInfo[RowIndex].EndIndex) {
- LineWidth -= (Cell[Index1].Width + Cell[Index1].OffsetX);
- } else {
- LineWidth -= Cell[Index1].AdvanceX;
- }
-
- if (IsLineBreak (StringPtr[Index1]) > 0) {
- LineBreak = TRUE;
- if (Index1 > RowInfo[RowIndex].StartIndex) {
- RowInfo[RowIndex].EndIndex = Index1 - 1;
- }
-
- //
- // relocate to the character after the right-most line break opportunity of this line
- //
- NextIndex = Index1 + 1;
- break;
- }
-
- //
- // If don't find a line break opportunity from EndIndex to StartIndex,
- // then jump out.
- //
- if (Index1 == RowInfo[RowIndex].StartIndex) {
- break;
- }
- }
-
- //
- // Update LineWidth to the real width
- //
- if (IsLineBreak (StringPtr[Index1]) > 0) {
- if (Index1 == RowInfo[RowIndex].StartIndex) {
- LineWidth = 0;
- } else {
- LineWidth -= (Cell[Index1 - 1].AdvanceX - Cell[Index1 - 1].Width - Cell[Index1 - 1].OffsetX);
- }
-
- RowInfo[RowIndex].LineWidth = LineWidth;
- }
- }
-
- //
- // If no line-break opportunity can be found, then the text will
- // behave as if EFI_HII_OUT_FLAG_CLEAN_X is set.
- //
- if (!LineBreak) {
- LineWidth = RowInfo[RowIndex].LineWidth;
- Index1 = RowInfo[RowIndex].EndIndex;
- if (LineWidth + BltX > Image->Width) {
- if (Index1 > RowInfo[RowIndex].StartIndex) {
- //
- // Don't draw the last char on this row. And, don't draw the second last char (AdvanceX - Width - OffsetX).
- //
- LineWidth -= (Cell[Index1].Width + Cell[Index1].OffsetX);
- LineWidth -= (Cell[Index1 - 1].AdvanceX - Cell[Index1 - 1].Width - Cell[Index1 - 1].OffsetX);
- RowInfo[RowIndex].EndIndex = Index1 - 1;
- RowInfo[RowIndex].LineWidth = LineWidth;
- } else {
- //
- // There is no enough column to draw any character, so set current line width to zero.
- // And go to draw Next line if LineBreak is set.
- //
- RowInfo[RowIndex].LineWidth = 0;
- goto NextLine;
- }
- }
- }
- }
-
- //
- // LineWidth can't exceed Image width.
- //
- if (RowInfo[RowIndex].LineWidth + BltX > Image->Width) {
- RowInfo[RowIndex].LineWidth = Image->Width - BltX;
- }
-
- //
- // Draw it to screen or existing bitmap depending on whether
- // EFI_HII_DIRECT_TO_SCREEN is set.
- //
- LineOffset = 0;
- if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
- BltBuffer = NULL;
- if (RowInfo[RowIndex].LineWidth != 0) {
- BltBuffer = AllocatePool (RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
- if (BltBuffer == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- //
- // Initialize the background color.
- //
- PreInitBkgnd = Background.Blue | Background.Green << 8 | Background.Red << 16;
- SetMem32 (BltBuffer, RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), PreInitBkgnd);
- //
- // Set BufferPtr to Origin by adding baseline to the starting position.
- //
- BufferPtr = BltBuffer + BaseLine * RowInfo[RowIndex].LineWidth;
- }
-
- for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {
- if ((RowInfo[RowIndex].LineWidth > 0) && (RowInfo[RowIndex].LineWidth > LineOffset)) {
- //
- // Only BLT these character which have corresponding glyph in font database.
- //
- GlyphToImage (
- GlyphBuf[Index1],
- Foreground,
- Background,
- (UINT16)RowInfo[RowIndex].LineWidth,
- BaseLine,
- RowInfo[RowIndex].LineWidth - LineOffset,
- RowInfo[RowIndex].LineHeight,
- Transparent,
- &Cell[Index1],
- Attributes[Index1],
- &BufferPtr
- );
- }
-
- if (ColumnInfoArray != NULL) {
- if ( ((GlyphBuf[Index1] == NULL) && (Cell[Index1].AdvanceX == 0))
- || (RowInfo[RowIndex].LineWidth == 0))
- {
- *ColumnInfoArray = (UINTN) ~0;
- } else {
- *ColumnInfoArray = LineOffset + Cell[Index1].OffsetX + BltX;
- }
-
- ColumnInfoArray++;
- }
-
- LineOffset += Cell[Index1].AdvanceX;
- }
-
- if (BltBuffer != NULL) {
- Status = Image->Image.Screen->Blt (
- Image->Image.Screen,
- BltBuffer,
- EfiBltBufferToVideo,
- 0,
- 0,
- BltX,
- BltY,
- RowInfo[RowIndex].LineWidth,
- RowInfo[RowIndex].LineHeight,
- 0
- );
- if (EFI_ERROR (Status)) {
- FreePool (BltBuffer);
- goto Exit;
- }
-
- FreePool (BltBuffer);
- }
- } else {
- //
- // Save the starting position for calculate the starting position of next row.
- //
- RowBufferPtr = BufferPtr;
- //
- // Set BufferPtr to Origin by adding baseline to the starting position.
- //
- BufferPtr = BufferPtr + BaseLine * Image->Width;
- for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {
- if ((RowInfo[RowIndex].LineWidth > 0) && (RowInfo[RowIndex].LineWidth > LineOffset)) {
- //
- // Only BLT these character which have corresponding glyph in font database.
- //
- GlyphToImage (
- GlyphBuf[Index1],
- Foreground,
- Background,
- Image->Width,
- BaseLine,
- RowInfo[RowIndex].LineWidth - LineOffset,
- RowInfo[RowIndex].LineHeight,
- Transparent,
- &Cell[Index1],
- Attributes[Index1],
- &BufferPtr
- );
- }
-
- if (ColumnInfoArray != NULL) {
- if ( ((GlyphBuf[Index1] == NULL) && (Cell[Index1].AdvanceX == 0))
- || (RowInfo[RowIndex].LineWidth == 0))
- {
- *ColumnInfoArray = (UINTN) ~0;
- } else {
- *ColumnInfoArray = LineOffset + Cell[Index1].OffsetX + BltX;
- }
-
- ColumnInfoArray++;
- }
-
- LineOffset += Cell[Index1].AdvanceX;
- }
-
- //
- // Jump to starting position of next row.
- //
- if (RowIndex == 0) {
- BufferPtr = RowBufferPtr - BltX + LineHeight * Image->Width;
- } else {
- BufferPtr = RowBufferPtr + LineHeight * Image->Width;
- }
- }
-
-NextLine:
- //
- // Recalculate the start point of Y axis to draw multi-lines with the order of top-to-down
- //
- BltY += RowInfo[RowIndex].LineHeight;
-
- RowIndex++;
- Index = NextIndex;
-
- if (!LineBreak) {
- //
- // If there is not a mandatory line break or line break opportunity, only render one line to image
- //
- break;
- }
- }
-
- //
- // Write output parameters.
- //
- RowInfoSize = RowIndex * sizeof (EFI_HII_ROW_INFO);
- if (RowInfoArray != NULL) {
- if (RowInfoSize > 0) {
- *RowInfoArray = AllocateZeroPool (RowInfoSize);
- if (*RowInfoArray == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- CopyMem (*RowInfoArray, RowInfo, RowInfoSize);
- } else {
- *RowInfoArray = NULL;
- }
- }
-
- if (RowInfoArraySize != NULL) {
- *RowInfoArraySize = RowIndex;
- }
-
- Status = EFI_SUCCESS;
-
-Exit:
-
- for (Index = 0; Index < StrLength; Index++) {
- if (GlyphBuf[Index] != NULL) {
- FreePool (GlyphBuf[Index]);
- }
- }
-
- if (StringIn != NULL) {
- FreePool (StringIn);
- }
-
- if (StringIn2 != NULL) {
- FreePool (StringIn2);
- }
-
- if (StringInfoOut != NULL) {
- FreePool (StringInfoOut);
- }
-
- if (RowInfo != NULL) {
- FreePool (RowInfo);
- }
-
- if (SystemDefault != NULL) {
- FreePool (SystemDefault);
- }
-
- if (GlyphBuf != NULL) {
- FreePool (GlyphBuf);
- }
-
- if (Cell != NULL) {
- FreePool (Cell);
- }
-
- if (Attributes != NULL) {
- FreePool (Attributes);
- }
-
- return Status;
-}
-
-/**
- Render a string to a bitmap or the screen containing the contents of the specified string.
-
- @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
- @param Flags Describes how the string is to be drawn.
- @param PackageList The package list in the HII database to search
- for the specified string.
- @param StringId The string's id, which is unique within
- PackageList.
- @param Language Points to the language for the retrieved string.
- If NULL, then the current system language is
- used.
- @param StringInfo Points to the string output information,
- including the color and font. If NULL, then the
- string will be output in the default system font
- and color.
- @param Blt If this points to a non-NULL on entry, this
- points to the image, which is Width pixels wide
- and Height pixels high. The string will be drawn
- onto this image and
- EFI_HII_OUT_FLAG_CLIP is implied. If this points
- to a NULL on entry, then a buffer
- will be allocated to hold the generated image and
- the pointer updated on exit. It is the caller's
- responsibility to free this buffer.
- @param BltX Specifies the offset from the left and top edge
- of the image of the first character cell in the
- image.
- @param BltY Specifies the offset from the left and top edge
- of the image of the first character cell in the
- image.
- @param RowInfoArray If this is non-NULL on entry, then on exit, this
- will point to an allocated buffer containing
- row information and RowInfoArraySize will be
- updated to contain the number of elements.
- This array describes the characters which were at
- least partially drawn and the heights of the
- rows. It is the caller's responsibility to free
- this buffer.
- @param RowInfoArraySize If this is non-NULL on entry, then on exit it
- contains the number of elements in RowInfoArray.
- @param ColumnInfoArray If this is non-NULL, then on return it will be
- filled with the horizontal offset for each
- character in the string on the row where it is
- displayed. Non-printing characters will have
- the offset ~0. The caller is responsible to
- allocate a buffer large enough so that there
- is one entry for each character in the string,
- not including the null-terminator. It is possible
- when character display is normalized that some
- character cells overlap.
-
- @retval EFI_SUCCESS The string was successfully rendered.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for
- RowInfoArray or Blt.
- @retval EFI_INVALID_PARAMETER The Blt or PackageList was NULL.
- @retval EFI_INVALID_PARAMETER Flags were invalid combination.
- @retval EFI_NOT_FOUND The specified PackageList is not in the Database or the string id is not
- in the specified PackageList.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiStringIdToImage (
- IN CONST EFI_HII_FONT_PROTOCOL *This,
- IN EFI_HII_OUT_FLAGS Flags,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_STRING_ID StringId,
- IN CONST CHAR8 *Language,
- IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL,
- IN OUT EFI_IMAGE_OUTPUT **Blt,
- IN UINTN BltX,
- IN UINTN BltY,
- OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL,
- OUT UINTN *RowInfoArraySize OPTIONAL,
- OUT UINTN *ColumnInfoArray OPTIONAL
- )
-{
- EFI_STATUS Status;
- HII_DATABASE_PRIVATE_DATA *Private;
- EFI_HII_STRING_PROTOCOL *HiiString;
- EFI_STRING String;
- UINTN StringSize;
- UINTN FontLen;
- UINTN NameSize;
- EFI_FONT_INFO *StringFontInfo;
- EFI_FONT_DISPLAY_INFO *NewStringInfo;
- CHAR8 TempSupportedLanguages;
- CHAR8 *SupportedLanguages;
- UINTN SupportedLanguagesSize;
- CHAR8 *CurrentLanguage;
- CHAR8 *BestLanguage;
-
- if ((This == NULL) || (PackageList == NULL) || (Blt == NULL) || (PackageList == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (!IsHiiHandleValid (PackageList)) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Initialize string pointers to be NULL
- //
- SupportedLanguages = NULL;
- CurrentLanguage = NULL;
- BestLanguage = NULL;
- String = NULL;
- StringFontInfo = NULL;
- NewStringInfo = NULL;
-
- //
- // Get the string to be displayed.
- //
- Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- HiiString = &Private->HiiString;
-
- //
- // Get the size of supported language.
- //
- SupportedLanguagesSize = 0;
- Status = HiiString->GetLanguages (
- HiiString,
- PackageList,
- &TempSupportedLanguages,
- &SupportedLanguagesSize
- );
- if (Status != EFI_BUFFER_TOO_SMALL) {
- return Status;
- }
-
- SupportedLanguages = AllocatePool (SupportedLanguagesSize);
- if (SupportedLanguages == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Status = HiiString->GetLanguages (
- HiiString,
- PackageList,
- SupportedLanguages,
- &SupportedLanguagesSize
- );
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
-
- if (Language == NULL) {
- Language = "";
- }
-
- GetEfiGlobalVariable2 (L"PlatformLang", (VOID **)&CurrentLanguage, NULL);
- BestLanguage = GetBestLanguage (
- SupportedLanguages,
- FALSE,
- Language,
- (CurrentLanguage == NULL) ? CurrentLanguage : "",
- (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLang),
- NULL
- );
- if (BestLanguage == NULL) {
- Status = EFI_NOT_FOUND;
- goto Exit;
- }
-
- StringSize = MAX_STRING_LENGTH;
- String = (EFI_STRING)AllocateZeroPool (StringSize);
- if (String == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- Status = HiiString->GetString (
- HiiString,
- BestLanguage,
- PackageList,
- StringId,
- String,
- &StringSize,
- &StringFontInfo
- );
- if (Status == EFI_BUFFER_TOO_SMALL) {
- FreePool (String);
- String = (EFI_STRING)AllocateZeroPool (StringSize);
- if (String == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- Status = HiiString->GetString (
- HiiString,
- BestLanguage,
- PackageList,
- StringId,
- String,
- &StringSize,
- NULL
- );
- }
-
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
-
- //
- // When StringInfo specifies that string will be output in the system default font and color,
- // use particular stringfontinfo described in string package instead if exists.
- // StringFontInfo equals NULL means system default font attaches with the string block.
- //
- if ((StringFontInfo != NULL) && IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *)StringInfo, NULL, NULL)) {
- NameSize = StrSize (StringFontInfo->FontName);
- FontLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + NameSize;
- NewStringInfo = AllocateZeroPool (FontLen);
- if (NewStringInfo == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- NewStringInfo->FontInfoMask = EFI_FONT_INFO_SYS_FORE_COLOR | EFI_FONT_INFO_SYS_BACK_COLOR;
- NewStringInfo->FontInfo.FontStyle = StringFontInfo->FontStyle;
- NewStringInfo->FontInfo.FontSize = StringFontInfo->FontSize;
- StrCpyS (NewStringInfo->FontInfo.FontName, NameSize / sizeof (CHAR16), StringFontInfo->FontName);
-
- Status = HiiStringToImage (
- This,
- Flags,
- String,
- NewStringInfo,
- Blt,
- BltX,
- BltY,
- RowInfoArray,
- RowInfoArraySize,
- ColumnInfoArray
- );
- goto Exit;
- }
-
- Status = HiiStringToImage (
- This,
- Flags,
- String,
- StringInfo,
- Blt,
- BltX,
- BltY,
- RowInfoArray,
- RowInfoArraySize,
- ColumnInfoArray
- );
-
-Exit:
- if (SupportedLanguages != NULL) {
- FreePool (SupportedLanguages);
- }
-
- if (CurrentLanguage != NULL) {
- FreePool (CurrentLanguage);
- }
-
- if (BestLanguage != NULL) {
- FreePool (BestLanguage);
- }
-
- if (String != NULL) {
- FreePool (String);
- }
-
- if (StringFontInfo != NULL) {
- FreePool (StringFontInfo);
- }
-
- if (NewStringInfo != NULL) {
- FreePool (NewStringInfo);
- }
-
- return Status;
-}
-
-/**
- Convert the glyph for a single character into a bitmap.
-
- @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
- @param Char Character to retrieve.
- @param StringInfo Points to the string font and color information
- or NULL if the string should use the default
- system font and color.
- @param Blt Thus must point to a NULL on entry. A buffer will
- be allocated to hold the output and the pointer
- updated on exit. It is the caller's
- responsibility to free this buffer.
- @param Baseline Number of pixels from the bottom of the bitmap to
- the baseline.
-
- @retval EFI_SUCCESS Glyph bitmap created.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate the output buffer Blt.
- @retval EFI_WARN_UNKNOWN_GLYPH The glyph was unknown and was replaced with the
- glyph for Unicode character 0xFFFD.
- @retval EFI_INVALID_PARAMETER Blt is NULL or *Blt is not NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetGlyph (
- IN CONST EFI_HII_FONT_PROTOCOL *This,
- IN CHAR16 Char,
- IN CONST EFI_FONT_DISPLAY_INFO *StringInfo,
- OUT EFI_IMAGE_OUTPUT **Blt,
- OUT UINTN *Baseline OPTIONAL
- )
-{
- EFI_STATUS Status;
- HII_DATABASE_PRIVATE_DATA *Private;
- EFI_IMAGE_OUTPUT *Image;
- UINT8 *GlyphBuffer;
- EFI_FONT_DISPLAY_INFO *SystemDefault;
- EFI_FONT_DISPLAY_INFO *StringInfoOut;
- BOOLEAN Default;
- EFI_FONT_HANDLE FontHandle;
- EFI_STRING String;
- EFI_HII_GLYPH_INFO Cell;
- EFI_FONT_INFO *FontInfo;
- UINT8 Attributes;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
- UINT16 BaseLine;
-
- if ((This == NULL) || (Blt == NULL) || (*Blt != NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
-
- Default = FALSE;
- Image = NULL;
- SystemDefault = NULL;
- FontHandle = NULL;
- String = NULL;
- GlyphBuffer = NULL;
- StringInfoOut = NULL;
- FontInfo = NULL;
-
- ZeroMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
- ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
-
- Default = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *)StringInfo, &SystemDefault, NULL);
-
- if (!Default) {
- //
- // Find out a EFI_FONT_DISPLAY_INFO which could display the character in
- // the specified color and font.
- //
- String = (EFI_STRING)AllocateZeroPool (sizeof (CHAR16) * 2);
- if (String == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- *String = Char;
- *(String + 1) = 0;
-
- Status = HiiGetFontInfo (This, &FontHandle, StringInfo, &StringInfoOut, String);
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
-
- ASSERT (StringInfoOut != NULL);
- FontInfo = &StringInfoOut->FontInfo;
- Foreground = StringInfoOut->ForegroundColor;
- Background = StringInfoOut->BackgroundColor;
- } else {
- ASSERT (SystemDefault != NULL);
- Foreground = SystemDefault->ForegroundColor;
- Background = SystemDefault->BackgroundColor;
- }
-
- Status = GetGlyphBuffer (Private, Char, FontInfo, &GlyphBuffer, &Cell, &Attributes);
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
-
- Image = (EFI_IMAGE_OUTPUT *)AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
- if (Image == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- Image->Width = Cell.Width;
- Image->Height = Cell.Height;
-
- if (Image->Width * Image->Height > 0) {
- Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
- if (Image->Image.Bitmap == NULL) {
- FreePool (Image);
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- //
- // Set BaseLine to the char height.
- //
- BaseLine = (UINT16)(Cell.Height + Cell.OffsetY);
- //
- // Set BltBuffer to the position of Origin.
- //
- BltBuffer = Image->Image.Bitmap + (Cell.Height + Cell.OffsetY) * Image->Width - Cell.OffsetX;
- GlyphToImage (
- GlyphBuffer,
- Foreground,
- Background,
- Image->Width,
- BaseLine,
- Cell.Width + Cell.OffsetX,
- BaseLine - Cell.OffsetY,
- FALSE,
- &Cell,
- Attributes,
- &BltBuffer
- );
- }
-
- *Blt = Image;
- if (Baseline != NULL) {
- *Baseline = Cell.OffsetY;
- }
-
- Status = EFI_SUCCESS;
-
-Exit:
-
- if (Status == EFI_NOT_FOUND) {
- //
- // Glyph is unknown and replaced with the glyph for unicode character 0xFFFD
- //
- if (Char != REPLACE_UNKNOWN_GLYPH) {
- Status = HiiGetGlyph (This, REPLACE_UNKNOWN_GLYPH, StringInfo, Blt, Baseline);
- if (!EFI_ERROR (Status)) {
- Status = EFI_WARN_UNKNOWN_GLYPH;
- }
- } else {
- Status = EFI_WARN_UNKNOWN_GLYPH;
- }
- }
-
- if (SystemDefault != NULL) {
- FreePool (SystemDefault);
- }
-
- if (StringInfoOut != NULL) {
- FreePool (StringInfoOut);
- }
-
- if (String != NULL) {
- FreePool (String);
- }
-
- if (GlyphBuffer != NULL) {
- FreePool (GlyphBuffer);
- }
-
- return Status;
-}
-
-/**
- This function iterates through fonts which match the specified font, using
- the specified criteria. If String is non-NULL, then all of the characters in
- the string must exist in order for a candidate font to be returned.
-
- @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
- @param FontHandle On entry, points to the font handle returned by a
- previous call to GetFontInfo() or NULL to start
- with the first font. On return, points to the
- returned font handle or points to NULL if there
- are no more matching fonts.
- @param StringInfoIn Upon entry, points to the font to return information
- about. If NULL, then the information about the system
- default font will be returned.
- @param StringInfoOut Upon return, contains the matching font's information.
- If NULL, then no information is returned. This buffer
- is allocated with a call to the Boot Service AllocatePool().
- It is the caller's responsibility to call the Boot
- Service FreePool() when the caller no longer requires
- the contents of StringInfoOut.
- @param String Points to the string which will be tested to
- determine if all characters are available. If
- NULL, then any font is acceptable.
-
- @retval EFI_SUCCESS Matching font returned successfully.
- @retval EFI_NOT_FOUND No matching font was found.
- @retval EFI_INVALID_PARAMETER StringInfoIn->FontInfoMask is an invalid combination.
- @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the
- request.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetFontInfo (
- IN CONST EFI_HII_FONT_PROTOCOL *This,
- IN OUT EFI_FONT_HANDLE *FontHandle,
- IN CONST EFI_FONT_DISPLAY_INFO *StringInfoIn OPTIONAL,
- OUT EFI_FONT_DISPLAY_INFO **StringInfoOut,
- IN CONST EFI_STRING String OPTIONAL
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
- EFI_STATUS Status;
- EFI_FONT_DISPLAY_INFO *SystemDefault;
- EFI_FONT_DISPLAY_INFO InfoOut;
- UINTN StringInfoOutLen;
- EFI_FONT_INFO *FontInfo;
- HII_GLOBAL_FONT_INFO *GlobalFont;
- EFI_STRING StringIn;
- EFI_FONT_HANDLE LocalFontHandle;
-
- if (This == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- StringInfoOutLen = 0;
- FontInfo = NULL;
- SystemDefault = NULL;
- LocalFontHandle = NULL;
- if (FontHandle != NULL) {
- LocalFontHandle = *FontHandle;
- }
-
- Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
-
- //
- // Already searched to the end of the whole list, return directly.
- //
- if (LocalFontHandle == &Private->FontInfoList) {
- LocalFontHandle = NULL;
- Status = EFI_NOT_FOUND;
- goto Exit;
- }
-
- //
- // Get default system display info, if StringInfoIn points to
- // system display info, return it directly.
- //
- if (IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *)StringInfoIn, &SystemDefault, &StringInfoOutLen)) {
- //
- // System font is the first node. When handle is not NULL, system font can not
- // be found any more.
- //
- if (LocalFontHandle == NULL) {
- if (StringInfoOut != NULL) {
- *StringInfoOut = AllocateCopyPool (StringInfoOutLen, SystemDefault);
- if (*StringInfoOut == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- LocalFontHandle = NULL;
- goto Exit;
- }
- }
-
- LocalFontHandle = Private->FontInfoList.ForwardLink;
- Status = EFI_SUCCESS;
- goto Exit;
- } else {
- LocalFontHandle = NULL;
- Status = EFI_NOT_FOUND;
- goto Exit;
- }
- }
-
- //
- // StringInfoIn must not be NULL if it is not system default font info.
- //
- ASSERT (StringInfoIn != NULL);
- //
- // Check the font information mask to make sure it is valid.
- //
- if (((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) ==
- (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) ||
- ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) ==
- (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) ||
- ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ==
- (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ||
- ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE)) ==
- (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE)) ||
- ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE)) ==
- (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE)))
- {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Parse the font information mask to find a matching font.
- //
-
- CopyMem (&InfoOut, (EFI_FONT_DISPLAY_INFO *)StringInfoIn, sizeof (EFI_FONT_DISPLAY_INFO));
-
- if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FONT) == EFI_FONT_INFO_SYS_FONT) {
- Status = SaveFontName (SystemDefault->FontInfo.FontName, &FontInfo);
- } else {
- Status = SaveFontName (((EFI_FONT_DISPLAY_INFO *)StringInfoIn)->FontInfo.FontName, &FontInfo);
- }
-
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
-
- if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_SIZE) == EFI_FONT_INFO_SYS_SIZE) {
- InfoOut.FontInfo.FontSize = SystemDefault->FontInfo.FontSize;
- }
-
- if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_STYLE) == EFI_FONT_INFO_SYS_STYLE) {
- InfoOut.FontInfo.FontStyle = SystemDefault->FontInfo.FontStyle;
- }
-
- if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) == EFI_FONT_INFO_SYS_FORE_COLOR) {
- InfoOut.ForegroundColor = SystemDefault->ForegroundColor;
- }
-
- if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) == EFI_FONT_INFO_SYS_BACK_COLOR) {
- InfoOut.BackgroundColor = SystemDefault->BackgroundColor;
- }
-
- ASSERT (FontInfo != NULL);
- FontInfo->FontSize = InfoOut.FontInfo.FontSize;
- FontInfo->FontStyle = InfoOut.FontInfo.FontStyle;
-
- if (IsFontInfoExisted (Private, FontInfo, &InfoOut.FontInfoMask, LocalFontHandle, &GlobalFont)) {
- //
- // Test to guarantee all characters are available in the found font.
- //
- if (String != NULL) {
- StringIn = String;
- while (*StringIn != 0) {
- Status = FindGlyphBlock (GlobalFont->FontPackage, *StringIn, NULL, NULL, NULL);
- if (EFI_ERROR (Status)) {
- LocalFontHandle = NULL;
- goto Exit;
- }
-
- StringIn++;
- }
- }
-
- //
- // Write to output parameter
- //
- if (StringInfoOut != NULL) {
- StringInfoOutLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (EFI_FONT_INFO) + GlobalFont->FontInfoSize;
- *StringInfoOut = (EFI_FONT_DISPLAY_INFO *)AllocateZeroPool (StringInfoOutLen);
- if (*StringInfoOut == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- LocalFontHandle = NULL;
- goto Exit;
- }
-
- CopyMem (*StringInfoOut, &InfoOut, sizeof (EFI_FONT_DISPLAY_INFO));
- CopyMem (&(*StringInfoOut)->FontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize);
- }
-
- LocalFontHandle = GlobalFont->Entry.ForwardLink;
- Status = EFI_SUCCESS;
- goto Exit;
- }
-
- Status = EFI_NOT_FOUND;
-
-Exit:
-
- if (FontHandle != NULL) {
- *FontHandle = LocalFontHandle;
- }
-
- if (SystemDefault != NULL) {
- FreePool (SystemDefault);
- }
-
- if (FontInfo != NULL) {
- FreePool (FontInfo);
- }
-
- return Status;
-}
+/** @file
+Implementation for EFI_HII_FONT_PROTOCOL.
+
+
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "HiiDatabase.h"
+
+EFI_GRAPHICS_OUTPUT_BLT_PIXEL mHiiEfiColors[16] = {
+ //
+ // B G R
+ //
+ { 0x00, 0x00, 0x00, 0x00 }, // BLACK
+ { 0x98, 0x00, 0x00, 0x00 }, // BLUE
+ { 0x00, 0x98, 0x00, 0x00 }, // GREEN
+ { 0x98, 0x98, 0x00, 0x00 }, // CYAN
+ { 0x00, 0x00, 0x98, 0x00 }, // RED
+ { 0x98, 0x00, 0x98, 0x00 }, // MAGENTA
+ { 0x00, 0x98, 0x98, 0x00 }, // BROWN
+ { 0x98, 0x98, 0x98, 0x00 }, // LIGHTGRAY
+ { 0x30, 0x30, 0x30, 0x00 }, // DARKGRAY - BRIGHT BLACK
+ { 0xff, 0x00, 0x00, 0x00 }, // LIGHTBLUE
+ { 0x00, 0xff, 0x00, 0x00 }, // LIGHTGREEN
+ { 0xff, 0xff, 0x00, 0x00 }, // LIGHTCYAN
+ { 0x00, 0x00, 0xff, 0x00 }, // LIGHTRED
+ { 0xff, 0x00, 0xff, 0x00 }, // LIGHTMAGENTA
+ { 0x00, 0xff, 0xff, 0x00 }, // YELLOW
+ { 0xff, 0xff, 0xff, 0x00 }, // WHITE
+};
+
+/**
+ Insert a character cell information to the list specified by GlyphInfoList.
+
+ This is a internal function.
+
+ @param CharValue Unicode character value, which identifies a glyph
+ block.
+ @param GlyphInfoList HII_GLYPH_INFO list head.
+ @param Cell Incoming character cell information.
+
+ @retval EFI_SUCCESS Cell information is added to the GlyphInfoList.
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
+ task.
+
+**/
+EFI_STATUS
+NewCell (
+ IN CHAR16 CharValue,
+ IN LIST_ENTRY *GlyphInfoList,
+ IN EFI_HII_GLYPH_INFO *Cell
+ )
+{
+ HII_GLYPH_INFO *GlyphInfo;
+
+ ASSERT (Cell != NULL && GlyphInfoList != NULL);
+
+ GlyphInfo = (HII_GLYPH_INFO *)AllocateZeroPool (sizeof (HII_GLYPH_INFO));
+ if (GlyphInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // GlyphInfoList stores a list of default character cell information, each is
+ // identified by "CharId".
+ //
+ GlyphInfo->Signature = HII_GLYPH_INFO_SIGNATURE;
+ GlyphInfo->CharId = CharValue;
+ if (Cell->AdvanceX == 0) {
+ Cell->AdvanceX = Cell->Width;
+ }
+
+ CopyMem (&GlyphInfo->Cell, Cell, sizeof (EFI_HII_GLYPH_INFO));
+ InsertTailList (GlyphInfoList, &GlyphInfo->Entry);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get a character cell information from the list specified by GlyphInfoList.
+
+ This is a internal function.
+
+ @param CharValue Unicode character value, which identifies a glyph
+ block.
+ @param GlyphInfoList HII_GLYPH_INFO list head.
+ @param Cell Buffer which stores output character cell
+ information.
+
+ @retval EFI_SUCCESS Cell information is added to the GlyphInfoList.
+ @retval EFI_NOT_FOUND The character info specified by CharValue does
+ not exist.
+
+**/
+EFI_STATUS
+GetCell (
+ IN CHAR16 CharValue,
+ IN LIST_ENTRY *GlyphInfoList,
+ OUT EFI_HII_GLYPH_INFO *Cell
+ )
+{
+ HII_GLYPH_INFO *GlyphInfo;
+ LIST_ENTRY *Link;
+
+ ASSERT (Cell != NULL && GlyphInfoList != NULL);
+
+ //
+ // Since the EFI_HII_GIBT_DEFAULTS block won't increment CharValueCurrent,
+ // the value of "CharId" of a default character cell which is used for a
+ // EFI_HII_GIBT_GLYPH_DEFAULT or EFI_HII_GIBT_GLYPHS_DEFAULT should be
+ // less or equal to the value of "CharValueCurrent" of this default block.
+ //
+ // For instance, if the CharId of a GlyphInfoList is {1, 3, 7}, a default glyph
+ // with CharValue equals "7" uses the GlyphInfo with CharId = 7;
+ // a default glyph with CharValue equals "6" uses the GlyphInfo with CharId = 3.
+ //
+ for (Link = GlyphInfoList->BackLink; Link != GlyphInfoList; Link = Link->BackLink) {
+ GlyphInfo = CR (Link, HII_GLYPH_INFO, Entry, HII_GLYPH_INFO_SIGNATURE);
+ if (GlyphInfo->CharId <= CharValue) {
+ CopyMem (Cell, &GlyphInfo->Cell, sizeof (EFI_HII_GLYPH_INFO));
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Convert the glyph for a single character into a bitmap.
+
+ This is a internal function.
+
+ @param Private HII database driver private data.
+ @param Char Character to retrieve.
+ @param StringInfo Points to the string font and color information
+ or NULL if the string should use the default
+ system font and color.
+ @param GlyphBuffer Buffer to store the retrieved bitmap data.
+ @param Cell Points to EFI_HII_GLYPH_INFO structure.
+ @param Attributes If not NULL, output the glyph attributes if any.
+
+ @retval EFI_SUCCESS Glyph bitmap outputted.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate the output buffer GlyphBuffer.
+ @retval EFI_NOT_FOUND The glyph was unknown can not be found.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+EFI_STATUS
+GetGlyphBuffer (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN CHAR16 Char,
+ IN EFI_FONT_INFO *StringInfo,
+ OUT UINT8 **GlyphBuffer,
+ OUT EFI_HII_GLYPH_INFO *Cell,
+ OUT UINT8 *Attributes OPTIONAL
+ )
+{
+ HII_DATABASE_RECORD *Node;
+ LIST_ENTRY *Link;
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFont;
+ LIST_ENTRY *Link1;
+ UINT16 Index;
+ EFI_NARROW_GLYPH Narrow;
+ EFI_WIDE_GLYPH Wide;
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+ UINTN HeaderSize;
+ EFI_NARROW_GLYPH *NarrowPtr;
+ EFI_WIDE_GLYPH *WidePtr;
+
+ if ((GlyphBuffer == NULL) || (Cell == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Private == NULL) || (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (Cell, sizeof (EFI_HII_GLYPH_INFO));
+
+ //
+ // If StringInfo is not NULL, it must point to an existing EFI_FONT_INFO rather
+ // than system default font and color.
+ // If NULL, try to find the character in simplified font packages since
+ // default system font is the fixed font (narrow or wide glyph).
+ //
+ if (StringInfo != NULL) {
+ if (!IsFontInfoExisted (Private, StringInfo, NULL, NULL, &GlobalFont)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Attributes != NULL) {
+ *Attributes = PROPORTIONAL_GLYPH;
+ }
+
+ return FindGlyphBlock (GlobalFont->FontPackage, Char, GlyphBuffer, Cell, NULL);
+ } else {
+ HeaderSize = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR);
+
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ for (Link1 = Node->PackageList->SimpleFontPkgHdr.ForwardLink;
+ Link1 != &Node->PackageList->SimpleFontPkgHdr;
+ Link1 = Link1->ForwardLink
+ )
+ {
+ SimpleFont = CR (Link1, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE);
+ //
+ // Search the narrow glyph array
+ //
+ NarrowPtr = (EFI_NARROW_GLYPH *)((UINT8 *)(SimpleFont->SimpleFontPkgHdr) + HeaderSize);
+ for (Index = 0; Index < SimpleFont->SimpleFontPkgHdr->NumberOfNarrowGlyphs; Index++) {
+ CopyMem (&Narrow, NarrowPtr + Index, sizeof (EFI_NARROW_GLYPH));
+ if (Narrow.UnicodeWeight == Char) {
+ *GlyphBuffer = (UINT8 *)AllocateZeroPool (EFI_GLYPH_HEIGHT);
+ if (*GlyphBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Cell->Width = EFI_GLYPH_WIDTH;
+ Cell->Height = EFI_GLYPH_HEIGHT;
+ Cell->AdvanceX = Cell->Width;
+ CopyMem (*GlyphBuffer, Narrow.GlyphCol1, Cell->Height);
+ if (Attributes != NULL) {
+ *Attributes = (UINT8)(Narrow.Attributes | NARROW_GLYPH);
+ }
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Search the wide glyph array
+ //
+ WidePtr = (EFI_WIDE_GLYPH *)(NarrowPtr + SimpleFont->SimpleFontPkgHdr->NumberOfNarrowGlyphs);
+ for (Index = 0; Index < SimpleFont->SimpleFontPkgHdr->NumberOfWideGlyphs; Index++) {
+ CopyMem (&Wide, WidePtr + Index, sizeof (EFI_WIDE_GLYPH));
+ if (Wide.UnicodeWeight == Char) {
+ *GlyphBuffer = (UINT8 *)AllocateZeroPool (EFI_GLYPH_HEIGHT * 2);
+ if (*GlyphBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Cell->Width = EFI_GLYPH_WIDTH * 2;
+ Cell->Height = EFI_GLYPH_HEIGHT;
+ Cell->AdvanceX = Cell->Width;
+ CopyMem (*GlyphBuffer, Wide.GlyphCol1, EFI_GLYPH_HEIGHT);
+ CopyMem (*GlyphBuffer + EFI_GLYPH_HEIGHT, Wide.GlyphCol2, EFI_GLYPH_HEIGHT);
+ if (Attributes != NULL) {
+ *Attributes = (UINT8)(Wide.Attributes | EFI_GLYPH_WIDE);
+ }
+
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Convert bitmap data of the glyph to blt structure.
+
+ This is a internal function.
+
+ @param GlyphBuffer Buffer points to bitmap data of glyph.
+ @param Foreground The color of the "on" pixels in the glyph in the
+ bitmap.
+ @param Background The color of the "off" pixels in the glyph in the
+ bitmap.
+ @param ImageWidth Width of the whole image in pixels.
+ @param RowWidth The width of the text on the line, in pixels.
+ @param RowHeight The height of the line, in pixels.
+ @param Transparent If TRUE, the Background color is ignored and all
+ "off" pixels in the character's drawn will use the
+ pixel value from BltBuffer.
+ @param Origin On input, points to the origin of the to be
+ displayed character, on output, points to the
+ next glyph's origin.
+
+**/
+VOID
+NarrowGlyphToBlt (
+ IN UINT8 *GlyphBuffer,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
+ IN UINT16 ImageWidth,
+ IN UINTN RowWidth,
+ IN UINTN RowHeight,
+ IN BOOLEAN Transparent,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
+ )
+{
+ UINT8 Xpos;
+ UINT8 Ypos;
+ UINT8 Height;
+ UINT8 Width;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Buffer;
+
+ ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL);
+
+ Height = EFI_GLYPH_HEIGHT;
+ Width = EFI_GLYPH_WIDTH;
+
+ //
+ // Move position to the left-top corner of char.
+ //
+ Buffer = *Origin - EFI_GLYPH_HEIGHT * ImageWidth;
+
+ //
+ // Char may be partially displayed when CLIP_X or CLIP_Y is not set.
+ //
+ if (RowHeight < Height) {
+ Height = (UINT8)RowHeight;
+ }
+
+ if (RowWidth < Width) {
+ Width = (UINT8)RowWidth;
+ }
+
+ for (Ypos = 0; Ypos < Height; Ypos++) {
+ for (Xpos = 0; Xpos < Width; Xpos++) {
+ if ((GlyphBuffer[Ypos] & (1 << (EFI_GLYPH_WIDTH - Xpos - 1))) != 0) {
+ Buffer[Ypos * ImageWidth + Xpos] = Foreground;
+ } else {
+ if (!Transparent) {
+ Buffer[Ypos * ImageWidth + Xpos] = Background;
+ }
+ }
+ }
+ }
+
+ *Origin = *Origin + EFI_GLYPH_WIDTH;
+}
+
+/**
+ Convert bitmap data of the glyph to blt structure.
+
+ This is a internal function.
+
+ @param GlyphBuffer Buffer points to bitmap data of glyph.
+ @param Foreground The color of the "on" pixels in the glyph in the
+ bitmap.
+ @param Background The color of the "off" pixels in the glyph in the
+ bitmap.
+ @param ImageWidth Width of the whole image in pixels.
+ @param BaseLine BaseLine in the line.
+ @param RowWidth The width of the text on the line, in pixels.
+ @param RowHeight The height of the line, in pixels.
+ @param Transparent If TRUE, the Background color is ignored and all
+ "off" pixels in the character's drawn will use the
+ pixel value from BltBuffer.
+ @param Cell Points to EFI_HII_GLYPH_INFO structure.
+ @param Attributes The attribute of incoming glyph in GlyphBuffer.
+ @param Origin On input, points to the origin of the to be
+ displayed character, on output, points to the
+ next glyph's origin.
+
+
+**/
+VOID
+GlyphToBlt (
+ IN UINT8 *GlyphBuffer,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
+ IN UINT16 ImageWidth,
+ IN UINT16 BaseLine,
+ IN UINTN RowWidth,
+ IN UINTN RowHeight,
+ IN BOOLEAN Transparent,
+ IN CONST EFI_HII_GLYPH_INFO *Cell,
+ IN UINT8 Attributes,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
+ )
+{
+ UINT16 Xpos;
+ UINT16 Ypos;
+ UINT8 Data;
+ UINT16 Index;
+ UINT16 YposOffset;
+ UINTN OffsetY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+
+ ASSERT (Origin != NULL && *Origin != NULL && Cell != NULL);
+
+ //
+ // Only adjust origin position if char has no bitmap.
+ //
+ if (GlyphBuffer == NULL) {
+ *Origin = *Origin + Cell->AdvanceX;
+ return;
+ }
+
+ //
+ // Move position to the left-top corner of char.
+ //
+ BltBuffer = *Origin + Cell->OffsetX - (Cell->OffsetY + Cell->Height) * ImageWidth;
+ YposOffset = (UINT16)(BaseLine - (Cell->OffsetY + Cell->Height));
+
+ //
+ // Since non-spacing key will be printed OR'd with the previous glyph, don't
+ // write 0.
+ //
+ if ((Attributes & EFI_GLYPH_NON_SPACING) == EFI_GLYPH_NON_SPACING) {
+ Transparent = TRUE;
+ }
+
+ //
+ // The glyph's upper left hand corner pixel is the most significant bit of the
+ // first bitmap byte.
+ //
+ for (Ypos = 0; Ypos < Cell->Height && (((UINT32)Ypos + YposOffset) < RowHeight); Ypos++) {
+ OffsetY = BITMAP_LEN_1_BIT (Cell->Width, Ypos);
+
+ //
+ // All bits in these bytes are meaningful.
+ //
+ for (Xpos = 0; Xpos < Cell->Width / 8; Xpos++) {
+ Data = *(GlyphBuffer + OffsetY + Xpos);
+ for (Index = 0; Index < 8 && (((UINT32)Xpos * 8 + Index + Cell->OffsetX) < RowWidth); Index++) {
+ if ((Data & (1 << (8 - Index - 1))) != 0) {
+ BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Foreground;
+ } else {
+ if (!Transparent) {
+ BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Background;
+ }
+ }
+ }
+ }
+
+ if (Cell->Width % 8 != 0) {
+ //
+ // There are some padding bits in this byte. Ignore them.
+ //
+ Data = *(GlyphBuffer + OffsetY + Xpos);
+ for (Index = 0; Index < Cell->Width % 8 && (((UINT32)Xpos * 8 + Index + Cell->OffsetX) < RowWidth); Index++) {
+ if ((Data & (1 << (8 - Index - 1))) != 0) {
+ BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Foreground;
+ } else {
+ if (!Transparent) {
+ BltBuffer[Ypos * ImageWidth + Xpos * 8 + Index] = Background;
+ }
+ }
+ }
+ } // end of if (Width % 8...)
+ } // end of for (Ypos=0...)
+
+ *Origin = *Origin + Cell->AdvanceX;
+}
+
+/**
+ Convert bitmap data of the glyph to blt structure.
+
+ This is a internal function.
+
+ @param GlyphBuffer Buffer points to bitmap data of glyph.
+ @param Foreground The color of the "on" pixels in the glyph in the
+ bitmap.
+ @param Background The color of the "off" pixels in the glyph in the
+ bitmap.
+ @param ImageWidth Width of the whole image in pixels.
+ @param BaseLine BaseLine in the line.
+ @param RowWidth The width of the text on the line, in pixels.
+ @param RowHeight The height of the line, in pixels.
+ @param Transparent If TRUE, the Background color is ignored and all
+ "off" pixels in the character's drawn will use the
+ pixel value from BltBuffer.
+ @param Cell Points to EFI_HII_GLYPH_INFO structure.
+ @param Attributes The attribute of incoming glyph in GlyphBuffer.
+ @param Origin On input, points to the origin of the to be
+ displayed character, on output, points to the
+ next glyph's origin.
+
+ @return Points to the address of next origin node in BltBuffer.
+
+**/
+VOID
+GlyphToImage (
+ IN UINT8 *GlyphBuffer,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
+ IN UINT16 ImageWidth,
+ IN UINT16 BaseLine,
+ IN UINTN RowWidth,
+ IN UINTN RowHeight,
+ IN BOOLEAN Transparent,
+ IN CONST EFI_HII_GLYPH_INFO *Cell,
+ IN UINT8 Attributes,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
+ )
+{
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Buffer;
+
+ ASSERT (Origin != NULL && *Origin != NULL && Cell != NULL);
+
+ Buffer = *Origin;
+
+ if ((Attributes & EFI_GLYPH_NON_SPACING) == EFI_GLYPH_NON_SPACING) {
+ //
+ // This character is a non-spacing key, print it OR'd with the previous glyph.
+ // without advancing cursor.
+ //
+ Buffer -= Cell->AdvanceX;
+ GlyphToBlt (
+ GlyphBuffer,
+ Foreground,
+ Background,
+ ImageWidth,
+ BaseLine,
+ RowWidth,
+ RowHeight,
+ Transparent,
+ Cell,
+ Attributes,
+ &Buffer
+ );
+ } else if ((Attributes & EFI_GLYPH_WIDE) == EFI_GLYPH_WIDE) {
+ //
+ // This character is wide glyph, i.e. 16 pixels * 19 pixels.
+ // Draw it as two narrow glyphs.
+ //
+ NarrowGlyphToBlt (
+ GlyphBuffer,
+ Foreground,
+ Background,
+ ImageWidth,
+ RowWidth,
+ RowHeight,
+ Transparent,
+ Origin
+ );
+
+ NarrowGlyphToBlt (
+ GlyphBuffer + EFI_GLYPH_HEIGHT,
+ Foreground,
+ Background,
+ ImageWidth,
+ RowWidth,
+ RowHeight,
+ Transparent,
+ Origin
+ );
+ } else if ((Attributes & NARROW_GLYPH) == NARROW_GLYPH) {
+ //
+ // This character is narrow glyph, i.e. 8 pixels * 19 pixels.
+ //
+ NarrowGlyphToBlt (
+ GlyphBuffer,
+ Foreground,
+ Background,
+ ImageWidth,
+ RowWidth,
+ RowHeight,
+ Transparent,
+ Origin
+ );
+ } else if ((Attributes & PROPORTIONAL_GLYPH) == PROPORTIONAL_GLYPH) {
+ //
+ // This character is proportional glyph, i.e. Cell->Width * Cell->Height pixels.
+ //
+ GlyphToBlt (
+ GlyphBuffer,
+ Foreground,
+ Background,
+ ImageWidth,
+ BaseLine,
+ RowWidth,
+ RowHeight,
+ Transparent,
+ Cell,
+ Attributes,
+ Origin
+ );
+ }
+}
+
+/**
+ Write the output parameters of FindGlyphBlock().
+
+ This is a internal function.
+
+ @param BufferIn Buffer which stores the bitmap data of the found
+ block.
+ @param BufferLen Length of BufferIn.
+ @param InputCell Buffer which stores cell information of the
+ encoded bitmap.
+ @param GlyphBuffer Output the corresponding bitmap data of the found
+ block. It is the caller's responsibility to free
+ this buffer.
+ @param Cell Output cell information of the encoded bitmap.
+ @param GlyphBufferLen If not NULL, output the length of GlyphBuffer.
+
+ @retval EFI_SUCCESS The operation is performed successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
+ task.
+
+**/
+EFI_STATUS
+WriteOutputParam (
+ IN UINT8 *BufferIn,
+ IN UINTN BufferLen,
+ IN EFI_HII_GLYPH_INFO *InputCell,
+ OUT UINT8 **GlyphBuffer OPTIONAL,
+ OUT EFI_HII_GLYPH_INFO *Cell OPTIONAL,
+ OUT UINTN *GlyphBufferLen OPTIONAL
+ )
+{
+ if ((BufferIn == NULL) || (InputCell == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Cell != NULL) {
+ CopyMem (Cell, InputCell, sizeof (EFI_HII_GLYPH_INFO));
+ }
+
+ if ((GlyphBuffer != NULL) && (BufferLen > 0)) {
+ *GlyphBuffer = (UINT8 *)AllocateZeroPool (BufferLen);
+ if (*GlyphBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (*GlyphBuffer, BufferIn, BufferLen);
+ }
+
+ if (GlyphBufferLen != NULL) {
+ *GlyphBufferLen = BufferLen;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Parse all glyph blocks to find a glyph block specified by CharValue.
+ If CharValue = (CHAR16) (-1), collect all default character cell information
+ within this font package and backup its information.
+
+ @param FontPackage Hii string package instance.
+ @param CharValue Unicode character value, which identifies a glyph
+ block.
+ @param GlyphBuffer Output the corresponding bitmap data of the found
+ block. It is the caller's responsibility to free
+ this buffer.
+ @param Cell Output cell information of the encoded bitmap.
+ @param GlyphBufferLen If not NULL, output the length of GlyphBuffer.
+
+ @retval EFI_SUCCESS The bitmap data is retrieved successfully.
+ @retval EFI_NOT_FOUND The specified CharValue does not exist in current
+ database.
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
+ task.
+
+**/
+EFI_STATUS
+FindGlyphBlock (
+ IN HII_FONT_PACKAGE_INSTANCE *FontPackage,
+ IN CHAR16 CharValue,
+ OUT UINT8 **GlyphBuffer OPTIONAL,
+ OUT EFI_HII_GLYPH_INFO *Cell OPTIONAL,
+ OUT UINTN *GlyphBufferLen OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *BlockPtr;
+ UINT16 CharCurrent;
+ UINT16 Length16;
+ UINT32 Length32;
+ EFI_HII_GIBT_GLYPHS_BLOCK Glyphs;
+ UINTN BufferLen;
+ UINT16 Index;
+ EFI_HII_GLYPH_INFO DefaultCell;
+ EFI_HII_GLYPH_INFO LocalCell;
+ INT16 MinOffsetY;
+ UINT16 BaseLine;
+
+ ASSERT (FontPackage != NULL);
+ ASSERT (FontPackage->Signature == HII_FONT_PACKAGE_SIGNATURE);
+ BaseLine = 0;
+ MinOffsetY = 0;
+
+ if (CharValue == (CHAR16)(-1)) {
+ //
+ // Collect the cell information specified in font package fixed header.
+ // Use CharValue =0 to represent this particular cell.
+ //
+ Status = NewCell (
+ 0,
+ &FontPackage->GlyphInfoList,
+ (EFI_HII_GLYPH_INFO *)((UINT8 *)FontPackage->FontPkgHdr + 3 * sizeof (UINT32))
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CopyMem (
+ &LocalCell,
+ (UINT8 *)FontPackage->FontPkgHdr + 3 * sizeof (UINT32),
+ sizeof (EFI_HII_GLYPH_INFO)
+ );
+ }
+
+ BlockPtr = FontPackage->GlyphBlock;
+ CharCurrent = 1;
+ BufferLen = 0;
+
+ while (*BlockPtr != EFI_HII_GIBT_END) {
+ switch (*BlockPtr) {
+ case EFI_HII_GIBT_DEFAULTS:
+ //
+ // Collect all default character cell information specified by
+ // EFI_HII_GIBT_DEFAULTS.
+ //
+ if (CharValue == (CHAR16)(-1)) {
+ Status = NewCell (
+ CharCurrent,
+ &FontPackage->GlyphInfoList,
+ (EFI_HII_GLYPH_INFO *)(BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK))
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CopyMem (
+ &LocalCell,
+ BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),
+ sizeof (EFI_HII_GLYPH_INFO)
+ );
+ if (BaseLine < LocalCell.Height + LocalCell.OffsetY) {
+ BaseLine = (UINT16)(LocalCell.Height + LocalCell.OffsetY);
+ }
+
+ if (MinOffsetY > LocalCell.OffsetY) {
+ MinOffsetY = LocalCell.OffsetY;
+ }
+ }
+
+ BlockPtr += sizeof (EFI_HII_GIBT_DEFAULTS_BLOCK);
+ break;
+
+ case EFI_HII_GIBT_DUPLICATE:
+ if (CharCurrent == CharValue) {
+ CopyMem (&CharValue, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (CHAR16));
+ CharCurrent = 1;
+ BlockPtr = FontPackage->GlyphBlock;
+ continue;
+ }
+
+ CharCurrent++;
+ BlockPtr += sizeof (EFI_HII_GIBT_DUPLICATE_BLOCK);
+ break;
+
+ case EFI_HII_GIBT_EXT1:
+ BlockPtr += *(UINT8 *)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8));
+ break;
+ case EFI_HII_GIBT_EXT2:
+ CopyMem (
+ &Length16,
+ (UINT8 *)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8)),
+ sizeof (UINT16)
+ );
+ BlockPtr += Length16;
+ break;
+ case EFI_HII_GIBT_EXT4:
+ CopyMem (
+ &Length32,
+ (UINT8 *)((UINTN)BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8)),
+ sizeof (UINT32)
+ );
+ BlockPtr += Length32;
+ break;
+
+ case EFI_HII_GIBT_GLYPH:
+ CopyMem (
+ &LocalCell,
+ BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),
+ sizeof (EFI_HII_GLYPH_INFO)
+ );
+ if (CharValue == (CHAR16)(-1)) {
+ if (BaseLine < LocalCell.Height + LocalCell.OffsetY) {
+ BaseLine = (UINT16)(LocalCell.Height + LocalCell.OffsetY);
+ }
+
+ if (MinOffsetY > LocalCell.OffsetY) {
+ MinOffsetY = LocalCell.OffsetY;
+ }
+ }
+
+ BufferLen = BITMAP_LEN_1_BIT (LocalCell.Width, LocalCell.Height);
+ if (CharCurrent == CharValue) {
+ return WriteOutputParam (
+ (UINT8 *)((UINTN)BlockPtr + sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8)),
+ BufferLen,
+ &LocalCell,
+ GlyphBuffer,
+ Cell,
+ GlyphBufferLen
+ );
+ }
+
+ CharCurrent++;
+ BlockPtr += sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8) + BufferLen;
+ break;
+
+ case EFI_HII_GIBT_GLYPHS:
+ BlockPtr += sizeof (EFI_HII_GLYPH_BLOCK);
+ CopyMem (&Glyphs.Cell, BlockPtr, sizeof (EFI_HII_GLYPH_INFO));
+ BlockPtr += sizeof (EFI_HII_GLYPH_INFO);
+ CopyMem (&Glyphs.Count, BlockPtr, sizeof (UINT16));
+ BlockPtr += sizeof (UINT16);
+
+ if (CharValue == (CHAR16)(-1)) {
+ if (BaseLine < Glyphs.Cell.Height + Glyphs.Cell.OffsetY) {
+ BaseLine = (UINT16)(Glyphs.Cell.Height + Glyphs.Cell.OffsetY);
+ }
+
+ if (MinOffsetY > Glyphs.Cell.OffsetY) {
+ MinOffsetY = Glyphs.Cell.OffsetY;
+ }
+ }
+
+ BufferLen = BITMAP_LEN_1_BIT (Glyphs.Cell.Width, Glyphs.Cell.Height);
+ for (Index = 0; Index < Glyphs.Count; Index++) {
+ if (CharCurrent + Index == CharValue) {
+ return WriteOutputParam (
+ BlockPtr,
+ BufferLen,
+ &Glyphs.Cell,
+ GlyphBuffer,
+ Cell,
+ GlyphBufferLen
+ );
+ }
+
+ BlockPtr += BufferLen;
+ }
+
+ CharCurrent = (UINT16)(CharCurrent + Glyphs.Count);
+ break;
+
+ case EFI_HII_GIBT_GLYPH_DEFAULT:
+ Status = GetCell (CharCurrent, &FontPackage->GlyphInfoList, &DefaultCell);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (CharValue == (CHAR16)(-1)) {
+ if (BaseLine < DefaultCell.Height + DefaultCell.OffsetY) {
+ BaseLine = (UINT16)(DefaultCell.Height + DefaultCell.OffsetY);
+ }
+
+ if (MinOffsetY > DefaultCell.OffsetY) {
+ MinOffsetY = DefaultCell.OffsetY;
+ }
+ }
+
+ BufferLen = BITMAP_LEN_1_BIT (DefaultCell.Width, DefaultCell.Height);
+
+ if (CharCurrent == CharValue) {
+ return WriteOutputParam (
+ BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),
+ BufferLen,
+ &DefaultCell,
+ GlyphBuffer,
+ Cell,
+ GlyphBufferLen
+ );
+ }
+
+ CharCurrent++;
+ BlockPtr += sizeof (EFI_HII_GLYPH_BLOCK) + BufferLen;
+ break;
+
+ case EFI_HII_GIBT_GLYPHS_DEFAULT:
+ CopyMem (&Length16, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (UINT16));
+ Status = GetCell (CharCurrent, &FontPackage->GlyphInfoList, &DefaultCell);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (CharValue == (CHAR16)(-1)) {
+ if (BaseLine < DefaultCell.Height + DefaultCell.OffsetY) {
+ BaseLine = (UINT16)(DefaultCell.Height + DefaultCell.OffsetY);
+ }
+
+ if (MinOffsetY > DefaultCell.OffsetY) {
+ MinOffsetY = DefaultCell.OffsetY;
+ }
+ }
+
+ BufferLen = BITMAP_LEN_1_BIT (DefaultCell.Width, DefaultCell.Height);
+ BlockPtr += sizeof (EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK) - sizeof (UINT8);
+ for (Index = 0; Index < Length16; Index++) {
+ if (CharCurrent + Index == CharValue) {
+ return WriteOutputParam (
+ BlockPtr,
+ BufferLen,
+ &DefaultCell,
+ GlyphBuffer,
+ Cell,
+ GlyphBufferLen
+ );
+ }
+
+ BlockPtr += BufferLen;
+ }
+
+ CharCurrent = (UINT16)(CharCurrent + Length16);
+ break;
+
+ case EFI_HII_GIBT_SKIP1:
+ CharCurrent = (UINT16)(CharCurrent + (UINT16)(*(BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK))));
+ BlockPtr += sizeof (EFI_HII_GIBT_SKIP1_BLOCK);
+ break;
+ case EFI_HII_GIBT_SKIP2:
+ CopyMem (&Length16, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (UINT16));
+ CharCurrent = (UINT16)(CharCurrent + Length16);
+ BlockPtr += sizeof (EFI_HII_GIBT_SKIP2_BLOCK);
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ if (CharValue < CharCurrent) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ if (CharValue == (CHAR16)(-1)) {
+ FontPackage->BaseLine = BaseLine;
+ FontPackage->Height = (UINT16)(BaseLine - MinOffsetY);
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Copy a Font Name to a new created EFI_FONT_INFO structure.
+
+ This is a internal function.
+
+ @param FontName NULL-terminated string.
+ @param FontInfo a new EFI_FONT_INFO which stores the FontName.
+ It's caller's responsibility to free this buffer.
+
+ @retval EFI_SUCCESS FontInfo is allocated and copied with FontName.
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
+ task.
+
+**/
+EFI_STATUS
+SaveFontName (
+ IN EFI_STRING FontName,
+ OUT EFI_FONT_INFO **FontInfo
+ )
+{
+ UINTN FontInfoLen;
+ UINTN NameSize;
+
+ ASSERT (FontName != NULL && FontInfo != NULL);
+
+ NameSize = StrSize (FontName);
+ FontInfoLen = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + NameSize;
+ *FontInfo = (EFI_FONT_INFO *)AllocateZeroPool (FontInfoLen);
+ if (*FontInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StrCpyS ((*FontInfo)->FontName, NameSize / sizeof (CHAR16), FontName);
+ return EFI_SUCCESS;
+}
+
+/**
+ Retrieve system default font and color.
+
+ @param Private HII database driver private data.
+ @param FontInfo Points to system default font output-related
+ information. It's caller's responsibility to free
+ this buffer.
+ @param FontInfoSize If not NULL, output the size of buffer FontInfo.
+
+ @retval EFI_SUCCESS Cell information is added to the GlyphInfoList.
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
+ task.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+EFI_STATUS
+GetSystemFont (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ OUT EFI_FONT_DISPLAY_INFO **FontInfo,
+ OUT UINTN *FontInfoSize OPTIONAL
+ )
+{
+ EFI_FONT_DISPLAY_INFO *Info;
+ UINTN InfoSize;
+ UINTN NameSize;
+
+ if ((Private == NULL) || (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FontInfo == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // The standard font always has the name "sysdefault".
+ //
+ NameSize = StrSize (L"sysdefault");
+ InfoSize = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + NameSize;
+ Info = (EFI_FONT_DISPLAY_INFO *)AllocateZeroPool (InfoSize);
+ if (Info == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Info->ForegroundColor = mHiiEfiColors[Private->Attribute & 0x0f];
+ ASSERT ((Private->Attribute >> 4) < 8);
+ Info->BackgroundColor = mHiiEfiColors[Private->Attribute >> 4];
+ Info->FontInfoMask = EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_SYS_STYLE;
+ Info->FontInfo.FontStyle = 0;
+ Info->FontInfo.FontSize = EFI_GLYPH_HEIGHT;
+ StrCpyS (Info->FontInfo.FontName, NameSize / sizeof (CHAR16), L"sysdefault");
+
+ *FontInfo = Info;
+ if (FontInfoSize != NULL) {
+ *FontInfoSize = InfoSize;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check whether EFI_FONT_DISPLAY_INFO points to system default font and color or
+ returns the system default according to the optional inputs.
+
+ This is a internal function.
+
+ @param Private HII database driver private data.
+ @param StringInfo Points to the string output information,
+ including the color and font.
+ @param SystemInfo If not NULL, points to system default font and color.
+
+ @param SystemInfoLen If not NULL, output the length of default system
+ info.
+
+ @retval TRUE Yes, it points to system default.
+ @retval FALSE No.
+
+**/
+BOOLEAN
+IsSystemFontInfo (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_FONT_DISPLAY_INFO *StringInfo,
+ OUT EFI_FONT_DISPLAY_INFO **SystemInfo OPTIONAL,
+ OUT UINTN *SystemInfoLen OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_FONT_DISPLAY_INFO *SystemDefault;
+ UINTN DefaultLen;
+ BOOLEAN Flag;
+
+ ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
+
+ if ((StringInfo == NULL) && (SystemInfo == NULL)) {
+ return TRUE;
+ }
+
+ SystemDefault = NULL;
+ DefaultLen = 0;
+
+ Status = GetSystemFont (Private, &SystemDefault, &DefaultLen);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT ((SystemDefault != NULL) && (DefaultLen != 0));
+
+ //
+ // Record the system default info.
+ //
+ if (SystemInfo != NULL) {
+ *SystemInfo = SystemDefault;
+ }
+
+ if (SystemInfoLen != NULL) {
+ *SystemInfoLen = DefaultLen;
+ }
+
+ if (StringInfo == NULL) {
+ return TRUE;
+ }
+
+ Flag = FALSE;
+ //
+ // Check the FontInfoMask to see whether it is retrieving system info.
+ //
+ if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) == 0) {
+ if (StrCmp (StringInfo->FontInfo.FontName, SystemDefault->FontInfo.FontName) != 0) {
+ goto Exit;
+ }
+ }
+
+ if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) == 0) {
+ if (StringInfo->FontInfo.FontSize != SystemDefault->FontInfo.FontSize) {
+ goto Exit;
+ }
+ }
+
+ if ((StringInfo->FontInfoMask & (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) == 0) {
+ if (StringInfo->FontInfo.FontStyle != SystemDefault->FontInfo.FontStyle) {
+ goto Exit;
+ }
+ }
+
+ if ((StringInfo->FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) == 0) {
+ if (CompareMem (
+ &StringInfo->ForegroundColor,
+ &SystemDefault->ForegroundColor,
+ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ ) != 0)
+ {
+ goto Exit;
+ }
+ }
+
+ if ((StringInfo->FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) == 0) {
+ if (CompareMem (
+ &StringInfo->BackgroundColor,
+ &SystemDefault->BackgroundColor,
+ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ ) != 0)
+ {
+ goto Exit;
+ }
+ }
+
+ Flag = TRUE;
+
+Exit:
+ if (SystemInfo == NULL) {
+ if (SystemDefault != NULL) {
+ FreePool (SystemDefault);
+ }
+ }
+
+ return Flag;
+}
+
+/**
+ This function checks whether EFI_FONT_INFO exists in current database. If
+ FontInfoMask is specified, check what options can be used to make a match.
+ Note that the masks relate to where the system default should be supplied
+ are ignored by this function.
+
+ @param Private Hii database private structure.
+ @param FontInfo Points to EFI_FONT_INFO structure.
+ @param FontInfoMask If not NULL, describes what options can be used
+ to make a match between the font requested and
+ the font available. The caller must guarantee
+ this mask is valid.
+ @param FontHandle On entry, Points to the font handle returned by a
+ previous call to GetFontInfo() or NULL to start
+ with the first font.
+ @param GlobalFontInfo If not NULL, output the corresponding global font
+ info.
+
+ @retval TRUE Existed
+ @retval FALSE Not existed
+
+**/
+BOOLEAN
+IsFontInfoExisted (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_FONT_INFO *FontInfo,
+ IN EFI_FONT_INFO_MASK *FontInfoMask OPTIONAL,
+ IN EFI_FONT_HANDLE FontHandle OPTIONAL,
+ OUT HII_GLOBAL_FONT_INFO **GlobalFontInfo OPTIONAL
+ )
+{
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+ HII_GLOBAL_FONT_INFO *GlobalFontBackup1;
+ HII_GLOBAL_FONT_INFO *GlobalFontBackup2;
+ LIST_ENTRY *Link;
+ EFI_FONT_INFO_MASK Mask;
+ BOOLEAN Matched;
+ BOOLEAN VagueMatched1;
+ BOOLEAN VagueMatched2;
+
+ ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
+ ASSERT (FontInfo != NULL);
+
+ //
+ // Matched flag represents an exactly match; VagueMatched1 represents a RESIZE
+ // or RESTYLE match; VagueMatched2 represents a RESIZE | RESTYLE match.
+ //
+ Matched = FALSE;
+ VagueMatched1 = FALSE;
+ VagueMatched2 = FALSE;
+
+ Mask = 0;
+ GlobalFontBackup1 = NULL;
+ GlobalFontBackup2 = NULL;
+
+ // The process of where the system default should be supplied instead of
+ // the specified font info beyonds this function's scope.
+ //
+ if (FontInfoMask != NULL) {
+ Mask = *FontInfoMask & (~SYS_FONT_INFO_MASK);
+ }
+
+ //
+ // If not NULL, FontHandle points to the next node of the last searched font
+ // node by previous call.
+ //
+ if (FontHandle == NULL) {
+ Link = Private->FontInfoList.ForwardLink;
+ } else {
+ Link = (LIST_ENTRY *)FontHandle;
+ }
+
+ for ( ; Link != &Private->FontInfoList; Link = Link->ForwardLink) {
+ GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);
+ if (FontInfoMask == NULL) {
+ if (CompareMem (GlobalFont->FontInfo, FontInfo, GlobalFont->FontInfoSize) == 0) {
+ if (GlobalFontInfo != NULL) {
+ *GlobalFontInfo = GlobalFont;
+ }
+
+ return TRUE;
+ }
+ } else {
+ //
+ // Check which options could be used to make a match.
+ //
+ switch (Mask) {
+ case EFI_FONT_INFO_ANY_FONT:
+ if ((GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) &&
+ (GlobalFont->FontInfo->FontSize == FontInfo->FontSize))
+ {
+ Matched = TRUE;
+ }
+
+ break;
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE:
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ Matched = TRUE;
+ }
+
+ break;
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE:
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+ Matched = TRUE;
+ }
+
+ break;
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_ANY_STYLE:
+ Matched = TRUE;
+ break;
+ //
+ // If EFI_FONT_INFO_RESTYLE is specified, then the system may attempt to
+ // remove some of the specified styles to meet the style requested.
+ //
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE:
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+ Matched = TRUE;
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ }
+
+ break;
+ //
+ // If EFI_FONT_INFO_RESIZE is specified, then the system may attempt to
+ // stretch or shrink a font to meet the size requested.
+ //
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESIZE:
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ Matched = TRUE;
+ } else {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ }
+
+ break;
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_RESIZE:
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ Matched = TRUE;
+ } else {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ } else {
+ VagueMatched2 = TRUE;
+ GlobalFontBackup2 = GlobalFont;
+ }
+ }
+
+ break;
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE:
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ Matched = TRUE;
+ } else {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+
+ break;
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE:
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+ Matched = TRUE;
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+
+ break;
+ case EFI_FONT_INFO_ANY_STYLE:
+ if ((CompareMem (
+ GlobalFont->FontInfo->FontName,
+ FontInfo->FontName,
+ StrSize (FontInfo->FontName)
+ ) == 0) &&
+ (GlobalFont->FontInfo->FontSize == FontInfo->FontSize))
+ {
+ Matched = TRUE;
+ }
+
+ break;
+ case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_ANY_SIZE:
+ if (CompareMem (
+ GlobalFont->FontInfo->FontName,
+ FontInfo->FontName,
+ StrSize (FontInfo->FontName)
+ ) == 0)
+ {
+ Matched = TRUE;
+ }
+
+ break;
+ case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE:
+ if (CompareMem (
+ GlobalFont->FontInfo->FontName,
+ FontInfo->FontName,
+ StrSize (FontInfo->FontName)
+ ) == 0)
+ {
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ Matched = TRUE;
+ } else {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ }
+
+ break;
+ case EFI_FONT_INFO_ANY_SIZE:
+ if ((CompareMem (
+ GlobalFont->FontInfo->FontName,
+ FontInfo->FontName,
+ StrSize (FontInfo->FontName)
+ ) == 0) &&
+ (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle))
+ {
+ Matched = TRUE;
+ }
+
+ break;
+ case EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE:
+ if (CompareMem (
+ GlobalFont->FontInfo->FontName,
+ FontInfo->FontName,
+ StrSize (FontInfo->FontName)
+ ) == 0)
+ {
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+ Matched = TRUE;
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ }
+
+ break;
+ case EFI_FONT_INFO_RESTYLE:
+ if ((CompareMem (
+ GlobalFont->FontInfo->FontName,
+ FontInfo->FontName,
+ StrSize (FontInfo->FontName)
+ ) == 0) &&
+ (GlobalFont->FontInfo->FontSize == FontInfo->FontSize))
+ {
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+ Matched = TRUE;
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ }
+
+ break;
+ case EFI_FONT_INFO_RESIZE:
+ if ((CompareMem (
+ GlobalFont->FontInfo->FontName,
+ FontInfo->FontName,
+ StrSize (FontInfo->FontName)
+ ) == 0) &&
+ (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle))
+ {
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ Matched = TRUE;
+ } else {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ }
+
+ break;
+ case EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_RESTYLE:
+ if (CompareMem (
+ GlobalFont->FontInfo->FontName,
+ FontInfo->FontName,
+ StrSize (FontInfo->FontName)
+ ) == 0)
+ {
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ Matched = TRUE;
+ } else {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ } else {
+ VagueMatched2 = TRUE;
+ GlobalFontBackup2 = GlobalFont;
+ }
+ }
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ if (Matched) {
+ if (GlobalFontInfo != NULL) {
+ *GlobalFontInfo = GlobalFont;
+ }
+
+ return TRUE;
+ }
+ }
+ }
+
+ if (VagueMatched1) {
+ if (GlobalFontInfo != NULL) {
+ *GlobalFontInfo = GlobalFontBackup1;
+ }
+
+ return TRUE;
+ } else if (VagueMatched2) {
+ if (GlobalFontInfo != NULL) {
+ *GlobalFontInfo = GlobalFontBackup2;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Check whether the unicode represents a line break or not.
+
+ This is a internal function. Please see Section 27.2.6 of the UEFI Specification
+ for a description of the supported string format.
+
+ @param Char Unicode character
+
+ @retval 0 Yes, it forces a line break.
+ @retval 1 Yes, it presents a line break opportunity
+ @retval 2 Yes, it requires a line break happen before and after it.
+ @retval -1 No, it is not a link break.
+
+**/
+INT8
+IsLineBreak (
+ IN CHAR16 Char
+ )
+{
+ switch (Char) {
+ //
+ // Mandatory line break characters, which force a line-break
+ //
+ case 0x000A:
+ case 0x000C:
+ case 0x000D:
+ case 0x2028:
+ case 0x2029:
+ return 0;
+ //
+ // Space characters, which is taken as a line-break opportunity
+ //
+ case 0x0020:
+ case 0x1680:
+ case 0x2000:
+ case 0x2001:
+ case 0x2002:
+ case 0x2003:
+ case 0x2004:
+ case 0x2005:
+ case 0x2006:
+ case 0x2008:
+ case 0x2009:
+ case 0x200A:
+ case 0x205F:
+ //
+ // In-Word Break Opportunities
+ //
+ case 0x200B:
+ return 1;
+ //
+ // A space which is not a line-break opportunity
+ //
+ case 0x00A0:
+ case 0x202F:
+ //
+ // A hyphen which is not a line-break opportunity
+ //
+ case 0x2011:
+ return -1;
+ //
+ // Hyphen characters which describe line break opportunities after the character
+ //
+ case 0x058A:
+ case 0x2010:
+ case 0x2012:
+ case 0x2013:
+ case 0x0F0B:
+ case 0x1361:
+ case 0x17D5:
+ return 1;
+ //
+ // A hyphen which describes line break opportunities before and after them, but not between a pair of them
+ //
+ case 0x2014:
+ return 2;
+ }
+
+ return -1;
+}
+
+/**
+ Renders a string to a bitmap or to the display.
+
+ @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
+ @param Flags Describes how the string is to be drawn.
+ @param String Points to the null-terminated string to be
+ displayed.
+ @param StringInfo Points to the string output information,
+ including the color and font. If NULL, then the
+ string will be output in the default system font
+ and color.
+ @param Blt If this points to a non-NULL on entry, this
+ points to the image, which is Width pixels wide
+ and Height pixels high. The string will be drawn
+ onto this image and
+ EFI_HII_OUT_FLAG_CLIP is implied. If this points
+ to a NULL on entry, then a buffer
+ will be allocated to hold the generated image and
+ the pointer updated on exit. It is the caller's
+ responsibility to free this buffer.
+ @param BltX Specifies the offset from the left and top edge
+ of the image of the first character cell in the
+ image.
+ @param BltY Specifies the offset from the left and top edge
+ of the image of the first character cell in the
+ image.
+ @param RowInfoArray If this is non-NULL on entry, then on exit, this
+ will point to an allocated buffer containing
+ row information and RowInfoArraySize will be
+ updated to contain the number of elements.
+ This array describes the characters which were at
+ least partially drawn and the heights of the
+ rows. It is the caller's responsibility to free
+ this buffer.
+ @param RowInfoArraySize If this is non-NULL on entry, then on exit it
+ contains the number of elements in RowInfoArray.
+ @param ColumnInfoArray If this is non-NULL, then on return it will be
+ filled with the horizontal offset for each
+ character in the string on the row where it is
+ displayed. Non-printing characters will have
+ the offset ~0. The caller is responsible to
+ allocate a buffer large enough so that there
+ is one entry for each character in the string,
+ not including the null-terminator. It is possible
+ when character display is normalized that some
+ character cells overlap.
+
+ @retval EFI_SUCCESS The string was successfully rendered.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for
+ RowInfoArray or Blt.
+ @retval EFI_INVALID_PARAMETER The String or Blt was NULL.
+ @retval EFI_INVALID_PARAMETER Flags were invalid combination..
+
+**/
+EFI_STATUS
+EFIAPI
+HiiStringToImage (
+ IN CONST EFI_HII_FONT_PROTOCOL *This,
+ IN EFI_HII_OUT_FLAGS Flags,
+ IN CONST EFI_STRING String,
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY,
+ OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL,
+ OUT UINTN *RowInfoArraySize OPTIONAL,
+ OUT UINTN *ColumnInfoArray OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ UINT8 **GlyphBuf;
+ EFI_HII_GLYPH_INFO *Cell;
+ UINT8 *Attributes;
+ EFI_IMAGE_OUTPUT *Image;
+ EFI_STRING StringPtr;
+ EFI_STRING StringTmp;
+ EFI_HII_ROW_INFO *RowInfo;
+ UINTN LineWidth;
+ UINTN LineHeight;
+ UINTN LineOffset;
+ UINTN LastLineHeight;
+ UINTN BaseLineOffset;
+ UINT16 MaxRowNum;
+ UINT16 RowIndex;
+ UINTN Index;
+ UINTN NextIndex;
+ UINTN Index1;
+ EFI_FONT_DISPLAY_INFO *StringInfoOut;
+ EFI_FONT_DISPLAY_INFO *SystemDefault;
+ EFI_FONT_HANDLE FontHandle;
+ EFI_STRING StringIn;
+ EFI_STRING StringIn2;
+ UINT16 Height;
+ UINT16 BaseLine;
+ EFI_FONT_INFO *FontInfo;
+ BOOLEAN SysFontFlag;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
+ BOOLEAN Transparent;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BufferPtr;
+ UINTN RowInfoSize;
+ BOOLEAN LineBreak;
+ UINTN StrLength;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *RowBufferPtr;
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+ UINT32 PreInitBkgnd;
+
+ //
+ // Check incoming parameters.
+ //
+
+ if ((This == NULL) || (String == NULL) || (Blt == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*Blt == NULL) {
+ //
+ // These two flag cannot be used if Blt is NULL upon entry.
+ //
+ if ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Flags & EFI_HII_OUT_FLAG_CLIP) == EFI_HII_OUT_FLAG_CLIP) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // These two flags require that EFI_HII_OUT_FLAG_CLIP be also set.
+ //
+ if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) == EFI_HII_OUT_FLAG_CLIP_CLEAN_X) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLIP_CLEAN_Y)) == EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // This flag cannot be used with EFI_HII_OUT_FLAG_CLEAN_X.
+ //
+ if ((Flags & (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) == (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*Blt == NULL) {
+ //
+ // Create a new bitmap and draw the string onto this image.
+ //
+ Image = AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
+ if (Image == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Image->Width = 800;
+ Image->Height = 600;
+ Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height *sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ if (Image->Image.Bitmap == NULL) {
+ FreePool (Image);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Other flags are not permitted when Blt is NULL.
+ //
+ Flags &= EFI_HII_OUT_FLAG_WRAP | EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_IGNORE_LINE_BREAK;
+ *Blt = Image;
+ }
+
+ StrLength = StrLen (String);
+ GlyphBuf = (UINT8 **)AllocateZeroPool (StrLength * sizeof (UINT8 *));
+ ASSERT (GlyphBuf != NULL);
+ Cell = (EFI_HII_GLYPH_INFO *)AllocateZeroPool (StrLength * sizeof (EFI_HII_GLYPH_INFO));
+ ASSERT (Cell != NULL);
+ Attributes = (UINT8 *)AllocateZeroPool (StrLength * sizeof (UINT8));
+ ASSERT (Attributes != NULL);
+
+ FontInfo = NULL;
+ RowInfo = NULL;
+ Status = EFI_SUCCESS;
+ StringIn2 = NULL;
+ SystemDefault = NULL;
+ StringIn = NULL;
+
+ //
+ // Calculate the string output information, including specified color and font .
+ // If StringInfo does not points to system font info, it must indicate an existing
+ // EFI_FONT_INFO.
+ //
+ StringInfoOut = NULL;
+ FontHandle = NULL;
+ Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ SysFontFlag = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *)StringInfo, &SystemDefault, NULL);
+
+ if (SysFontFlag) {
+ ASSERT (SystemDefault != NULL);
+ FontInfo = NULL;
+ Height = SystemDefault->FontInfo.FontSize;
+ BaseLine = SystemDefault->FontInfo.FontSize;
+ Foreground = SystemDefault->ForegroundColor;
+ Background = SystemDefault->BackgroundColor;
+ } else {
+ //
+ // StringInfo must not be NULL if it is not system info.
+ //
+ ASSERT (StringInfo != NULL);
+ Status = HiiGetFontInfo (This, &FontHandle, (EFI_FONT_DISPLAY_INFO *)StringInfo, &StringInfoOut, NULL);
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // The specified EFI_FONT_DISPLAY_INFO does not exist in current database.
+ // Use the system font instead. Still use the color specified by StringInfo.
+ //
+ SysFontFlag = TRUE;
+ FontInfo = NULL;
+ Height = SystemDefault->FontInfo.FontSize;
+ BaseLine = SystemDefault->FontInfo.FontSize;
+ Foreground = ((EFI_FONT_DISPLAY_INFO *)StringInfo)->ForegroundColor;
+ Background = ((EFI_FONT_DISPLAY_INFO *)StringInfo)->BackgroundColor;
+ } else if (Status == EFI_SUCCESS) {
+ FontInfo = &StringInfoOut->FontInfo;
+ if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont)) {
+ Height = GlobalFont->FontPackage->Height;
+ BaseLine = GlobalFont->FontPackage->BaseLine;
+ Foreground = StringInfoOut->ForegroundColor;
+ Background = StringInfoOut->BackgroundColor;
+ } else {
+ goto Exit;
+ }
+ } else {
+ goto Exit;
+ }
+ }
+
+ //
+ // Use the maximum height of font as the base line.
+ // And, use the maximum height as line height.
+ //
+ LineHeight = Height;
+ LastLineHeight = Height;
+ BaseLineOffset = Height - BaseLine;
+
+ //
+ // Parse the string to be displayed to drop some ignored characters.
+ //
+
+ StringPtr = String;
+
+ //
+ // Ignore line-break characters only. Hyphens or dash character will be displayed
+ // without line-break opportunity.
+ //
+ if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == EFI_HII_IGNORE_LINE_BREAK) {
+ StringIn = AllocateZeroPool (StrSize (StringPtr));
+ if (StringIn == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ StringTmp = StringIn;
+ while (*StringPtr != 0) {
+ if (IsLineBreak (*StringPtr) == 0) {
+ StringPtr++;
+ } else {
+ *StringTmp++ = *StringPtr++;
+ }
+ }
+
+ *StringTmp = 0;
+ StringPtr = StringIn;
+ }
+
+ //
+ // If EFI_HII_IGNORE_IF_NO_GLYPH is set, then characters which have no glyphs
+ // are not drawn. Otherwise they are replaced with Unicode character 0xFFFD.
+ //
+ StringIn2 = AllocateZeroPool (StrSize (StringPtr));
+ if (StringIn2 == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ Index = 0;
+ StringTmp = StringIn2;
+ StrLength = StrLen (StringPtr);
+ while (*StringPtr != 0 && Index < StrLength) {
+ if (IsLineBreak (*StringPtr) == 0) {
+ *StringTmp++ = *StringPtr++;
+ Index++;
+ continue;
+ }
+
+ Status = GetGlyphBuffer (Private, *StringPtr, FontInfo, &GlyphBuf[Index], &Cell[Index], &Attributes[Index]);
+ if (Status == EFI_NOT_FOUND) {
+ if ((Flags & EFI_HII_IGNORE_IF_NO_GLYPH) == EFI_HII_IGNORE_IF_NO_GLYPH) {
+ GlyphBuf[Index] = NULL;
+ ZeroMem (&Cell[Index], sizeof (Cell[Index]));
+ Status = EFI_SUCCESS;
+ } else {
+ //
+ // Unicode 0xFFFD must exist in current hii database if this flag is not set.
+ //
+ Status = GetGlyphBuffer (
+ Private,
+ REPLACE_UNKNOWN_GLYPH,
+ FontInfo,
+ &GlyphBuf[Index],
+ &Cell[Index],
+ &Attributes[Index]
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ *StringTmp++ = *StringPtr++;
+ Index++;
+ }
+
+ *StringTmp = 0;
+ StringPtr = StringIn2;
+
+ //
+ // Draw the string according to the specified EFI_HII_OUT_FLAGS and Blt.
+ // If Blt is not NULL, then EFI_HII_OUT_FLAG_CLIP is implied, render this string
+ // to an existing image (bitmap or screen depending on flags) pointed by "*Blt".
+ // Otherwise render this string to a new allocated image and output it.
+ //
+ Image = *Blt;
+ BufferPtr = Image->Image.Bitmap + Image->Width * BltY + BltX;
+ if (Image->Height < BltY) {
+ //
+ // the top edge of the image should be in Image resolution scope.
+ //
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ MaxRowNum = (UINT16)((Image->Height - BltY) / Height);
+ if ((Image->Height - BltY) % Height != 0) {
+ LastLineHeight = (Image->Height - BltY) % Height;
+ MaxRowNum++;
+ }
+
+ RowInfo = (EFI_HII_ROW_INFO *)AllocateZeroPool (MaxRowNum * sizeof (EFI_HII_ROW_INFO));
+ if (RowInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ //
+ // Format the glyph buffer according to flags.
+ //
+ Transparent = (BOOLEAN)((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT ? TRUE : FALSE);
+
+ for (RowIndex = 0, Index = 0; RowIndex < MaxRowNum && StringPtr[Index] != 0; ) {
+ LineWidth = 0;
+ LineBreak = FALSE;
+
+ //
+ // Clip the final row if the row's bottom-most on pixel cannot fit when
+ // EFI_HII_OUT_FLAG_CLEAN_Y is set.
+ //
+ if (RowIndex == MaxRowNum - 1) {
+ if (((Flags & EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) == EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) && (LastLineHeight < LineHeight)) {
+ //
+ // Don't draw at all if the row's bottom-most on pixel cannot fit.
+ //
+ break;
+ }
+
+ LineHeight = LastLineHeight;
+ }
+
+ //
+ // Calculate how many characters there are in a row.
+ //
+ RowInfo[RowIndex].StartIndex = Index;
+
+ while (LineWidth + BltX < Image->Width && StringPtr[Index] != 0) {
+ if (((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0) &&
+ (IsLineBreak (StringPtr[Index]) == 0))
+ {
+ //
+ // It forces a line break that ends this row.
+ //
+ Index++;
+ LineBreak = TRUE;
+ break;
+ }
+
+ //
+ // If the glyph of the character is existing, then accumulate the actual printed width
+ //
+ LineWidth += (UINTN)Cell[Index].AdvanceX;
+
+ Index++;
+ }
+
+ //
+ // Record index of next char.
+ //
+ NextIndex = Index;
+ //
+ // Return to the previous char.
+ //
+ Index--;
+ if (LineBreak && (Index > 0)) {
+ //
+ // Return the previous non line break char.
+ //
+ Index--;
+ }
+
+ //
+ // If this character is the last character of a row, we need not
+ // draw its (AdvanceX - Width - OffsetX) for next character.
+ //
+ LineWidth -= (Cell[Index].AdvanceX - Cell[Index].Width - Cell[Index].OffsetX);
+
+ //
+ // Clip the right-most character if cannot fit when EFI_HII_OUT_FLAG_CLEAN_X is set.
+ //
+ if ((LineWidth + BltX <= Image->Width) ||
+ ((LineWidth + BltX > Image->Width) && ((Flags & EFI_HII_OUT_FLAG_CLIP_CLEAN_X) == 0)))
+ {
+ //
+ // Record right-most character in RowInfo even if it is partially displayed.
+ //
+ RowInfo[RowIndex].EndIndex = Index;
+ RowInfo[RowIndex].LineWidth = LineWidth;
+ RowInfo[RowIndex].LineHeight = LineHeight;
+ RowInfo[RowIndex].BaselineOffset = BaseLineOffset;
+ } else {
+ //
+ // When EFI_HII_OUT_FLAG_CLEAN_X is set, it will not draw a character
+ // if its right-most on pixel cannot fit.
+ //
+ if (Index > RowInfo[RowIndex].StartIndex) {
+ //
+ // Don't draw the last char on this row. And, don't draw the second last char (AdvanceX - Width - OffsetX).
+ //
+ LineWidth -= (Cell[Index].Width + Cell[Index].OffsetX);
+ LineWidth -= (Cell[Index - 1].AdvanceX - Cell[Index - 1].Width - Cell[Index - 1].OffsetX);
+ RowInfo[RowIndex].EndIndex = Index - 1;
+ RowInfo[RowIndex].LineWidth = LineWidth;
+ RowInfo[RowIndex].LineHeight = LineHeight;
+ RowInfo[RowIndex].BaselineOffset = BaseLineOffset;
+ } else {
+ //
+ // There is no enough column to draw any character, so set current line width to zero.
+ // And go to draw Next line if LineBreak is set.
+ //
+ RowInfo[RowIndex].LineWidth = 0;
+ goto NextLine;
+ }
+ }
+
+ //
+ // EFI_HII_OUT_FLAG_WRAP will wrap the text at the right-most line-break
+ // opportunity prior to a character whose right-most extent would exceed Width.
+ // Search the right-most line-break opportunity here.
+ //
+ if (((Flags & EFI_HII_OUT_FLAG_WRAP) == EFI_HII_OUT_FLAG_WRAP) &&
+ ((RowInfo[RowIndex].LineWidth + BltX > Image->Width) || (StringPtr[NextIndex] != 0)) &&
+ !LineBreak)
+ {
+ if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0) {
+ LineWidth = RowInfo[RowIndex].LineWidth;
+ for (Index1 = RowInfo[RowIndex].EndIndex; Index1 >= RowInfo[RowIndex].StartIndex; Index1--) {
+ if (Index1 == RowInfo[RowIndex].EndIndex) {
+ LineWidth -= (Cell[Index1].Width + Cell[Index1].OffsetX);
+ } else {
+ LineWidth -= Cell[Index1].AdvanceX;
+ }
+
+ if (IsLineBreak (StringPtr[Index1]) > 0) {
+ LineBreak = TRUE;
+ if (Index1 > RowInfo[RowIndex].StartIndex) {
+ RowInfo[RowIndex].EndIndex = Index1 - 1;
+ }
+
+ //
+ // relocate to the character after the right-most line break opportunity of this line
+ //
+ NextIndex = Index1 + 1;
+ break;
+ }
+
+ //
+ // If don't find a line break opportunity from EndIndex to StartIndex,
+ // then jump out.
+ //
+ if (Index1 == RowInfo[RowIndex].StartIndex) {
+ break;
+ }
+ }
+
+ //
+ // Update LineWidth to the real width
+ //
+ if (IsLineBreak (StringPtr[Index1]) > 0) {
+ if (Index1 == RowInfo[RowIndex].StartIndex) {
+ LineWidth = 0;
+ } else {
+ LineWidth -= (Cell[Index1 - 1].AdvanceX - Cell[Index1 - 1].Width - Cell[Index1 - 1].OffsetX);
+ }
+
+ RowInfo[RowIndex].LineWidth = LineWidth;
+ }
+ }
+
+ //
+ // If no line-break opportunity can be found, then the text will
+ // behave as if EFI_HII_OUT_FLAG_CLEAN_X is set.
+ //
+ if (!LineBreak) {
+ LineWidth = RowInfo[RowIndex].LineWidth;
+ Index1 = RowInfo[RowIndex].EndIndex;
+ if (LineWidth + BltX > Image->Width) {
+ if (Index1 > RowInfo[RowIndex].StartIndex) {
+ //
+ // Don't draw the last char on this row. And, don't draw the second last char (AdvanceX - Width - OffsetX).
+ //
+ LineWidth -= (Cell[Index1].Width + Cell[Index1].OffsetX);
+ LineWidth -= (Cell[Index1 - 1].AdvanceX - Cell[Index1 - 1].Width - Cell[Index1 - 1].OffsetX);
+ RowInfo[RowIndex].EndIndex = Index1 - 1;
+ RowInfo[RowIndex].LineWidth = LineWidth;
+ } else {
+ //
+ // There is no enough column to draw any character, so set current line width to zero.
+ // And go to draw Next line if LineBreak is set.
+ //
+ RowInfo[RowIndex].LineWidth = 0;
+ goto NextLine;
+ }
+ }
+ }
+ }
+
+ //
+ // LineWidth can't exceed Image width.
+ //
+ if (RowInfo[RowIndex].LineWidth + BltX > Image->Width) {
+ RowInfo[RowIndex].LineWidth = Image->Width - BltX;
+ }
+
+ //
+ // Draw it to screen or existing bitmap depending on whether
+ // EFI_HII_DIRECT_TO_SCREEN is set.
+ //
+ LineOffset = 0;
+ if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
+ BltBuffer = NULL;
+ if (RowInfo[RowIndex].LineWidth != 0) {
+ BltBuffer = AllocatePool (RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ if (BltBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ //
+ // Initialize the background color.
+ //
+ PreInitBkgnd = Background.Blue | Background.Green << 8 | Background.Red << 16;
+ SetMem32 (BltBuffer, RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), PreInitBkgnd);
+ //
+ // Set BufferPtr to Origin by adding baseline to the starting position.
+ //
+ BufferPtr = BltBuffer + BaseLine * RowInfo[RowIndex].LineWidth;
+ }
+
+ for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {
+ if ((RowInfo[RowIndex].LineWidth > 0) && (RowInfo[RowIndex].LineWidth > LineOffset)) {
+ //
+ // Only BLT these character which have corresponding glyph in font database.
+ //
+ GlyphToImage (
+ GlyphBuf[Index1],
+ Foreground,
+ Background,
+ (UINT16)RowInfo[RowIndex].LineWidth,
+ BaseLine,
+ RowInfo[RowIndex].LineWidth - LineOffset,
+ RowInfo[RowIndex].LineHeight,
+ Transparent,
+ &Cell[Index1],
+ Attributes[Index1],
+ &BufferPtr
+ );
+ }
+
+ if (ColumnInfoArray != NULL) {
+ if ( ((GlyphBuf[Index1] == NULL) && (Cell[Index1].AdvanceX == 0))
+ || (RowInfo[RowIndex].LineWidth == 0))
+ {
+ *ColumnInfoArray = (UINTN) ~0;
+ } else {
+ *ColumnInfoArray = LineOffset + Cell[Index1].OffsetX + BltX;
+ }
+
+ ColumnInfoArray++;
+ }
+
+ LineOffset += Cell[Index1].AdvanceX;
+ }
+
+ if (BltBuffer != NULL) {
+ Status = Image->Image.Screen->Blt (
+ Image->Image.Screen,
+ BltBuffer,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ BltX,
+ BltY,
+ RowInfo[RowIndex].LineWidth,
+ RowInfo[RowIndex].LineHeight,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (BltBuffer);
+ goto Exit;
+ }
+
+ FreePool (BltBuffer);
+ }
+ } else {
+ //
+ // Save the starting position for calculate the starting position of next row.
+ //
+ RowBufferPtr = BufferPtr;
+ //
+ // Set BufferPtr to Origin by adding baseline to the starting position.
+ //
+ BufferPtr = BufferPtr + BaseLine * Image->Width;
+ for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {
+ if ((RowInfo[RowIndex].LineWidth > 0) && (RowInfo[RowIndex].LineWidth > LineOffset)) {
+ //
+ // Only BLT these character which have corresponding glyph in font database.
+ //
+ GlyphToImage (
+ GlyphBuf[Index1],
+ Foreground,
+ Background,
+ Image->Width,
+ BaseLine,
+ RowInfo[RowIndex].LineWidth - LineOffset,
+ RowInfo[RowIndex].LineHeight,
+ Transparent,
+ &Cell[Index1],
+ Attributes[Index1],
+ &BufferPtr
+ );
+ }
+
+ if (ColumnInfoArray != NULL) {
+ if ( ((GlyphBuf[Index1] == NULL) && (Cell[Index1].AdvanceX == 0))
+ || (RowInfo[RowIndex].LineWidth == 0))
+ {
+ *ColumnInfoArray = (UINTN) ~0;
+ } else {
+ *ColumnInfoArray = LineOffset + Cell[Index1].OffsetX + BltX;
+ }
+
+ ColumnInfoArray++;
+ }
+
+ LineOffset += Cell[Index1].AdvanceX;
+ }
+
+ //
+ // Jump to starting position of next row.
+ //
+ if (RowIndex == 0) {
+ BufferPtr = RowBufferPtr - BltX + LineHeight * Image->Width;
+ } else {
+ BufferPtr = RowBufferPtr + LineHeight * Image->Width;
+ }
+ }
+
+NextLine:
+ //
+ // Recalculate the start point of Y axis to draw multi-lines with the order of top-to-down
+ //
+ BltY += RowInfo[RowIndex].LineHeight;
+
+ RowIndex++;
+ Index = NextIndex;
+
+ if (!LineBreak) {
+ //
+ // If there is not a mandatory line break or line break opportunity, only render one line to image
+ //
+ break;
+ }
+ }
+
+ //
+ // Write output parameters.
+ //
+ RowInfoSize = RowIndex * sizeof (EFI_HII_ROW_INFO);
+ if (RowInfoArray != NULL) {
+ if (RowInfoSize > 0) {
+ *RowInfoArray = AllocateZeroPool (RowInfoSize);
+ if (*RowInfoArray == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ CopyMem (*RowInfoArray, RowInfo, RowInfoSize);
+ } else {
+ *RowInfoArray = NULL;
+ }
+ }
+
+ if (RowInfoArraySize != NULL) {
+ *RowInfoArraySize = RowIndex;
+ }
+
+ Status = EFI_SUCCESS;
+
+Exit:
+
+ for (Index = 0; Index < StrLength; Index++) {
+ if (GlyphBuf[Index] != NULL) {
+ FreePool (GlyphBuf[Index]);
+ }
+ }
+
+ if (StringIn != NULL) {
+ FreePool (StringIn);
+ }
+
+ if (StringIn2 != NULL) {
+ FreePool (StringIn2);
+ }
+
+ if (StringInfoOut != NULL) {
+ FreePool (StringInfoOut);
+ }
+
+ if (RowInfo != NULL) {
+ FreePool (RowInfo);
+ }
+
+ if (SystemDefault != NULL) {
+ FreePool (SystemDefault);
+ }
+
+ if (GlyphBuf != NULL) {
+ FreePool (GlyphBuf);
+ }
+
+ if (Cell != NULL) {
+ FreePool (Cell);
+ }
+
+ if (Attributes != NULL) {
+ FreePool (Attributes);
+ }
+
+ return Status;
+}
+
+/**
+ Render a string to a bitmap or the screen containing the contents of the specified string.
+
+ @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
+ @param Flags Describes how the string is to be drawn.
+ @param PackageList The package list in the HII database to search
+ for the specified string.
+ @param StringId The string's id, which is unique within
+ PackageList.
+ @param Language Points to the language for the retrieved string.
+ If NULL, then the current system language is
+ used.
+ @param StringInfo Points to the string output information,
+ including the color and font. If NULL, then the
+ string will be output in the default system font
+ and color.
+ @param Blt If this points to a non-NULL on entry, this
+ points to the image, which is Width pixels wide
+ and Height pixels high. The string will be drawn
+ onto this image and
+ EFI_HII_OUT_FLAG_CLIP is implied. If this points
+ to a NULL on entry, then a buffer
+ will be allocated to hold the generated image and
+ the pointer updated on exit. It is the caller's
+ responsibility to free this buffer.
+ @param BltX Specifies the offset from the left and top edge
+ of the image of the first character cell in the
+ image.
+ @param BltY Specifies the offset from the left and top edge
+ of the image of the first character cell in the
+ image.
+ @param RowInfoArray If this is non-NULL on entry, then on exit, this
+ will point to an allocated buffer containing
+ row information and RowInfoArraySize will be
+ updated to contain the number of elements.
+ This array describes the characters which were at
+ least partially drawn and the heights of the
+ rows. It is the caller's responsibility to free
+ this buffer.
+ @param RowInfoArraySize If this is non-NULL on entry, then on exit it
+ contains the number of elements in RowInfoArray.
+ @param ColumnInfoArray If this is non-NULL, then on return it will be
+ filled with the horizontal offset for each
+ character in the string on the row where it is
+ displayed. Non-printing characters will have
+ the offset ~0. The caller is responsible to
+ allocate a buffer large enough so that there
+ is one entry for each character in the string,
+ not including the null-terminator. It is possible
+ when character display is normalized that some
+ character cells overlap.
+
+ @retval EFI_SUCCESS The string was successfully rendered.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for
+ RowInfoArray or Blt.
+ @retval EFI_INVALID_PARAMETER The Blt or PackageList was NULL.
+ @retval EFI_INVALID_PARAMETER Flags were invalid combination.
+ @retval EFI_NOT_FOUND The specified PackageList is not in the Database or the string id is not
+ in the specified PackageList.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiStringIdToImage (
+ IN CONST EFI_HII_FONT_PROTOCOL *This,
+ IN EFI_HII_OUT_FLAGS Flags,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_STRING_ID StringId,
+ IN CONST CHAR8 *Language,
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY,
+ OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL,
+ OUT UINTN *RowInfoArraySize OPTIONAL,
+ OUT UINTN *ColumnInfoArray OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_HII_STRING_PROTOCOL *HiiString;
+ EFI_STRING String;
+ UINTN StringSize;
+ UINTN FontLen;
+ UINTN NameSize;
+ EFI_FONT_INFO *StringFontInfo;
+ EFI_FONT_DISPLAY_INFO *NewStringInfo;
+ CHAR8 TempSupportedLanguages;
+ CHAR8 *SupportedLanguages;
+ UINTN SupportedLanguagesSize;
+ CHAR8 *CurrentLanguage;
+ CHAR8 *BestLanguage;
+
+ if ((This == NULL) || (PackageList == NULL) || (Blt == NULL) || (PackageList == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Initialize string pointers to be NULL
+ //
+ SupportedLanguages = NULL;
+ CurrentLanguage = NULL;
+ BestLanguage = NULL;
+ String = NULL;
+ StringFontInfo = NULL;
+ NewStringInfo = NULL;
+
+ //
+ // Get the string to be displayed.
+ //
+ Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ HiiString = &Private->HiiString;
+
+ //
+ // Get the size of supported language.
+ //
+ SupportedLanguagesSize = 0;
+ Status = HiiString->GetLanguages (
+ HiiString,
+ PackageList,
+ &TempSupportedLanguages,
+ &SupportedLanguagesSize
+ );
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ return Status;
+ }
+
+ SupportedLanguages = AllocatePool (SupportedLanguagesSize);
+ if (SupportedLanguages == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = HiiString->GetLanguages (
+ HiiString,
+ PackageList,
+ SupportedLanguages,
+ &SupportedLanguagesSize
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ if (Language == NULL) {
+ Language = "";
+ }
+
+ GetEfiGlobalVariable2 (L"PlatformLang", (VOID **)&CurrentLanguage, NULL);
+ BestLanguage = GetBestLanguage (
+ SupportedLanguages,
+ FALSE,
+ Language,
+ (CurrentLanguage == NULL) ? CurrentLanguage : "",
+ (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLang),
+ NULL
+ );
+ if (BestLanguage == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+
+ StringSize = MAX_STRING_LENGTH;
+ String = (EFI_STRING)AllocateZeroPool (StringSize);
+ if (String == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ Status = HiiString->GetString (
+ HiiString,
+ BestLanguage,
+ PackageList,
+ StringId,
+ String,
+ &StringSize,
+ &StringFontInfo
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ FreePool (String);
+ String = (EFI_STRING)AllocateZeroPool (StringSize);
+ if (String == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ Status = HiiString->GetString (
+ HiiString,
+ BestLanguage,
+ PackageList,
+ StringId,
+ String,
+ &StringSize,
+ NULL
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // When StringInfo specifies that string will be output in the system default font and color,
+ // use particular stringfontinfo described in string package instead if exists.
+ // StringFontInfo equals NULL means system default font attaches with the string block.
+ //
+ if ((StringFontInfo != NULL) && IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *)StringInfo, NULL, NULL)) {
+ NameSize = StrSize (StringFontInfo->FontName);
+ FontLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + NameSize;
+ NewStringInfo = AllocateZeroPool (FontLen);
+ if (NewStringInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ NewStringInfo->FontInfoMask = EFI_FONT_INFO_SYS_FORE_COLOR | EFI_FONT_INFO_SYS_BACK_COLOR;
+ NewStringInfo->FontInfo.FontStyle = StringFontInfo->FontStyle;
+ NewStringInfo->FontInfo.FontSize = StringFontInfo->FontSize;
+ StrCpyS (NewStringInfo->FontInfo.FontName, NameSize / sizeof (CHAR16), StringFontInfo->FontName);
+
+ Status = HiiStringToImage (
+ This,
+ Flags,
+ String,
+ NewStringInfo,
+ Blt,
+ BltX,
+ BltY,
+ RowInfoArray,
+ RowInfoArraySize,
+ ColumnInfoArray
+ );
+ goto Exit;
+ }
+
+ Status = HiiStringToImage (
+ This,
+ Flags,
+ String,
+ StringInfo,
+ Blt,
+ BltX,
+ BltY,
+ RowInfoArray,
+ RowInfoArraySize,
+ ColumnInfoArray
+ );
+
+Exit:
+ if (SupportedLanguages != NULL) {
+ FreePool (SupportedLanguages);
+ }
+
+ if (CurrentLanguage != NULL) {
+ FreePool (CurrentLanguage);
+ }
+
+ if (BestLanguage != NULL) {
+ FreePool (BestLanguage);
+ }
+
+ if (String != NULL) {
+ FreePool (String);
+ }
+
+ if (StringFontInfo != NULL) {
+ FreePool (StringFontInfo);
+ }
+
+ if (NewStringInfo != NULL) {
+ FreePool (NewStringInfo);
+ }
+
+ return Status;
+}
+
+/**
+ Convert the glyph for a single character into a bitmap.
+
+ @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
+ @param Char Character to retrieve.
+ @param StringInfo Points to the string font and color information
+ or NULL if the string should use the default
+ system font and color.
+ @param Blt Thus must point to a NULL on entry. A buffer will
+ be allocated to hold the output and the pointer
+ updated on exit. It is the caller's
+ responsibility to free this buffer.
+ @param Baseline Number of pixels from the bottom of the bitmap to
+ the baseline.
+
+ @retval EFI_SUCCESS Glyph bitmap created.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate the output buffer Blt.
+ @retval EFI_WARN_UNKNOWN_GLYPH The glyph was unknown and was replaced with the
+ glyph for Unicode character 0xFFFD.
+ @retval EFI_INVALID_PARAMETER Blt is NULL or *Blt is not NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetGlyph (
+ IN CONST EFI_HII_FONT_PROTOCOL *This,
+ IN CHAR16 Char,
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfo,
+ OUT EFI_IMAGE_OUTPUT **Blt,
+ OUT UINTN *Baseline OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_IMAGE_OUTPUT *Image;
+ UINT8 *GlyphBuffer;
+ EFI_FONT_DISPLAY_INFO *SystemDefault;
+ EFI_FONT_DISPLAY_INFO *StringInfoOut;
+ BOOLEAN Default;
+ EFI_FONT_HANDLE FontHandle;
+ EFI_STRING String;
+ EFI_HII_GLYPH_INFO Cell;
+ EFI_FONT_INFO *FontInfo;
+ UINT8 Attributes;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+ UINT16 BaseLine;
+
+ if ((This == NULL) || (Blt == NULL) || (*Blt != NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ Default = FALSE;
+ Image = NULL;
+ SystemDefault = NULL;
+ FontHandle = NULL;
+ String = NULL;
+ GlyphBuffer = NULL;
+ StringInfoOut = NULL;
+ FontInfo = NULL;
+
+ ZeroMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+ Default = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *)StringInfo, &SystemDefault, NULL);
+
+ if (!Default) {
+ //
+ // Find out a EFI_FONT_DISPLAY_INFO which could display the character in
+ // the specified color and font.
+ //
+ String = (EFI_STRING)AllocateZeroPool (sizeof (CHAR16) * 2);
+ if (String == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ *String = Char;
+ *(String + 1) = 0;
+
+ Status = HiiGetFontInfo (This, &FontHandle, StringInfo, &StringInfoOut, String);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ ASSERT (StringInfoOut != NULL);
+ FontInfo = &StringInfoOut->FontInfo;
+ Foreground = StringInfoOut->ForegroundColor;
+ Background = StringInfoOut->BackgroundColor;
+ } else {
+ ASSERT (SystemDefault != NULL);
+ Foreground = SystemDefault->ForegroundColor;
+ Background = SystemDefault->BackgroundColor;
+ }
+
+ Status = GetGlyphBuffer (Private, Char, FontInfo, &GlyphBuffer, &Cell, &Attributes);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ Image = (EFI_IMAGE_OUTPUT *)AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
+ if (Image == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ Image->Width = Cell.Width;
+ Image->Height = Cell.Height;
+
+ if (Image->Width * Image->Height > 0) {
+ Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ if (Image->Image.Bitmap == NULL) {
+ FreePool (Image);
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ //
+ // Set BaseLine to the char height.
+ //
+ BaseLine = (UINT16)(Cell.Height + Cell.OffsetY);
+ //
+ // Set BltBuffer to the position of Origin.
+ //
+ BltBuffer = Image->Image.Bitmap + (Cell.Height + Cell.OffsetY) * Image->Width - Cell.OffsetX;
+ GlyphToImage (
+ GlyphBuffer,
+ Foreground,
+ Background,
+ Image->Width,
+ BaseLine,
+ Cell.Width + Cell.OffsetX,
+ BaseLine - Cell.OffsetY,
+ FALSE,
+ &Cell,
+ Attributes,
+ &BltBuffer
+ );
+ }
+
+ *Blt = Image;
+ if (Baseline != NULL) {
+ *Baseline = Cell.OffsetY;
+ }
+
+ Status = EFI_SUCCESS;
+
+Exit:
+
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // Glyph is unknown and replaced with the glyph for unicode character 0xFFFD
+ //
+ if (Char != REPLACE_UNKNOWN_GLYPH) {
+ Status = HiiGetGlyph (This, REPLACE_UNKNOWN_GLYPH, StringInfo, Blt, Baseline);
+ if (!EFI_ERROR (Status)) {
+ Status = EFI_WARN_UNKNOWN_GLYPH;
+ }
+ } else {
+ Status = EFI_WARN_UNKNOWN_GLYPH;
+ }
+ }
+
+ if (SystemDefault != NULL) {
+ FreePool (SystemDefault);
+ }
+
+ if (StringInfoOut != NULL) {
+ FreePool (StringInfoOut);
+ }
+
+ if (String != NULL) {
+ FreePool (String);
+ }
+
+ if (GlyphBuffer != NULL) {
+ FreePool (GlyphBuffer);
+ }
+
+ return Status;
+}
+
+/**
+ This function iterates through fonts which match the specified font, using
+ the specified criteria. If String is non-NULL, then all of the characters in
+ the string must exist in order for a candidate font to be returned.
+
+ @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
+ @param FontHandle On entry, points to the font handle returned by a
+ previous call to GetFontInfo() or NULL to start
+ with the first font. On return, points to the
+ returned font handle or points to NULL if there
+ are no more matching fonts.
+ @param StringInfoIn Upon entry, points to the font to return information
+ about. If NULL, then the information about the system
+ default font will be returned.
+ @param StringInfoOut Upon return, contains the matching font's information.
+ If NULL, then no information is returned. This buffer
+ is allocated with a call to the Boot Service AllocatePool().
+ It is the caller's responsibility to call the Boot
+ Service FreePool() when the caller no longer requires
+ the contents of StringInfoOut.
+ @param String Points to the string which will be tested to
+ determine if all characters are available. If
+ NULL, then any font is acceptable.
+
+ @retval EFI_SUCCESS Matching font returned successfully.
+ @retval EFI_NOT_FOUND No matching font was found.
+ @retval EFI_INVALID_PARAMETER StringInfoIn->FontInfoMask is an invalid combination.
+ @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the
+ request.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetFontInfo (
+ IN CONST EFI_HII_FONT_PROTOCOL *This,
+ IN OUT EFI_FONT_HANDLE *FontHandle,
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfoIn OPTIONAL,
+ OUT EFI_FONT_DISPLAY_INFO **StringInfoOut,
+ IN CONST EFI_STRING String OPTIONAL
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_STATUS Status;
+ EFI_FONT_DISPLAY_INFO *SystemDefault;
+ EFI_FONT_DISPLAY_INFO InfoOut;
+ UINTN StringInfoOutLen;
+ EFI_FONT_INFO *FontInfo;
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+ EFI_STRING StringIn;
+ EFI_FONT_HANDLE LocalFontHandle;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ StringInfoOutLen = 0;
+ FontInfo = NULL;
+ SystemDefault = NULL;
+ LocalFontHandle = NULL;
+ if (FontHandle != NULL) {
+ LocalFontHandle = *FontHandle;
+ }
+
+ Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Already searched to the end of the whole list, return directly.
+ //
+ if (LocalFontHandle == &Private->FontInfoList) {
+ LocalFontHandle = NULL;
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+
+ //
+ // Get default system display info, if StringInfoIn points to
+ // system display info, return it directly.
+ //
+ if (IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *)StringInfoIn, &SystemDefault, &StringInfoOutLen)) {
+ //
+ // System font is the first node. When handle is not NULL, system font can not
+ // be found any more.
+ //
+ if (LocalFontHandle == NULL) {
+ if (StringInfoOut != NULL) {
+ *StringInfoOut = AllocateCopyPool (StringInfoOutLen, SystemDefault);
+ if (*StringInfoOut == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ LocalFontHandle = NULL;
+ goto Exit;
+ }
+ }
+
+ LocalFontHandle = Private->FontInfoList.ForwardLink;
+ Status = EFI_SUCCESS;
+ goto Exit;
+ } else {
+ LocalFontHandle = NULL;
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+ }
+
+ //
+ // StringInfoIn must not be NULL if it is not system default font info.
+ //
+ ASSERT (StringInfoIn != NULL);
+ //
+ // Check the font information mask to make sure it is valid.
+ //
+ if (((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) ==
+ (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) ||
+ ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) ==
+ (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) ||
+ ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ==
+ (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ||
+ ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE)) ==
+ (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE)) ||
+ ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE)) ==
+ (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE)))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Parse the font information mask to find a matching font.
+ //
+
+ CopyMem (&InfoOut, (EFI_FONT_DISPLAY_INFO *)StringInfoIn, sizeof (EFI_FONT_DISPLAY_INFO));
+
+ if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FONT) == EFI_FONT_INFO_SYS_FONT) {
+ Status = SaveFontName (SystemDefault->FontInfo.FontName, &FontInfo);
+ } else {
+ Status = SaveFontName (((EFI_FONT_DISPLAY_INFO *)StringInfoIn)->FontInfo.FontName, &FontInfo);
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_SIZE) == EFI_FONT_INFO_SYS_SIZE) {
+ InfoOut.FontInfo.FontSize = SystemDefault->FontInfo.FontSize;
+ }
+
+ if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_STYLE) == EFI_FONT_INFO_SYS_STYLE) {
+ InfoOut.FontInfo.FontStyle = SystemDefault->FontInfo.FontStyle;
+ }
+
+ if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) == EFI_FONT_INFO_SYS_FORE_COLOR) {
+ InfoOut.ForegroundColor = SystemDefault->ForegroundColor;
+ }
+
+ if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) == EFI_FONT_INFO_SYS_BACK_COLOR) {
+ InfoOut.BackgroundColor = SystemDefault->BackgroundColor;
+ }
+
+ ASSERT (FontInfo != NULL);
+ FontInfo->FontSize = InfoOut.FontInfo.FontSize;
+ FontInfo->FontStyle = InfoOut.FontInfo.FontStyle;
+
+ if (IsFontInfoExisted (Private, FontInfo, &InfoOut.FontInfoMask, LocalFontHandle, &GlobalFont)) {
+ //
+ // Test to guarantee all characters are available in the found font.
+ //
+ if (String != NULL) {
+ StringIn = String;
+ while (*StringIn != 0) {
+ Status = FindGlyphBlock (GlobalFont->FontPackage, *StringIn, NULL, NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ LocalFontHandle = NULL;
+ goto Exit;
+ }
+
+ StringIn++;
+ }
+ }
+
+ //
+ // Write to output parameter
+ //
+ if (StringInfoOut != NULL) {
+ StringInfoOutLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (EFI_FONT_INFO) + GlobalFont->FontInfoSize;
+ *StringInfoOut = (EFI_FONT_DISPLAY_INFO *)AllocateZeroPool (StringInfoOutLen);
+ if (*StringInfoOut == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ LocalFontHandle = NULL;
+ goto Exit;
+ }
+
+ CopyMem (*StringInfoOut, &InfoOut, sizeof (EFI_FONT_DISPLAY_INFO));
+ CopyMem (&(*StringInfoOut)->FontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize);
+ }
+
+ LocalFontHandle = GlobalFont->Entry.ForwardLink;
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+
+ Status = EFI_NOT_FOUND;
+
+Exit:
+
+ if (FontHandle != NULL) {
+ *FontHandle = LocalFontHandle;
+ }
+
+ if (SystemDefault != NULL) {
+ FreePool (SystemDefault);
+ }
+
+ if (FontInfo != NULL) {
+ FreePool (FontInfo);
+ }
+
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
index 421c293cfc..e416a133d0 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
@@ -1,2340 +1,2340 @@
-/** @file
-Private structures definitions in HiiDatabase.
-
-Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef __HII_DATABASE_PRIVATE_H__
-#define __HII_DATABASE_PRIVATE_H__
-
-#include <Uefi.h>
-
-#include <Protocol/DevicePath.h>
-#include <Protocol/HiiFont.h>
-#include <Protocol/HiiImage.h>
-#include <Protocol/HiiImageEx.h>
-#include <Protocol/HiiImageDecoder.h>
-#include <Protocol/HiiString.h>
-#include <Protocol/HiiDatabase.h>
-#include <Protocol/HiiConfigRouting.h>
-#include <Protocol/HiiConfigAccess.h>
-#include <Protocol/HiiConfigKeyword.h>
-#include <Protocol/SimpleTextOut.h>
-
-#include <Guid/HiiKeyBoardLayout.h>
-#include <Guid/GlobalVariable.h>
-#include <Guid/MdeModuleHii.h>
-#include <Guid/VariableFormat.h>
-#include <Guid/PcdDataBaseSignatureGuid.h>
-
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/UefiDriverEntryPoint.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/BaseLib.h>
-#include <Library/DevicePathLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiLib.h>
-#include <Library/PcdLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
-#include <Library/PrintLib.h>
-
-#define MAX_STRING_LENGTH 1024
-#define MAX_FONT_NAME_LEN 256
-#define NARROW_BASELINE 15
-#define WIDE_BASELINE 14
-#define SYS_FONT_INFO_MASK 0x37
-#define REPLACE_UNKNOWN_GLYPH 0xFFFD
-#define PROPORTIONAL_GLYPH 0x80
-#define NARROW_GLYPH 0x40
-
-#define BITMAP_LEN_1_BIT(Width, Height) (((Width) + 7) / 8 * (Height))
-#define BITMAP_LEN_4_BIT(Width, Height) (((Width) + 1) / 2 * (Height))
-#define BITMAP_LEN_8_BIT(Width, Height) ((Width) * (Height))
-#define BITMAP_LEN_24_BIT(Width, Height) ((Width) * (Height) * 3)
-
-extern EFI_LOCK mHiiDatabaseLock;
-
-//
-// IFR data structure
-//
-// BASE_CR (a, IFR_DEFAULT_VALUE_DATA, Entry) to get the whole structure.
-
-typedef struct {
- LIST_ENTRY Entry; // Link to VarStorage Default Data
- UINT16 DefaultId;
- VARIABLE_STORE_HEADER *VariableStorage;
-} VARSTORAGE_DEFAULT_DATA;
-
-typedef struct {
- LIST_ENTRY Entry; // Link to VarStorage
- EFI_GUID Guid;
- CHAR16 *Name;
- UINT16 Size;
- UINT8 Type;
- LIST_ENTRY BlockEntry; // Link to its Block array
-} IFR_VARSTORAGE_DATA;
-
-typedef struct {
- LIST_ENTRY Entry; // Link to Block array
- UINT16 Offset;
- UINT16 Width;
- UINT16 BitOffset;
- UINT16 BitWidth;
- EFI_QUESTION_ID QuestionId;
- UINT8 OpCode;
- UINT8 Scope;
- LIST_ENTRY DefaultValueEntry; // Link to its default value array
- CHAR16 *Name;
- BOOLEAN IsBitVar;
-} IFR_BLOCK_DATA;
-
-//
-// Get default value from IFR data.
-//
-typedef enum {
- DefaultValueFromDefault = 0, // Get from the minimum or first one when not set default value.
- DefaultValueFromOtherDefault, // Get default vale from other default when no default(When other
- // defaults are more than one, use the default with smallest default id).
- DefaultValueFromFlag, // Get default value from the default flag.
- DefaultValueFromOpcode // Get default value from default opcode, highest priority.
-} DEFAULT_VALUE_TYPE;
-
-typedef struct {
- LIST_ENTRY Entry;
- DEFAULT_VALUE_TYPE Type;
- BOOLEAN Cleaned; // Whether this value is cleaned
- // TRUE Cleaned, the value can't be used
- // FALSE Not cleaned, the value can be used.
- UINT16 DefaultId;
- EFI_IFR_TYPE_VALUE Value;
-} IFR_DEFAULT_DATA;
-
-//
-// Storage types
-//
-#define EFI_HII_VARSTORE_BUFFER 0
-#define EFI_HII_VARSTORE_NAME_VALUE 1
-#define EFI_HII_VARSTORE_EFI_VARIABLE 2
-#define EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER 3
-
-//
-// Keyword handler protocol filter type.
-//
-#define EFI_KEYWORD_FILTER_READONY 0x01
-#define EFI_KEYWORD_FILTER_REAWRITE 0x02
-#define EFI_KEYWORD_FILTER_BUFFER 0x10
-#define EFI_KEYWORD_FILTER_NUMERIC 0x20
-#define EFI_KEYWORD_FILTER_NUMERIC_1 0x30
-#define EFI_KEYWORD_FILTER_NUMERIC_2 0x40
-#define EFI_KEYWORD_FILTER_NUMERIC_4 0x50
-#define EFI_KEYWORD_FILTER_NUMERIC_8 0x60
-
-#define HII_FORMSET_STORAGE_SIGNATURE SIGNATURE_32 ('H', 'S', 'T', 'G')
-typedef struct {
- UINTN Signature;
- LIST_ENTRY Entry;
-
- EFI_HII_HANDLE HiiHandle;
- EFI_HANDLE DriverHandle;
-
- UINT8 Type; // EFI_HII_VARSTORE_BUFFER, EFI_HII_VARSTORE_NAME_VALUE, EFI_HII_VARSTORE_EFI_VARIABLE
- EFI_GUID Guid;
- CHAR16 *Name;
- UINT16 Size;
-} HII_FORMSET_STORAGE;
-
-//
-// String Package definitions
-//
-#define HII_STRING_PACKAGE_SIGNATURE SIGNATURE_32 ('h','i','s','p')
-typedef struct _HII_STRING_PACKAGE_INSTANCE {
- UINTN Signature;
- EFI_HII_STRING_PACKAGE_HDR *StringPkgHdr;
- UINT8 *StringBlock;
- LIST_ENTRY StringEntry;
- LIST_ENTRY FontInfoList; // local font info list
- UINT8 FontId;
- EFI_STRING_ID MaxStringId; // record StringId
-} HII_STRING_PACKAGE_INSTANCE;
-
-//
-// Form Package definitions
-//
-#define HII_IFR_PACKAGE_SIGNATURE SIGNATURE_32 ('h','f','r','p')
-typedef struct _HII_IFR_PACKAGE_INSTANCE {
- UINTN Signature;
- EFI_HII_PACKAGE_HEADER FormPkgHdr;
- UINT8 *IfrData;
- LIST_ENTRY IfrEntry;
-} HII_IFR_PACKAGE_INSTANCE;
-
-//
-// Simple Font Package definitions
-//
-#define HII_S_FONT_PACKAGE_SIGNATURE SIGNATURE_32 ('h','s','f','p')
-typedef struct _HII_SIMPLE_FONT_PACKAGE_INSTANCE {
- UINTN Signature;
- EFI_HII_SIMPLE_FONT_PACKAGE_HDR *SimpleFontPkgHdr;
- LIST_ENTRY SimpleFontEntry;
-} HII_SIMPLE_FONT_PACKAGE_INSTANCE;
-
-//
-// Font Package definitions
-//
-#define HII_FONT_PACKAGE_SIGNATURE SIGNATURE_32 ('h','i','f','p')
-typedef struct _HII_FONT_PACKAGE_INSTANCE {
- UINTN Signature;
- EFI_HII_FONT_PACKAGE_HDR *FontPkgHdr;
- UINT16 Height;
- UINT16 BaseLine;
- UINT8 *GlyphBlock;
- LIST_ENTRY FontEntry;
- LIST_ENTRY GlyphInfoList;
-} HII_FONT_PACKAGE_INSTANCE;
-
-#define HII_GLYPH_INFO_SIGNATURE SIGNATURE_32 ('h','g','i','s')
-typedef struct _HII_GLYPH_INFO {
- UINTN Signature;
- LIST_ENTRY Entry;
- CHAR16 CharId;
- EFI_HII_GLYPH_INFO Cell;
-} HII_GLYPH_INFO;
-
-#define HII_FONT_INFO_SIGNATURE SIGNATURE_32 ('h','l','f','i')
-typedef struct _HII_FONT_INFO {
- UINTN Signature;
- LIST_ENTRY Entry;
- LIST_ENTRY *GlobalEntry;
- UINT8 FontId;
-} HII_FONT_INFO;
-
-#define HII_GLOBAL_FONT_INFO_SIGNATURE SIGNATURE_32 ('h','g','f','i')
-typedef struct _HII_GLOBAL_FONT_INFO {
- UINTN Signature;
- LIST_ENTRY Entry;
- HII_FONT_PACKAGE_INSTANCE *FontPackage;
- UINTN FontInfoSize;
- EFI_FONT_INFO *FontInfo;
-} HII_GLOBAL_FONT_INFO;
-
-//
-// Image Package definitions
-//
-
-#define HII_PIXEL_MASK 0x80
-
-typedef struct _HII_IMAGE_PACKAGE_INSTANCE {
- EFI_HII_IMAGE_PACKAGE_HDR ImagePkgHdr;
- UINT32 ImageBlockSize;
- UINT32 PaletteInfoSize;
- EFI_HII_IMAGE_BLOCK *ImageBlock;
- UINT8 *PaletteBlock;
-} HII_IMAGE_PACKAGE_INSTANCE;
-
-//
-// Keyboard Layout Package definitions
-//
-#define HII_KB_LAYOUT_PACKAGE_SIGNATURE SIGNATURE_32 ('h','k','l','p')
-typedef struct _HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE {
- UINTN Signature;
- UINT8 *KeyboardPkg;
- LIST_ENTRY KeyboardEntry;
-} HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE;
-
-//
-// Guid Package definitions
-//
-#define HII_GUID_PACKAGE_SIGNATURE SIGNATURE_32 ('h','i','g','p')
-typedef struct _HII_GUID_PACKAGE_INSTANCE {
- UINTN Signature;
- UINT8 *GuidPkg;
- LIST_ENTRY GuidEntry;
-} HII_GUID_PACKAGE_INSTANCE;
-
-//
-// A package list can contain only one or less than one device path package.
-// This rule also applies to image package since ImageId can not be duplicate.
-//
-typedef struct _HII_DATABASE_PACKAGE_LIST_INSTANCE {
- EFI_HII_PACKAGE_LIST_HEADER PackageListHdr;
- LIST_ENTRY GuidPkgHdr;
- LIST_ENTRY FormPkgHdr;
- LIST_ENTRY KeyboardLayoutHdr;
- LIST_ENTRY StringPkgHdr;
- LIST_ENTRY FontPkgHdr;
- HII_IMAGE_PACKAGE_INSTANCE *ImagePkg;
- LIST_ENTRY SimpleFontPkgHdr;
- UINT8 *DevicePathPkg;
-} HII_DATABASE_PACKAGE_LIST_INSTANCE;
-
-#define HII_HANDLE_SIGNATURE SIGNATURE_32 ('h','i','h','l')
-
-typedef struct {
- UINTN Signature;
- LIST_ENTRY Handle;
- UINTN Key;
-} HII_HANDLE;
-
-#define HII_DATABASE_RECORD_SIGNATURE SIGNATURE_32 ('h','i','d','r')
-
-typedef struct _HII_DATABASE_RECORD {
- UINTN Signature;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
- EFI_HANDLE DriverHandle;
- EFI_HII_HANDLE Handle;
- LIST_ENTRY DatabaseEntry;
-} HII_DATABASE_RECORD;
-
-#define HII_DATABASE_NOTIFY_SIGNATURE SIGNATURE_32 ('h','i','d','n')
-
-typedef struct _HII_DATABASE_NOTIFY {
- UINTN Signature;
- EFI_HANDLE NotifyHandle;
- UINT8 PackageType;
- EFI_GUID *PackageGuid;
- EFI_HII_DATABASE_NOTIFY PackageNotifyFn;
- EFI_HII_DATABASE_NOTIFY_TYPE NotifyType;
- LIST_ENTRY DatabaseNotifyEntry;
-} HII_DATABASE_NOTIFY;
-
-#define HII_DATABASE_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('H', 'i', 'D', 'p')
-
-typedef struct _HII_DATABASE_PRIVATE_DATA {
- UINTN Signature;
- LIST_ENTRY DatabaseList;
- LIST_ENTRY DatabaseNotifyList;
- EFI_HII_FONT_PROTOCOL HiiFont;
- EFI_HII_IMAGE_PROTOCOL HiiImage;
- EFI_HII_IMAGE_EX_PROTOCOL HiiImageEx;
- EFI_HII_STRING_PROTOCOL HiiString;
- EFI_HII_DATABASE_PROTOCOL HiiDatabase;
- EFI_HII_CONFIG_ROUTING_PROTOCOL ConfigRouting;
- EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL ConfigKeywordHandler;
- LIST_ENTRY HiiHandleList;
- INTN HiiHandleCount;
- LIST_ENTRY FontInfoList; // global font info list
- UINTN Attribute; // default system color
- EFI_GUID CurrentLayoutGuid;
- EFI_HII_KEYBOARD_LAYOUT *CurrentLayout;
-} HII_DATABASE_PRIVATE_DATA;
-
-#define HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
- CR (a, \
- HII_DATABASE_PRIVATE_DATA, \
- HiiFont, \
- HII_DATABASE_PRIVATE_DATA_SIGNATURE \
- )
-
-#define HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
- CR (a, \
- HII_DATABASE_PRIVATE_DATA, \
- HiiImage, \
- HII_DATABASE_PRIVATE_DATA_SIGNATURE \
- )
-
-#define HII_IMAGE_EX_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
- CR (a, \
- HII_DATABASE_PRIVATE_DATA, \
- HiiImageEx, \
- HII_DATABASE_PRIVATE_DATA_SIGNATURE \
- )
-
-#define HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
- CR (a, \
- HII_DATABASE_PRIVATE_DATA, \
- HiiString, \
- HII_DATABASE_PRIVATE_DATA_SIGNATURE \
- )
-
-#define HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
- CR (a, \
- HII_DATABASE_PRIVATE_DATA, \
- HiiDatabase, \
- HII_DATABASE_PRIVATE_DATA_SIGNATURE \
- )
-
-#define CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
- CR (a, \
- HII_DATABASE_PRIVATE_DATA, \
- ConfigRouting, \
- HII_DATABASE_PRIVATE_DATA_SIGNATURE \
- )
-
-#define CONFIG_KEYWORD_HANDLER_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
- CR (a, \
- HII_DATABASE_PRIVATE_DATA, \
- ConfigKeywordHandler, \
- HII_DATABASE_PRIVATE_DATA_SIGNATURE \
- )
-
-//
-// Internal function prototypes.
-//
-
-/**
- Generate a sub string then output it.
-
- This is a internal function.
-
- @param String A constant string which is the prefix of the to be
- generated string, e.g. GUID=
-
- @param BufferLen The length of the Buffer in bytes.
-
- @param Buffer Points to a buffer which will be converted to be the
- content of the generated string.
-
- @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
- UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
- if 3, the buffer contains other data.
-
- @param SubStr Points to the output string. It's caller's
- responsibility to free this buffer.
-
-
-**/
-VOID
-GenerateSubStr (
- IN CONST EFI_STRING String,
- IN UINTN BufferLen,
- IN VOID *Buffer,
- IN UINT8 Flag,
- OUT EFI_STRING *SubStr
- );
-
-/**
- This function checks whether a handle is a valid EFI_HII_HANDLE.
-
- @param Handle Pointer to a EFI_HII_HANDLE
-
- @retval TRUE Valid
- @retval FALSE Invalid
-
-**/
-BOOLEAN
-IsHiiHandleValid (
- EFI_HII_HANDLE Handle
- );
-
-/**
- This function checks whether EFI_FONT_INFO exists in current database. If
- FontInfoMask is specified, check what options can be used to make a match.
- Note that the masks relate to where the system default should be supplied
- are ignored by this function.
-
- @param Private Hii database private structure.
- @param FontInfo Points to EFI_FONT_INFO structure.
- @param FontInfoMask If not NULL, describes what options can be used
- to make a match between the font requested and
- the font available. The caller must guarantee
- this mask is valid.
- @param FontHandle On entry, Points to the font handle returned by a
- previous call to GetFontInfo() or NULL to start
- with the first font.
- @param GlobalFontInfo If not NULL, output the corresponding global font
- info.
-
- @retval TRUE Existed
- @retval FALSE Not existed
-
-**/
-BOOLEAN
-IsFontInfoExisted (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_FONT_INFO *FontInfo,
- IN EFI_FONT_INFO_MASK *FontInfoMask OPTIONAL,
- IN EFI_FONT_HANDLE FontHandle OPTIONAL,
- OUT HII_GLOBAL_FONT_INFO **GlobalFontInfo OPTIONAL
- );
-
-/**
-
- This function invokes the matching registered function.
-
- @param Private HII Database driver private structure.
- @param NotifyType The type of change concerning the database.
- @param PackageInstance Points to the package referred to by the notification.
- @param PackageType Package type
- @param Handle The handle of the package list which contains the specified package.
-
- @retval EFI_SUCCESS Already checked all registered function and invoked
- if matched.
- @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
-
-**/
-EFI_STATUS
-InvokeRegisteredFunction (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
- IN VOID *PackageInstance,
- IN UINT8 PackageType,
- IN EFI_HII_HANDLE Handle
- )
-;
-
-/**
- Retrieve system default font and color.
-
- @param Private HII database driver private data.
- @param FontInfo Points to system default font output-related
- information. It's caller's responsibility to free
- this buffer.
- @param FontInfoSize If not NULL, output the size of buffer FontInfo.
-
- @retval EFI_SUCCESS Cell information is added to the GlyphInfoList.
- @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
- task.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
-
-**/
-EFI_STATUS
-GetSystemFont (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- OUT EFI_FONT_DISPLAY_INFO **FontInfo,
- OUT UINTN *FontInfoSize OPTIONAL
- );
-
-/**
- Parse all string blocks to find a String block specified by StringId.
- If StringId = (EFI_STRING_ID) (-1), find out all EFI_HII_SIBT_FONT blocks
- within this string package and backup its information. If LastStringId is
- specified, the string id of last string block will also be output.
- If StringId = 0, output the string id of last string block (EFI_HII_SIBT_STRING).
-
- @param Private Hii database private structure.
- @param StringPackage Hii string package instance.
- @param StringId The string's id, which is unique within
- PackageList.
- @param BlockType Output the block type of found string block.
- @param StringBlockAddr Output the block address of found string block.
- @param StringTextOffset Offset, relative to the found block address, of
- the string text information.
- @param LastStringId Output the last string id when StringId = 0 or StringId = -1.
- @param StartStringId The first id in the skip block which StringId in the block.
-
- @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
-FindStringBlock (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
- IN EFI_STRING_ID StringId,
- OUT UINT8 *BlockType OPTIONAL,
- OUT UINT8 **StringBlockAddr OPTIONAL,
- OUT UINTN *StringTextOffset OPTIONAL,
- OUT EFI_STRING_ID *LastStringId OPTIONAL,
- OUT EFI_STRING_ID *StartStringId OPTIONAL
- );
-
-/**
- Parse all glyph blocks to find a glyph block specified by CharValue.
- If CharValue = (CHAR16) (-1), collect all default character cell information
- within this font package and backup its information.
-
- @param FontPackage Hii string package instance.
- @param CharValue Unicode character value, which identifies a glyph
- block.
- @param GlyphBuffer Output the corresponding bitmap data of the found
- block. It is the caller's responsibility to free
- this buffer.
- @param Cell Output cell information of the encoded bitmap.
- @param GlyphBufferLen If not NULL, output the length of GlyphBuffer.
-
- @retval EFI_SUCCESS The bitmap data is retrieved successfully.
- @retval EFI_NOT_FOUND The specified CharValue does not exist in current
- database.
- @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
- task.
-
-**/
-EFI_STATUS
-FindGlyphBlock (
- IN HII_FONT_PACKAGE_INSTANCE *FontPackage,
- IN CHAR16 CharValue,
- OUT UINT8 **GlyphBuffer OPTIONAL,
- OUT EFI_HII_GLYPH_INFO *Cell OPTIONAL,
- OUT UINTN *GlyphBufferLen OPTIONAL
- );
-
-/**
- This function exports Form packages to a buffer.
- This is a internal function.
-
- @param Private Hii database private structure.
- @param Handle Identification of a package list.
- @param PackageList Pointer to a package list which will be exported.
- @param UsedSize The length of buffer be used.
- @param BufferSize Length of the Buffer.
- @param Buffer Allocated space for storing exported data.
- @param ResultSize The size of the already exported content of this
- package list.
-
- @retval EFI_SUCCESS Form Packages are exported successfully.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
-
-**/
-EFI_STATUS
-ExportFormPackages (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN EFI_HII_HANDLE Handle,
- IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
- IN UINTN UsedSize,
- IN UINTN BufferSize,
- IN OUT VOID *Buffer,
- IN OUT UINTN *ResultSize
- );
-
-//
-// EFI_HII_FONT_PROTOCOL protocol interfaces
-//
-
-/**
- Renders a string to a bitmap or to the display.
-
- @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
- @param Flags Describes how the string is to be drawn.
- @param String Points to the null-terminated string to be
- displayed.
- @param StringInfo Points to the string output information,
- including the color and font. If NULL, then the
- string will be output in the default system font
- and color.
- @param Blt If this points to a non-NULL on entry, this
- points to the image, which is Width pixels wide
- and Height pixels high. The string will be drawn
- onto this image and
- EFI_HII_OUT_FLAG_CLIP is implied. If this points
- to a NULL on entry, then a buffer
- will be allocated to hold the generated image and
- the pointer updated on exit. It is the caller's
- responsibility to free this buffer.
- @param BltX Together with BltX, Specifies the offset from the left and top edge
- of the image of the first character cell in the
- image.
- @param BltY Together with BltY, Specifies the offset from the left and top edge
- of the image of the first character cell in the
- image.
- @param RowInfoArray If this is non-NULL on entry, then on exit, this
- will point to an allocated buffer containing
- row information and RowInfoArraySize will be
- updated to contain the number of elements.
- This array describes the characters which were at
- least partially drawn and the heights of the
- rows. It is the caller's responsibility to free
- this buffer.
- @param RowInfoArraySize If this is non-NULL on entry, then on exit it
- contains the number of elements in RowInfoArray.
- @param ColumnInfoArray If this is non-NULL, then on return it will be
- filled with the horizontal offset for each
- character in the string on the row where it is
- displayed. Non-printing characters will have
- the offset ~0. The caller is responsible to
- allocate a buffer large enough so that there
- is one entry for each character in the string,
- not including the null-terminator. It is possible
- when character display is normalized that some
- character cells overlap.
-
- @retval EFI_SUCCESS The string was successfully rendered.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for
- RowInfoArray or Blt.
- @retval EFI_INVALID_PARAMETER The String or Blt.
- @retval EFI_INVALID_PARAMETER Flags were invalid combination..
-
-**/
-EFI_STATUS
-EFIAPI
-HiiStringToImage (
- IN CONST EFI_HII_FONT_PROTOCOL *This,
- IN EFI_HII_OUT_FLAGS Flags,
- IN CONST EFI_STRING String,
- IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL,
- IN OUT EFI_IMAGE_OUTPUT **Blt,
- IN UINTN BltX,
- IN UINTN BltY,
- OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL,
- OUT UINTN *RowInfoArraySize OPTIONAL,
- OUT UINTN *ColumnInfoArray OPTIONAL
- );
-
-/**
- Render a string to a bitmap or the screen containing the contents of the specified string.
-
- @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
- @param Flags Describes how the string is to be drawn.
- @param PackageList The package list in the HII database to search
- for the specified string.
- @param StringId The string's id, which is unique within
- PackageList.
- @param Language Points to the language for the retrieved string.
- If NULL, then the current system language is
- used.
- @param StringInfo Points to the string output information,
- including the color and font. If NULL, then the
- string will be output in the default system font
- and color.
- @param Blt If this points to a non-NULL on entry, this
- points to the image, which is Width pixels wide
- and Height pixels high. The string will be drawn
- onto this image and
- EFI_HII_OUT_FLAG_CLIP is implied. If this points
- to a NULL on entry, then a buffer
- will be allocated to hold the generated image and
- the pointer updated on exit. It is the caller's
- responsibility to free this buffer.
- @param BltX Together with BltX, Specifies the offset from the left and top edge
- of the image of the first character cell in the
- image.
- @param BltY Together with BltY, Specifies the offset from the left and top edge
- of the image of the first character cell in the
- image.
- @param RowInfoArray If this is non-NULL on entry, then on exit, this
- will point to an allocated buffer containing
- row information and RowInfoArraySize will be
- updated to contain the number of elements.
- This array describes the characters which were at
- least partially drawn and the heights of the
- rows. It is the caller's responsibility to free
- this buffer.
- @param RowInfoArraySize If this is non-NULL on entry, then on exit it
- contains the number of elements in RowInfoArray.
- @param ColumnInfoArray If this is non-NULL, then on return it will be
- filled with the horizontal offset for each
- character in the string on the row where it is
- displayed. Non-printing characters will have
- the offset ~0. The caller is responsible to
- allocate a buffer large enough so that there
- is one entry for each character in the string,
- not including the null-terminator. It is possible
- when character display is normalized that some
- character cells overlap.
-
- @retval EFI_SUCCESS The string was successfully rendered.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for
- RowInfoArray or Blt.
- @retval EFI_INVALID_PARAMETER The Blt or PackageList was NULL.
- @retval EFI_INVALID_PARAMETER Flags were invalid combination.
- @retval EFI_NOT_FOUND The specified PackageList is not in the Database or the stringid is not
- in the specified PackageList.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiStringIdToImage (
- IN CONST EFI_HII_FONT_PROTOCOL *This,
- IN EFI_HII_OUT_FLAGS Flags,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_STRING_ID StringId,
- IN CONST CHAR8 *Language,
- IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL,
- IN OUT EFI_IMAGE_OUTPUT **Blt,
- IN UINTN BltX,
- IN UINTN BltY,
- OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL,
- OUT UINTN *RowInfoArraySize OPTIONAL,
- OUT UINTN *ColumnInfoArray OPTIONAL
- );
-
-/**
- Convert the glyph for a single character into a bitmap.
-
- @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
- @param Char Character to retrieve.
- @param StringInfo Points to the string font and color information
- or NULL if the string should use the default
- system font and color.
- @param Blt Thus must point to a NULL on entry. A buffer will
- be allocated to hold the output and the pointer
- updated on exit. It is the caller's
- responsibility to free this buffer.
- @param Baseline Number of pixels from the bottom of the bitmap to
- the baseline.
-
- @retval EFI_SUCCESS Glyph bitmap created.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate the output buffer Blt.
- @retval EFI_WARN_UNKNOWN_GLYPH The glyph was unknown and was replaced with the
- glyph for Unicode character 0xFFFD.
- @retval EFI_INVALID_PARAMETER Blt is NULL or *Blt is not NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetGlyph (
- IN CONST EFI_HII_FONT_PROTOCOL *This,
- IN CHAR16 Char,
- IN CONST EFI_FONT_DISPLAY_INFO *StringInfo,
- OUT EFI_IMAGE_OUTPUT **Blt,
- OUT UINTN *Baseline OPTIONAL
- );
-
-/**
- This function iterates through fonts which match the specified font, using
- the specified criteria. If String is non-NULL, then all of the characters in
- the string must exist in order for a candidate font to be returned.
-
- @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
- @param FontHandle On entry, points to the font handle returned by a
- previous call to GetFontInfo() or NULL to start
- with the first font. On return, points to the
- returned font handle or points to NULL if there
- are no more matching fonts.
- @param StringInfoIn Upon entry, points to the font to return information
- about. If NULL, then the information about the system
- default font will be returned.
- @param StringInfoOut Upon return, contains the matching font's information.
- If NULL, then no information is returned. This buffer
- is allocated with a call to the Boot Service AllocatePool().
- It is the caller's responsibility to call the Boot
- Service FreePool() when the caller no longer requires
- the contents of StringInfoOut.
- @param String Points to the string which will be tested to
- determine if all characters are available. If
- NULL, then any font is acceptable.
-
- @retval EFI_SUCCESS Matching font returned successfully.
- @retval EFI_NOT_FOUND No matching font was found.
- @retval EFI_INVALID_PARAMETER StringInfoIn is NULL.
- @retval EFI_INVALID_PARAMETER StringInfoIn->FontInfoMask is an invalid combination.
- @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the
- request.
-**/
-EFI_STATUS
-EFIAPI
-HiiGetFontInfo (
- IN CONST EFI_HII_FONT_PROTOCOL *This,
- IN OUT EFI_FONT_HANDLE *FontHandle,
- IN CONST EFI_FONT_DISPLAY_INFO *StringInfoIn OPTIONAL,
- OUT EFI_FONT_DISPLAY_INFO **StringInfoOut,
- IN CONST EFI_STRING String OPTIONAL
- );
-
-//
-// EFI_HII_IMAGE_PROTOCOL interfaces
-//
-
-/**
- Get the image id of last image block: EFI_HII_IIBT_END_BLOCK when input
- ImageId is zero, otherwise return the address of the
- corresponding image block with identifier specified by ImageId.
-
- This is a internal function.
-
- @param ImageBlocks Points to the beginning of a series of image blocks stored in order.
- @param ImageId If input ImageId is 0, output the image id of the EFI_HII_IIBT_END_BLOCK;
- else use this id to find its corresponding image block address.
-
- @return The image block address when input ImageId is not zero; otherwise return NULL.
-
-**/
-EFI_HII_IMAGE_BLOCK *
-GetImageIdOrAddress (
- IN EFI_HII_IMAGE_BLOCK *ImageBlocks,
- IN OUT EFI_IMAGE_ID *ImageId
- );
-
-/**
- Return the HII package list identified by PackageList HII handle.
-
- @param Database Pointer to HII database list header.
- @param PackageList HII handle of the package list to locate.
-
- @retval The HII package list instance.
-**/
-HII_DATABASE_PACKAGE_LIST_INSTANCE *
-LocatePackageList (
- IN LIST_ENTRY *Database,
- IN EFI_HII_HANDLE PackageList
- );
-
-/**
- This function retrieves the image specified by ImageId which is associated with
- the specified PackageList and copies it into the buffer specified by Image.
-
- @param Database A pointer to the database list header.
- @param PackageList Handle of the package list where this image will
- be searched.
- @param ImageId The image's id,, which is unique within
- PackageList.
- @param Image Points to the image.
- @param BitmapOnly TRUE to only return the bitmap type image.
- FALSE to locate image decoder instance to decode image.
-
- @retval EFI_SUCCESS The new image was returned successfully.
- @retval EFI_NOT_FOUND The image specified by ImageId is not in the
- database. The specified PackageList is not in the database.
- @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
- hold the image.
- @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.
- @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not
- enough memory.
-**/
-EFI_STATUS
-IGetImage (
- IN LIST_ENTRY *Database,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_IMAGE_ID ImageId,
- OUT EFI_IMAGE_INPUT *Image,
- IN BOOLEAN BitmapOnly
- );
-
-/**
- Return the first HII image decoder instance which supports the DecoderName.
-
- @param BlockType The image block type.
-
- @retval Pointer to the HII image decoder instance.
-**/
-EFI_HII_IMAGE_DECODER_PROTOCOL *
-LocateHiiImageDecoder (
- UINT8 BlockType
- );
-
-/**
- This function adds the image Image to the group of images owned by PackageList, and returns
- a new image identifier (ImageId).
-
- @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
- @param PackageList Handle of the package list where this image will
- be added.
- @param ImageId On return, contains the new image id, which is
- unique within PackageList.
- @param Image Points to the image.
-
- @retval EFI_SUCCESS The new image was added successfully.
- @retval EFI_NOT_FOUND The specified PackageList could not be found in
- database.
- @retval EFI_OUT_OF_RESOURCES Could not add the image due to lack of resources.
- @retval EFI_INVALID_PARAMETER Image is NULL or ImageId is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiNewImage (
- IN CONST EFI_HII_IMAGE_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- OUT EFI_IMAGE_ID *ImageId,
- IN CONST EFI_IMAGE_INPUT *Image
- );
-
-/**
- This function retrieves the image specified by ImageId which is associated with
- the specified PackageList and copies it into the buffer specified by Image.
-
- @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
- @param PackageList Handle of the package list where this image will
- be searched.
- @param ImageId The image's id,, which is unique within
- PackageList.
- @param Image Points to the image.
-
- @retval EFI_SUCCESS The new image was returned successfully.
- @retval EFI_NOT_FOUND The image specified by ImageId is not available.
- The specified PackageList is not in the database.
- @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
- hold the image.
- @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.
- @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not
- enough memory.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetImage (
- IN CONST EFI_HII_IMAGE_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_IMAGE_ID ImageId,
- OUT EFI_IMAGE_INPUT *Image
- );
-
-/**
- This function updates the image specified by ImageId in the specified PackageListHandle to
- the image specified by Image.
-
- @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
- @param PackageList The package list containing the images.
- @param ImageId The image's id,, which is unique within
- PackageList.
- @param Image Points to the image.
-
- @retval EFI_SUCCESS The new image was updated successfully.
- @retval EFI_NOT_FOUND The image specified by ImageId is not in the
- database. The specified PackageList is not in the database.
- @retval EFI_INVALID_PARAMETER The Image was NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiSetImage (
- IN CONST EFI_HII_IMAGE_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_IMAGE_ID ImageId,
- IN CONST EFI_IMAGE_INPUT *Image
- );
-
-/**
- This function renders an image to a bitmap or the screen using the specified
- color and options. It draws the image on an existing bitmap, allocates a new
- bitmap or uses the screen. The images can be clipped.
-
- @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
- @param Flags Describes how the image is to be drawn.
- @param Image Points to the image to be displayed.
- @param Blt If this points to a non-NULL on entry, this
- points to the image, which is Width pixels wide
- and Height pixels high. The image will be drawn
- onto this image and EFI_HII_DRAW_FLAG_CLIP is
- implied. If this points to a NULL on entry, then
- a buffer will be allocated to hold the generated
- image and the pointer updated on exit. It is the
- caller's responsibility to free this buffer.
- @param BltX Specifies the offset from the left and top edge
- of the output image of the first pixel in the
- image.
- @param BltY Specifies the offset from the left and top edge
- of the output image of the first pixel in the
- image.
-
- @retval EFI_SUCCESS The image was successfully drawn.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
- @retval EFI_INVALID_PARAMETER The Image or Blt was NULL.
- @retval EFI_INVALID_PARAMETER Any combination of Flags is invalid.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiDrawImage (
- IN CONST EFI_HII_IMAGE_PROTOCOL *This,
- IN EFI_HII_DRAW_FLAGS Flags,
- IN CONST EFI_IMAGE_INPUT *Image,
- IN OUT EFI_IMAGE_OUTPUT **Blt,
- IN UINTN BltX,
- IN UINTN BltY
- );
-
-/**
- This function renders an image to a bitmap or the screen using the specified
- color and options. It draws the image on an existing bitmap, allocates a new
- bitmap or uses the screen. The images can be clipped.
-
- @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
- @param Flags Describes how the image is to be drawn.
- @param PackageList The package list in the HII database to search
- for the specified image.
- @param ImageId The image's id, which is unique within
- PackageList.
- @param Blt If this points to a non-NULL on entry, this
- points to the image, which is Width pixels wide
- and Height pixels high. The image will be drawn
- onto this image and
- EFI_HII_DRAW_FLAG_CLIP is implied. If this points
- to a NULL on entry, then a buffer will be
- allocated to hold the generated image and the
- pointer updated on exit. It is the caller's
- responsibility to free this buffer.
- @param BltX Specifies the offset from the left and top edge
- of the output image of the first pixel in the
- image.
- @param BltY Specifies the offset from the left and top edge
- of the output image of the first pixel in the
- image.
-
- @retval EFI_SUCCESS The image was successfully drawn.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
- @retval EFI_INVALID_PARAMETER The Blt was NULL.
- @retval EFI_NOT_FOUND The image specified by ImageId is not in the database.
- The specified PackageList is not in the database.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiDrawImageId (
- IN CONST EFI_HII_IMAGE_PROTOCOL *This,
- IN EFI_HII_DRAW_FLAGS Flags,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_IMAGE_ID ImageId,
- IN OUT EFI_IMAGE_OUTPUT **Blt,
- IN UINTN BltX,
- IN UINTN BltY
- );
-
-/**
- The prototype of this extension function is the same with EFI_HII_IMAGE_PROTOCOL.NewImage().
- This protocol invokes EFI_HII_IMAGE_PROTOCOL.NewImage() implicitly.
-
- @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
- @param PackageList Handle of the package list where this image will
- be added.
- @param ImageId On return, contains the new image id, which is
- unique within PackageList.
- @param Image Points to the image.
-
- @retval EFI_SUCCESS The new image was added successfully.
- @retval EFI_NOT_FOUND The PackageList could not be found.
- @retval EFI_OUT_OF_RESOURCES Could not add the image due to lack of resources.
- @retval EFI_INVALID_PARAMETER Image is NULL or ImageId is NULL.
-**/
-EFI_STATUS
-EFIAPI
-HiiNewImageEx (
- IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- OUT EFI_IMAGE_ID *ImageId,
- IN CONST EFI_IMAGE_INPUT *Image
- );
-
-/**
- Return the information about the image, associated with the package list.
- The prototype of this extension function is the same with EFI_HII_IMAGE_PROTOCOL.GetImage().
-
- This function is similar to EFI_HII_IMAGE_PROTOCOL.GetImage(). The difference is that
- this function will locate all EFI_HII_IMAGE_DECODER_PROTOCOL instances installed in the
- system if the decoder of the certain image type is not supported by the
- EFI_HII_IMAGE_EX_PROTOCOL. The function will attempt to decode the image to the
- EFI_IMAGE_INPUT using the first EFI_HII_IMAGE_DECODER_PROTOCOL instance that
- supports the requested image type.
-
- @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
- @param PackageList The package list in the HII database to search for the
- specified image.
- @param ImageId The image's id, which is unique within PackageList.
- @param Image Points to the image.
-
- @retval EFI_SUCCESS The new image was returned successfully.
- @retval EFI_NOT_FOUND The image specified by ImageId is not available. The specified
- PackageList is not in the Database.
- @retval EFI_INVALID_PARAMETER Image was NULL or ImageId was 0.
- @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there
- was not enough memory.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetImageEx (
- IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_IMAGE_ID ImageId,
- OUT EFI_IMAGE_INPUT *Image
- );
-
-/**
- Change the information about the image.
-
- Same with EFI_HII_IMAGE_PROTOCOL.SetImage(), this protocol invokes
- EFI_HII_IMAGE_PROTOCOL.SetImage()implicitly.
-
- @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
- @param PackageList The package list containing the images.
- @param ImageId The image's id, which is unique within PackageList.
- @param Image Points to the image.
-
- @retval EFI_SUCCESS The new image was successfully updated.
- @retval EFI_NOT_FOUND The image specified by ImageId is not in the
- database. The specified PackageList is not in
- the database.
- @retval EFI_INVALID_PARAMETER The Image was NULL, the ImageId was 0 or
- the Image->Bitmap was NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiSetImageEx (
- IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_IMAGE_ID ImageId,
- IN CONST EFI_IMAGE_INPUT *Image
- );
-
-/**
- Renders an image to a bitmap or to the display.
-
- The prototype of this extension function is the same with
- EFI_HII_IMAGE_PROTOCOL.DrawImage(). This protocol invokes
- EFI_HII_IMAGE_PROTOCOL.DrawImage() implicitly.
-
- @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
- @param Flags Describes how the image is to be drawn.
- @param Image Points to the image to be displayed.
- @param Blt If this points to a non-NULL on entry, this points
- to the image, which is Width pixels wide and
- Height pixels high. The image will be drawn onto
- this image and EFI_HII_DRAW_FLAG_CLIP is implied.
- If this points to a NULL on entry, then a buffer
- will be allocated to hold the generated image and
- the pointer updated on exit. It is the caller's
- responsibility to free this buffer.
- @param BltX Specifies the offset from the left and top edge of
- the output image of the first pixel in the image.
- @param BltY Specifies the offset from the left and top edge of
- the output image of the first pixel in the image.
-
- @retval EFI_SUCCESS The image was successfully drawn.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
- @retval EFI_INVALID_PARAMETER The Image or Blt was NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiDrawImageEx (
- IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
- IN EFI_HII_DRAW_FLAGS Flags,
- IN CONST EFI_IMAGE_INPUT *Image,
- IN OUT EFI_IMAGE_OUTPUT **Blt,
- IN UINTN BltX,
- IN UINTN BltY
- );
-
-/**
- Renders an image to a bitmap or the screen containing the contents of the specified
- image.
-
- This function is similar to EFI_HII_IMAGE_PROTOCOL.DrawImageId(). The difference is that
- this function will locate all EFI_HII_IMAGE_DECODER_PROTOCOL instances installed in the
- system if the decoder of the certain image type is not supported by the
- EFI_HII_IMAGE_EX_PROTOCOL. The function will attempt to decode the image to the
- EFI_IMAGE_INPUT using the first EFI_HII_IMAGE_DECODER_PROTOCOL instance that
- supports the requested image type.
-
- @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
- @param Flags Describes how the image is to be drawn.
- @param PackageList The package list in the HII database to search for
- the specified image.
- @param ImageId The image's id, which is unique within PackageList.
- @param Blt If this points to a non-NULL on entry, this points
- to the image, which is Width pixels wide and
- Height pixels high. The image will be drawn onto
- this image and EFI_HII_DRAW_FLAG_CLIP is implied.
- If this points to a NULL on entry, then a buffer
- will be allocated to hold the generated image
- and the pointer updated on exit. It is the caller's
- responsibility to free this buffer.
- @param BltX Specifies the offset from the left and top edge of
- the output image of the first pixel in the image.
- @param BltY Specifies the offset from the left and top edge of
- the output image of the first pixel in the image.
-
- @retval EFI_SUCCESS The image was successfully drawn.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
- @retval EFI_INVALID_PARAMETER The Blt was NULL or ImageId was 0.
- @retval EFI_NOT_FOUND The image specified by ImageId is not in the database.
- The specified PackageList is not in the database.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiDrawImageIdEx (
- IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
- IN EFI_HII_DRAW_FLAGS Flags,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_IMAGE_ID ImageId,
- IN OUT EFI_IMAGE_OUTPUT **Blt,
- IN UINTN BltX,
- IN UINTN BltY
- );
-
-/**
- This function returns the image information to EFI_IMAGE_OUTPUT. Only the width
- and height are returned to the EFI_IMAGE_OUTPUT instead of decoding the image
- to the buffer. This function is used to get the geometry of the image. This function
- will try to locate all of the EFI_HII_IMAGE_DECODER_PROTOCOL installed on the
- system if the decoder of image type is not supported by the EFI_HII_IMAGE_EX_PROTOCOL.
-
- @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
- @param PackageList Handle of the package list where this image will
- be searched.
- @param ImageId The image's id, which is unique within PackageList.
- @param Image Points to the image.
-
- @retval EFI_SUCCESS The new image was returned successfully.
- @retval EFI_NOT_FOUND The image specified by ImageId is not in the
- database. The specified PackageList is not in the database.
- @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
- hold the image.
- @retval EFI_INVALID_PARAMETER The Image was NULL or the ImageId was 0.
- @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there
- was not enough memory.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetImageInfo (
- IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_IMAGE_ID ImageId,
- OUT EFI_IMAGE_OUTPUT *Image
- );
-
-//
-// EFI_HII_STRING_PROTOCOL
-//
-
-/**
- This function adds the string String to the group of strings owned by PackageList, with the
- specified font information StringFontInfo and returns a new string id.
-
- @param This A pointer to the EFI_HII_STRING_PROTOCOL
- instance.
- @param PackageList Handle of the package list where this string will
- be added.
- @param StringId On return, contains the new strings id, which is
- unique within PackageList.
- @param Language Points to the language for the new string.
- @param LanguageName Points to the printable language name to
- associate with the passed in Language field.If
- LanguageName is not NULL and the string package
- header's LanguageName associated with a given
- Language is not zero, the LanguageName being
- passed in will be ignored.
- @param String Points to the new null-terminated string.
- @param StringFontInfo Points to the new string's font information or
- NULL if the string should have the default system
- font, size and style.
-
- @retval EFI_SUCCESS The new string was added successfully.
- @retval EFI_NOT_FOUND The specified PackageList could not be found in
- database.
- @retval EFI_OUT_OF_RESOURCES Could not add the string due to lack of
- resources.
- @retval EFI_INVALID_PARAMETER String is NULL or StringId is NULL or Language is
- NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiNewString (
- IN CONST EFI_HII_STRING_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- OUT EFI_STRING_ID *StringId,
- IN CONST CHAR8 *Language,
- IN CONST CHAR16 *LanguageName OPTIONAL,
- IN CONST EFI_STRING String,
- IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL
- );
-
-/**
- This function retrieves the string specified by StringId which is associated
- with the specified PackageList in the language Language and copies it into
- the buffer specified by String.
-
- @param This A pointer to the EFI_HII_STRING_PROTOCOL
- instance.
- @param Language Points to the language for the retrieved string.
- @param PackageList The package list in the HII database to search
- for the specified string.
- @param StringId The string's id, which is unique within
- PackageList.
- @param String Points to the new null-terminated string.
- @param StringSize On entry, points to the size of the buffer
- pointed to by String, in bytes. On return,
- points to the length of the string, in bytes.
- @param StringFontInfo If not NULL, points to the string's font
- information. It's caller's responsibility to
- free this buffer.
-
- @retval EFI_SUCCESS The string was returned successfully.
- @retval EFI_NOT_FOUND The string specified by StringId is not
- available.
- The specified PackageList is not in the database.
- @retval EFI_INVALID_LANGUAGE The string specified by StringId is available but
- not in the specified language.
- @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small
- to hold the string.
- @retval EFI_INVALID_PARAMETER The Language or StringSize was NULL.
- @retval EFI_INVALID_PARAMETER The value referenced by StringSize was not zero
- and String was NULL.
- @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the
- request.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetString (
- IN CONST EFI_HII_STRING_PROTOCOL *This,
- IN CONST CHAR8 *Language,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_STRING_ID StringId,
- OUT EFI_STRING String,
- IN OUT UINTN *StringSize,
- OUT EFI_FONT_INFO **StringFontInfo OPTIONAL
- );
-
-/**
- This function updates the string specified by StringId in the specified PackageList to the text
- specified by String and, optionally, the font information specified by StringFontInfo.
-
- @param This A pointer to the EFI_HII_STRING_PROTOCOL
- instance.
- @param PackageList The package list containing the strings.
- @param StringId The string's id, which is unique within
- PackageList.
- @param Language Points to the language for the updated string.
- @param String Points to the new null-terminated string.
- @param StringFontInfo Points to the string's font information or NULL
- if the string font information is not changed.
-
- @retval EFI_SUCCESS The string was updated successfully.
- @retval EFI_NOT_FOUND The string specified by StringId is not in the
- database.
- @retval EFI_INVALID_PARAMETER The String or Language was NULL.
- @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
- task.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiSetString (
- IN CONST EFI_HII_STRING_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_STRING_ID StringId,
- IN CONST CHAR8 *Language,
- IN CONST EFI_STRING String,
- IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL
- );
-
-/**
- This function returns the list of supported languages, in the format specified
- in Appendix M of UEFI 2.1 spec.
-
- @param This A pointer to the EFI_HII_STRING_PROTOCOL
- instance.
- @param PackageList The package list to examine.
- @param Languages Points to the buffer to hold the returned
- null-terminated ASCII string.
- @param LanguagesSize On entry, points to the size of the buffer
- pointed to by Languages, in bytes. On return,
- points to the length of Languages, in bytes.
-
- @retval EFI_SUCCESS The languages were returned successfully.
- @retval EFI_INVALID_PARAMETER The LanguagesSize was NULL.
- @retval EFI_INVALID_PARAMETER The value referenced by LanguagesSize is not zero and Languages is NULL.
- @retval EFI_BUFFER_TOO_SMALL The LanguagesSize is too small to hold the list
- of supported languages. LanguageSize is updated
- to contain the required size.
- @retval EFI_NOT_FOUND Could not find string package in specified
- packagelist.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetLanguages (
- IN CONST EFI_HII_STRING_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- IN OUT CHAR8 *Languages,
- IN OUT UINTN *LanguagesSize
- );
-
-/**
- Each string package has associated with it a single primary language and zero
- or more secondary languages. This routine returns the secondary languages
- associated with a package list.
-
- @param This A pointer to the EFI_HII_STRING_PROTOCOL
- instance.
- @param PackageList The package list to examine.
- @param PrimaryLanguage Points to the null-terminated ASCII string that specifies
- the primary language. Languages are specified in the
- format specified in Appendix M of the UEFI 2.0 specification.
- @param SecondaryLanguages Points to the buffer to hold the returned null-terminated
- ASCII string that describes the list of
- secondary languages for the specified
- PrimaryLanguage. If there are no secondary
- languages, the function returns successfully,
- but this is set to NULL.
- @param SecondaryLanguagesSize On entry, points to the size of the buffer
- pointed to by SecondaryLanguages, in bytes. On
- return, points to the length of SecondaryLanguages
- in bytes.
-
- @retval EFI_SUCCESS Secondary languages were correctly returned.
- @retval EFI_INVALID_PARAMETER PrimaryLanguage or SecondaryLanguagesSize was NULL.
- @retval EFI_INVALID_PARAMETER The value referenced by SecondaryLanguagesSize is not
- zero and SecondaryLanguages is NULL.
- @retval EFI_BUFFER_TOO_SMALL The buffer specified by SecondaryLanguagesSize is
- too small to hold the returned information.
- SecondaryLanguageSize is updated to hold the size of
- the buffer required.
- @retval EFI_INVALID_LANGUAGE The language specified by PrimaryLanguage is not
- present in the specified package list.
- @retval EFI_NOT_FOUND The specified PackageList is not in the Database.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetSecondaryLanguages (
- IN CONST EFI_HII_STRING_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- IN CONST CHAR8 *PrimaryLanguage,
- IN OUT CHAR8 *SecondaryLanguages,
- IN OUT UINTN *SecondaryLanguagesSize
- );
-
-//
-// EFI_HII_DATABASE_PROTOCOL protocol interfaces
-//
-
-/**
- This function adds the packages in the package list to the database and returns a handle. If there is a
- EFI_DEVICE_PATH_PROTOCOL associated with the DriverHandle, then this function will
- create a package of type EFI_PACKAGE_TYPE_DEVICE_PATH and add it to the package list.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER
- structure.
- @param DriverHandle Associate the package list with this EFI handle.
- If a NULL is specified, this data will not be associate
- with any drivers and cannot have a callback induced.
- @param Handle A pointer to the EFI_HII_HANDLE instance.
-
- @retval EFI_SUCCESS The package list associated with the Handle was
- added to the HII database.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the
- new database contents.
- @retval EFI_INVALID_PARAMETER PackageList is NULL or Handle is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiNewPackageList (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
- IN CONST EFI_HANDLE DriverHandle OPTIONAL,
- OUT EFI_HII_HANDLE *Handle
- );
-
-/**
- This function removes the package list that is associated with a handle Handle
- from the HII database. Before removing the package, any registered functions
- with the notification type REMOVE_PACK and the same package type will be called.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param Handle The handle that was registered to the data that
- is requested for removal.
-
- @retval EFI_SUCCESS The data associated with the Handle was removed
- from the HII database.
- @retval EFI_NOT_FOUND The specified Handle is not in database.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiRemovePackageList (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN EFI_HII_HANDLE Handle
- );
-
-/**
- This function updates the existing package list (which has the specified Handle)
- in the HII databases, using the new package list specified by PackageList.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param Handle The handle that was registered to the data that
- is requested to be updated.
- @param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER
- package.
-
- @retval EFI_SUCCESS The HII database was successfully updated.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate enough memory for the updated
- database.
- @retval EFI_INVALID_PARAMETER PackageList was NULL.
- @retval EFI_NOT_FOUND The specified Handle is not in database.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiUpdatePackageList (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN EFI_HII_HANDLE Handle,
- IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList
- );
-
-/**
- This function returns a list of the package handles of the specified type
- that are currently active in the database. The pseudo-type
- EFI_HII_PACKAGE_TYPE_ALL will cause all package handles to be listed.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param PackageType Specifies the package type of the packages to
- list or EFI_HII_PACKAGE_TYPE_ALL for all packages
- to be listed.
- @param PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then
- this is the pointer to the GUID which must match
- the Guid field of EFI_HII_GUID_PACKAGE_GUID_HDR.
- Otherwise, it must be NULL.
- @param HandleBufferLength On input, a pointer to the length of the handle
- buffer. On output, the length of the handle
- buffer that is required for the handles found.
- @param Handle An array of EFI_HII_HANDLE instances returned.
-
- @retval EFI_SUCCESS The matching handles are outputted successfully.
- HandleBufferLength is updated with the actual length.
- @retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that
- Handle is too small to support the number of
- handles. HandleBufferLength is updated with a
- value that will enable the data to fit.
- @retval EFI_NOT_FOUND No matching handle could not be found in
- database.
- @retval EFI_INVALID_PARAMETER HandleBufferLength was NULL.
- @retval EFI_INVALID_PARAMETER The value referenced by HandleBufferLength was not
- zero and Handle was NULL.
- @retval EFI_INVALID_PARAMETER PackageType is not a EFI_HII_PACKAGE_TYPE_GUID but
- PackageGuid is not NULL, PackageType is a EFI_HII_
- PACKAGE_TYPE_GUID but PackageGuid is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiListPackageLists (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN UINT8 PackageType,
- IN CONST EFI_GUID *PackageGuid,
- IN OUT UINTN *HandleBufferLength,
- OUT EFI_HII_HANDLE *Handle
- );
-
-/**
- This function will export one or all package lists in the database to a buffer.
- For each package list exported, this function will call functions registered
- with EXPORT_PACK and then copy the package list to the buffer.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param Handle An EFI_HII_HANDLE that corresponds to the desired
- package list in the HII database to export or
- NULL to indicate all package lists should be
- exported.
- @param BufferSize On input, a pointer to the length of the buffer.
- On output, the length of the buffer that is
- required for the exported data.
- @param Buffer A pointer to a buffer that will contain the
- results of the export function.
-
- @retval EFI_SUCCESS Package exported.
- @retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that
- Handle is too small to support the number of
- handles. HandleBufferLength is updated with
- a value that will enable the data to fit.
- @retval EFI_NOT_FOUND The specified Handle could not be found in the
- current database.
- @retval EFI_INVALID_PARAMETER BufferSize was NULL.
- @retval EFI_INVALID_PARAMETER The value referenced by BufferSize was not zero
- and Buffer was NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiExportPackageLists (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN EFI_HII_HANDLE Handle,
- IN OUT UINTN *BufferSize,
- OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer
- );
-
-/**
- This function registers a function which will be called when specified actions related to packages of
- the specified type occur in the HII database. By registering a function, other HII-related drivers are
- notified when specific package types are added, removed or updated in the HII database.
- Each driver or application which registers a notification should use
- EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify() before exiting.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param PackageType Specifies the package type of the packages to
- list or EFI_HII_PACKAGE_TYPE_ALL for all packages
- to be listed.
- @param PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then
- this is the pointer to the GUID which must match
- the Guid field of
- EFI_HII_GUID_PACKAGE_GUID_HDR. Otherwise, it must
- be NULL.
- @param PackageNotifyFn Points to the function to be called when the
- event specified by
- NotificationType occurs.
- @param NotifyType Describes the types of notification which this
- function will be receiving.
- @param NotifyHandle Points to the unique handle assigned to the
- registered notification. Can be used in
- EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify()
- to stop notifications.
-
- @retval EFI_SUCCESS Notification registered successfully.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures
- @retval EFI_INVALID_PARAMETER NotifyHandle is NULL.
- @retval EFI_INVALID_PARAMETER PackageGuid is not NULL when PackageType is not
- EFI_HII_PACKAGE_TYPE_GUID.
- @retval EFI_INVALID_PARAMETER PackageGuid is NULL when PackageType is
- EFI_HII_PACKAGE_TYPE_GUID.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiRegisterPackageNotify (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN UINT8 PackageType,
- IN CONST EFI_GUID *PackageGuid,
- IN CONST EFI_HII_DATABASE_NOTIFY PackageNotifyFn,
- IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
- OUT EFI_HANDLE *NotifyHandle
- );
-
-/**
- Removes the specified HII database package-related notification.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param NotificationHandle The handle of the notification function being
- unregistered.
-
- @retval EFI_SUCCESS Notification is unregistered successfully.
- @retval EFI_NOT_FOUND The incoming notification handle does not exist
- in current hii database.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiUnregisterPackageNotify (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN EFI_HANDLE NotificationHandle
- );
-
-/**
- This routine retrieves an array of GUID values for each keyboard layout that
- was previously registered in the system.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param KeyGuidBufferLength On input, a pointer to the length of the keyboard
- GUID buffer. On output, the length of the handle
- buffer that is required for the handles found.
- @param KeyGuidBuffer An array of keyboard layout GUID instances
- returned.
-
- @retval EFI_SUCCESS KeyGuidBuffer was updated successfully.
- @retval EFI_BUFFER_TOO_SMALL The KeyGuidBufferLength parameter indicates
- that KeyGuidBuffer is too small to support the
- number of GUIDs. KeyGuidBufferLength is
- updated with a value that will enable the data to
- fit.
- @retval EFI_INVALID_PARAMETER The KeyGuidBufferLength is NULL.
- @retval EFI_INVALID_PARAMETER The value referenced by KeyGuidBufferLength is not
- zero and KeyGuidBuffer is NULL.
- @retval EFI_NOT_FOUND There was no keyboard layout.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiFindKeyboardLayouts (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN OUT UINT16 *KeyGuidBufferLength,
- OUT EFI_GUID *KeyGuidBuffer
- );
-
-/**
- This routine retrieves the requested keyboard layout. The layout is a physical description of the keys
- on a keyboard and the character(s) that are associated with a particular set of key strokes.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param KeyGuid A pointer to the unique ID associated with a
- given keyboard layout. If KeyGuid is NULL then
- the current layout will be retrieved.
- @param KeyboardLayoutLength On input, a pointer to the length of the
- KeyboardLayout buffer. On output, the length of
- the data placed into KeyboardLayout.
- @param KeyboardLayout A pointer to a buffer containing the retrieved
- keyboard layout.
-
- @retval EFI_SUCCESS The keyboard layout was retrieved successfully.
- @retval EFI_NOT_FOUND The requested keyboard layout was not found.
- @retval EFI_INVALID_PARAMETER The KeyboardLayout or KeyboardLayoutLength was
- NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetKeyboardLayout (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN CONST EFI_GUID *KeyGuid,
- IN OUT UINT16 *KeyboardLayoutLength,
- OUT EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout
- );
-
-/**
- This routine sets the default keyboard layout to the one referenced by KeyGuid. When this routine
- is called, an event will be signaled of the EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID
- group type. This is so that agents which are sensitive to the current keyboard layout being changed
- can be notified of this change.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param KeyGuid A pointer to the unique ID associated with a
- given keyboard layout.
-
- @retval EFI_SUCCESS The current keyboard layout was successfully set.
- @retval EFI_NOT_FOUND The referenced keyboard layout was not found, so
- action was taken.
- @retval EFI_INVALID_PARAMETER The KeyGuid was NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiSetKeyboardLayout (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN CONST EFI_GUID *KeyGuid
- );
-
-/**
- Return the EFI handle associated with a package list.
-
- @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
- instance.
- @param PackageListHandle An EFI_HII_HANDLE that corresponds to the desired
- package list in the HIIdatabase.
- @param DriverHandle On return, contains the EFI_HANDLE which was
- registered with the package list in
- NewPackageList().
-
- @retval EFI_SUCCESS The DriverHandle was returned successfully.
- @retval EFI_INVALID_PARAMETER The PackageListHandle was not valid or
- DriverHandle was NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetPackageListHandle (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageListHandle,
- OUT EFI_HANDLE *DriverHandle
- );
-
-//
-// EFI_HII_CONFIG_ROUTING_PROTOCOL interfaces
-//
-
-/**
- This function allows a caller to extract the current configuration
- for one or more named elements from one or more drivers.
-
- @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
- instance.
- @param Request A null-terminated Unicode string in
- <MultiConfigRequest> format.
- @param Progress On return, points to a character in the Request
- string. Points to the string's null terminator if
- 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 Results Null-terminated Unicode string in
- <MultiConfigAltResp> format which has all values
- filled in for the names in the Request string.
- String to be allocated by the called function.
-
- @retval EFI_SUCCESS The Results string is filled with the values
- corresponding to all requested names.
- @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
- results that must be stored awaiting possible
- future protocols.
- @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
- Progress set to the "G" in "GUID" of the
- routing header that doesn't match. Note: There
- is no requirement that all routing data
- be validated before any configuration extraction.
- @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
- parameter would result in this type of error. The
- Progress parameter is set to NULL.
- @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
- before the error or the beginning of the string.
- @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
- name in question.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiConfigRoutingExtractConfig (
- IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
- IN CONST EFI_STRING Request,
- OUT EFI_STRING *Progress,
- OUT EFI_STRING *Results
- );
-
-/**
- This function allows the caller to request the current configuration for the
- entirety of the current HII database and returns the data in a null-terminated Unicode string.
-
- @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
- instance.
- @param Results Null-terminated Unicode string in
- <MultiConfigAltResp> format which has all values
- filled in for the entirety of the current HII
- database. String to be allocated by the called
- function. De-allocation is up to the caller.
-
- @retval EFI_SUCCESS The Results string is filled with the values
- corresponding to all requested names.
- @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
- results that must be stored awaiting possible
- future protocols.
- @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
- parameter would result in this type of error.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiConfigRoutingExportConfig (
- IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
- OUT EFI_STRING *Results
- );
-
-/**
- This function processes the results of processing forms and routes it to the
- appropriate handlers or storage.
-
- @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
- instance.
- @param Configuration A null-terminated Unicode string in
- <MulltiConfigResp> format.
- @param Progress A pointer to a string filled in with the offset
- of 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)
- or the terminating NULL if all was successful.
-
- @retval EFI_SUCCESS The results have been distributed or are awaiting
- distribution.
- @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
- results that must be stored awaiting possible
- future protocols.
- @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
- would result in this type of error.
- @retval EFI_NOT_FOUND Target for the specified routing data was not
- found.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiConfigRoutingRouteConfig (
- IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
- IN CONST EFI_STRING Configuration,
- OUT EFI_STRING *Progress
- );
-
-/**
- This helper function is to be called by drivers to map configuration data stored
- in byte array ("block") formats such as UEFI Variables into current configuration strings.
-
- @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
- instance.
- @param ConfigRequest A null-terminated Unicode string in
- <ConfigRequest> format.
- @param Block Array of bytes defining the block's
- configuration.
- @param BlockSize Length in bytes of Block.
- @param Config Filled-in configuration string. String allocated
- by the function. Returned only if call is
- successful.
- @param Progress A pointer to a string filled in with the offset
- of 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)
- or the terminating NULL if all was successful.
-
- @retval EFI_SUCCESS The request succeeded. Progress points to the
- null terminator at the end of the ConfigRequest
- string.
- @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config.
- Progress points to the first character of
- ConfigRequest.
- @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
- Block parameter would result in this type of
- error. Progress points to the first character of
- ConfigRequest.
- @retval EFI_NOT_FOUND Target for the specified routing data was not
- found. Progress points to the "G" in "GUID" of
- the errant routing data.
- @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
- @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
- Block is left updated and Progress points at
- the '&' preceding the first non-<BlockName>.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiBlockToConfig (
- IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
- IN CONST EFI_STRING ConfigRequest,
- IN CONST UINT8 *Block,
- IN CONST UINTN BlockSize,
- OUT EFI_STRING *Config,
- OUT EFI_STRING *Progress
- );
-
-/**
- This helper function is to be called by drivers to map configuration strings
- to configurations stored in byte array ("block") formats such as UEFI Variables.
-
- @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
- instance.
- @param ConfigResp A null-terminated Unicode string in <ConfigResp>
- format.
- @param Block A possibly null array of bytes representing the
- current block. Only bytes referenced in the
- ConfigResp string in the block are modified. If
- this parameter is null or if the *BlockSize
- parameter is (on input) shorter than required by
- the Configuration string, only the BlockSize
- parameter is updated and an appropriate status
- (see below) is returned.
- @param BlockSize The length of the Block in units of UINT8. On
- input, this is the size of the Block. On output,
- if successful, contains the largest index of the
- modified byte in the Block, or the required buffer
- size if the Block is not large enough.
- @param Progress On return, points to an element of the ConfigResp
- string filled in with the offset of 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) or
- the terminating NULL if all was successful.
-
- @retval EFI_SUCCESS The request succeeded. Progress points to the
- null terminator at the end of the ConfigResp
- string.
- @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config.
- Progress points to the first character of
- ConfigResp.
- @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
- Block parameter would result in this type of
- error. Progress points to the first character of
- ConfigResp.
- @retval EFI_NOT_FOUND Target for the specified routing data was not
- found. Progress points to the "G" in "GUID" of
- the errant routing data.
- @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
- value pair. Block is left updated and
- Progress points at the '&' preceding the first
- non-<BlockName>.
- @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
- BlockSize is updated with the required buffer size.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiConfigToBlock (
- IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
- IN CONST EFI_STRING ConfigResp,
- IN OUT UINT8 *Block,
- IN OUT UINTN *BlockSize,
- OUT EFI_STRING *Progress
- );
-
-/**
- This helper function is to be called by drivers to extract portions of
- a larger configuration string.
-
- @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
- instance.
- @param Configuration A null-terminated Unicode string in
- <MultiConfigAltResp> format.
- @param Guid A pointer to the GUID value to search for in the
- routing portion of the ConfigResp string when
- retrieving the requested data. If Guid is NULL,
- then all GUID values will be searched for.
- @param Name A pointer to the NAME value to search for in the
- routing portion of the ConfigResp string when
- retrieving the requested data. If Name is NULL,
- then all Name values will be searched for.
- @param DevicePath A pointer to the PATH value to search for in the
- routing portion of the ConfigResp string when
- retrieving the requested data. If DevicePath is
- NULL, then all DevicePath values will be
- searched for.
- @param AltCfgId A pointer to the ALTCFG value to search for in
- the routing portion of the ConfigResp string
- when retrieving the requested data. If this
- parameter is NULL, then the current setting will
- be retrieved.
- @param AltCfgResp A pointer to a buffer which will be allocated by
- the function which contains the retrieved string
- as requested. This buffer is only allocated if
- the call was successful.
-
- @retval EFI_SUCCESS The request succeeded. The requested data was
- extracted and placed in the newly allocated
- AltCfgResp buffer.
- @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
- @retval EFI_INVALID_PARAMETER Any parameter is invalid.
- @retval EFI_NOT_FOUND Target for the specified routing data was not
- found.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetAltCfg (
- IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
- IN CONST EFI_STRING Configuration,
- IN CONST EFI_GUID *Guid,
- IN CONST EFI_STRING Name,
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- IN CONST UINT16 *AltCfgId,
- OUT EFI_STRING *AltCfgResp
- );
-
-/**
-
- 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
- );
-
-/**
-
- 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
- );
-
-/**
- Compare whether two names of languages are identical.
-
- @param Language1 Name of language 1 from StringPackage
- @param Language2 Name of language 2 to be compared with language 1.
-
- @retval TRUE same
- @retval FALSE not same
-
-**/
-BOOLEAN
-HiiCompareLanguage (
- IN CHAR8 *Language1,
- IN CHAR8 *Language2
- )
-;
-
-/**
- Retrieves a pointer to a Null-terminated ASCII string containing the list
- of languages that an HII handle in the HII Database supports. The returned
- string is allocated using AllocatePool(). The caller is responsible for freeing
- the returned string using FreePool(). The format of the returned string follows
- the language format assumed the HII Database.
-
- If HiiHandle is NULL, then ASSERT().
-
- @param[in] HiiHandle A handle that was previously registered in the HII Database.
-
- @retval NULL HiiHandle is not registered in the HII database
- @retval NULL There are not enough resources available to retrieve the supported
- languages.
- @retval NULL The list of supported languages could not be retrieved.
- @retval Other A pointer to the Null-terminated ASCII string of supported languages.
-
-**/
-CHAR8 *
-GetSupportedLanguages (
- IN EFI_HII_HANDLE HiiHandle
- );
-
-/**
-This function mainly use to get HiiDatabase information.
-
-@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
-
-@retval EFI_SUCCESS Get the information successfully.
-@retval EFI_OUT_OF_RESOURCES Not enough memory to store the Hiidatabase data.
-
-**/
-EFI_STATUS
-HiiGetDatabaseInfo (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This
- );
-
-/**
-This function mainly use to get and update ConfigResp string.
-
-@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
-
-@retval EFI_SUCCESS Get the information successfully.
-@retval EFI_OUT_OF_RESOURCES Not enough memory to store the Configuration Setting data.
-
-**/
-EFI_STATUS
-HiiGetConfigRespInfo (
- IN CONST EFI_HII_DATABASE_PROTOCOL *This
- );
-
-/**
- Find question default value from PcdNvStoreDefaultValueBuffer
-
- @param DefaultId Default store ID
- @param EfiVarStore Point to EFI VarStore header
- @param IfrQuestionHdr Point to Question header
- @param ValueBuffer Point to Buffer includes the found default setting
- @param Width Width of the default value
- @param BitFieldQuestion Whether the Question is stored in Bit field.
-
- @retval EFI_SUCCESS Question default value is found.
- @retval EFI_NOT_FOUND Question default value is not found.
-**/
-EFI_STATUS
-FindQuestionDefaultSetting (
- IN UINT16 DefaultId,
- IN EFI_IFR_VARSTORE_EFI *EfiVarStore,
- IN EFI_IFR_QUESTION_HEADER *IfrQuestionHdr,
- OUT VOID *ValueBuffer,
- IN UINTN Width,
- IN BOOLEAN BitFieldQuestion
- );
-
-//
-// Global variables
-//
-extern EFI_EVENT gHiiKeyboardLayoutChanged;
-extern BOOLEAN gExportAfterReadyToBoot;
-
-#endif
+/** @file
+Private structures definitions in HiiDatabase.
+
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __HII_DATABASE_PRIVATE_H__
+#define __HII_DATABASE_PRIVATE_H__
+
+#include <Uefi.h>
+
+#include <Protocol/DevicePath.h>
+#include <Protocol/HiiFont.h>
+#include <Protocol/HiiImage.h>
+#include <Protocol/HiiImageEx.h>
+#include <Protocol/HiiImageDecoder.h>
+#include <Protocol/HiiString.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigKeyword.h>
+#include <Protocol/SimpleTextOut.h>
+
+#include <Guid/HiiKeyBoardLayout.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/MdeModuleHii.h>
+#include <Guid/VariableFormat.h>
+#include <Guid/PcdDataBaseSignatureGuid.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/PrintLib.h>
+
+#define MAX_STRING_LENGTH 1024
+#define MAX_FONT_NAME_LEN 256
+#define NARROW_BASELINE 15
+#define WIDE_BASELINE 14
+#define SYS_FONT_INFO_MASK 0x37
+#define REPLACE_UNKNOWN_GLYPH 0xFFFD
+#define PROPORTIONAL_GLYPH 0x80
+#define NARROW_GLYPH 0x40
+
+#define BITMAP_LEN_1_BIT(Width, Height) (((Width) + 7) / 8 * (Height))
+#define BITMAP_LEN_4_BIT(Width, Height) (((Width) + 1) / 2 * (Height))
+#define BITMAP_LEN_8_BIT(Width, Height) ((Width) * (Height))
+#define BITMAP_LEN_24_BIT(Width, Height) ((Width) * (Height) * 3)
+
+extern EFI_LOCK mHiiDatabaseLock;
+
+//
+// IFR data structure
+//
+// BASE_CR (a, IFR_DEFAULT_VALUE_DATA, Entry) to get the whole structure.
+
+typedef struct {
+ LIST_ENTRY Entry; // Link to VarStorage Default Data
+ UINT16 DefaultId;
+ VARIABLE_STORE_HEADER *VariableStorage;
+} VARSTORAGE_DEFAULT_DATA;
+
+typedef struct {
+ LIST_ENTRY Entry; // Link to VarStorage
+ EFI_GUID Guid;
+ CHAR16 *Name;
+ UINT16 Size;
+ UINT8 Type;
+ LIST_ENTRY BlockEntry; // Link to its Block array
+} IFR_VARSTORAGE_DATA;
+
+typedef struct {
+ LIST_ENTRY Entry; // Link to Block array
+ UINT16 Offset;
+ UINT16 Width;
+ UINT16 BitOffset;
+ UINT16 BitWidth;
+ EFI_QUESTION_ID QuestionId;
+ UINT8 OpCode;
+ UINT8 Scope;
+ LIST_ENTRY DefaultValueEntry; // Link to its default value array
+ CHAR16 *Name;
+ BOOLEAN IsBitVar;
+} IFR_BLOCK_DATA;
+
+//
+// Get default value from IFR data.
+//
+typedef enum {
+ DefaultValueFromDefault = 0, // Get from the minimum or first one when not set default value.
+ DefaultValueFromOtherDefault, // Get default vale from other default when no default(When other
+ // defaults are more than one, use the default with smallest default id).
+ DefaultValueFromFlag, // Get default value from the default flag.
+ DefaultValueFromOpcode // Get default value from default opcode, highest priority.
+} DEFAULT_VALUE_TYPE;
+
+typedef struct {
+ LIST_ENTRY Entry;
+ DEFAULT_VALUE_TYPE Type;
+ BOOLEAN Cleaned; // Whether this value is cleaned
+ // TRUE Cleaned, the value can't be used
+ // FALSE Not cleaned, the value can be used.
+ UINT16 DefaultId;
+ EFI_IFR_TYPE_VALUE Value;
+} IFR_DEFAULT_DATA;
+
+//
+// Storage types
+//
+#define EFI_HII_VARSTORE_BUFFER 0
+#define EFI_HII_VARSTORE_NAME_VALUE 1
+#define EFI_HII_VARSTORE_EFI_VARIABLE 2
+#define EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER 3
+
+//
+// Keyword handler protocol filter type.
+//
+#define EFI_KEYWORD_FILTER_READONY 0x01
+#define EFI_KEYWORD_FILTER_REAWRITE 0x02
+#define EFI_KEYWORD_FILTER_BUFFER 0x10
+#define EFI_KEYWORD_FILTER_NUMERIC 0x20
+#define EFI_KEYWORD_FILTER_NUMERIC_1 0x30
+#define EFI_KEYWORD_FILTER_NUMERIC_2 0x40
+#define EFI_KEYWORD_FILTER_NUMERIC_4 0x50
+#define EFI_KEYWORD_FILTER_NUMERIC_8 0x60
+
+#define HII_FORMSET_STORAGE_SIGNATURE SIGNATURE_32 ('H', 'S', 'T', 'G')
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Entry;
+
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HANDLE DriverHandle;
+
+ UINT8 Type; // EFI_HII_VARSTORE_BUFFER, EFI_HII_VARSTORE_NAME_VALUE, EFI_HII_VARSTORE_EFI_VARIABLE
+ EFI_GUID Guid;
+ CHAR16 *Name;
+ UINT16 Size;
+} HII_FORMSET_STORAGE;
+
+//
+// String Package definitions
+//
+#define HII_STRING_PACKAGE_SIGNATURE SIGNATURE_32 ('h','i','s','p')
+typedef struct _HII_STRING_PACKAGE_INSTANCE {
+ UINTN Signature;
+ EFI_HII_STRING_PACKAGE_HDR *StringPkgHdr;
+ UINT8 *StringBlock;
+ LIST_ENTRY StringEntry;
+ LIST_ENTRY FontInfoList; // local font info list
+ UINT8 FontId;
+ EFI_STRING_ID MaxStringId; // record StringId
+} HII_STRING_PACKAGE_INSTANCE;
+
+//
+// Form Package definitions
+//
+#define HII_IFR_PACKAGE_SIGNATURE SIGNATURE_32 ('h','f','r','p')
+typedef struct _HII_IFR_PACKAGE_INSTANCE {
+ UINTN Signature;
+ EFI_HII_PACKAGE_HEADER FormPkgHdr;
+ UINT8 *IfrData;
+ LIST_ENTRY IfrEntry;
+} HII_IFR_PACKAGE_INSTANCE;
+
+//
+// Simple Font Package definitions
+//
+#define HII_S_FONT_PACKAGE_SIGNATURE SIGNATURE_32 ('h','s','f','p')
+typedef struct _HII_SIMPLE_FONT_PACKAGE_INSTANCE {
+ UINTN Signature;
+ EFI_HII_SIMPLE_FONT_PACKAGE_HDR *SimpleFontPkgHdr;
+ LIST_ENTRY SimpleFontEntry;
+} HII_SIMPLE_FONT_PACKAGE_INSTANCE;
+
+//
+// Font Package definitions
+//
+#define HII_FONT_PACKAGE_SIGNATURE SIGNATURE_32 ('h','i','f','p')
+typedef struct _HII_FONT_PACKAGE_INSTANCE {
+ UINTN Signature;
+ EFI_HII_FONT_PACKAGE_HDR *FontPkgHdr;
+ UINT16 Height;
+ UINT16 BaseLine;
+ UINT8 *GlyphBlock;
+ LIST_ENTRY FontEntry;
+ LIST_ENTRY GlyphInfoList;
+} HII_FONT_PACKAGE_INSTANCE;
+
+#define HII_GLYPH_INFO_SIGNATURE SIGNATURE_32 ('h','g','i','s')
+typedef struct _HII_GLYPH_INFO {
+ UINTN Signature;
+ LIST_ENTRY Entry;
+ CHAR16 CharId;
+ EFI_HII_GLYPH_INFO Cell;
+} HII_GLYPH_INFO;
+
+#define HII_FONT_INFO_SIGNATURE SIGNATURE_32 ('h','l','f','i')
+typedef struct _HII_FONT_INFO {
+ UINTN Signature;
+ LIST_ENTRY Entry;
+ LIST_ENTRY *GlobalEntry;
+ UINT8 FontId;
+} HII_FONT_INFO;
+
+#define HII_GLOBAL_FONT_INFO_SIGNATURE SIGNATURE_32 ('h','g','f','i')
+typedef struct _HII_GLOBAL_FONT_INFO {
+ UINTN Signature;
+ LIST_ENTRY Entry;
+ HII_FONT_PACKAGE_INSTANCE *FontPackage;
+ UINTN FontInfoSize;
+ EFI_FONT_INFO *FontInfo;
+} HII_GLOBAL_FONT_INFO;
+
+//
+// Image Package definitions
+//
+
+#define HII_PIXEL_MASK 0x80
+
+typedef struct _HII_IMAGE_PACKAGE_INSTANCE {
+ EFI_HII_IMAGE_PACKAGE_HDR ImagePkgHdr;
+ UINT32 ImageBlockSize;
+ UINT32 PaletteInfoSize;
+ EFI_HII_IMAGE_BLOCK *ImageBlock;
+ UINT8 *PaletteBlock;
+} HII_IMAGE_PACKAGE_INSTANCE;
+
+//
+// Keyboard Layout Package definitions
+//
+#define HII_KB_LAYOUT_PACKAGE_SIGNATURE SIGNATURE_32 ('h','k','l','p')
+typedef struct _HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE {
+ UINTN Signature;
+ UINT8 *KeyboardPkg;
+ LIST_ENTRY KeyboardEntry;
+} HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE;
+
+//
+// Guid Package definitions
+//
+#define HII_GUID_PACKAGE_SIGNATURE SIGNATURE_32 ('h','i','g','p')
+typedef struct _HII_GUID_PACKAGE_INSTANCE {
+ UINTN Signature;
+ UINT8 *GuidPkg;
+ LIST_ENTRY GuidEntry;
+} HII_GUID_PACKAGE_INSTANCE;
+
+//
+// A package list can contain only one or less than one device path package.
+// This rule also applies to image package since ImageId can not be duplicate.
+//
+typedef struct _HII_DATABASE_PACKAGE_LIST_INSTANCE {
+ EFI_HII_PACKAGE_LIST_HEADER PackageListHdr;
+ LIST_ENTRY GuidPkgHdr;
+ LIST_ENTRY FormPkgHdr;
+ LIST_ENTRY KeyboardLayoutHdr;
+ LIST_ENTRY StringPkgHdr;
+ LIST_ENTRY FontPkgHdr;
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePkg;
+ LIST_ENTRY SimpleFontPkgHdr;
+ UINT8 *DevicePathPkg;
+} HII_DATABASE_PACKAGE_LIST_INSTANCE;
+
+#define HII_HANDLE_SIGNATURE SIGNATURE_32 ('h','i','h','l')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Handle;
+ UINTN Key;
+} HII_HANDLE;
+
+#define HII_DATABASE_RECORD_SIGNATURE SIGNATURE_32 ('h','i','d','r')
+
+typedef struct _HII_DATABASE_RECORD {
+ UINTN Signature;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE Handle;
+ LIST_ENTRY DatabaseEntry;
+} HII_DATABASE_RECORD;
+
+#define HII_DATABASE_NOTIFY_SIGNATURE SIGNATURE_32 ('h','i','d','n')
+
+typedef struct _HII_DATABASE_NOTIFY {
+ UINTN Signature;
+ EFI_HANDLE NotifyHandle;
+ UINT8 PackageType;
+ EFI_GUID *PackageGuid;
+ EFI_HII_DATABASE_NOTIFY PackageNotifyFn;
+ EFI_HII_DATABASE_NOTIFY_TYPE NotifyType;
+ LIST_ENTRY DatabaseNotifyEntry;
+} HII_DATABASE_NOTIFY;
+
+#define HII_DATABASE_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('H', 'i', 'D', 'p')
+
+typedef struct _HII_DATABASE_PRIVATE_DATA {
+ UINTN Signature;
+ LIST_ENTRY DatabaseList;
+ LIST_ENTRY DatabaseNotifyList;
+ EFI_HII_FONT_PROTOCOL HiiFont;
+ EFI_HII_IMAGE_PROTOCOL HiiImage;
+ EFI_HII_IMAGE_EX_PROTOCOL HiiImageEx;
+ EFI_HII_STRING_PROTOCOL HiiString;
+ EFI_HII_DATABASE_PROTOCOL HiiDatabase;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL ConfigRouting;
+ EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL ConfigKeywordHandler;
+ LIST_ENTRY HiiHandleList;
+ INTN HiiHandleCount;
+ LIST_ENTRY FontInfoList; // global font info list
+ UINTN Attribute; // default system color
+ EFI_GUID CurrentLayoutGuid;
+ EFI_HII_KEYBOARD_LAYOUT *CurrentLayout;
+} HII_DATABASE_PRIVATE_DATA;
+
+#define HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
+ CR (a, \
+ HII_DATABASE_PRIVATE_DATA, \
+ HiiFont, \
+ HII_DATABASE_PRIVATE_DATA_SIGNATURE \
+ )
+
+#define HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
+ CR (a, \
+ HII_DATABASE_PRIVATE_DATA, \
+ HiiImage, \
+ HII_DATABASE_PRIVATE_DATA_SIGNATURE \
+ )
+
+#define HII_IMAGE_EX_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
+ CR (a, \
+ HII_DATABASE_PRIVATE_DATA, \
+ HiiImageEx, \
+ HII_DATABASE_PRIVATE_DATA_SIGNATURE \
+ )
+
+#define HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
+ CR (a, \
+ HII_DATABASE_PRIVATE_DATA, \
+ HiiString, \
+ HII_DATABASE_PRIVATE_DATA_SIGNATURE \
+ )
+
+#define HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
+ CR (a, \
+ HII_DATABASE_PRIVATE_DATA, \
+ HiiDatabase, \
+ HII_DATABASE_PRIVATE_DATA_SIGNATURE \
+ )
+
+#define CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
+ CR (a, \
+ HII_DATABASE_PRIVATE_DATA, \
+ ConfigRouting, \
+ HII_DATABASE_PRIVATE_DATA_SIGNATURE \
+ )
+
+#define CONFIG_KEYWORD_HANDLER_DATABASE_PRIVATE_DATA_FROM_THIS(a) \
+ CR (a, \
+ HII_DATABASE_PRIVATE_DATA, \
+ ConfigKeywordHandler, \
+ HII_DATABASE_PRIVATE_DATA_SIGNATURE \
+ )
+
+//
+// Internal function prototypes.
+//
+
+/**
+ Generate a sub string then output it.
+
+ This is a internal function.
+
+ @param String A constant string which is the prefix of the to be
+ generated string, e.g. GUID=
+
+ @param BufferLen The length of the Buffer in bytes.
+
+ @param Buffer Points to a buffer which will be converted to be the
+ content of the generated string.
+
+ @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
+ UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
+ if 3, the buffer contains other data.
+
+ @param SubStr Points to the output string. It's caller's
+ responsibility to free this buffer.
+
+
+**/
+VOID
+GenerateSubStr (
+ IN CONST EFI_STRING String,
+ IN UINTN BufferLen,
+ IN VOID *Buffer,
+ IN UINT8 Flag,
+ OUT EFI_STRING *SubStr
+ );
+
+/**
+ This function checks whether a handle is a valid EFI_HII_HANDLE.
+
+ @param Handle Pointer to a EFI_HII_HANDLE
+
+ @retval TRUE Valid
+ @retval FALSE Invalid
+
+**/
+BOOLEAN
+IsHiiHandleValid (
+ EFI_HII_HANDLE Handle
+ );
+
+/**
+ This function checks whether EFI_FONT_INFO exists in current database. If
+ FontInfoMask is specified, check what options can be used to make a match.
+ Note that the masks relate to where the system default should be supplied
+ are ignored by this function.
+
+ @param Private Hii database private structure.
+ @param FontInfo Points to EFI_FONT_INFO structure.
+ @param FontInfoMask If not NULL, describes what options can be used
+ to make a match between the font requested and
+ the font available. The caller must guarantee
+ this mask is valid.
+ @param FontHandle On entry, Points to the font handle returned by a
+ previous call to GetFontInfo() or NULL to start
+ with the first font.
+ @param GlobalFontInfo If not NULL, output the corresponding global font
+ info.
+
+ @retval TRUE Existed
+ @retval FALSE Not existed
+
+**/
+BOOLEAN
+IsFontInfoExisted (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_FONT_INFO *FontInfo,
+ IN EFI_FONT_INFO_MASK *FontInfoMask OPTIONAL,
+ IN EFI_FONT_HANDLE FontHandle OPTIONAL,
+ OUT HII_GLOBAL_FONT_INFO **GlobalFontInfo OPTIONAL
+ );
+
+/**
+
+ This function invokes the matching registered function.
+
+ @param Private HII Database driver private structure.
+ @param NotifyType The type of change concerning the database.
+ @param PackageInstance Points to the package referred to by the notification.
+ @param PackageType Package type
+ @param Handle The handle of the package list which contains the specified package.
+
+ @retval EFI_SUCCESS Already checked all registered function and invoked
+ if matched.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+EFI_STATUS
+InvokeRegisteredFunction (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN VOID *PackageInstance,
+ IN UINT8 PackageType,
+ IN EFI_HII_HANDLE Handle
+ )
+;
+
+/**
+ Retrieve system default font and color.
+
+ @param Private HII database driver private data.
+ @param FontInfo Points to system default font output-related
+ information. It's caller's responsibility to free
+ this buffer.
+ @param FontInfoSize If not NULL, output the size of buffer FontInfo.
+
+ @retval EFI_SUCCESS Cell information is added to the GlyphInfoList.
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
+ task.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+EFI_STATUS
+GetSystemFont (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ OUT EFI_FONT_DISPLAY_INFO **FontInfo,
+ OUT UINTN *FontInfoSize OPTIONAL
+ );
+
+/**
+ Parse all string blocks to find a String block specified by StringId.
+ If StringId = (EFI_STRING_ID) (-1), find out all EFI_HII_SIBT_FONT blocks
+ within this string package and backup its information. If LastStringId is
+ specified, the string id of last string block will also be output.
+ If StringId = 0, output the string id of last string block (EFI_HII_SIBT_STRING).
+
+ @param Private Hii database private structure.
+ @param StringPackage Hii string package instance.
+ @param StringId The string's id, which is unique within
+ PackageList.
+ @param BlockType Output the block type of found string block.
+ @param StringBlockAddr Output the block address of found string block.
+ @param StringTextOffset Offset, relative to the found block address, of
+ the string text information.
+ @param LastStringId Output the last string id when StringId = 0 or StringId = -1.
+ @param StartStringId The first id in the skip block which StringId in the block.
+
+ @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
+FindStringBlock (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
+ IN EFI_STRING_ID StringId,
+ OUT UINT8 *BlockType OPTIONAL,
+ OUT UINT8 **StringBlockAddr OPTIONAL,
+ OUT UINTN *StringTextOffset OPTIONAL,
+ OUT EFI_STRING_ID *LastStringId OPTIONAL,
+ OUT EFI_STRING_ID *StartStringId OPTIONAL
+ );
+
+/**
+ Parse all glyph blocks to find a glyph block specified by CharValue.
+ If CharValue = (CHAR16) (-1), collect all default character cell information
+ within this font package and backup its information.
+
+ @param FontPackage Hii string package instance.
+ @param CharValue Unicode character value, which identifies a glyph
+ block.
+ @param GlyphBuffer Output the corresponding bitmap data of the found
+ block. It is the caller's responsibility to free
+ this buffer.
+ @param Cell Output cell information of the encoded bitmap.
+ @param GlyphBufferLen If not NULL, output the length of GlyphBuffer.
+
+ @retval EFI_SUCCESS The bitmap data is retrieved successfully.
+ @retval EFI_NOT_FOUND The specified CharValue does not exist in current
+ database.
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
+ task.
+
+**/
+EFI_STATUS
+FindGlyphBlock (
+ IN HII_FONT_PACKAGE_INSTANCE *FontPackage,
+ IN CHAR16 CharValue,
+ OUT UINT8 **GlyphBuffer OPTIONAL,
+ OUT EFI_HII_GLYPH_INFO *Cell OPTIONAL,
+ OUT UINTN *GlyphBufferLen OPTIONAL
+ );
+
+/**
+ This function exports Form packages to a buffer.
+ This is a internal function.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer be used.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+ @param ResultSize The size of the already exported content of this
+ package list.
+
+ @retval EFI_SUCCESS Form Packages are exported successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+EFI_STATUS
+ExportFormPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN UINTN UsedSize,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *ResultSize
+ );
+
+//
+// EFI_HII_FONT_PROTOCOL protocol interfaces
+//
+
+/**
+ Renders a string to a bitmap or to the display.
+
+ @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
+ @param Flags Describes how the string is to be drawn.
+ @param String Points to the null-terminated string to be
+ displayed.
+ @param StringInfo Points to the string output information,
+ including the color and font. If NULL, then the
+ string will be output in the default system font
+ and color.
+ @param Blt If this points to a non-NULL on entry, this
+ points to the image, which is Width pixels wide
+ and Height pixels high. The string will be drawn
+ onto this image and
+ EFI_HII_OUT_FLAG_CLIP is implied. If this points
+ to a NULL on entry, then a buffer
+ will be allocated to hold the generated image and
+ the pointer updated on exit. It is the caller's
+ responsibility to free this buffer.
+ @param BltX Together with BltX, Specifies the offset from the left and top edge
+ of the image of the first character cell in the
+ image.
+ @param BltY Together with BltY, Specifies the offset from the left and top edge
+ of the image of the first character cell in the
+ image.
+ @param RowInfoArray If this is non-NULL on entry, then on exit, this
+ will point to an allocated buffer containing
+ row information and RowInfoArraySize will be
+ updated to contain the number of elements.
+ This array describes the characters which were at
+ least partially drawn and the heights of the
+ rows. It is the caller's responsibility to free
+ this buffer.
+ @param RowInfoArraySize If this is non-NULL on entry, then on exit it
+ contains the number of elements in RowInfoArray.
+ @param ColumnInfoArray If this is non-NULL, then on return it will be
+ filled with the horizontal offset for each
+ character in the string on the row where it is
+ displayed. Non-printing characters will have
+ the offset ~0. The caller is responsible to
+ allocate a buffer large enough so that there
+ is one entry for each character in the string,
+ not including the null-terminator. It is possible
+ when character display is normalized that some
+ character cells overlap.
+
+ @retval EFI_SUCCESS The string was successfully rendered.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for
+ RowInfoArray or Blt.
+ @retval EFI_INVALID_PARAMETER The String or Blt.
+ @retval EFI_INVALID_PARAMETER Flags were invalid combination..
+
+**/
+EFI_STATUS
+EFIAPI
+HiiStringToImage (
+ IN CONST EFI_HII_FONT_PROTOCOL *This,
+ IN EFI_HII_OUT_FLAGS Flags,
+ IN CONST EFI_STRING String,
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY,
+ OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL,
+ OUT UINTN *RowInfoArraySize OPTIONAL,
+ OUT UINTN *ColumnInfoArray OPTIONAL
+ );
+
+/**
+ Render a string to a bitmap or the screen containing the contents of the specified string.
+
+ @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
+ @param Flags Describes how the string is to be drawn.
+ @param PackageList The package list in the HII database to search
+ for the specified string.
+ @param StringId The string's id, which is unique within
+ PackageList.
+ @param Language Points to the language for the retrieved string.
+ If NULL, then the current system language is
+ used.
+ @param StringInfo Points to the string output information,
+ including the color and font. If NULL, then the
+ string will be output in the default system font
+ and color.
+ @param Blt If this points to a non-NULL on entry, this
+ points to the image, which is Width pixels wide
+ and Height pixels high. The string will be drawn
+ onto this image and
+ EFI_HII_OUT_FLAG_CLIP is implied. If this points
+ to a NULL on entry, then a buffer
+ will be allocated to hold the generated image and
+ the pointer updated on exit. It is the caller's
+ responsibility to free this buffer.
+ @param BltX Together with BltX, Specifies the offset from the left and top edge
+ of the image of the first character cell in the
+ image.
+ @param BltY Together with BltY, Specifies the offset from the left and top edge
+ of the image of the first character cell in the
+ image.
+ @param RowInfoArray If this is non-NULL on entry, then on exit, this
+ will point to an allocated buffer containing
+ row information and RowInfoArraySize will be
+ updated to contain the number of elements.
+ This array describes the characters which were at
+ least partially drawn and the heights of the
+ rows. It is the caller's responsibility to free
+ this buffer.
+ @param RowInfoArraySize If this is non-NULL on entry, then on exit it
+ contains the number of elements in RowInfoArray.
+ @param ColumnInfoArray If this is non-NULL, then on return it will be
+ filled with the horizontal offset for each
+ character in the string on the row where it is
+ displayed. Non-printing characters will have
+ the offset ~0. The caller is responsible to
+ allocate a buffer large enough so that there
+ is one entry for each character in the string,
+ not including the null-terminator. It is possible
+ when character display is normalized that some
+ character cells overlap.
+
+ @retval EFI_SUCCESS The string was successfully rendered.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for
+ RowInfoArray or Blt.
+ @retval EFI_INVALID_PARAMETER The Blt or PackageList was NULL.
+ @retval EFI_INVALID_PARAMETER Flags were invalid combination.
+ @retval EFI_NOT_FOUND The specified PackageList is not in the Database or the stringid is not
+ in the specified PackageList.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiStringIdToImage (
+ IN CONST EFI_HII_FONT_PROTOCOL *This,
+ IN EFI_HII_OUT_FLAGS Flags,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_STRING_ID StringId,
+ IN CONST CHAR8 *Language,
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY,
+ OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL,
+ OUT UINTN *RowInfoArraySize OPTIONAL,
+ OUT UINTN *ColumnInfoArray OPTIONAL
+ );
+
+/**
+ Convert the glyph for a single character into a bitmap.
+
+ @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
+ @param Char Character to retrieve.
+ @param StringInfo Points to the string font and color information
+ or NULL if the string should use the default
+ system font and color.
+ @param Blt Thus must point to a NULL on entry. A buffer will
+ be allocated to hold the output and the pointer
+ updated on exit. It is the caller's
+ responsibility to free this buffer.
+ @param Baseline Number of pixels from the bottom of the bitmap to
+ the baseline.
+
+ @retval EFI_SUCCESS Glyph bitmap created.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate the output buffer Blt.
+ @retval EFI_WARN_UNKNOWN_GLYPH The glyph was unknown and was replaced with the
+ glyph for Unicode character 0xFFFD.
+ @retval EFI_INVALID_PARAMETER Blt is NULL or *Blt is not NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetGlyph (
+ IN CONST EFI_HII_FONT_PROTOCOL *This,
+ IN CHAR16 Char,
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfo,
+ OUT EFI_IMAGE_OUTPUT **Blt,
+ OUT UINTN *Baseline OPTIONAL
+ );
+
+/**
+ This function iterates through fonts which match the specified font, using
+ the specified criteria. If String is non-NULL, then all of the characters in
+ the string must exist in order for a candidate font to be returned.
+
+ @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.
+ @param FontHandle On entry, points to the font handle returned by a
+ previous call to GetFontInfo() or NULL to start
+ with the first font. On return, points to the
+ returned font handle or points to NULL if there
+ are no more matching fonts.
+ @param StringInfoIn Upon entry, points to the font to return information
+ about. If NULL, then the information about the system
+ default font will be returned.
+ @param StringInfoOut Upon return, contains the matching font's information.
+ If NULL, then no information is returned. This buffer
+ is allocated with a call to the Boot Service AllocatePool().
+ It is the caller's responsibility to call the Boot
+ Service FreePool() when the caller no longer requires
+ the contents of StringInfoOut.
+ @param String Points to the string which will be tested to
+ determine if all characters are available. If
+ NULL, then any font is acceptable.
+
+ @retval EFI_SUCCESS Matching font returned successfully.
+ @retval EFI_NOT_FOUND No matching font was found.
+ @retval EFI_INVALID_PARAMETER StringInfoIn is NULL.
+ @retval EFI_INVALID_PARAMETER StringInfoIn->FontInfoMask is an invalid combination.
+ @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the
+ request.
+**/
+EFI_STATUS
+EFIAPI
+HiiGetFontInfo (
+ IN CONST EFI_HII_FONT_PROTOCOL *This,
+ IN OUT EFI_FONT_HANDLE *FontHandle,
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfoIn OPTIONAL,
+ OUT EFI_FONT_DISPLAY_INFO **StringInfoOut,
+ IN CONST EFI_STRING String OPTIONAL
+ );
+
+//
+// EFI_HII_IMAGE_PROTOCOL interfaces
+//
+
+/**
+ Get the image id of last image block: EFI_HII_IIBT_END_BLOCK when input
+ ImageId is zero, otherwise return the address of the
+ corresponding image block with identifier specified by ImageId.
+
+ This is a internal function.
+
+ @param ImageBlocks Points to the beginning of a series of image blocks stored in order.
+ @param ImageId If input ImageId is 0, output the image id of the EFI_HII_IIBT_END_BLOCK;
+ else use this id to find its corresponding image block address.
+
+ @return The image block address when input ImageId is not zero; otherwise return NULL.
+
+**/
+EFI_HII_IMAGE_BLOCK *
+GetImageIdOrAddress (
+ IN EFI_HII_IMAGE_BLOCK *ImageBlocks,
+ IN OUT EFI_IMAGE_ID *ImageId
+ );
+
+/**
+ Return the HII package list identified by PackageList HII handle.
+
+ @param Database Pointer to HII database list header.
+ @param PackageList HII handle of the package list to locate.
+
+ @retval The HII package list instance.
+**/
+HII_DATABASE_PACKAGE_LIST_INSTANCE *
+LocatePackageList (
+ IN LIST_ENTRY *Database,
+ IN EFI_HII_HANDLE PackageList
+ );
+
+/**
+ This function retrieves the image specified by ImageId which is associated with
+ the specified PackageList and copies it into the buffer specified by Image.
+
+ @param Database A pointer to the database list header.
+ @param PackageList Handle of the package list where this image will
+ be searched.
+ @param ImageId The image's id,, which is unique within
+ PackageList.
+ @param Image Points to the image.
+ @param BitmapOnly TRUE to only return the bitmap type image.
+ FALSE to locate image decoder instance to decode image.
+
+ @retval EFI_SUCCESS The new image was returned successfully.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the
+ database. The specified PackageList is not in the database.
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
+ hold the image.
+ @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.
+ @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not
+ enough memory.
+**/
+EFI_STATUS
+IGetImage (
+ IN LIST_ENTRY *Database,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ OUT EFI_IMAGE_INPUT *Image,
+ IN BOOLEAN BitmapOnly
+ );
+
+/**
+ Return the first HII image decoder instance which supports the DecoderName.
+
+ @param BlockType The image block type.
+
+ @retval Pointer to the HII image decoder instance.
+**/
+EFI_HII_IMAGE_DECODER_PROTOCOL *
+LocateHiiImageDecoder (
+ UINT8 BlockType
+ );
+
+/**
+ This function adds the image Image to the group of images owned by PackageList, and returns
+ a new image identifier (ImageId).
+
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+ @param PackageList Handle of the package list where this image will
+ be added.
+ @param ImageId On return, contains the new image id, which is
+ unique within PackageList.
+ @param Image Points to the image.
+
+ @retval EFI_SUCCESS The new image was added successfully.
+ @retval EFI_NOT_FOUND The specified PackageList could not be found in
+ database.
+ @retval EFI_OUT_OF_RESOURCES Could not add the image due to lack of resources.
+ @retval EFI_INVALID_PARAMETER Image is NULL or ImageId is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiNewImage (
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ OUT EFI_IMAGE_ID *ImageId,
+ IN CONST EFI_IMAGE_INPUT *Image
+ );
+
+/**
+ This function retrieves the image specified by ImageId which is associated with
+ the specified PackageList and copies it into the buffer specified by Image.
+
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+ @param PackageList Handle of the package list where this image will
+ be searched.
+ @param ImageId The image's id,, which is unique within
+ PackageList.
+ @param Image Points to the image.
+
+ @retval EFI_SUCCESS The new image was returned successfully.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not available.
+ The specified PackageList is not in the database.
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
+ hold the image.
+ @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.
+ @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not
+ enough memory.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetImage (
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ OUT EFI_IMAGE_INPUT *Image
+ );
+
+/**
+ This function updates the image specified by ImageId in the specified PackageListHandle to
+ the image specified by Image.
+
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+ @param PackageList The package list containing the images.
+ @param ImageId The image's id,, which is unique within
+ PackageList.
+ @param Image Points to the image.
+
+ @retval EFI_SUCCESS The new image was updated successfully.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the
+ database. The specified PackageList is not in the database.
+ @retval EFI_INVALID_PARAMETER The Image was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiSetImage (
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ IN CONST EFI_IMAGE_INPUT *Image
+ );
+
+/**
+ This function renders an image to a bitmap or the screen using the specified
+ color and options. It draws the image on an existing bitmap, allocates a new
+ bitmap or uses the screen. The images can be clipped.
+
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+ @param Flags Describes how the image is to be drawn.
+ @param Image Points to the image to be displayed.
+ @param Blt If this points to a non-NULL on entry, this
+ points to the image, which is Width pixels wide
+ and Height pixels high. The image will be drawn
+ onto this image and EFI_HII_DRAW_FLAG_CLIP is
+ implied. If this points to a NULL on entry, then
+ a buffer will be allocated to hold the generated
+ image and the pointer updated on exit. It is the
+ caller's responsibility to free this buffer.
+ @param BltX Specifies the offset from the left and top edge
+ of the output image of the first pixel in the
+ image.
+ @param BltY Specifies the offset from the left and top edge
+ of the output image of the first pixel in the
+ image.
+
+ @retval EFI_SUCCESS The image was successfully drawn.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
+ @retval EFI_INVALID_PARAMETER The Image or Blt was NULL.
+ @retval EFI_INVALID_PARAMETER Any combination of Flags is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiDrawImage (
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,
+ IN EFI_HII_DRAW_FLAGS Flags,
+ IN CONST EFI_IMAGE_INPUT *Image,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY
+ );
+
+/**
+ This function renders an image to a bitmap or the screen using the specified
+ color and options. It draws the image on an existing bitmap, allocates a new
+ bitmap or uses the screen. The images can be clipped.
+
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+ @param Flags Describes how the image is to be drawn.
+ @param PackageList The package list in the HII database to search
+ for the specified image.
+ @param ImageId The image's id, which is unique within
+ PackageList.
+ @param Blt If this points to a non-NULL on entry, this
+ points to the image, which is Width pixels wide
+ and Height pixels high. The image will be drawn
+ onto this image and
+ EFI_HII_DRAW_FLAG_CLIP is implied. If this points
+ to a NULL on entry, then a buffer will be
+ allocated to hold the generated image and the
+ pointer updated on exit. It is the caller's
+ responsibility to free this buffer.
+ @param BltX Specifies the offset from the left and top edge
+ of the output image of the first pixel in the
+ image.
+ @param BltY Specifies the offset from the left and top edge
+ of the output image of the first pixel in the
+ image.
+
+ @retval EFI_SUCCESS The image was successfully drawn.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
+ @retval EFI_INVALID_PARAMETER The Blt was NULL.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the database.
+ The specified PackageList is not in the database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiDrawImageId (
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,
+ IN EFI_HII_DRAW_FLAGS Flags,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY
+ );
+
+/**
+ The prototype of this extension function is the same with EFI_HII_IMAGE_PROTOCOL.NewImage().
+ This protocol invokes EFI_HII_IMAGE_PROTOCOL.NewImage() implicitly.
+
+ @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
+ @param PackageList Handle of the package list where this image will
+ be added.
+ @param ImageId On return, contains the new image id, which is
+ unique within PackageList.
+ @param Image Points to the image.
+
+ @retval EFI_SUCCESS The new image was added successfully.
+ @retval EFI_NOT_FOUND The PackageList could not be found.
+ @retval EFI_OUT_OF_RESOURCES Could not add the image due to lack of resources.
+ @retval EFI_INVALID_PARAMETER Image is NULL or ImageId is NULL.
+**/
+EFI_STATUS
+EFIAPI
+HiiNewImageEx (
+ IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ OUT EFI_IMAGE_ID *ImageId,
+ IN CONST EFI_IMAGE_INPUT *Image
+ );
+
+/**
+ Return the information about the image, associated with the package list.
+ The prototype of this extension function is the same with EFI_HII_IMAGE_PROTOCOL.GetImage().
+
+ This function is similar to EFI_HII_IMAGE_PROTOCOL.GetImage(). The difference is that
+ this function will locate all EFI_HII_IMAGE_DECODER_PROTOCOL instances installed in the
+ system if the decoder of the certain image type is not supported by the
+ EFI_HII_IMAGE_EX_PROTOCOL. The function will attempt to decode the image to the
+ EFI_IMAGE_INPUT using the first EFI_HII_IMAGE_DECODER_PROTOCOL instance that
+ supports the requested image type.
+
+ @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
+ @param PackageList The package list in the HII database to search for the
+ specified image.
+ @param ImageId The image's id, which is unique within PackageList.
+ @param Image Points to the image.
+
+ @retval EFI_SUCCESS The new image was returned successfully.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not available. The specified
+ PackageList is not in the Database.
+ @retval EFI_INVALID_PARAMETER Image was NULL or ImageId was 0.
+ @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there
+ was not enough memory.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetImageEx (
+ IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ OUT EFI_IMAGE_INPUT *Image
+ );
+
+/**
+ Change the information about the image.
+
+ Same with EFI_HII_IMAGE_PROTOCOL.SetImage(), this protocol invokes
+ EFI_HII_IMAGE_PROTOCOL.SetImage()implicitly.
+
+ @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
+ @param PackageList The package list containing the images.
+ @param ImageId The image's id, which is unique within PackageList.
+ @param Image Points to the image.
+
+ @retval EFI_SUCCESS The new image was successfully updated.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the
+ database. The specified PackageList is not in
+ the database.
+ @retval EFI_INVALID_PARAMETER The Image was NULL, the ImageId was 0 or
+ the Image->Bitmap was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiSetImageEx (
+ IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ IN CONST EFI_IMAGE_INPUT *Image
+ );
+
+/**
+ Renders an image to a bitmap or to the display.
+
+ The prototype of this extension function is the same with
+ EFI_HII_IMAGE_PROTOCOL.DrawImage(). This protocol invokes
+ EFI_HII_IMAGE_PROTOCOL.DrawImage() implicitly.
+
+ @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
+ @param Flags Describes how the image is to be drawn.
+ @param Image Points to the image to be displayed.
+ @param Blt If this points to a non-NULL on entry, this points
+ to the image, which is Width pixels wide and
+ Height pixels high. The image will be drawn onto
+ this image and EFI_HII_DRAW_FLAG_CLIP is implied.
+ If this points to a NULL on entry, then a buffer
+ will be allocated to hold the generated image and
+ the pointer updated on exit. It is the caller's
+ responsibility to free this buffer.
+ @param BltX Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+ @param BltY Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+
+ @retval EFI_SUCCESS The image was successfully drawn.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
+ @retval EFI_INVALID_PARAMETER The Image or Blt was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiDrawImageEx (
+ IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
+ IN EFI_HII_DRAW_FLAGS Flags,
+ IN CONST EFI_IMAGE_INPUT *Image,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY
+ );
+
+/**
+ Renders an image to a bitmap or the screen containing the contents of the specified
+ image.
+
+ This function is similar to EFI_HII_IMAGE_PROTOCOL.DrawImageId(). The difference is that
+ this function will locate all EFI_HII_IMAGE_DECODER_PROTOCOL instances installed in the
+ system if the decoder of the certain image type is not supported by the
+ EFI_HII_IMAGE_EX_PROTOCOL. The function will attempt to decode the image to the
+ EFI_IMAGE_INPUT using the first EFI_HII_IMAGE_DECODER_PROTOCOL instance that
+ supports the requested image type.
+
+ @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
+ @param Flags Describes how the image is to be drawn.
+ @param PackageList The package list in the HII database to search for
+ the specified image.
+ @param ImageId The image's id, which is unique within PackageList.
+ @param Blt If this points to a non-NULL on entry, this points
+ to the image, which is Width pixels wide and
+ Height pixels high. The image will be drawn onto
+ this image and EFI_HII_DRAW_FLAG_CLIP is implied.
+ If this points to a NULL on entry, then a buffer
+ will be allocated to hold the generated image
+ and the pointer updated on exit. It is the caller's
+ responsibility to free this buffer.
+ @param BltX Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+ @param BltY Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+
+ @retval EFI_SUCCESS The image was successfully drawn.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
+ @retval EFI_INVALID_PARAMETER The Blt was NULL or ImageId was 0.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the database.
+ The specified PackageList is not in the database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiDrawImageIdEx (
+ IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
+ IN EFI_HII_DRAW_FLAGS Flags,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY
+ );
+
+/**
+ This function returns the image information to EFI_IMAGE_OUTPUT. Only the width
+ and height are returned to the EFI_IMAGE_OUTPUT instead of decoding the image
+ to the buffer. This function is used to get the geometry of the image. This function
+ will try to locate all of the EFI_HII_IMAGE_DECODER_PROTOCOL installed on the
+ system if the decoder of image type is not supported by the EFI_HII_IMAGE_EX_PROTOCOL.
+
+ @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
+ @param PackageList Handle of the package list where this image will
+ be searched.
+ @param ImageId The image's id, which is unique within PackageList.
+ @param Image Points to the image.
+
+ @retval EFI_SUCCESS The new image was returned successfully.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the
+ database. The specified PackageList is not in the database.
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
+ hold the image.
+ @retval EFI_INVALID_PARAMETER The Image was NULL or the ImageId was 0.
+ @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there
+ was not enough memory.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetImageInfo (
+ IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ OUT EFI_IMAGE_OUTPUT *Image
+ );
+
+//
+// EFI_HII_STRING_PROTOCOL
+//
+
+/**
+ This function adds the string String to the group of strings owned by PackageList, with the
+ specified font information StringFontInfo and returns a new string id.
+
+ @param This A pointer to the EFI_HII_STRING_PROTOCOL
+ instance.
+ @param PackageList Handle of the package list where this string will
+ be added.
+ @param StringId On return, contains the new strings id, which is
+ unique within PackageList.
+ @param Language Points to the language for the new string.
+ @param LanguageName Points to the printable language name to
+ associate with the passed in Language field.If
+ LanguageName is not NULL and the string package
+ header's LanguageName associated with a given
+ Language is not zero, the LanguageName being
+ passed in will be ignored.
+ @param String Points to the new null-terminated string.
+ @param StringFontInfo Points to the new string's font information or
+ NULL if the string should have the default system
+ font, size and style.
+
+ @retval EFI_SUCCESS The new string was added successfully.
+ @retval EFI_NOT_FOUND The specified PackageList could not be found in
+ database.
+ @retval EFI_OUT_OF_RESOURCES Could not add the string due to lack of
+ resources.
+ @retval EFI_INVALID_PARAMETER String is NULL or StringId is NULL or Language is
+ NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiNewString (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ OUT EFI_STRING_ID *StringId,
+ IN CONST CHAR8 *Language,
+ IN CONST CHAR16 *LanguageName OPTIONAL,
+ IN CONST EFI_STRING String,
+ IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL
+ );
+
+/**
+ This function retrieves the string specified by StringId which is associated
+ with the specified PackageList in the language Language and copies it into
+ the buffer specified by String.
+
+ @param This A pointer to the EFI_HII_STRING_PROTOCOL
+ instance.
+ @param Language Points to the language for the retrieved string.
+ @param PackageList The package list in the HII database to search
+ for the specified string.
+ @param StringId The string's id, which is unique within
+ PackageList.
+ @param String Points to the new null-terminated string.
+ @param StringSize On entry, points to the size of the buffer
+ pointed to by String, in bytes. On return,
+ points to the length of the string, in bytes.
+ @param StringFontInfo If not NULL, points to the string's font
+ information. It's caller's responsibility to
+ free this buffer.
+
+ @retval EFI_SUCCESS The string was returned successfully.
+ @retval EFI_NOT_FOUND The string specified by StringId is not
+ available.
+ The specified PackageList is not in the database.
+ @retval EFI_INVALID_LANGUAGE The string specified by StringId is available but
+ not in the specified language.
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small
+ to hold the string.
+ @retval EFI_INVALID_PARAMETER The Language or StringSize was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by StringSize was not zero
+ and String was NULL.
+ @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the
+ request.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetString (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN CONST CHAR8 *Language,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_STRING_ID StringId,
+ OUT EFI_STRING String,
+ IN OUT UINTN *StringSize,
+ OUT EFI_FONT_INFO **StringFontInfo OPTIONAL
+ );
+
+/**
+ This function updates the string specified by StringId in the specified PackageList to the text
+ specified by String and, optionally, the font information specified by StringFontInfo.
+
+ @param This A pointer to the EFI_HII_STRING_PROTOCOL
+ instance.
+ @param PackageList The package list containing the strings.
+ @param StringId The string's id, which is unique within
+ PackageList.
+ @param Language Points to the language for the updated string.
+ @param String Points to the new null-terminated string.
+ @param StringFontInfo Points to the string's font information or NULL
+ if the string font information is not changed.
+
+ @retval EFI_SUCCESS The string was updated successfully.
+ @retval EFI_NOT_FOUND The string specified by StringId is not in the
+ database.
+ @retval EFI_INVALID_PARAMETER The String or Language was NULL.
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
+ task.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiSetString (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_STRING_ID StringId,
+ IN CONST CHAR8 *Language,
+ IN CONST EFI_STRING String,
+ IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL
+ );
+
+/**
+ This function returns the list of supported languages, in the format specified
+ in Appendix M of UEFI 2.1 spec.
+
+ @param This A pointer to the EFI_HII_STRING_PROTOCOL
+ instance.
+ @param PackageList The package list to examine.
+ @param Languages Points to the buffer to hold the returned
+ null-terminated ASCII string.
+ @param LanguagesSize On entry, points to the size of the buffer
+ pointed to by Languages, in bytes. On return,
+ points to the length of Languages, in bytes.
+
+ @retval EFI_SUCCESS The languages were returned successfully.
+ @retval EFI_INVALID_PARAMETER The LanguagesSize was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by LanguagesSize is not zero and Languages is NULL.
+ @retval EFI_BUFFER_TOO_SMALL The LanguagesSize is too small to hold the list
+ of supported languages. LanguageSize is updated
+ to contain the required size.
+ @retval EFI_NOT_FOUND Could not find string package in specified
+ packagelist.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetLanguages (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN OUT CHAR8 *Languages,
+ IN OUT UINTN *LanguagesSize
+ );
+
+/**
+ Each string package has associated with it a single primary language and zero
+ or more secondary languages. This routine returns the secondary languages
+ associated with a package list.
+
+ @param This A pointer to the EFI_HII_STRING_PROTOCOL
+ instance.
+ @param PackageList The package list to examine.
+ @param PrimaryLanguage Points to the null-terminated ASCII string that specifies
+ the primary language. Languages are specified in the
+ format specified in Appendix M of the UEFI 2.0 specification.
+ @param SecondaryLanguages Points to the buffer to hold the returned null-terminated
+ ASCII string that describes the list of
+ secondary languages for the specified
+ PrimaryLanguage. If there are no secondary
+ languages, the function returns successfully,
+ but this is set to NULL.
+ @param SecondaryLanguagesSize On entry, points to the size of the buffer
+ pointed to by SecondaryLanguages, in bytes. On
+ return, points to the length of SecondaryLanguages
+ in bytes.
+
+ @retval EFI_SUCCESS Secondary languages were correctly returned.
+ @retval EFI_INVALID_PARAMETER PrimaryLanguage or SecondaryLanguagesSize was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by SecondaryLanguagesSize is not
+ zero and SecondaryLanguages is NULL.
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by SecondaryLanguagesSize is
+ too small to hold the returned information.
+ SecondaryLanguageSize is updated to hold the size of
+ the buffer required.
+ @retval EFI_INVALID_LANGUAGE The language specified by PrimaryLanguage is not
+ present in the specified package list.
+ @retval EFI_NOT_FOUND The specified PackageList is not in the Database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetSecondaryLanguages (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN CONST CHAR8 *PrimaryLanguage,
+ IN OUT CHAR8 *SecondaryLanguages,
+ IN OUT UINTN *SecondaryLanguagesSize
+ );
+
+//
+// EFI_HII_DATABASE_PROTOCOL protocol interfaces
+//
+
+/**
+ This function adds the packages in the package list to the database and returns a handle. If there is a
+ EFI_DEVICE_PATH_PROTOCOL associated with the DriverHandle, then this function will
+ create a package of type EFI_PACKAGE_TYPE_DEVICE_PATH and add it to the package list.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER
+ structure.
+ @param DriverHandle Associate the package list with this EFI handle.
+ If a NULL is specified, this data will not be associate
+ with any drivers and cannot have a callback induced.
+ @param Handle A pointer to the EFI_HII_HANDLE instance.
+
+ @retval EFI_SUCCESS The package list associated with the Handle was
+ added to the HII database.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the
+ new database contents.
+ @retval EFI_INVALID_PARAMETER PackageList is NULL or Handle is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiNewPackageList (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
+ IN CONST EFI_HANDLE DriverHandle OPTIONAL,
+ OUT EFI_HII_HANDLE *Handle
+ );
+
+/**
+ This function removes the package list that is associated with a handle Handle
+ from the HII database. Before removing the package, any registered functions
+ with the notification type REMOVE_PACK and the same package type will be called.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param Handle The handle that was registered to the data that
+ is requested for removal.
+
+ @retval EFI_SUCCESS The data associated with the Handle was removed
+ from the HII database.
+ @retval EFI_NOT_FOUND The specified Handle is not in database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiRemovePackageList (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle
+ );
+
+/**
+ This function updates the existing package list (which has the specified Handle)
+ in the HII databases, using the new package list specified by PackageList.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param Handle The handle that was registered to the data that
+ is requested to be updated.
+ @param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER
+ package.
+
+ @retval EFI_SUCCESS The HII database was successfully updated.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate enough memory for the updated
+ database.
+ @retval EFI_INVALID_PARAMETER PackageList was NULL.
+ @retval EFI_NOT_FOUND The specified Handle is not in database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiUpdatePackageList (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList
+ );
+
+/**
+ This function returns a list of the package handles of the specified type
+ that are currently active in the database. The pseudo-type
+ EFI_HII_PACKAGE_TYPE_ALL will cause all package handles to be listed.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param PackageType Specifies the package type of the packages to
+ list or EFI_HII_PACKAGE_TYPE_ALL for all packages
+ to be listed.
+ @param PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then
+ this is the pointer to the GUID which must match
+ the Guid field of EFI_HII_GUID_PACKAGE_GUID_HDR.
+ Otherwise, it must be NULL.
+ @param HandleBufferLength On input, a pointer to the length of the handle
+ buffer. On output, the length of the handle
+ buffer that is required for the handles found.
+ @param Handle An array of EFI_HII_HANDLE instances returned.
+
+ @retval EFI_SUCCESS The matching handles are outputted successfully.
+ HandleBufferLength is updated with the actual length.
+ @retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that
+ Handle is too small to support the number of
+ handles. HandleBufferLength is updated with a
+ value that will enable the data to fit.
+ @retval EFI_NOT_FOUND No matching handle could not be found in
+ database.
+ @retval EFI_INVALID_PARAMETER HandleBufferLength was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by HandleBufferLength was not
+ zero and Handle was NULL.
+ @retval EFI_INVALID_PARAMETER PackageType is not a EFI_HII_PACKAGE_TYPE_GUID but
+ PackageGuid is not NULL, PackageType is a EFI_HII_
+ PACKAGE_TYPE_GUID but PackageGuid is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiListPackageLists (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN OUT UINTN *HandleBufferLength,
+ OUT EFI_HII_HANDLE *Handle
+ );
+
+/**
+ This function will export one or all package lists in the database to a buffer.
+ For each package list exported, this function will call functions registered
+ with EXPORT_PACK and then copy the package list to the buffer.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param Handle An EFI_HII_HANDLE that corresponds to the desired
+ package list in the HII database to export or
+ NULL to indicate all package lists should be
+ exported.
+ @param BufferSize On input, a pointer to the length of the buffer.
+ On output, the length of the buffer that is
+ required for the exported data.
+ @param Buffer A pointer to a buffer that will contain the
+ results of the export function.
+
+ @retval EFI_SUCCESS Package exported.
+ @retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that
+ Handle is too small to support the number of
+ handles. HandleBufferLength is updated with
+ a value that will enable the data to fit.
+ @retval EFI_NOT_FOUND The specified Handle could not be found in the
+ current database.
+ @retval EFI_INVALID_PARAMETER BufferSize was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by BufferSize was not zero
+ and Buffer was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiExportPackageLists (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer
+ );
+
+/**
+ This function registers a function which will be called when specified actions related to packages of
+ the specified type occur in the HII database. By registering a function, other HII-related drivers are
+ notified when specific package types are added, removed or updated in the HII database.
+ Each driver or application which registers a notification should use
+ EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify() before exiting.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param PackageType Specifies the package type of the packages to
+ list or EFI_HII_PACKAGE_TYPE_ALL for all packages
+ to be listed.
+ @param PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then
+ this is the pointer to the GUID which must match
+ the Guid field of
+ EFI_HII_GUID_PACKAGE_GUID_HDR. Otherwise, it must
+ be NULL.
+ @param PackageNotifyFn Points to the function to be called when the
+ event specified by
+ NotificationType occurs.
+ @param NotifyType Describes the types of notification which this
+ function will be receiving.
+ @param NotifyHandle Points to the unique handle assigned to the
+ registered notification. Can be used in
+ EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify()
+ to stop notifications.
+
+ @retval EFI_SUCCESS Notification registered successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures
+ @retval EFI_INVALID_PARAMETER NotifyHandle is NULL.
+ @retval EFI_INVALID_PARAMETER PackageGuid is not NULL when PackageType is not
+ EFI_HII_PACKAGE_TYPE_GUID.
+ @retval EFI_INVALID_PARAMETER PackageGuid is NULL when PackageType is
+ EFI_HII_PACKAGE_TYPE_GUID.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiRegisterPackageNotify (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN CONST EFI_HII_DATABASE_NOTIFY PackageNotifyFn,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ OUT EFI_HANDLE *NotifyHandle
+ );
+
+/**
+ Removes the specified HII database package-related notification.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param NotificationHandle The handle of the notification function being
+ unregistered.
+
+ @retval EFI_SUCCESS Notification is unregistered successfully.
+ @retval EFI_NOT_FOUND The incoming notification handle does not exist
+ in current hii database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiUnregisterPackageNotify (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HANDLE NotificationHandle
+ );
+
+/**
+ This routine retrieves an array of GUID values for each keyboard layout that
+ was previously registered in the system.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param KeyGuidBufferLength On input, a pointer to the length of the keyboard
+ GUID buffer. On output, the length of the handle
+ buffer that is required for the handles found.
+ @param KeyGuidBuffer An array of keyboard layout GUID instances
+ returned.
+
+ @retval EFI_SUCCESS KeyGuidBuffer was updated successfully.
+ @retval EFI_BUFFER_TOO_SMALL The KeyGuidBufferLength parameter indicates
+ that KeyGuidBuffer is too small to support the
+ number of GUIDs. KeyGuidBufferLength is
+ updated with a value that will enable the data to
+ fit.
+ @retval EFI_INVALID_PARAMETER The KeyGuidBufferLength is NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by KeyGuidBufferLength is not
+ zero and KeyGuidBuffer is NULL.
+ @retval EFI_NOT_FOUND There was no keyboard layout.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiFindKeyboardLayouts (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN OUT UINT16 *KeyGuidBufferLength,
+ OUT EFI_GUID *KeyGuidBuffer
+ );
+
+/**
+ This routine retrieves the requested keyboard layout. The layout is a physical description of the keys
+ on a keyboard and the character(s) that are associated with a particular set of key strokes.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param KeyGuid A pointer to the unique ID associated with a
+ given keyboard layout. If KeyGuid is NULL then
+ the current layout will be retrieved.
+ @param KeyboardLayoutLength On input, a pointer to the length of the
+ KeyboardLayout buffer. On output, the length of
+ the data placed into KeyboardLayout.
+ @param KeyboardLayout A pointer to a buffer containing the retrieved
+ keyboard layout.
+
+ @retval EFI_SUCCESS The keyboard layout was retrieved successfully.
+ @retval EFI_NOT_FOUND The requested keyboard layout was not found.
+ @retval EFI_INVALID_PARAMETER The KeyboardLayout or KeyboardLayoutLength was
+ NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetKeyboardLayout (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN CONST EFI_GUID *KeyGuid,
+ IN OUT UINT16 *KeyboardLayoutLength,
+ OUT EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout
+ );
+
+/**
+ This routine sets the default keyboard layout to the one referenced by KeyGuid. When this routine
+ is called, an event will be signaled of the EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID
+ group type. This is so that agents which are sensitive to the current keyboard layout being changed
+ can be notified of this change.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param KeyGuid A pointer to the unique ID associated with a
+ given keyboard layout.
+
+ @retval EFI_SUCCESS The current keyboard layout was successfully set.
+ @retval EFI_NOT_FOUND The referenced keyboard layout was not found, so
+ action was taken.
+ @retval EFI_INVALID_PARAMETER The KeyGuid was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiSetKeyboardLayout (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN CONST EFI_GUID *KeyGuid
+ );
+
+/**
+ Return the EFI handle associated with a package list.
+
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
+ instance.
+ @param PackageListHandle An EFI_HII_HANDLE that corresponds to the desired
+ package list in the HIIdatabase.
+ @param DriverHandle On return, contains the EFI_HANDLE which was
+ registered with the package list in
+ NewPackageList().
+
+ @retval EFI_SUCCESS The DriverHandle was returned successfully.
+ @retval EFI_INVALID_PARAMETER The PackageListHandle was not valid or
+ DriverHandle was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetPackageListHandle (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageListHandle,
+ OUT EFI_HANDLE *DriverHandle
+ );
+
+//
+// EFI_HII_CONFIG_ROUTING_PROTOCOL interfaces
+//
+
+/**
+ This function allows a caller to extract the current configuration
+ for one or more named elements from one or more drivers.
+
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+ instance.
+ @param Request A null-terminated Unicode string in
+ <MultiConfigRequest> format.
+ @param Progress On return, points to a character in the Request
+ string. Points to the string's null terminator if
+ 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 Results Null-terminated Unicode string in
+ <MultiConfigAltResp> format which has all values
+ filled in for the names in the Request string.
+ String to be allocated by the called function.
+
+ @retval EFI_SUCCESS The Results string is filled with the values
+ corresponding to all requested names.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
+ results that must be stored awaiting possible
+ future protocols.
+ @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
+ Progress set to the "G" in "GUID" of the
+ routing header that doesn't match. Note: There
+ is no requirement that all routing data
+ be validated before any configuration extraction.
+ @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
+ parameter would result in this type of error. The
+ Progress parameter is set to NULL.
+ @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
+ before the error or the beginning of the string.
+ @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
+ name in question.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiConfigRoutingExtractConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ );
+
+/**
+ This function allows the caller to request the current configuration for the
+ entirety of the current HII database and returns the data in a null-terminated Unicode string.
+
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+ instance.
+ @param Results Null-terminated Unicode string in
+ <MultiConfigAltResp> format which has all values
+ filled in for the entirety of the current HII
+ database. String to be allocated by the called
+ function. De-allocation is up to the caller.
+
+ @retval EFI_SUCCESS The Results string is filled with the values
+ corresponding to all requested names.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
+ results that must be stored awaiting possible
+ future protocols.
+ @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
+ parameter would result in this type of error.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiConfigRoutingExportConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ OUT EFI_STRING *Results
+ );
+
+/**
+ This function processes the results of processing forms and routes it to the
+ appropriate handlers or storage.
+
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+ instance.
+ @param Configuration A null-terminated Unicode string in
+ <MulltiConfigResp> format.
+ @param Progress A pointer to a string filled in with the offset
+ of 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)
+ or the terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The results have been distributed or are awaiting
+ distribution.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
+ results that must be stored awaiting possible
+ future protocols.
+ @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
+ would result in this type of error.
+ @retval EFI_NOT_FOUND Target for the specified routing data was not
+ found.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiConfigRoutingRouteConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ );
+
+/**
+ This helper function is to be called by drivers to map configuration data stored
+ in byte array ("block") formats such as UEFI Variables into current configuration strings.
+
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+ instance.
+ @param ConfigRequest A null-terminated Unicode string in
+ <ConfigRequest> format.
+ @param Block Array of bytes defining the block's
+ configuration.
+ @param BlockSize Length in bytes of Block.
+ @param Config Filled-in configuration string. String allocated
+ by the function. Returned only if call is
+ successful.
+ @param Progress A pointer to a string filled in with the offset
+ of 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)
+ or the terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The request succeeded. Progress points to the
+ null terminator at the end of the ConfigRequest
+ string.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config.
+ Progress points to the first character of
+ ConfigRequest.
+ @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
+ Block parameter would result in this type of
+ error. Progress points to the first character of
+ ConfigRequest.
+ @retval EFI_NOT_FOUND Target for the specified routing data was not
+ found. Progress points to the "G" in "GUID" of
+ the errant routing data.
+ @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
+ @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
+ Block is left updated and Progress points at
+ the '&' preceding the first non-<BlockName>.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiBlockToConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING ConfigRequest,
+ IN CONST UINT8 *Block,
+ IN CONST UINTN BlockSize,
+ OUT EFI_STRING *Config,
+ OUT EFI_STRING *Progress
+ );
+
+/**
+ This helper function is to be called by drivers to map configuration strings
+ to configurations stored in byte array ("block") formats such as UEFI Variables.
+
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+ instance.
+ @param ConfigResp A null-terminated Unicode string in <ConfigResp>
+ format.
+ @param Block A possibly null array of bytes representing the
+ current block. Only bytes referenced in the
+ ConfigResp string in the block are modified. If
+ this parameter is null or if the *BlockSize
+ parameter is (on input) shorter than required by
+ the Configuration string, only the BlockSize
+ parameter is updated and an appropriate status
+ (see below) is returned.
+ @param BlockSize The length of the Block in units of UINT8. On
+ input, this is the size of the Block. On output,
+ if successful, contains the largest index of the
+ modified byte in the Block, or the required buffer
+ size if the Block is not large enough.
+ @param Progress On return, points to an element of the ConfigResp
+ string filled in with the offset of 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) or
+ the terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The request succeeded. Progress points to the
+ null terminator at the end of the ConfigResp
+ string.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config.
+ Progress points to the first character of
+ ConfigResp.
+ @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
+ Block parameter would result in this type of
+ error. Progress points to the first character of
+ ConfigResp.
+ @retval EFI_NOT_FOUND Target for the specified routing data was not
+ found. Progress points to the "G" in "GUID" of
+ the errant routing data.
+ @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
+ value pair. Block is left updated and
+ Progress points at the '&' preceding the first
+ non-<BlockName>.
+ @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
+ BlockSize is updated with the required buffer size.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiConfigToBlock (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING ConfigResp,
+ IN OUT UINT8 *Block,
+ IN OUT UINTN *BlockSize,
+ OUT EFI_STRING *Progress
+ );
+
+/**
+ This helper function is to be called by drivers to extract portions of
+ a larger configuration string.
+
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+ instance.
+ @param Configuration A null-terminated Unicode string in
+ <MultiConfigAltResp> format.
+ @param Guid A pointer to the GUID value to search for in the
+ routing portion of the ConfigResp string when
+ retrieving the requested data. If Guid is NULL,
+ then all GUID values will be searched for.
+ @param Name A pointer to the NAME value to search for in the
+ routing portion of the ConfigResp string when
+ retrieving the requested data. If Name is NULL,
+ then all Name values will be searched for.
+ @param DevicePath A pointer to the PATH value to search for in the
+ routing portion of the ConfigResp string when
+ retrieving the requested data. If DevicePath is
+ NULL, then all DevicePath values will be
+ searched for.
+ @param AltCfgId A pointer to the ALTCFG value to search for in
+ the routing portion of the ConfigResp string
+ when retrieving the requested data. If this
+ parameter is NULL, then the current setting will
+ be retrieved.
+ @param AltCfgResp A pointer to a buffer which will be allocated by
+ the function which contains the retrieved string
+ as requested. This buffer is only allocated if
+ the call was successful.
+
+ @retval EFI_SUCCESS The request succeeded. The requested data was
+ extracted and placed in the newly allocated
+ AltCfgResp buffer.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
+ @retval EFI_INVALID_PARAMETER Any parameter is invalid.
+ @retval EFI_NOT_FOUND Target for the specified routing data was not
+ found.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetAltCfg (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ IN CONST EFI_GUID *Guid,
+ IN CONST EFI_STRING Name,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN CONST UINT16 *AltCfgId,
+ OUT EFI_STRING *AltCfgResp
+ );
+
+/**
+
+ 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
+ );
+
+/**
+
+ 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
+ );
+
+/**
+ Compare whether two names of languages are identical.
+
+ @param Language1 Name of language 1 from StringPackage
+ @param Language2 Name of language 2 to be compared with language 1.
+
+ @retval TRUE same
+ @retval FALSE not same
+
+**/
+BOOLEAN
+HiiCompareLanguage (
+ IN CHAR8 *Language1,
+ IN CHAR8 *Language2
+ )
+;
+
+/**
+ Retrieves a pointer to a Null-terminated ASCII string containing the list
+ of languages that an HII handle in the HII Database supports. The returned
+ string is allocated using AllocatePool(). The caller is responsible for freeing
+ the returned string using FreePool(). The format of the returned string follows
+ the language format assumed the HII Database.
+
+ If HiiHandle is NULL, then ASSERT().
+
+ @param[in] HiiHandle A handle that was previously registered in the HII Database.
+
+ @retval NULL HiiHandle is not registered in the HII database
+ @retval NULL There are not enough resources available to retrieve the supported
+ languages.
+ @retval NULL The list of supported languages could not be retrieved.
+ @retval Other A pointer to the Null-terminated ASCII string of supported languages.
+
+**/
+CHAR8 *
+GetSupportedLanguages (
+ IN EFI_HII_HANDLE HiiHandle
+ );
+
+/**
+This function mainly use to get HiiDatabase information.
+
+@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
+
+@retval EFI_SUCCESS Get the information successfully.
+@retval EFI_OUT_OF_RESOURCES Not enough memory to store the Hiidatabase data.
+
+**/
+EFI_STATUS
+HiiGetDatabaseInfo (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This
+ );
+
+/**
+This function mainly use to get and update ConfigResp string.
+
+@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
+
+@retval EFI_SUCCESS Get the information successfully.
+@retval EFI_OUT_OF_RESOURCES Not enough memory to store the Configuration Setting data.
+
+**/
+EFI_STATUS
+HiiGetConfigRespInfo (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This
+ );
+
+/**
+ Find question default value from PcdNvStoreDefaultValueBuffer
+
+ @param DefaultId Default store ID
+ @param EfiVarStore Point to EFI VarStore header
+ @param IfrQuestionHdr Point to Question header
+ @param ValueBuffer Point to Buffer includes the found default setting
+ @param Width Width of the default value
+ @param BitFieldQuestion Whether the Question is stored in Bit field.
+
+ @retval EFI_SUCCESS Question default value is found.
+ @retval EFI_NOT_FOUND Question default value is not found.
+**/
+EFI_STATUS
+FindQuestionDefaultSetting (
+ IN UINT16 DefaultId,
+ IN EFI_IFR_VARSTORE_EFI *EfiVarStore,
+ IN EFI_IFR_QUESTION_HEADER *IfrQuestionHdr,
+ OUT VOID *ValueBuffer,
+ IN UINTN Width,
+ IN BOOLEAN BitFieldQuestion
+ );
+
+//
+// Global variables
+//
+extern EFI_EVENT gHiiKeyboardLayoutChanged;
+extern BOOLEAN gExportAfterReadyToBoot;
+
+#endif
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.uni b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.uni
index c799672b7b..31db2f9788 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.uni
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.uni
@@ -1,17 +1,17 @@
-// /** @file
-// The DXE driver produces HII protocols defined in UEFI specification.
-//
-// This driver produces all required HII serivces that includes HiiDataBase, HiiString,
-// HiiFont, HiiConfigRouting. To support UEFI HII, this driver is required.
-//
-// Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
-//
-// SPDX-License-Identifier: BSD-2-Clause-Patent
-//
-// **/
-
-
-#string STR_MODULE_ABSTRACT #language en-US "Produces HII protocols defined in the UEFI Specification"
-
-#string STR_MODULE_DESCRIPTION #language en-US "This driver produces all required HII services that includes HiiDataBase, HiiString, HiiFont, HiiConfigRouting. To support UEFI HII, this driver is required."
-
+// /** @file
+// The DXE driver produces HII protocols defined in UEFI specification.
+//
+// This driver produces all required HII serivces that includes HiiDataBase, HiiString,
+// HiiFont, HiiConfigRouting. To support UEFI HII, this driver is required.
+//
+// Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Produces HII protocols defined in the UEFI Specification"
+
+#string STR_MODULE_DESCRIPTION #language en-US "This driver produces all required HII services that includes HiiDataBase, HiiString, HiiFont, HiiConfigRouting. To support UEFI HII, this driver is required."
+
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
index 0116fb6ecb..6b8fa206f3 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
@@ -1,94 +1,94 @@
-## @file
-# The DXE driver produces HII protocols defined in UEFI specification.
-#
-# This driver produces all required HII serivces that includes HiiDataBase, HiiString,
-# HiiFont, HiiConfigRouting. To support UEFI HII, this driver is required.
-#
-# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
-#
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-#
-##
-
-[Defines]
- INF_VERSION = 0x00010005
- BASE_NAME = HiiDatabase
- MODULE_UNI_FILE = HiiDatabase.uni
- FILE_GUID = 348C4D62-BFBD-4882-9ECE-C80BB1C4783B
- MODULE_TYPE = DXE_DRIVER
- VERSION_STRING = 1.0
- ENTRY_POINT = InitializeHiiDatabase
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-# VALID_ARCHITECTURES = IA32 X64 EBC
-#
-
-[Sources]
- HiiDatabaseEntry.c
- Image.c
- ImageEx.c
- HiiDatabase.h
- ConfigRouting.c
- String.c
- Database.c
- Font.c
- ConfigKeywordHandler.c
-
-[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
-
-
-[LibraryClasses]
- MemoryAllocationLib
- DevicePathLib
- BaseLib
- UefiBootServicesTableLib
- UefiDriverEntryPoint
- BaseMemoryLib
- DebugLib
- UefiLib
- PcdLib
- UefiRuntimeServicesTableLib
- PrintLib
-
-[Protocols]
- gEfiDevicePathProtocolGuid ## SOMETIMES_CONSUMES
- gEfiHiiStringProtocolGuid ## PRODUCES
- gEfiHiiImageProtocolGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_PRODUCES
- gEfiHiiImageExProtocolGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_PRODUCES
- gEfiHiiImageDecoderProtocolGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_CONSUMES
- gEfiHiiConfigRoutingProtocolGuid ## PRODUCES
- gEfiHiiDatabaseProtocolGuid ## PRODUCES
- gEfiHiiFontProtocolGuid ## PRODUCES
- gEfiHiiConfigAccessProtocolGuid ## SOMETIMES_CONSUMES
- gEfiConfigKeywordHandlerProtocolGuid ## PRODUCES
-
-[FeaturePcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdHiiOsRuntimeSupport ## CONSUMES
-
-[Pcd]
- gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer ## CONSUMES
-
-[Guids]
- #
- # Event registered to EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group,
- # which will be triggered by EFI_HII_DATABASE_PROTOCOL.SetKeyboardLayout().
- #
- ## CONSUMES ## Event
- ## PRODUCES ## Event
- gEfiHiiKeyBoardLayoutGuid
- gEfiHiiImageDecoderNameJpegGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_CONSUMES ## GUID
- gEfiHiiImageDecoderNamePngGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_CONSUMES ## GUID
- gEdkiiIfrBitVarstoreGuid ## SOMETIMES_CONSUMES ## GUID
-
-[Depex]
- TRUE
-
-[UserExtensions.TianoCore."ExtraFiles"]
- HiiDatabaseExtra.uni
+## @file
+# The DXE driver produces HII protocols defined in UEFI specification.
+#
+# This driver produces all required HII serivces that includes HiiDataBase, HiiString,
+# HiiFont, HiiConfigRouting. To support UEFI HII, this driver is required.
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = HiiDatabase
+ MODULE_UNI_FILE = HiiDatabase.uni
+ FILE_GUID = 348C4D62-BFBD-4882-9ECE-C80BB1C4783B
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeHiiDatabase
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ HiiDatabaseEntry.c
+ Image.c
+ ImageEx.c
+ HiiDatabase.h
+ ConfigRouting.c
+ String.c
+ Database.c
+ Font.c
+ ConfigKeywordHandler.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+ MemoryAllocationLib
+ DevicePathLib
+ BaseLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ DebugLib
+ UefiLib
+ PcdLib
+ UefiRuntimeServicesTableLib
+ PrintLib
+
+[Protocols]
+ gEfiDevicePathProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiHiiStringProtocolGuid ## PRODUCES
+ gEfiHiiImageProtocolGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_PRODUCES
+ gEfiHiiImageExProtocolGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_PRODUCES
+ gEfiHiiImageDecoderProtocolGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_CONSUMES
+ gEfiHiiConfigRoutingProtocolGuid ## PRODUCES
+ gEfiHiiDatabaseProtocolGuid ## PRODUCES
+ gEfiHiiFontProtocolGuid ## PRODUCES
+ gEfiHiiConfigAccessProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiConfigKeywordHandlerProtocolGuid ## PRODUCES
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHiiOsRuntimeSupport ## CONSUMES
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer ## CONSUMES
+
+[Guids]
+ #
+ # Event registered to EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group,
+ # which will be triggered by EFI_HII_DATABASE_PROTOCOL.SetKeyboardLayout().
+ #
+ ## CONSUMES ## Event
+ ## PRODUCES ## Event
+ gEfiHiiKeyBoardLayoutGuid
+ gEfiHiiImageDecoderNameJpegGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_CONSUMES ## GUID
+ gEfiHiiImageDecoderNamePngGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_CONSUMES ## GUID
+ gEdkiiIfrBitVarstoreGuid ## SOMETIMES_CONSUMES ## GUID
+
+[Depex]
+ TRUE
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ HiiDatabaseExtra.uni
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c
index e4bdfdeed0..e041420731 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c
@@ -1,250 +1,250 @@
-/** @file
-This file contains the entry code to the HII database, which is defined by
-UEFI 2.1 specification.
-
-Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "HiiDatabase.h"
-
-//
-// Global variables
-//
-EFI_EVENT gHiiKeyboardLayoutChanged;
-BOOLEAN gExportAfterReadyToBoot = FALSE;
-
-HII_DATABASE_PRIVATE_DATA mPrivate = {
- HII_DATABASE_PRIVATE_DATA_SIGNATURE,
- {
- (LIST_ENTRY *)NULL,
- (LIST_ENTRY *)NULL
- },
- {
- (LIST_ENTRY *)NULL,
- (LIST_ENTRY *)NULL
- },
- {
- HiiStringToImage,
- HiiStringIdToImage,
- HiiGetGlyph,
- HiiGetFontInfo
- },
- {
- HiiNewImage,
- HiiGetImage,
- HiiSetImage,
- HiiDrawImage,
- HiiDrawImageId
- },
- {
- HiiNewImageEx,
- HiiGetImageEx,
- HiiSetImageEx,
- HiiDrawImageEx,
- HiiDrawImageIdEx,
- HiiGetImageInfo
- },
- {
- HiiNewString,
- HiiGetString,
- HiiSetString,
- HiiGetLanguages,
- HiiGetSecondaryLanguages
- },
- {
- HiiNewPackageList,
- HiiRemovePackageList,
- HiiUpdatePackageList,
- HiiListPackageLists,
- HiiExportPackageLists,
- HiiRegisterPackageNotify,
- HiiUnregisterPackageNotify,
- HiiFindKeyboardLayouts,
- HiiGetKeyboardLayout,
- HiiSetKeyboardLayout,
- HiiGetPackageListHandle
- },
- {
- HiiConfigRoutingExtractConfig,
- HiiConfigRoutingExportConfig,
- HiiConfigRoutingRouteConfig,
- HiiBlockToConfig,
- HiiConfigToBlock,
- HiiGetAltCfg
- },
- {
- EfiConfigKeywordHandlerSetData,
- EfiConfigKeywordHandlerGetData
- },
- {
- (LIST_ENTRY *)NULL,
- (LIST_ENTRY *)NULL
- },
- 0,
- {
- (LIST_ENTRY *)NULL,
- (LIST_ENTRY *)NULL
- },
- EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK),
- {
- 0x00000000,
- 0x0000,
- 0x0000,
- { 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00 }
- },
- NULL
-};
-
-/**
- The default event handler for gHiiKeyboardLayoutChanged
- event group.
-
- This is internal function.
-
- @param Event The event that triggered this notification function.
- @param Context Pointer to the notification functions context.
-
-**/
-VOID
-EFIAPI
-KeyboardLayoutChangeNullEvent (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- return;
-}
-
-/**
- On Ready To Boot Services Event notification handler.
-
- To trigger the function that to export the Hii Configuration setting.
-
- @param[in] Event Event whose notification function is being invoked
- @param[in] Context Pointer to the notification function's context
-
-**/
-VOID
-EFIAPI
-OnReadyToBoot (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- //
- // When ready to boot, we begin to export the HiiDatabase date.
- // And hook all the possible HiiDatabase change actions to export data.
- //
- HiiGetDatabaseInfo (&mPrivate.HiiDatabase);
- HiiGetConfigRespInfo (&mPrivate.HiiDatabase);
- gExportAfterReadyToBoot = TRUE;
-
- gBS->CloseEvent (Event);
-}
-
-/**
- Initialize HII Database.
-
-
- @param ImageHandle The image handle.
- @param SystemTable The system table.
-
- @retval EFI_SUCCESS The Hii database is setup correctly.
- @return Other value if failed to create the default event for
- gHiiKeyboardLayoutChanged. Check gBS->CreateEventEx for
- details. Or failed to install the protocols.
- Check gBS->InstallMultipleProtocolInterfaces for details.
- Or failed to create Ready To Boot Event.
- Check EfiCreateEventReadyToBootEx for details.
-
-**/
-EFI_STATUS
-EFIAPI
-InitializeHiiDatabase (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE Handle;
- EFI_EVENT ReadyToBootEvent;
-
- //
- // There will be only one HII Database in the system
- // If there is another out there, someone is trying to install us
- // again. Fail that scenario.
- //
- ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiHiiDatabaseProtocolGuid);
- ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiHiiFontProtocolGuid);
- ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiHiiImageProtocolGuid);
- ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiHiiStringProtocolGuid);
- ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiHiiConfigRoutingProtocolGuid);
- ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiConfigKeywordHandlerProtocolGuid);
-
- InitializeListHead (&mPrivate.DatabaseList);
- InitializeListHead (&mPrivate.DatabaseNotifyList);
- InitializeListHead (&mPrivate.HiiHandleList);
- InitializeListHead (&mPrivate.FontInfoList);
-
- //
- // Create a event with EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group type.
- //
- Status = gBS->CreateEventEx (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- KeyboardLayoutChangeNullEvent,
- NULL,
- &gEfiHiiKeyBoardLayoutGuid,
- &gHiiKeyboardLayoutChanged
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Handle = NULL;
- Status = gBS->InstallMultipleProtocolInterfaces (
- &Handle,
- &gEfiHiiFontProtocolGuid,
- &mPrivate.HiiFont,
- &gEfiHiiStringProtocolGuid,
- &mPrivate.HiiString,
- &gEfiHiiDatabaseProtocolGuid,
- &mPrivate.HiiDatabase,
- &gEfiHiiConfigRoutingProtocolGuid,
- &mPrivate.ConfigRouting,
- &gEfiConfigKeywordHandlerProtocolGuid,
- &mPrivate.ConfigKeywordHandler,
- NULL
- );
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (FeaturePcdGet (PcdSupportHiiImageProtocol)) {
- Status = gBS->InstallMultipleProtocolInterfaces (
- &Handle,
- &gEfiHiiImageProtocolGuid,
- &mPrivate.HiiImage,
- &gEfiHiiImageExProtocolGuid,
- &mPrivate.HiiImageEx,
- NULL
- );
- }
-
- if (FeaturePcdGet (PcdHiiOsRuntimeSupport)) {
- Status = EfiCreateEventReadyToBootEx (
- TPL_CALLBACK,
- OnReadyToBoot,
- NULL,
- &ReadyToBootEvent
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
-
- return Status;
-}
+/** @file
+This file contains the entry code to the HII database, which is defined by
+UEFI 2.1 specification.
+
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "HiiDatabase.h"
+
+//
+// Global variables
+//
+EFI_EVENT gHiiKeyboardLayoutChanged;
+BOOLEAN gExportAfterReadyToBoot = FALSE;
+
+HII_DATABASE_PRIVATE_DATA mPrivate = {
+ HII_DATABASE_PRIVATE_DATA_SIGNATURE,
+ {
+ (LIST_ENTRY *)NULL,
+ (LIST_ENTRY *)NULL
+ },
+ {
+ (LIST_ENTRY *)NULL,
+ (LIST_ENTRY *)NULL
+ },
+ {
+ HiiStringToImage,
+ HiiStringIdToImage,
+ HiiGetGlyph,
+ HiiGetFontInfo
+ },
+ {
+ HiiNewImage,
+ HiiGetImage,
+ HiiSetImage,
+ HiiDrawImage,
+ HiiDrawImageId
+ },
+ {
+ HiiNewImageEx,
+ HiiGetImageEx,
+ HiiSetImageEx,
+ HiiDrawImageEx,
+ HiiDrawImageIdEx,
+ HiiGetImageInfo
+ },
+ {
+ HiiNewString,
+ HiiGetString,
+ HiiSetString,
+ HiiGetLanguages,
+ HiiGetSecondaryLanguages
+ },
+ {
+ HiiNewPackageList,
+ HiiRemovePackageList,
+ HiiUpdatePackageList,
+ HiiListPackageLists,
+ HiiExportPackageLists,
+ HiiRegisterPackageNotify,
+ HiiUnregisterPackageNotify,
+ HiiFindKeyboardLayouts,
+ HiiGetKeyboardLayout,
+ HiiSetKeyboardLayout,
+ HiiGetPackageListHandle
+ },
+ {
+ HiiConfigRoutingExtractConfig,
+ HiiConfigRoutingExportConfig,
+ HiiConfigRoutingRouteConfig,
+ HiiBlockToConfig,
+ HiiConfigToBlock,
+ HiiGetAltCfg
+ },
+ {
+ EfiConfigKeywordHandlerSetData,
+ EfiConfigKeywordHandlerGetData
+ },
+ {
+ (LIST_ENTRY *)NULL,
+ (LIST_ENTRY *)NULL
+ },
+ 0,
+ {
+ (LIST_ENTRY *)NULL,
+ (LIST_ENTRY *)NULL
+ },
+ EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK),
+ {
+ 0x00000000,
+ 0x0000,
+ 0x0000,
+ { 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00 }
+ },
+ NULL
+};
+
+/**
+ The default event handler for gHiiKeyboardLayoutChanged
+ event group.
+
+ This is internal function.
+
+ @param Event The event that triggered this notification function.
+ @param Context Pointer to the notification functions context.
+
+**/
+VOID
+EFIAPI
+KeyboardLayoutChangeNullEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ return;
+}
+
+/**
+ On Ready To Boot Services Event notification handler.
+
+ To trigger the function that to export the Hii Configuration setting.
+
+ @param[in] Event Event whose notification function is being invoked
+ @param[in] Context Pointer to the notification function's context
+
+**/
+VOID
+EFIAPI
+OnReadyToBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ //
+ // When ready to boot, we begin to export the HiiDatabase date.
+ // And hook all the possible HiiDatabase change actions to export data.
+ //
+ HiiGetDatabaseInfo (&mPrivate.HiiDatabase);
+ HiiGetConfigRespInfo (&mPrivate.HiiDatabase);
+ gExportAfterReadyToBoot = TRUE;
+
+ gBS->CloseEvent (Event);
+}
+
+/**
+ Initialize HII Database.
+
+
+ @param ImageHandle The image handle.
+ @param SystemTable The system table.
+
+ @retval EFI_SUCCESS The Hii database is setup correctly.
+ @return Other value if failed to create the default event for
+ gHiiKeyboardLayoutChanged. Check gBS->CreateEventEx for
+ details. Or failed to install the protocols.
+ Check gBS->InstallMultipleProtocolInterfaces for details.
+ Or failed to create Ready To Boot Event.
+ Check EfiCreateEventReadyToBootEx for details.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeHiiDatabase (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ EFI_EVENT ReadyToBootEvent;
+
+ //
+ // There will be only one HII Database in the system
+ // If there is another out there, someone is trying to install us
+ // again. Fail that scenario.
+ //
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiHiiDatabaseProtocolGuid);
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiHiiFontProtocolGuid);
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiHiiImageProtocolGuid);
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiHiiStringProtocolGuid);
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiHiiConfigRoutingProtocolGuid);
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiConfigKeywordHandlerProtocolGuid);
+
+ InitializeListHead (&mPrivate.DatabaseList);
+ InitializeListHead (&mPrivate.DatabaseNotifyList);
+ InitializeListHead (&mPrivate.HiiHandleList);
+ InitializeListHead (&mPrivate.FontInfoList);
+
+ //
+ // Create a event with EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group type.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ KeyboardLayoutChangeNullEvent,
+ NULL,
+ &gEfiHiiKeyBoardLayoutGuid,
+ &gHiiKeyboardLayoutChanged
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiHiiFontProtocolGuid,
+ &mPrivate.HiiFont,
+ &gEfiHiiStringProtocolGuid,
+ &mPrivate.HiiString,
+ &gEfiHiiDatabaseProtocolGuid,
+ &mPrivate.HiiDatabase,
+ &gEfiHiiConfigRoutingProtocolGuid,
+ &mPrivate.ConfigRouting,
+ &gEfiConfigKeywordHandlerProtocolGuid,
+ &mPrivate.ConfigKeywordHandler,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (FeaturePcdGet (PcdSupportHiiImageProtocol)) {
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiHiiImageProtocolGuid,
+ &mPrivate.HiiImage,
+ &gEfiHiiImageExProtocolGuid,
+ &mPrivate.HiiImageEx,
+ NULL
+ );
+ }
+
+ if (FeaturePcdGet (PcdHiiOsRuntimeSupport)) {
+ Status = EfiCreateEventReadyToBootEx (
+ TPL_CALLBACK,
+ OnReadyToBoot,
+ NULL,
+ &ReadyToBootEvent
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseExtra.uni b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseExtra.uni
index 81a33ecd5d..0f71038f9b 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseExtra.uni
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseExtra.uni
@@ -1,14 +1,14 @@
-// /** @file
-// HiiDatabase Localized Strings and Content
-//
-// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
-//
-// SPDX-License-Identifier: BSD-2-Clause-Patent
-//
-// **/
-
-#string STR_PROPERTIES_MODULE_NAME
-#language en-US
-"HII Database DXE Driver"
-
-
+// /** @file
+// HiiDatabase Localized Strings and Content
+//
+// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"HII Database DXE Driver"
+
+
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
index b5b9625969..afb312c361 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
@@ -1,1583 +1,1583 @@
-/** @file
-Implementation for EFI_HII_IMAGE_PROTOCOL.
-
-
-Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "HiiDatabase.h"
-
-#define MAX_UINT24 0xFFFFFF
-
-/**
- Get the imageid of last image block: EFI_HII_IIBT_END_BLOCK when input
- ImageId is zero, otherwise return the address of the
- corresponding image block with identifier specified by ImageId.
-
- This is a internal function.
-
- @param ImageBlocks Points to the beginning of a series of image blocks stored in order.
- @param ImageId If input ImageId is 0, output the image id of the EFI_HII_IIBT_END_BLOCK;
- else use this id to find its corresponding image block address.
-
- @return The image block address when input ImageId is not zero; otherwise return NULL.
-
-**/
-EFI_HII_IMAGE_BLOCK *
-GetImageIdOrAddress (
- IN EFI_HII_IMAGE_BLOCK *ImageBlocks,
- IN OUT EFI_IMAGE_ID *ImageId
- )
-{
- EFI_IMAGE_ID ImageIdCurrent;
- EFI_HII_IMAGE_BLOCK *CurrentImageBlock;
- UINTN Length;
-
- ASSERT (ImageBlocks != NULL && ImageId != NULL);
- CurrentImageBlock = ImageBlocks;
- ImageIdCurrent = 1;
-
- while (CurrentImageBlock->BlockType != EFI_HII_IIBT_END) {
- if (*ImageId != 0) {
- if (*ImageId == ImageIdCurrent) {
- //
- // If the found image block is a duplicate block, update the ImageId to
- // find the previous defined image block.
- //
- if (CurrentImageBlock->BlockType == EFI_HII_IIBT_DUPLICATE) {
- *ImageId = ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_DUPLICATE_BLOCK *)CurrentImageBlock)->ImageId);
- ASSERT (*ImageId != ImageIdCurrent);
- ASSERT (*ImageId != 0);
- CurrentImageBlock = ImageBlocks;
- ImageIdCurrent = 1;
- continue;
- }
-
- return CurrentImageBlock;
- }
-
- if (*ImageId < ImageIdCurrent) {
- //
- // Can not find the specified image block in this image.
- //
- return NULL;
- }
- }
-
- switch (CurrentImageBlock->BlockType) {
- case EFI_HII_IIBT_EXT1:
- Length = ((EFI_HII_IIBT_EXT1_BLOCK *)CurrentImageBlock)->Length;
- break;
- case EFI_HII_IIBT_EXT2:
- Length = ReadUnaligned16 (&((EFI_HII_IIBT_EXT2_BLOCK *)CurrentImageBlock)->Length);
- break;
- case EFI_HII_IIBT_EXT4:
- Length = ReadUnaligned32 ((VOID *)&((EFI_HII_IIBT_EXT4_BLOCK *)CurrentImageBlock)->Length);
- break;
-
- case EFI_HII_IIBT_IMAGE_1BIT:
- case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
- Length = sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +
- BITMAP_LEN_1_BIT (
- ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width),
- ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height)
- );
- ImageIdCurrent++;
- break;
-
- case EFI_HII_IIBT_IMAGE_4BIT:
- case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
- Length = sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +
- BITMAP_LEN_4_BIT (
- ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width),
- ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height)
- );
- ImageIdCurrent++;
- break;
-
- case EFI_HII_IIBT_IMAGE_8BIT:
- case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
- Length = sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +
- BITMAP_LEN_8_BIT (
- (UINT32)ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width),
- ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height)
- );
- ImageIdCurrent++;
- break;
-
- case EFI_HII_IIBT_IMAGE_24BIT:
- case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
- Length = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
- BITMAP_LEN_24_BIT (
- (UINT32)ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width),
- ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height)
- );
- ImageIdCurrent++;
- break;
-
- case EFI_HII_IIBT_DUPLICATE:
- Length = sizeof (EFI_HII_IIBT_DUPLICATE_BLOCK);
- ImageIdCurrent++;
- break;
-
- case EFI_HII_IIBT_IMAGE_JPEG:
- Length = OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Data) + ReadUnaligned32 ((VOID *)&((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Size);
- ImageIdCurrent++;
- break;
-
- case EFI_HII_IIBT_IMAGE_PNG:
- Length = OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Data) + ReadUnaligned32 ((VOID *)&((EFI_HII_IIBT_PNG_BLOCK *)CurrentImageBlock)->Size);
- ImageIdCurrent++;
- break;
-
- case EFI_HII_IIBT_SKIP1:
- Length = sizeof (EFI_HII_IIBT_SKIP1_BLOCK);
- ImageIdCurrent += ((EFI_HII_IIBT_SKIP1_BLOCK *)CurrentImageBlock)->SkipCount;
- break;
-
- case EFI_HII_IIBT_SKIP2:
- Length = sizeof (EFI_HII_IIBT_SKIP2_BLOCK);
- ImageIdCurrent += ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_SKIP2_BLOCK *)CurrentImageBlock)->SkipCount);
- break;
-
- default:
- //
- // Unknown image blocks can not be skipped, processing halts.
- //
- ASSERT (FALSE);
- Length = 0;
- break;
- }
-
- CurrentImageBlock = (EFI_HII_IMAGE_BLOCK *)((UINT8 *)CurrentImageBlock + Length);
- }
-
- //
- // When ImageId is zero, return the imageid of last image block: EFI_HII_IIBT_END_BLOCK.
- //
- if (*ImageId == 0) {
- *ImageId = ImageIdCurrent;
- return CurrentImageBlock;
- }
-
- return NULL;
-}
-
-/**
- Convert pixels from EFI_GRAPHICS_OUTPUT_BLT_PIXEL to EFI_HII_RGB_PIXEL style.
-
- This is a internal function.
-
-
- @param BitMapOut Pixels in EFI_HII_RGB_PIXEL format.
- @param BitMapIn Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.
- @param PixelNum The number of pixels to be converted.
-
-
-**/
-VOID
-CopyGopToRgbPixel (
- OUT EFI_HII_RGB_PIXEL *BitMapOut,
- IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapIn,
- IN UINTN PixelNum
- )
-{
- UINTN Index;
-
- ASSERT (BitMapOut != NULL && BitMapIn != NULL);
-
- for (Index = 0; Index < PixelNum; Index++) {
- CopyMem (BitMapOut + Index, BitMapIn + Index, sizeof (EFI_HII_RGB_PIXEL));
- }
-}
-
-/**
- Convert pixels from EFI_HII_RGB_PIXEL to EFI_GRAPHICS_OUTPUT_BLT_PIXEL style.
-
- This is a internal function.
-
-
- @param BitMapOut Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.
- @param BitMapIn Pixels in EFI_HII_RGB_PIXEL format.
- @param PixelNum The number of pixels to be converted.
-
-
-**/
-VOID
-CopyRgbToGopPixel (
- OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapOut,
- IN EFI_HII_RGB_PIXEL *BitMapIn,
- IN UINTN PixelNum
- )
-{
- UINTN Index;
-
- ASSERT (BitMapOut != NULL && BitMapIn != NULL);
-
- for (Index = 0; Index < PixelNum; Index++) {
- CopyMem (BitMapOut + Index, BitMapIn + Index, sizeof (EFI_HII_RGB_PIXEL));
- }
-}
-
-/**
- Output pixels in "1 bit per pixel" format to an image.
-
- This is a internal function.
-
-
- @param Image Points to the image which will store the pixels.
- @param Data Stores the value of output pixels, 0 or 1.
- @param PaletteInfo PaletteInfo which stores the color of the output
- pixels. First entry corresponds to color 0 and
- second one to color 1.
-
-
-**/
-VOID
-Output1bitPixel (
- IN OUT EFI_IMAGE_INPUT *Image,
- IN UINT8 *Data,
- IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
- )
-{
- UINT16 Xpos;
- UINT16 Ypos;
- UINTN OffsetY;
- UINT8 Index;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[2];
- EFI_HII_IMAGE_PALETTE_INFO *Palette;
- UINTN PaletteSize;
- UINT8 Byte;
-
- ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
-
- BitMapPtr = Image->Bitmap;
-
- //
- // First entry corresponds to color 0 and second entry corresponds to color 1.
- //
- PaletteSize = 0;
- CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
- PaletteSize += sizeof (UINT16);
- Palette = AllocateZeroPool (PaletteSize);
- ASSERT (Palette != NULL);
- if (Palette == NULL) {
- return;
- }
-
- CopyMem (Palette, PaletteInfo, PaletteSize);
-
- ZeroMem (PaletteValue, sizeof (PaletteValue));
- CopyRgbToGopPixel (&PaletteValue[0], &Palette->PaletteValue[0], 1);
- CopyRgbToGopPixel (&PaletteValue[1], &Palette->PaletteValue[1], 1);
- FreePool (Palette);
-
- //
- // Convert the pixel from one bit to corresponding color.
- //
- for (Ypos = 0; Ypos < Image->Height; Ypos++) {
- OffsetY = BITMAP_LEN_1_BIT (Image->Width, Ypos);
- //
- // All bits in these bytes are meaningful
- //
- for (Xpos = 0; Xpos < Image->Width / 8; Xpos++) {
- Byte = *(Data + OffsetY + Xpos);
- for (Index = 0; Index < 8; Index++) {
- if ((Byte & (1 << Index)) != 0) {
- BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[1];
- } else {
- BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[0];
- }
- }
- }
-
- if (Image->Width % 8 != 0) {
- //
- // Padding bits in this byte should be ignored.
- //
- Byte = *(Data + OffsetY + Xpos);
- for (Index = 0; Index < Image->Width % 8; Index++) {
- if ((Byte & (1 << (8 - Index - 1))) != 0) {
- BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[1];
- } else {
- BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[0];
- }
- }
- }
- }
-}
-
-/**
- Output pixels in "4 bit per pixel" format to an image.
-
- This is a internal function.
-
-
- @param Image Points to the image which will store the pixels.
- @param Data Stores the value of output pixels, 0 ~ 15.
- @param[in] PaletteInfo PaletteInfo which stores the color of the output
- pixels. Each entry corresponds to a color within
- [0, 15].
-
-
-**/
-VOID
-Output4bitPixel (
- IN OUT EFI_IMAGE_INPUT *Image,
- IN UINT8 *Data,
- IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
- )
-{
- UINT16 Xpos;
- UINT16 Ypos;
- UINTN OffsetY;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[16];
- EFI_HII_IMAGE_PALETTE_INFO *Palette;
- UINTN PaletteSize;
- UINT16 PaletteNum;
- UINT8 Byte;
-
- ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
-
- BitMapPtr = Image->Bitmap;
-
- //
- // The bitmap should allocate each color index starting from 0.
- //
- PaletteSize = 0;
- CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
- PaletteSize += sizeof (UINT16);
- Palette = AllocateZeroPool (PaletteSize);
- ASSERT (Palette != NULL);
- if (Palette == NULL) {
- return;
- }
-
- CopyMem (Palette, PaletteInfo, PaletteSize);
- PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));
-
- ZeroMem (PaletteValue, sizeof (PaletteValue));
- CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, MIN (PaletteNum, ARRAY_SIZE (PaletteValue)));
- FreePool (Palette);
-
- //
- // Convert the pixel from 4 bit to corresponding color.
- //
- for (Ypos = 0; Ypos < Image->Height; Ypos++) {
- OffsetY = BITMAP_LEN_4_BIT (Image->Width, Ypos);
- //
- // All bits in these bytes are meaningful
- //
- for (Xpos = 0; Xpos < Image->Width / 2; Xpos++) {
- Byte = *(Data + OffsetY + Xpos);
- BitMapPtr[Ypos * Image->Width + Xpos * 2] = PaletteValue[Byte >> 4];
- BitMapPtr[Ypos * Image->Width + Xpos * 2 + 1] = PaletteValue[Byte & 0x0F];
- }
-
- if (Image->Width % 2 != 0) {
- //
- // Padding bits in this byte should be ignored.
- //
- Byte = *(Data + OffsetY + Xpos);
- BitMapPtr[Ypos * Image->Width + Xpos * 2] = PaletteValue[Byte >> 4];
- }
- }
-}
-
-/**
- Output pixels in "8 bit per pixel" format to an image.
-
- This is a internal function.
-
-
- @param Image Points to the image which will store the pixels.
- @param Data Stores the value of output pixels, 0 ~ 255.
- @param[in] PaletteInfo PaletteInfo which stores the color of the output
- pixels. Each entry corresponds to a color within
- [0, 255].
-
-
-**/
-VOID
-Output8bitPixel (
- IN OUT EFI_IMAGE_INPUT *Image,
- IN UINT8 *Data,
- IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
- )
-{
- UINT16 Xpos;
- UINT16 Ypos;
- UINTN OffsetY;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[256];
- EFI_HII_IMAGE_PALETTE_INFO *Palette;
- UINTN PaletteSize;
- UINT16 PaletteNum;
- UINT8 Byte;
-
- ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
-
- BitMapPtr = Image->Bitmap;
-
- //
- // The bitmap should allocate each color index starting from 0.
- //
- PaletteSize = 0;
- CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
- PaletteSize += sizeof (UINT16);
- Palette = AllocateZeroPool (PaletteSize);
- ASSERT (Palette != NULL);
- if (Palette == NULL) {
- return;
- }
-
- CopyMem (Palette, PaletteInfo, PaletteSize);
- PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));
- ZeroMem (PaletteValue, sizeof (PaletteValue));
- CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, MIN (PaletteNum, ARRAY_SIZE (PaletteValue)));
- FreePool (Palette);
-
- //
- // Convert the pixel from 8 bits to corresponding color.
- //
- for (Ypos = 0; Ypos < Image->Height; Ypos++) {
- OffsetY = BITMAP_LEN_8_BIT ((UINT32)Image->Width, Ypos);
- //
- // All bits are meaningful since the bitmap is 8 bits per pixel.
- //
- for (Xpos = 0; Xpos < Image->Width; Xpos++) {
- Byte = *(Data + OffsetY + Xpos);
- BitMapPtr[OffsetY + Xpos] = PaletteValue[Byte];
- }
- }
-}
-
-/**
- Output pixels in "24 bit per pixel" format to an image.
-
- This is a internal function.
-
-
- @param Image Points to the image which will store the pixels.
- @param Data Stores the color of output pixels, allowing 16.8
- millions colors.
-
-
-**/
-VOID
-Output24bitPixel (
- IN OUT EFI_IMAGE_INPUT *Image,
- IN EFI_HII_RGB_PIXEL *Data
- )
-{
- UINT16 Ypos;
- UINTN OffsetY;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
-
- ASSERT (Image != NULL && Data != NULL);
-
- BitMapPtr = Image->Bitmap;
-
- for (Ypos = 0; Ypos < Image->Height; Ypos++) {
- OffsetY = BITMAP_LEN_8_BIT ((UINT32)Image->Width, Ypos);
- CopyRgbToGopPixel (&BitMapPtr[OffsetY], &Data[OffsetY], Image->Width);
- }
-}
-
-/**
- Convert the image from EFI_IMAGE_INPUT to EFI_IMAGE_OUTPUT format.
-
- This is a internal function.
-
-
- @param BltBuffer Buffer points to bitmap data of incoming image.
- @param BltX Specifies the offset from the left and top edge of
- the output image of the first pixel in the image.
- @param BltY Specifies the offset from the left and top edge of
- the output image of the first pixel in the image.
- @param Width Width of the incoming image, in pixels.
- @param Height Height of the incoming image, in pixels.
- @param Transparent If TRUE, all "off" pixels in the image will be
- drawn using the pixel value from blt and all other
- pixels will be copied.
- @param Blt Buffer points to bitmap data of output image.
-
- @retval EFI_SUCCESS The image was successfully converted.
- @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
-
-**/
-EFI_STATUS
-ImageToBlt (
- IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
- IN UINTN BltX,
- IN UINTN BltY,
- IN UINTN Width,
- IN UINTN Height,
- IN BOOLEAN Transparent,
- IN OUT EFI_IMAGE_OUTPUT **Blt
- )
-{
- EFI_IMAGE_OUTPUT *ImageOut;
- UINTN Xpos;
- UINTN Ypos;
- UINTN OffsetY1; // src buffer
- UINTN OffsetY2; // dest buffer
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL SrcPixel;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL ZeroPixel;
-
- if ((BltBuffer == NULL) || (Blt == NULL) || (*Blt == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- ImageOut = *Blt;
-
- if (Width + BltX > ImageOut->Width) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Height + BltY > ImageOut->Height) {
- return EFI_INVALID_PARAMETER;
- }
-
- ZeroMem (&ZeroPixel, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
-
- for (Ypos = 0; Ypos < Height; Ypos++) {
- OffsetY1 = Width * Ypos;
- OffsetY2 = ImageOut->Width * (BltY + Ypos);
- for (Xpos = 0; Xpos < Width; Xpos++) {
- SrcPixel = BltBuffer[OffsetY1 + Xpos];
- if (Transparent) {
- if (CompareMem (&SrcPixel, &ZeroPixel, 3) != 0) {
- ImageOut->Image.Bitmap[OffsetY2 + BltX + Xpos] = SrcPixel;
- }
- } else {
- ImageOut->Image.Bitmap[OffsetY2 + BltX + Xpos] = SrcPixel;
- }
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Return the HII package list identified by PackageList HII handle.
-
- @param Database Pointer to HII database list header.
- @param PackageList HII handle of the package list to locate.
-
- @retval The HII package list instance.
-**/
-HII_DATABASE_PACKAGE_LIST_INSTANCE *
-LocatePackageList (
- IN LIST_ENTRY *Database,
- IN EFI_HII_HANDLE PackageList
- )
-{
- LIST_ENTRY *Link;
- HII_DATABASE_RECORD *Record;
-
- //
- // Get the specified package list and image package.
- //
- for (Link = GetFirstNode (Database);
- !IsNull (Database, Link);
- Link = GetNextNode (Database, Link)
- )
- {
- Record = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- if (Record->Handle == PackageList) {
- return Record->PackageList;
- }
- }
-
- return NULL;
-}
-
-/**
- This function adds the image Image to the group of images owned by PackageList, and returns
- a new image identifier (ImageId).
-
- @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
- @param PackageList Handle of the package list where this image will
- be added.
- @param ImageId On return, contains the new image id, which is
- unique within PackageList.
- @param Image Points to the image.
-
- @retval EFI_SUCCESS The new image was added successfully.
- @retval EFI_NOT_FOUND The specified PackageList could not be found in
- database.
- @retval EFI_OUT_OF_RESOURCES Could not add the image due to lack of resources.
- @retval EFI_INVALID_PARAMETER Image is NULL or ImageId is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiNewImage (
- IN CONST EFI_HII_IMAGE_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- OUT EFI_IMAGE_ID *ImageId,
- IN CONST EFI_IMAGE_INPUT *Image
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
- HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
- EFI_HII_IMAGE_BLOCK *ImageBlocks;
- UINT32 NewBlockSize;
-
- if ((This == NULL) || (ImageId == NULL) || (Image == NULL) || (Image->Bitmap == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- PackageListNode = LocatePackageList (&Private->DatabaseList, PackageList);
- if (PackageListNode == NULL) {
- return EFI_NOT_FOUND;
- }
-
- EfiAcquireLock (&mHiiDatabaseLock);
-
- //
- // Calcuate the size of new image.
- // Make sure the size doesn't overflow UINT32.
- // Note: 24Bit BMP occpuies 3 bytes per pixel.
- //
- NewBlockSize = (UINT32)Image->Width * Image->Height;
- if (NewBlockSize > (MAX_UINT32 - (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))) / 3) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return EFI_OUT_OF_RESOURCES;
- }
-
- NewBlockSize = NewBlockSize * 3 + (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL));
-
- //
- // Get the image package in the package list,
- // or create a new image package if image package does not exist.
- //
- if (PackageListNode->ImagePkg != NULL) {
- ImagePackage = PackageListNode->ImagePkg;
-
- //
- // Output the image id of the incoming image being inserted, which is the
- // image id of the EFI_HII_IIBT_END block of old image package.
- //
- *ImageId = 0;
- GetImageIdOrAddress (ImagePackage->ImageBlock, ImageId);
-
- //
- // Update the package's image block by appending the new block to the end.
- //
-
- //
- // Make sure the final package length doesn't overflow.
- // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
- //
- if (NewBlockSize > MAX_UINT24 - ImagePackage->ImagePkgHdr.Header.Length) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Because ImagePackage->ImageBlockSize < ImagePackage->ImagePkgHdr.Header.Length,
- // So (ImagePackage->ImageBlockSize + NewBlockSize) <= MAX_UINT24
- //
- ImageBlocks = AllocatePool (ImagePackage->ImageBlockSize + NewBlockSize);
- if (ImageBlocks == NULL) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Copy the original content.
- //
- CopyMem (
- ImageBlocks,
- ImagePackage->ImageBlock,
- ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)
- );
- FreePool (ImagePackage->ImageBlock);
- ImagePackage->ImageBlock = ImageBlocks;
-
- //
- // Point to the very last block.
- //
- ImageBlocks = (EFI_HII_IMAGE_BLOCK *)(
- (UINT8 *)ImageBlocks + ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)
- );
- //
- // Update the length record.
- //
- ImagePackage->ImageBlockSize += NewBlockSize;
- ImagePackage->ImagePkgHdr.Header.Length += NewBlockSize;
- PackageListNode->PackageListHdr.PackageLength += NewBlockSize;
- } else {
- //
- // Make sure the final package length doesn't overflow.
- // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
- //
- if (NewBlockSize > MAX_UINT24 - (sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + sizeof (EFI_HII_IIBT_END_BLOCK))) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // The specified package list does not contain image package.
- // Create one to add this image block.
- //
- ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));
- if (ImagePackage == NULL) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Output the image id of the incoming image being inserted, which is the
- // first image block so that id is initially to one.
- //
- *ImageId = 1;
- //
- // Fill in image package header.
- //
- ImagePackage->ImagePkgHdr.Header.Length = sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK);
- ImagePackage->ImagePkgHdr.Header.Type = EFI_HII_PACKAGE_IMAGES;
- ImagePackage->ImagePkgHdr.ImageInfoOffset = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
- ImagePackage->ImagePkgHdr.PaletteInfoOffset = 0;
-
- //
- // Fill in palette info.
- //
- ImagePackage->PaletteBlock = NULL;
- ImagePackage->PaletteInfoSize = 0;
-
- //
- // Fill in image blocks.
- //
- ImagePackage->ImageBlockSize = NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK);
- ImagePackage->ImageBlock = AllocateZeroPool (NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK));
- if (ImagePackage->ImageBlock == NULL) {
- FreePool (ImagePackage);
- EfiReleaseLock (&mHiiDatabaseLock);
- return EFI_OUT_OF_RESOURCES;
- }
-
- ImageBlocks = ImagePackage->ImageBlock;
-
- //
- // Insert this image package.
- //
- PackageListNode->ImagePkg = ImagePackage;
- PackageListNode->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;
- }
-
- //
- // Append the new block here
- //
- if (Image->Flags == EFI_IMAGE_TRANSPARENT) {
- ImageBlocks->BlockType = EFI_HII_IIBT_IMAGE_24BIT_TRANS;
- } else {
- ImageBlocks->BlockType = EFI_HII_IIBT_IMAGE_24BIT;
- }
-
- WriteUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)ImageBlocks)->Bitmap.Width, Image->Width);
- WriteUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)ImageBlocks)->Bitmap.Height, Image->Height);
- CopyGopToRgbPixel (((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)ImageBlocks)->Bitmap.Bitmap, Image->Bitmap, (UINT32)Image->Width * Image->Height);
-
- //
- // Append the block end
- //
- ImageBlocks = (EFI_HII_IMAGE_BLOCK *)((UINT8 *)ImageBlocks + NewBlockSize);
- ImageBlocks->BlockType = EFI_HII_IIBT_END;
-
- //
- // Check whether need to get the contents of HiiDataBase.
- // Only after ReadyToBoot to do the export.
- //
- if (gExportAfterReadyToBoot) {
- HiiGetDatabaseInfo (&Private->HiiDatabase);
- }
-
- EfiReleaseLock (&mHiiDatabaseLock);
-
- return EFI_SUCCESS;
-}
-
-/**
- This function retrieves the image specified by ImageId which is associated with
- the specified PackageList and copies it into the buffer specified by Image.
-
- @param Database A pointer to the database list header.
- @param PackageList Handle of the package list where this image will
- be searched.
- @param ImageId The image's id,, which is unique within
- PackageList.
- @param Image Points to the image.
- @param BitmapOnly TRUE to only return the bitmap type image.
- FALSE to locate image decoder instance to decode image.
-
- @retval EFI_SUCCESS The new image was returned successfully.
- @retval EFI_NOT_FOUND The image specified by ImageId is not in the
- database. The specified PackageList is not in the database.
- @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
- hold the image.
- @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.
- @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not
- enough memory.
-**/
-EFI_STATUS
-IGetImage (
- IN LIST_ENTRY *Database,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_IMAGE_ID ImageId,
- OUT EFI_IMAGE_INPUT *Image,
- IN BOOLEAN BitmapOnly
- )
-{
- EFI_STATUS Status;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
- HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
- EFI_HII_IMAGE_BLOCK *CurrentImageBlock;
- EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit;
- UINT16 Width;
- UINT16 Height;
- UINTN ImageLength;
- UINT8 *PaletteInfo;
- UINT8 PaletteIndex;
- UINT16 PaletteSize;
- EFI_HII_IMAGE_DECODER_PROTOCOL *Decoder;
- EFI_IMAGE_OUTPUT *ImageOut;
-
- if ((Image == NULL) || (ImageId == 0)) {
- return EFI_INVALID_PARAMETER;
- }
-
- PackageListNode = LocatePackageList (Database, PackageList);
- if (PackageListNode == NULL) {
- return EFI_NOT_FOUND;
- }
-
- ImagePackage = PackageListNode->ImagePkg;
- if (ImagePackage == NULL) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Find the image block specified by ImageId
- //
- CurrentImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &ImageId);
- if (CurrentImageBlock == NULL) {
- return EFI_NOT_FOUND;
- }
-
- Image->Flags = 0;
- switch (CurrentImageBlock->BlockType) {
- case EFI_HII_IIBT_IMAGE_JPEG:
- case EFI_HII_IIBT_IMAGE_PNG:
- if (BitmapOnly) {
- return EFI_UNSUPPORTED;
- }
-
- ImageOut = NULL;
- Decoder = LocateHiiImageDecoder (CurrentImageBlock->BlockType);
- if (Decoder == NULL) {
- return EFI_UNSUPPORTED;
- }
-
- //
- // Use the common block code since the definition of two structures is the same.
- //
- ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Data) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Data));
- ASSERT (
- sizeof (((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Data) ==
- sizeof (((EFI_HII_IIBT_PNG_BLOCK *)CurrentImageBlock)->Data)
- );
- ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Size) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Size));
- ASSERT (
- sizeof (((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Size) ==
- sizeof (((EFI_HII_IIBT_PNG_BLOCK *)CurrentImageBlock)->Size)
- );
- Status = Decoder->DecodeImage (
- Decoder,
- ((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Data,
- ((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Size,
- &ImageOut,
- FALSE
- );
-
- //
- // Spec requires to use the first capable image decoder instance.
- // The first image decoder instance may fail to decode the image.
- //
- if (!EFI_ERROR (Status)) {
- Image->Bitmap = ImageOut->Image.Bitmap;
- Image->Height = ImageOut->Height;
- Image->Width = ImageOut->Width;
- FreePool (ImageOut);
- }
-
- return Status;
-
- case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
- case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
- case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
- Image->Flags = EFI_IMAGE_TRANSPARENT;
- //
- // fall through
- //
- case EFI_HII_IIBT_IMAGE_1BIT:
- case EFI_HII_IIBT_IMAGE_4BIT:
- case EFI_HII_IIBT_IMAGE_8BIT:
- //
- // Use the common block code since the definition of these structures is the same.
- //
- CopyMem (&Iibt1bit, CurrentImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));
- ImageLength = (UINTN)Iibt1bit.Bitmap.Width * Iibt1bit.Bitmap.Height;
- if (ImageLength > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- ImageLength *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
- Image->Bitmap = AllocateZeroPool (ImageLength);
- if (Image->Bitmap == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Image->Width = Iibt1bit.Bitmap.Width;
- Image->Height = Iibt1bit.Bitmap.Height;
-
- PaletteInfo = ImagePackage->PaletteBlock + sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);
- for (PaletteIndex = 1; PaletteIndex < Iibt1bit.PaletteIndex; PaletteIndex++) {
- CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
- PaletteInfo += PaletteSize + sizeof (UINT16);
- }
-
- ASSERT (PaletteIndex == Iibt1bit.PaletteIndex);
-
- //
- // Output bitmap data
- //
- if ((CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_1BIT) ||
- (CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_1BIT_TRANS))
- {
- Output1bitPixel (
- Image,
- ((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *)CurrentImageBlock)->Bitmap.Data,
- (EFI_HII_IMAGE_PALETTE_INFO *)PaletteInfo
- );
- } else if ((CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_4BIT) ||
- (CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_4BIT_TRANS))
- {
- Output4bitPixel (
- Image,
- ((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *)CurrentImageBlock)->Bitmap.Data,
- (EFI_HII_IMAGE_PALETTE_INFO *)PaletteInfo
- );
- } else {
- Output8bitPixel (
- Image,
- ((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *)CurrentImageBlock)->Bitmap.Data,
- (EFI_HII_IMAGE_PALETTE_INFO *)PaletteInfo
- );
- }
-
- return EFI_SUCCESS;
-
- case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
- Image->Flags = EFI_IMAGE_TRANSPARENT;
- //
- // fall through
- //
- case EFI_HII_IIBT_IMAGE_24BIT:
- Width = ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width);
- Height = ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height);
- ImageLength = (UINTN)Width * Height;
- if (ImageLength > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- ImageLength *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
- Image->Bitmap = AllocateZeroPool (ImageLength);
- if (Image->Bitmap == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Image->Width = Width;
- Image->Height = Height;
-
- //
- // Output the bitmap data directly.
- //
- Output24bitPixel (
- Image,
- ((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Bitmap
- );
- return EFI_SUCCESS;
-
- default:
- return EFI_NOT_FOUND;
- }
-}
-
-/**
- This function retrieves the image specified by ImageId which is associated with
- the specified PackageList and copies it into the buffer specified by Image.
-
- @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
- @param PackageList Handle of the package list where this image will
- be searched.
- @param ImageId The image's id,, which is unique within
- PackageList.
- @param Image Points to the image.
-
- @retval EFI_SUCCESS The new image was returned successfully.
- @retval EFI_NOT_FOUND The image specified by ImageId is not in the
- database. The specified PackageList is not in the database.
- @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
- hold the image.
- @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.
- @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not
- enough memory.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetImage (
- IN CONST EFI_HII_IMAGE_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_IMAGE_ID ImageId,
- OUT EFI_IMAGE_INPUT *Image
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
-
- Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- return IGetImage (&Private->DatabaseList, PackageList, ImageId, Image, TRUE);
-}
-
-/**
- This function updates the image specified by ImageId in the specified PackageListHandle to
- the image specified by Image.
-
- @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
- @param PackageList The package list containing the images.
- @param ImageId The image's id,, which is unique within
- PackageList.
- @param Image Points to the image.
-
- @retval EFI_SUCCESS The new image was updated successfully.
- @retval EFI_NOT_FOUND The image specified by ImageId is not in the
- database. The specified PackageList is not in the database.
- @retval EFI_INVALID_PARAMETER The Image was NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiSetImage (
- IN CONST EFI_HII_IMAGE_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_IMAGE_ID ImageId,
- IN CONST EFI_IMAGE_INPUT *Image
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
- HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
- EFI_HII_IMAGE_BLOCK *CurrentImageBlock;
- EFI_HII_IMAGE_BLOCK *ImageBlocks;
- EFI_HII_IMAGE_BLOCK *NewImageBlock;
- UINT32 NewBlockSize;
- UINT32 OldBlockSize;
- UINT32 Part1Size;
- UINT32 Part2Size;
-
- if ((This == NULL) || (Image == NULL) || (ImageId == 0) || (Image->Bitmap == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- PackageListNode = LocatePackageList (&Private->DatabaseList, PackageList);
- if (PackageListNode == NULL) {
- return EFI_NOT_FOUND;
- }
-
- ImagePackage = PackageListNode->ImagePkg;
- if (ImagePackage == NULL) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Find the image block specified by ImageId
- //
- CurrentImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &ImageId);
- if (CurrentImageBlock == NULL) {
- return EFI_NOT_FOUND;
- }
-
- EfiAcquireLock (&mHiiDatabaseLock);
-
- //
- // Get the size of original image block. Use some common block code here
- // since the definition of some structures is the same.
- //
- switch (CurrentImageBlock->BlockType) {
- case EFI_HII_IIBT_IMAGE_JPEG:
- OldBlockSize = OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Data) + ReadUnaligned32 ((VOID *)&((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Size);
- break;
- case EFI_HII_IIBT_IMAGE_PNG:
- OldBlockSize = OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Data) + ReadUnaligned32 ((VOID *)&((EFI_HII_IIBT_PNG_BLOCK *)CurrentImageBlock)->Size);
- break;
- case EFI_HII_IIBT_IMAGE_1BIT:
- case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
- OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +
- BITMAP_LEN_1_BIT (
- ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width),
- ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height)
- );
- break;
- case EFI_HII_IIBT_IMAGE_4BIT:
- case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
- OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +
- BITMAP_LEN_4_BIT (
- ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width),
- ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height)
- );
- break;
- case EFI_HII_IIBT_IMAGE_8BIT:
- case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
- OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +
- BITMAP_LEN_8_BIT (
- (UINT32)ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width),
- ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height)
- );
- break;
- case EFI_HII_IIBT_IMAGE_24BIT:
- case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
- OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
- BITMAP_LEN_24_BIT (
- (UINT32)ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width),
- ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height)
- );
- break;
- default:
- EfiReleaseLock (&mHiiDatabaseLock);
- return EFI_NOT_FOUND;
- }
-
- //
- // Create the new image block according to input image.
- //
-
- //
- // Make sure the final package length doesn't overflow.
- // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
- // 24Bit BMP occpuies 3 bytes per pixel.
- //
- NewBlockSize = (UINT32)Image->Width * Image->Height;
- if (NewBlockSize > (MAX_UINT32 - (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))) / 3) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return EFI_OUT_OF_RESOURCES;
- }
-
- NewBlockSize = NewBlockSize * 3 + (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL));
- if ((NewBlockSize > OldBlockSize) &&
- (NewBlockSize - OldBlockSize > MAX_UINT24 - ImagePackage->ImagePkgHdr.Header.Length)
- )
- {
- EfiReleaseLock (&mHiiDatabaseLock);
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Adjust the image package to remove the original block firstly then add the new block.
- //
- ImageBlocks = AllocateZeroPool (ImagePackage->ImageBlockSize + NewBlockSize - OldBlockSize);
- if (ImageBlocks == NULL) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return EFI_OUT_OF_RESOURCES;
- }
-
- Part1Size = (UINT32)((UINTN)CurrentImageBlock - (UINTN)ImagePackage->ImageBlock);
- Part2Size = ImagePackage->ImageBlockSize - Part1Size - OldBlockSize;
- CopyMem (ImageBlocks, ImagePackage->ImageBlock, Part1Size);
-
- //
- // Set the new image block
- //
- NewImageBlock = (EFI_HII_IMAGE_BLOCK *)((UINT8 *)ImageBlocks + Part1Size);
- if ((Image->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {
- NewImageBlock->BlockType = EFI_HII_IIBT_IMAGE_24BIT_TRANS;
- } else {
- NewImageBlock->BlockType = EFI_HII_IIBT_IMAGE_24BIT;
- }
-
- WriteUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)NewImageBlock)->Bitmap.Width, Image->Width);
- WriteUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)NewImageBlock)->Bitmap.Height, Image->Height);
- CopyGopToRgbPixel (
- ((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)NewImageBlock)->Bitmap.Bitmap,
- Image->Bitmap,
- (UINT32)Image->Width * Image->Height
- );
-
- CopyMem ((UINT8 *)NewImageBlock + NewBlockSize, (UINT8 *)CurrentImageBlock + OldBlockSize, Part2Size);
-
- FreePool (ImagePackage->ImageBlock);
- ImagePackage->ImageBlock = ImageBlocks;
- ImagePackage->ImageBlockSize += NewBlockSize - OldBlockSize;
- ImagePackage->ImagePkgHdr.Header.Length += NewBlockSize - OldBlockSize;
- PackageListNode->PackageListHdr.PackageLength += NewBlockSize - OldBlockSize;
-
- //
- // Check whether need to get the contents of HiiDataBase.
- // Only after ReadyToBoot to do the export.
- //
- if (gExportAfterReadyToBoot) {
- HiiGetDatabaseInfo (&Private->HiiDatabase);
- }
-
- EfiReleaseLock (&mHiiDatabaseLock);
- return EFI_SUCCESS;
-}
-
-/**
- This function renders an image to a bitmap or the screen using the specified
- color and options. It draws the image on an existing bitmap, allocates a new
- bitmap or uses the screen. The images can be clipped.
-
- @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
- @param Flags Describes how the image is to be drawn.
- @param Image Points to the image to be displayed.
- @param Blt If this points to a non-NULL on entry, this points
- to the image, which is Width pixels wide and
- Height pixels high. The image will be drawn onto
- this image and EFI_HII_DRAW_FLAG_CLIP is implied.
- If this points to a NULL on entry, then a buffer
- will be allocated to hold the generated image and
- the pointer updated on exit. It is the caller's
- responsibility to free this buffer.
- @param BltX Specifies the offset from the left and top edge of
- the output image of the first pixel in the image.
- @param BltY Specifies the offset from the left and top edge of
- the output image of the first pixel in the image.
-
- @retval EFI_SUCCESS The image was successfully drawn.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
- @retval EFI_INVALID_PARAMETER The Image or Blt was NULL.
- @retval EFI_INVALID_PARAMETER Any combination of Flags is invalid.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiDrawImage (
- IN CONST EFI_HII_IMAGE_PROTOCOL *This,
- IN EFI_HII_DRAW_FLAGS Flags,
- IN CONST EFI_IMAGE_INPUT *Image,
- IN OUT EFI_IMAGE_OUTPUT **Blt,
- IN UINTN BltX,
- IN UINTN BltY
- )
-{
- EFI_STATUS Status;
- HII_DATABASE_PRIVATE_DATA *Private;
- BOOLEAN Transparent;
- EFI_IMAGE_OUTPUT *ImageOut;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
- UINTN BufferLen;
- UINT16 Width;
- UINT16 Height;
- UINTN Xpos;
- UINTN Ypos;
- UINTN OffsetY1;
- UINTN OffsetY2;
- EFI_FONT_DISPLAY_INFO *FontInfo;
- UINTN Index;
-
- if ((This == NULL) || (Image == NULL) || (Blt == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (((Flags & EFI_HII_DRAW_FLAG_CLIP) == EFI_HII_DRAW_FLAG_CLIP) && (*Blt == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_TRANSPARENT) {
- return EFI_INVALID_PARAMETER;
- }
-
- FontInfo = NULL;
-
- //
- // Check whether the image will be drawn transparently or opaquely.
- //
- Transparent = FALSE;
- if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_TRANS) {
- Transparent = TRUE;
- } else if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_OPAQUE) {
- Transparent = FALSE;
- } else {
- //
- // Now EFI_HII_DRAW_FLAG_DEFAULT is set, whether image will be drawn depending
- // on the image's transparency setting.
- //
- if ((Image->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {
- Transparent = TRUE;
- }
- }
-
- //
- // Image cannot be drawn transparently if Blt points to NULL on entry.
- // Currently output to Screen transparently is not supported, either.
- //
- if (Transparent) {
- if (*Blt == NULL) {
- return EFI_INVALID_PARAMETER;
- } else if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
- return EFI_INVALID_PARAMETER;
- }
- }
-
- Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
-
- //
- // When Blt points to a non-NULL on entry, this image will be drawn onto
- // this bitmap or screen pointed by "*Blt" and EFI_HII_DRAW_FLAG_CLIP is implied.
- // Otherwise a new bitmap will be allocated to hold this image.
- //
- if (*Blt != NULL) {
- //
- // Make sure the BltX and BltY is inside the Blt area.
- //
- if ((BltX >= (*Blt)->Width) || (BltY >= (*Blt)->Height)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Clip the image by (Width, Height)
- //
-
- Width = Image->Width;
- Height = Image->Height;
-
- if (Width > (*Blt)->Width - (UINT16)BltX) {
- Width = (*Blt)->Width - (UINT16)BltX;
- }
-
- if (Height > (*Blt)->Height - (UINT16)BltY) {
- Height = (*Blt)->Height - (UINT16)BltY;
- }
-
- //
- // Prepare the buffer for the temporary image.
- // Make sure the buffer size doesn't overflow UINTN.
- //
- BufferLen = Width * Height;
- if (BufferLen > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- BufferLen *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
- BltBuffer = AllocateZeroPool (BufferLen);
- if (BltBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- if ((Width == Image->Width) && (Height == Image->Height)) {
- CopyMem (BltBuffer, Image->Bitmap, BufferLen);
- } else {
- for (Ypos = 0; Ypos < Height; Ypos++) {
- OffsetY1 = Image->Width * Ypos;
- OffsetY2 = Width * Ypos;
- for (Xpos = 0; Xpos < Width; Xpos++) {
- BltBuffer[OffsetY2 + Xpos] = Image->Bitmap[OffsetY1 + Xpos];
- }
- }
- }
-
- //
- // Draw the image to existing bitmap or screen depending on flag.
- //
- if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
- //
- // Caller should make sure the current UGA console is grarphic mode.
- //
-
- //
- // Write the image directly to the output device specified by Screen.
- //
- Status = (*Blt)->Image.Screen->Blt (
- (*Blt)->Image.Screen,
- BltBuffer,
- EfiBltBufferToVideo,
- 0,
- 0,
- BltX,
- BltY,
- Width,
- Height,
- 0
- );
- } else {
- //
- // Draw the image onto the existing bitmap specified by Bitmap.
- //
- Status = ImageToBlt (
- BltBuffer,
- BltX,
- BltY,
- Width,
- Height,
- Transparent,
- Blt
- );
- }
-
- FreePool (BltBuffer);
- return Status;
- } else {
- //
- // Allocate a new bitmap to hold the incoming image.
- //
-
- //
- // Make sure the final width and height doesn't overflow UINT16.
- //
- if ((BltX > (UINTN)MAX_UINT16 - Image->Width) || (BltY > (UINTN)MAX_UINT16 - Image->Height)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Width = Image->Width + (UINT16)BltX;
- Height = Image->Height + (UINT16)BltY;
-
- //
- // Make sure the output image size doesn't overflow UINTN.
- //
- BufferLen = Width * Height;
- if (BufferLen > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- BufferLen *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
- BltBuffer = AllocateZeroPool (BufferLen);
- if (BltBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- ImageOut = (EFI_IMAGE_OUTPUT *)AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
- if (ImageOut == NULL) {
- FreePool (BltBuffer);
- return EFI_OUT_OF_RESOURCES;
- }
-
- ImageOut->Width = Width;
- ImageOut->Height = Height;
- ImageOut->Image.Bitmap = BltBuffer;
-
- //
- // BUGBUG: Now all the "blank" pixels are filled with system default background
- // color. Not sure if it need to be updated or not.
- //
- Status = GetSystemFont (Private, &FontInfo, NULL);
- if (EFI_ERROR (Status)) {
- FreePool (BltBuffer);
- FreePool (ImageOut);
- return Status;
- }
-
- ASSERT (FontInfo != NULL);
- for (Index = 0; Index < (UINTN)Width * Height; Index++) {
- BltBuffer[Index] = FontInfo->BackgroundColor;
- }
-
- FreePool (FontInfo);
-
- //
- // Draw the incoming image to the new created image.
- //
- *Blt = ImageOut;
- return ImageToBlt (
- Image->Bitmap,
- BltX,
- BltY,
- Image->Width,
- Image->Height,
- Transparent,
- Blt
- );
- }
-}
-
-/**
- This function renders an image to a bitmap or the screen using the specified
- color and options. It draws the image on an existing bitmap, allocates a new
- bitmap or uses the screen. The images can be clipped.
-
- @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
- @param Flags Describes how the image is to be drawn.
- @param PackageList The package list in the HII database to search for
- the specified image.
- @param ImageId The image's id, which is unique within
- PackageList.
- @param Blt If this points to a non-NULL on entry, this points
- to the image, which is Width pixels wide and
- Height pixels high. The image will be drawn onto
- this image and
- EFI_HII_DRAW_FLAG_CLIP is implied. If this points
- to a NULL on entry, then a buffer will be
- allocated to hold the generated image and the
- pointer updated on exit. It is the caller's
- responsibility to free this buffer.
- @param BltX Specifies the offset from the left and top edge of
- the output image of the first pixel in the image.
- @param BltY Specifies the offset from the left and top edge of
- the output image of the first pixel in the image.
-
- @retval EFI_SUCCESS The image was successfully drawn.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
- @retval EFI_INVALID_PARAMETER The Blt was NULL.
- @retval EFI_NOT_FOUND The image specified by ImageId is not in the database.
- The specified PackageList is not in the database.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiDrawImageId (
- IN CONST EFI_HII_IMAGE_PROTOCOL *This,
- IN EFI_HII_DRAW_FLAGS Flags,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_IMAGE_ID ImageId,
- IN OUT EFI_IMAGE_OUTPUT **Blt,
- IN UINTN BltX,
- IN UINTN BltY
- )
-{
- EFI_STATUS Status;
- EFI_IMAGE_INPUT Image;
-
- //
- // Check input parameter.
- //
- if ((This == NULL) || (Blt == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Get the specified Image.
- //
- Status = HiiGetImage (This, PackageList, ImageId, &Image);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Draw this image.
- //
- Status = HiiDrawImage (This, Flags, &Image, Blt, BltX, BltY);
- if (Image.Bitmap != NULL) {
- FreePool (Image.Bitmap);
- }
-
- return Status;
-}
+/** @file
+Implementation for EFI_HII_IMAGE_PROTOCOL.
+
+
+Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "HiiDatabase.h"
+
+#define MAX_UINT24 0xFFFFFF
+
+/**
+ Get the imageid of last image block: EFI_HII_IIBT_END_BLOCK when input
+ ImageId is zero, otherwise return the address of the
+ corresponding image block with identifier specified by ImageId.
+
+ This is a internal function.
+
+ @param ImageBlocks Points to the beginning of a series of image blocks stored in order.
+ @param ImageId If input ImageId is 0, output the image id of the EFI_HII_IIBT_END_BLOCK;
+ else use this id to find its corresponding image block address.
+
+ @return The image block address when input ImageId is not zero; otherwise return NULL.
+
+**/
+EFI_HII_IMAGE_BLOCK *
+GetImageIdOrAddress (
+ IN EFI_HII_IMAGE_BLOCK *ImageBlocks,
+ IN OUT EFI_IMAGE_ID *ImageId
+ )
+{
+ EFI_IMAGE_ID ImageIdCurrent;
+ EFI_HII_IMAGE_BLOCK *CurrentImageBlock;
+ UINTN Length;
+
+ ASSERT (ImageBlocks != NULL && ImageId != NULL);
+ CurrentImageBlock = ImageBlocks;
+ ImageIdCurrent = 1;
+
+ while (CurrentImageBlock->BlockType != EFI_HII_IIBT_END) {
+ if (*ImageId != 0) {
+ if (*ImageId == ImageIdCurrent) {
+ //
+ // If the found image block is a duplicate block, update the ImageId to
+ // find the previous defined image block.
+ //
+ if (CurrentImageBlock->BlockType == EFI_HII_IIBT_DUPLICATE) {
+ *ImageId = ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_DUPLICATE_BLOCK *)CurrentImageBlock)->ImageId);
+ ASSERT (*ImageId != ImageIdCurrent);
+ ASSERT (*ImageId != 0);
+ CurrentImageBlock = ImageBlocks;
+ ImageIdCurrent = 1;
+ continue;
+ }
+
+ return CurrentImageBlock;
+ }
+
+ if (*ImageId < ImageIdCurrent) {
+ //
+ // Can not find the specified image block in this image.
+ //
+ return NULL;
+ }
+ }
+
+ switch (CurrentImageBlock->BlockType) {
+ case EFI_HII_IIBT_EXT1:
+ Length = ((EFI_HII_IIBT_EXT1_BLOCK *)CurrentImageBlock)->Length;
+ break;
+ case EFI_HII_IIBT_EXT2:
+ Length = ReadUnaligned16 (&((EFI_HII_IIBT_EXT2_BLOCK *)CurrentImageBlock)->Length);
+ break;
+ case EFI_HII_IIBT_EXT4:
+ Length = ReadUnaligned32 ((VOID *)&((EFI_HII_IIBT_EXT4_BLOCK *)CurrentImageBlock)->Length);
+ break;
+
+ case EFI_HII_IIBT_IMAGE_1BIT:
+ case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
+ Length = sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_1_BIT (
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width),
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height)
+ );
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_4BIT:
+ case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
+ Length = sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_4_BIT (
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width),
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height)
+ );
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_8BIT:
+ case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
+ Length = sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_8_BIT (
+ (UINT32)ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width),
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height)
+ );
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_24BIT:
+ case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
+ Length = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
+ BITMAP_LEN_24_BIT (
+ (UINT32)ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width),
+ ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height)
+ );
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_DUPLICATE:
+ Length = sizeof (EFI_HII_IIBT_DUPLICATE_BLOCK);
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_JPEG:
+ Length = OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Data) + ReadUnaligned32 ((VOID *)&((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Size);
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_PNG:
+ Length = OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Data) + ReadUnaligned32 ((VOID *)&((EFI_HII_IIBT_PNG_BLOCK *)CurrentImageBlock)->Size);
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_SKIP1:
+ Length = sizeof (EFI_HII_IIBT_SKIP1_BLOCK);
+ ImageIdCurrent += ((EFI_HII_IIBT_SKIP1_BLOCK *)CurrentImageBlock)->SkipCount;
+ break;
+
+ case EFI_HII_IIBT_SKIP2:
+ Length = sizeof (EFI_HII_IIBT_SKIP2_BLOCK);
+ ImageIdCurrent += ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_SKIP2_BLOCK *)CurrentImageBlock)->SkipCount);
+ break;
+
+ default:
+ //
+ // Unknown image blocks can not be skipped, processing halts.
+ //
+ ASSERT (FALSE);
+ Length = 0;
+ break;
+ }
+
+ CurrentImageBlock = (EFI_HII_IMAGE_BLOCK *)((UINT8 *)CurrentImageBlock + Length);
+ }
+
+ //
+ // When ImageId is zero, return the imageid of last image block: EFI_HII_IIBT_END_BLOCK.
+ //
+ if (*ImageId == 0) {
+ *ImageId = ImageIdCurrent;
+ return CurrentImageBlock;
+ }
+
+ return NULL;
+}
+
+/**
+ Convert pixels from EFI_GRAPHICS_OUTPUT_BLT_PIXEL to EFI_HII_RGB_PIXEL style.
+
+ This is a internal function.
+
+
+ @param BitMapOut Pixels in EFI_HII_RGB_PIXEL format.
+ @param BitMapIn Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.
+ @param PixelNum The number of pixels to be converted.
+
+
+**/
+VOID
+CopyGopToRgbPixel (
+ OUT EFI_HII_RGB_PIXEL *BitMapOut,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapIn,
+ IN UINTN PixelNum
+ )
+{
+ UINTN Index;
+
+ ASSERT (BitMapOut != NULL && BitMapIn != NULL);
+
+ for (Index = 0; Index < PixelNum; Index++) {
+ CopyMem (BitMapOut + Index, BitMapIn + Index, sizeof (EFI_HII_RGB_PIXEL));
+ }
+}
+
+/**
+ Convert pixels from EFI_HII_RGB_PIXEL to EFI_GRAPHICS_OUTPUT_BLT_PIXEL style.
+
+ This is a internal function.
+
+
+ @param BitMapOut Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.
+ @param BitMapIn Pixels in EFI_HII_RGB_PIXEL format.
+ @param PixelNum The number of pixels to be converted.
+
+
+**/
+VOID
+CopyRgbToGopPixel (
+ OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapOut,
+ IN EFI_HII_RGB_PIXEL *BitMapIn,
+ IN UINTN PixelNum
+ )
+{
+ UINTN Index;
+
+ ASSERT (BitMapOut != NULL && BitMapIn != NULL);
+
+ for (Index = 0; Index < PixelNum; Index++) {
+ CopyMem (BitMapOut + Index, BitMapIn + Index, sizeof (EFI_HII_RGB_PIXEL));
+ }
+}
+
+/**
+ Output pixels in "1 bit per pixel" format to an image.
+
+ This is a internal function.
+
+
+ @param Image Points to the image which will store the pixels.
+ @param Data Stores the value of output pixels, 0 or 1.
+ @param PaletteInfo PaletteInfo which stores the color of the output
+ pixels. First entry corresponds to color 0 and
+ second one to color 1.
+
+
+**/
+VOID
+Output1bitPixel (
+ IN OUT EFI_IMAGE_INPUT *Image,
+ IN UINT8 *Data,
+ IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
+ )
+{
+ UINT16 Xpos;
+ UINT16 Ypos;
+ UINTN OffsetY;
+ UINT8 Index;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[2];
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;
+ UINTN PaletteSize;
+ UINT8 Byte;
+
+ ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
+
+ BitMapPtr = Image->Bitmap;
+
+ //
+ // First entry corresponds to color 0 and second entry corresponds to color 1.
+ //
+ PaletteSize = 0;
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
+ PaletteSize += sizeof (UINT16);
+ Palette = AllocateZeroPool (PaletteSize);
+ ASSERT (Palette != NULL);
+ if (Palette == NULL) {
+ return;
+ }
+
+ CopyMem (Palette, PaletteInfo, PaletteSize);
+
+ ZeroMem (PaletteValue, sizeof (PaletteValue));
+ CopyRgbToGopPixel (&PaletteValue[0], &Palette->PaletteValue[0], 1);
+ CopyRgbToGopPixel (&PaletteValue[1], &Palette->PaletteValue[1], 1);
+ FreePool (Palette);
+
+ //
+ // Convert the pixel from one bit to corresponding color.
+ //
+ for (Ypos = 0; Ypos < Image->Height; Ypos++) {
+ OffsetY = BITMAP_LEN_1_BIT (Image->Width, Ypos);
+ //
+ // All bits in these bytes are meaningful
+ //
+ for (Xpos = 0; Xpos < Image->Width / 8; Xpos++) {
+ Byte = *(Data + OffsetY + Xpos);
+ for (Index = 0; Index < 8; Index++) {
+ if ((Byte & (1 << Index)) != 0) {
+ BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[1];
+ } else {
+ BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[0];
+ }
+ }
+ }
+
+ if (Image->Width % 8 != 0) {
+ //
+ // Padding bits in this byte should be ignored.
+ //
+ Byte = *(Data + OffsetY + Xpos);
+ for (Index = 0; Index < Image->Width % 8; Index++) {
+ if ((Byte & (1 << (8 - Index - 1))) != 0) {
+ BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[1];
+ } else {
+ BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[0];
+ }
+ }
+ }
+ }
+}
+
+/**
+ Output pixels in "4 bit per pixel" format to an image.
+
+ This is a internal function.
+
+
+ @param Image Points to the image which will store the pixels.
+ @param Data Stores the value of output pixels, 0 ~ 15.
+ @param[in] PaletteInfo PaletteInfo which stores the color of the output
+ pixels. Each entry corresponds to a color within
+ [0, 15].
+
+
+**/
+VOID
+Output4bitPixel (
+ IN OUT EFI_IMAGE_INPUT *Image,
+ IN UINT8 *Data,
+ IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
+ )
+{
+ UINT16 Xpos;
+ UINT16 Ypos;
+ UINTN OffsetY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[16];
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;
+ UINTN PaletteSize;
+ UINT16 PaletteNum;
+ UINT8 Byte;
+
+ ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
+
+ BitMapPtr = Image->Bitmap;
+
+ //
+ // The bitmap should allocate each color index starting from 0.
+ //
+ PaletteSize = 0;
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
+ PaletteSize += sizeof (UINT16);
+ Palette = AllocateZeroPool (PaletteSize);
+ ASSERT (Palette != NULL);
+ if (Palette == NULL) {
+ return;
+ }
+
+ CopyMem (Palette, PaletteInfo, PaletteSize);
+ PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));
+
+ ZeroMem (PaletteValue, sizeof (PaletteValue));
+ CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, MIN (PaletteNum, ARRAY_SIZE (PaletteValue)));
+ FreePool (Palette);
+
+ //
+ // Convert the pixel from 4 bit to corresponding color.
+ //
+ for (Ypos = 0; Ypos < Image->Height; Ypos++) {
+ OffsetY = BITMAP_LEN_4_BIT (Image->Width, Ypos);
+ //
+ // All bits in these bytes are meaningful
+ //
+ for (Xpos = 0; Xpos < Image->Width / 2; Xpos++) {
+ Byte = *(Data + OffsetY + Xpos);
+ BitMapPtr[Ypos * Image->Width + Xpos * 2] = PaletteValue[Byte >> 4];
+ BitMapPtr[Ypos * Image->Width + Xpos * 2 + 1] = PaletteValue[Byte & 0x0F];
+ }
+
+ if (Image->Width % 2 != 0) {
+ //
+ // Padding bits in this byte should be ignored.
+ //
+ Byte = *(Data + OffsetY + Xpos);
+ BitMapPtr[Ypos * Image->Width + Xpos * 2] = PaletteValue[Byte >> 4];
+ }
+ }
+}
+
+/**
+ Output pixels in "8 bit per pixel" format to an image.
+
+ This is a internal function.
+
+
+ @param Image Points to the image which will store the pixels.
+ @param Data Stores the value of output pixels, 0 ~ 255.
+ @param[in] PaletteInfo PaletteInfo which stores the color of the output
+ pixels. Each entry corresponds to a color within
+ [0, 255].
+
+
+**/
+VOID
+Output8bitPixel (
+ IN OUT EFI_IMAGE_INPUT *Image,
+ IN UINT8 *Data,
+ IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
+ )
+{
+ UINT16 Xpos;
+ UINT16 Ypos;
+ UINTN OffsetY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[256];
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;
+ UINTN PaletteSize;
+ UINT16 PaletteNum;
+ UINT8 Byte;
+
+ ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
+
+ BitMapPtr = Image->Bitmap;
+
+ //
+ // The bitmap should allocate each color index starting from 0.
+ //
+ PaletteSize = 0;
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
+ PaletteSize += sizeof (UINT16);
+ Palette = AllocateZeroPool (PaletteSize);
+ ASSERT (Palette != NULL);
+ if (Palette == NULL) {
+ return;
+ }
+
+ CopyMem (Palette, PaletteInfo, PaletteSize);
+ PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));
+ ZeroMem (PaletteValue, sizeof (PaletteValue));
+ CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, MIN (PaletteNum, ARRAY_SIZE (PaletteValue)));
+ FreePool (Palette);
+
+ //
+ // Convert the pixel from 8 bits to corresponding color.
+ //
+ for (Ypos = 0; Ypos < Image->Height; Ypos++) {
+ OffsetY = BITMAP_LEN_8_BIT ((UINT32)Image->Width, Ypos);
+ //
+ // All bits are meaningful since the bitmap is 8 bits per pixel.
+ //
+ for (Xpos = 0; Xpos < Image->Width; Xpos++) {
+ Byte = *(Data + OffsetY + Xpos);
+ BitMapPtr[OffsetY + Xpos] = PaletteValue[Byte];
+ }
+ }
+}
+
+/**
+ Output pixels in "24 bit per pixel" format to an image.
+
+ This is a internal function.
+
+
+ @param Image Points to the image which will store the pixels.
+ @param Data Stores the color of output pixels, allowing 16.8
+ millions colors.
+
+
+**/
+VOID
+Output24bitPixel (
+ IN OUT EFI_IMAGE_INPUT *Image,
+ IN EFI_HII_RGB_PIXEL *Data
+ )
+{
+ UINT16 Ypos;
+ UINTN OffsetY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
+
+ ASSERT (Image != NULL && Data != NULL);
+
+ BitMapPtr = Image->Bitmap;
+
+ for (Ypos = 0; Ypos < Image->Height; Ypos++) {
+ OffsetY = BITMAP_LEN_8_BIT ((UINT32)Image->Width, Ypos);
+ CopyRgbToGopPixel (&BitMapPtr[OffsetY], &Data[OffsetY], Image->Width);
+ }
+}
+
+/**
+ Convert the image from EFI_IMAGE_INPUT to EFI_IMAGE_OUTPUT format.
+
+ This is a internal function.
+
+
+ @param BltBuffer Buffer points to bitmap data of incoming image.
+ @param BltX Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+ @param BltY Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+ @param Width Width of the incoming image, in pixels.
+ @param Height Height of the incoming image, in pixels.
+ @param Transparent If TRUE, all "off" pixels in the image will be
+ drawn using the pixel value from blt and all other
+ pixels will be copied.
+ @param Blt Buffer points to bitmap data of output image.
+
+ @retval EFI_SUCCESS The image was successfully converted.
+ @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
+
+**/
+EFI_STATUS
+ImageToBlt (
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
+ IN UINTN BltX,
+ IN UINTN BltY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN BOOLEAN Transparent,
+ IN OUT EFI_IMAGE_OUTPUT **Blt
+ )
+{
+ EFI_IMAGE_OUTPUT *ImageOut;
+ UINTN Xpos;
+ UINTN Ypos;
+ UINTN OffsetY1; // src buffer
+ UINTN OffsetY2; // dest buffer
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL SrcPixel;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL ZeroPixel;
+
+ if ((BltBuffer == NULL) || (Blt == NULL) || (*Blt == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ImageOut = *Blt;
+
+ if (Width + BltX > ImageOut->Width) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Height + BltY > ImageOut->Height) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (&ZeroPixel, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+ for (Ypos = 0; Ypos < Height; Ypos++) {
+ OffsetY1 = Width * Ypos;
+ OffsetY2 = ImageOut->Width * (BltY + Ypos);
+ for (Xpos = 0; Xpos < Width; Xpos++) {
+ SrcPixel = BltBuffer[OffsetY1 + Xpos];
+ if (Transparent) {
+ if (CompareMem (&SrcPixel, &ZeroPixel, 3) != 0) {
+ ImageOut->Image.Bitmap[OffsetY2 + BltX + Xpos] = SrcPixel;
+ }
+ } else {
+ ImageOut->Image.Bitmap[OffsetY2 + BltX + Xpos] = SrcPixel;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the HII package list identified by PackageList HII handle.
+
+ @param Database Pointer to HII database list header.
+ @param PackageList HII handle of the package list to locate.
+
+ @retval The HII package list instance.
+**/
+HII_DATABASE_PACKAGE_LIST_INSTANCE *
+LocatePackageList (
+ IN LIST_ENTRY *Database,
+ IN EFI_HII_HANDLE PackageList
+ )
+{
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *Record;
+
+ //
+ // Get the specified package list and image package.
+ //
+ for (Link = GetFirstNode (Database);
+ !IsNull (Database, Link);
+ Link = GetNextNode (Database, Link)
+ )
+ {
+ Record = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (Record->Handle == PackageList) {
+ return Record->PackageList;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ This function adds the image Image to the group of images owned by PackageList, and returns
+ a new image identifier (ImageId).
+
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+ @param PackageList Handle of the package list where this image will
+ be added.
+ @param ImageId On return, contains the new image id, which is
+ unique within PackageList.
+ @param Image Points to the image.
+
+ @retval EFI_SUCCESS The new image was added successfully.
+ @retval EFI_NOT_FOUND The specified PackageList could not be found in
+ database.
+ @retval EFI_OUT_OF_RESOURCES Could not add the image due to lack of resources.
+ @retval EFI_INVALID_PARAMETER Image is NULL or ImageId is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiNewImage (
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ OUT EFI_IMAGE_ID *ImageId,
+ IN CONST EFI_IMAGE_INPUT *Image
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
+ EFI_HII_IMAGE_BLOCK *ImageBlocks;
+ UINT32 NewBlockSize;
+
+ if ((This == NULL) || (ImageId == NULL) || (Image == NULL) || (Image->Bitmap == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ PackageListNode = LocatePackageList (&Private->DatabaseList, PackageList);
+ if (PackageListNode == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ EfiAcquireLock (&mHiiDatabaseLock);
+
+ //
+ // Calcuate the size of new image.
+ // Make sure the size doesn't overflow UINT32.
+ // Note: 24Bit BMP occpuies 3 bytes per pixel.
+ //
+ NewBlockSize = (UINT32)Image->Width * Image->Height;
+ if (NewBlockSize > (MAX_UINT32 - (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))) / 3) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewBlockSize = NewBlockSize * 3 + (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL));
+
+ //
+ // Get the image package in the package list,
+ // or create a new image package if image package does not exist.
+ //
+ if (PackageListNode->ImagePkg != NULL) {
+ ImagePackage = PackageListNode->ImagePkg;
+
+ //
+ // Output the image id of the incoming image being inserted, which is the
+ // image id of the EFI_HII_IIBT_END block of old image package.
+ //
+ *ImageId = 0;
+ GetImageIdOrAddress (ImagePackage->ImageBlock, ImageId);
+
+ //
+ // Update the package's image block by appending the new block to the end.
+ //
+
+ //
+ // Make sure the final package length doesn't overflow.
+ // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
+ //
+ if (NewBlockSize > MAX_UINT24 - ImagePackage->ImagePkgHdr.Header.Length) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Because ImagePackage->ImageBlockSize < ImagePackage->ImagePkgHdr.Header.Length,
+ // So (ImagePackage->ImageBlockSize + NewBlockSize) <= MAX_UINT24
+ //
+ ImageBlocks = AllocatePool (ImagePackage->ImageBlockSize + NewBlockSize);
+ if (ImageBlocks == NULL) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Copy the original content.
+ //
+ CopyMem (
+ ImageBlocks,
+ ImagePackage->ImageBlock,
+ ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)
+ );
+ FreePool (ImagePackage->ImageBlock);
+ ImagePackage->ImageBlock = ImageBlocks;
+
+ //
+ // Point to the very last block.
+ //
+ ImageBlocks = (EFI_HII_IMAGE_BLOCK *)(
+ (UINT8 *)ImageBlocks + ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)
+ );
+ //
+ // Update the length record.
+ //
+ ImagePackage->ImageBlockSize += NewBlockSize;
+ ImagePackage->ImagePkgHdr.Header.Length += NewBlockSize;
+ PackageListNode->PackageListHdr.PackageLength += NewBlockSize;
+ } else {
+ //
+ // Make sure the final package length doesn't overflow.
+ // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
+ //
+ if (NewBlockSize > MAX_UINT24 - (sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + sizeof (EFI_HII_IIBT_END_BLOCK))) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // The specified package list does not contain image package.
+ // Create one to add this image block.
+ //
+ ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));
+ if (ImagePackage == NULL) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Output the image id of the incoming image being inserted, which is the
+ // first image block so that id is initially to one.
+ //
+ *ImageId = 1;
+ //
+ // Fill in image package header.
+ //
+ ImagePackage->ImagePkgHdr.Header.Length = sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK);
+ ImagePackage->ImagePkgHdr.Header.Type = EFI_HII_PACKAGE_IMAGES;
+ ImagePackage->ImagePkgHdr.ImageInfoOffset = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
+ ImagePackage->ImagePkgHdr.PaletteInfoOffset = 0;
+
+ //
+ // Fill in palette info.
+ //
+ ImagePackage->PaletteBlock = NULL;
+ ImagePackage->PaletteInfoSize = 0;
+
+ //
+ // Fill in image blocks.
+ //
+ ImagePackage->ImageBlockSize = NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK);
+ ImagePackage->ImageBlock = AllocateZeroPool (NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK));
+ if (ImagePackage->ImageBlock == NULL) {
+ FreePool (ImagePackage);
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ImageBlocks = ImagePackage->ImageBlock;
+
+ //
+ // Insert this image package.
+ //
+ PackageListNode->ImagePkg = ImagePackage;
+ PackageListNode->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;
+ }
+
+ //
+ // Append the new block here
+ //
+ if (Image->Flags == EFI_IMAGE_TRANSPARENT) {
+ ImageBlocks->BlockType = EFI_HII_IIBT_IMAGE_24BIT_TRANS;
+ } else {
+ ImageBlocks->BlockType = EFI_HII_IIBT_IMAGE_24BIT;
+ }
+
+ WriteUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)ImageBlocks)->Bitmap.Width, Image->Width);
+ WriteUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)ImageBlocks)->Bitmap.Height, Image->Height);
+ CopyGopToRgbPixel (((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)ImageBlocks)->Bitmap.Bitmap, Image->Bitmap, (UINT32)Image->Width * Image->Height);
+
+ //
+ // Append the block end
+ //
+ ImageBlocks = (EFI_HII_IMAGE_BLOCK *)((UINT8 *)ImageBlocks + NewBlockSize);
+ ImageBlocks->BlockType = EFI_HII_IIBT_END;
+
+ //
+ // Check whether need to get the contents of HiiDataBase.
+ // Only after ReadyToBoot to do the export.
+ //
+ if (gExportAfterReadyToBoot) {
+ HiiGetDatabaseInfo (&Private->HiiDatabase);
+ }
+
+ EfiReleaseLock (&mHiiDatabaseLock);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function retrieves the image specified by ImageId which is associated with
+ the specified PackageList and copies it into the buffer specified by Image.
+
+ @param Database A pointer to the database list header.
+ @param PackageList Handle of the package list where this image will
+ be searched.
+ @param ImageId The image's id,, which is unique within
+ PackageList.
+ @param Image Points to the image.
+ @param BitmapOnly TRUE to only return the bitmap type image.
+ FALSE to locate image decoder instance to decode image.
+
+ @retval EFI_SUCCESS The new image was returned successfully.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the
+ database. The specified PackageList is not in the database.
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
+ hold the image.
+ @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.
+ @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not
+ enough memory.
+**/
+EFI_STATUS
+IGetImage (
+ IN LIST_ENTRY *Database,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ OUT EFI_IMAGE_INPUT *Image,
+ IN BOOLEAN BitmapOnly
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
+ EFI_HII_IMAGE_BLOCK *CurrentImageBlock;
+ EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit;
+ UINT16 Width;
+ UINT16 Height;
+ UINTN ImageLength;
+ UINT8 *PaletteInfo;
+ UINT8 PaletteIndex;
+ UINT16 PaletteSize;
+ EFI_HII_IMAGE_DECODER_PROTOCOL *Decoder;
+ EFI_IMAGE_OUTPUT *ImageOut;
+
+ if ((Image == NULL) || (ImageId == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PackageListNode = LocatePackageList (Database, PackageList);
+ if (PackageListNode == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ ImagePackage = PackageListNode->ImagePkg;
+ if (ImagePackage == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Find the image block specified by ImageId
+ //
+ CurrentImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &ImageId);
+ if (CurrentImageBlock == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Image->Flags = 0;
+ switch (CurrentImageBlock->BlockType) {
+ case EFI_HII_IIBT_IMAGE_JPEG:
+ case EFI_HII_IIBT_IMAGE_PNG:
+ if (BitmapOnly) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ImageOut = NULL;
+ Decoder = LocateHiiImageDecoder (CurrentImageBlock->BlockType);
+ if (Decoder == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Use the common block code since the definition of two structures is the same.
+ //
+ ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Data) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Data));
+ ASSERT (
+ sizeof (((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Data) ==
+ sizeof (((EFI_HII_IIBT_PNG_BLOCK *)CurrentImageBlock)->Data)
+ );
+ ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Size) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Size));
+ ASSERT (
+ sizeof (((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Size) ==
+ sizeof (((EFI_HII_IIBT_PNG_BLOCK *)CurrentImageBlock)->Size)
+ );
+ Status = Decoder->DecodeImage (
+ Decoder,
+ ((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Data,
+ ((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Size,
+ &ImageOut,
+ FALSE
+ );
+
+ //
+ // Spec requires to use the first capable image decoder instance.
+ // The first image decoder instance may fail to decode the image.
+ //
+ if (!EFI_ERROR (Status)) {
+ Image->Bitmap = ImageOut->Image.Bitmap;
+ Image->Height = ImageOut->Height;
+ Image->Width = ImageOut->Width;
+ FreePool (ImageOut);
+ }
+
+ return Status;
+
+ case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
+ case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
+ case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
+ Image->Flags = EFI_IMAGE_TRANSPARENT;
+ //
+ // fall through
+ //
+ case EFI_HII_IIBT_IMAGE_1BIT:
+ case EFI_HII_IIBT_IMAGE_4BIT:
+ case EFI_HII_IIBT_IMAGE_8BIT:
+ //
+ // Use the common block code since the definition of these structures is the same.
+ //
+ CopyMem (&Iibt1bit, CurrentImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));
+ ImageLength = (UINTN)Iibt1bit.Bitmap.Width * Iibt1bit.Bitmap.Height;
+ if (ImageLength > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ImageLength *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ Image->Bitmap = AllocateZeroPool (ImageLength);
+ if (Image->Bitmap == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Image->Width = Iibt1bit.Bitmap.Width;
+ Image->Height = Iibt1bit.Bitmap.Height;
+
+ PaletteInfo = ImagePackage->PaletteBlock + sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);
+ for (PaletteIndex = 1; PaletteIndex < Iibt1bit.PaletteIndex; PaletteIndex++) {
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
+ PaletteInfo += PaletteSize + sizeof (UINT16);
+ }
+
+ ASSERT (PaletteIndex == Iibt1bit.PaletteIndex);
+
+ //
+ // Output bitmap data
+ //
+ if ((CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_1BIT) ||
+ (CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_1BIT_TRANS))
+ {
+ Output1bitPixel (
+ Image,
+ ((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *)CurrentImageBlock)->Bitmap.Data,
+ (EFI_HII_IMAGE_PALETTE_INFO *)PaletteInfo
+ );
+ } else if ((CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_4BIT) ||
+ (CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_4BIT_TRANS))
+ {
+ Output4bitPixel (
+ Image,
+ ((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *)CurrentImageBlock)->Bitmap.Data,
+ (EFI_HII_IMAGE_PALETTE_INFO *)PaletteInfo
+ );
+ } else {
+ Output8bitPixel (
+ Image,
+ ((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *)CurrentImageBlock)->Bitmap.Data,
+ (EFI_HII_IMAGE_PALETTE_INFO *)PaletteInfo
+ );
+ }
+
+ return EFI_SUCCESS;
+
+ case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
+ Image->Flags = EFI_IMAGE_TRANSPARENT;
+ //
+ // fall through
+ //
+ case EFI_HII_IIBT_IMAGE_24BIT:
+ Width = ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width);
+ Height = ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height);
+ ImageLength = (UINTN)Width * Height;
+ if (ImageLength > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ImageLength *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ Image->Bitmap = AllocateZeroPool (ImageLength);
+ if (Image->Bitmap == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Image->Width = Width;
+ Image->Height = Height;
+
+ //
+ // Output the bitmap data directly.
+ //
+ Output24bitPixel (
+ Image,
+ ((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Bitmap
+ );
+ return EFI_SUCCESS;
+
+ default:
+ return EFI_NOT_FOUND;
+ }
+}
+
+/**
+ This function retrieves the image specified by ImageId which is associated with
+ the specified PackageList and copies it into the buffer specified by Image.
+
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+ @param PackageList Handle of the package list where this image will
+ be searched.
+ @param ImageId The image's id,, which is unique within
+ PackageList.
+ @param Image Points to the image.
+
+ @retval EFI_SUCCESS The new image was returned successfully.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the
+ database. The specified PackageList is not in the database.
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
+ hold the image.
+ @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.
+ @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not
+ enough memory.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetImage (
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ OUT EFI_IMAGE_INPUT *Image
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ return IGetImage (&Private->DatabaseList, PackageList, ImageId, Image, TRUE);
+}
+
+/**
+ This function updates the image specified by ImageId in the specified PackageListHandle to
+ the image specified by Image.
+
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+ @param PackageList The package list containing the images.
+ @param ImageId The image's id,, which is unique within
+ PackageList.
+ @param Image Points to the image.
+
+ @retval EFI_SUCCESS The new image was updated successfully.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the
+ database. The specified PackageList is not in the database.
+ @retval EFI_INVALID_PARAMETER The Image was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiSetImage (
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ IN CONST EFI_IMAGE_INPUT *Image
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
+ EFI_HII_IMAGE_BLOCK *CurrentImageBlock;
+ EFI_HII_IMAGE_BLOCK *ImageBlocks;
+ EFI_HII_IMAGE_BLOCK *NewImageBlock;
+ UINT32 NewBlockSize;
+ UINT32 OldBlockSize;
+ UINT32 Part1Size;
+ UINT32 Part2Size;
+
+ if ((This == NULL) || (Image == NULL) || (ImageId == 0) || (Image->Bitmap == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ PackageListNode = LocatePackageList (&Private->DatabaseList, PackageList);
+ if (PackageListNode == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ ImagePackage = PackageListNode->ImagePkg;
+ if (ImagePackage == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Find the image block specified by ImageId
+ //
+ CurrentImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &ImageId);
+ if (CurrentImageBlock == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ EfiAcquireLock (&mHiiDatabaseLock);
+
+ //
+ // Get the size of original image block. Use some common block code here
+ // since the definition of some structures is the same.
+ //
+ switch (CurrentImageBlock->BlockType) {
+ case EFI_HII_IIBT_IMAGE_JPEG:
+ OldBlockSize = OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Data) + ReadUnaligned32 ((VOID *)&((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Size);
+ break;
+ case EFI_HII_IIBT_IMAGE_PNG:
+ OldBlockSize = OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Data) + ReadUnaligned32 ((VOID *)&((EFI_HII_IIBT_PNG_BLOCK *)CurrentImageBlock)->Size);
+ break;
+ case EFI_HII_IIBT_IMAGE_1BIT:
+ case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_1_BIT (
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width),
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height)
+ );
+ break;
+ case EFI_HII_IIBT_IMAGE_4BIT:
+ case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_4_BIT (
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width),
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height)
+ );
+ break;
+ case EFI_HII_IIBT_IMAGE_8BIT:
+ case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_8_BIT (
+ (UINT32)ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width),
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height)
+ );
+ break;
+ case EFI_HII_IIBT_IMAGE_24BIT:
+ case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
+ BITMAP_LEN_24_BIT (
+ (UINT32)ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width),
+ ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height)
+ );
+ break;
+ default:
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Create the new image block according to input image.
+ //
+
+ //
+ // Make sure the final package length doesn't overflow.
+ // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
+ // 24Bit BMP occpuies 3 bytes per pixel.
+ //
+ NewBlockSize = (UINT32)Image->Width * Image->Height;
+ if (NewBlockSize > (MAX_UINT32 - (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))) / 3) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewBlockSize = NewBlockSize * 3 + (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL));
+ if ((NewBlockSize > OldBlockSize) &&
+ (NewBlockSize - OldBlockSize > MAX_UINT24 - ImagePackage->ImagePkgHdr.Header.Length)
+ )
+ {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Adjust the image package to remove the original block firstly then add the new block.
+ //
+ ImageBlocks = AllocateZeroPool (ImagePackage->ImageBlockSize + NewBlockSize - OldBlockSize);
+ if (ImageBlocks == NULL) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Part1Size = (UINT32)((UINTN)CurrentImageBlock - (UINTN)ImagePackage->ImageBlock);
+ Part2Size = ImagePackage->ImageBlockSize - Part1Size - OldBlockSize;
+ CopyMem (ImageBlocks, ImagePackage->ImageBlock, Part1Size);
+
+ //
+ // Set the new image block
+ //
+ NewImageBlock = (EFI_HII_IMAGE_BLOCK *)((UINT8 *)ImageBlocks + Part1Size);
+ if ((Image->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {
+ NewImageBlock->BlockType = EFI_HII_IIBT_IMAGE_24BIT_TRANS;
+ } else {
+ NewImageBlock->BlockType = EFI_HII_IIBT_IMAGE_24BIT;
+ }
+
+ WriteUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)NewImageBlock)->Bitmap.Width, Image->Width);
+ WriteUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)NewImageBlock)->Bitmap.Height, Image->Height);
+ CopyGopToRgbPixel (
+ ((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)NewImageBlock)->Bitmap.Bitmap,
+ Image->Bitmap,
+ (UINT32)Image->Width * Image->Height
+ );
+
+ CopyMem ((UINT8 *)NewImageBlock + NewBlockSize, (UINT8 *)CurrentImageBlock + OldBlockSize, Part2Size);
+
+ FreePool (ImagePackage->ImageBlock);
+ ImagePackage->ImageBlock = ImageBlocks;
+ ImagePackage->ImageBlockSize += NewBlockSize - OldBlockSize;
+ ImagePackage->ImagePkgHdr.Header.Length += NewBlockSize - OldBlockSize;
+ PackageListNode->PackageListHdr.PackageLength += NewBlockSize - OldBlockSize;
+
+ //
+ // Check whether need to get the contents of HiiDataBase.
+ // Only after ReadyToBoot to do the export.
+ //
+ if (gExportAfterReadyToBoot) {
+ HiiGetDatabaseInfo (&Private->HiiDatabase);
+ }
+
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_SUCCESS;
+}
+
+/**
+ This function renders an image to a bitmap or the screen using the specified
+ color and options. It draws the image on an existing bitmap, allocates a new
+ bitmap or uses the screen. The images can be clipped.
+
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+ @param Flags Describes how the image is to be drawn.
+ @param Image Points to the image to be displayed.
+ @param Blt If this points to a non-NULL on entry, this points
+ to the image, which is Width pixels wide and
+ Height pixels high. The image will be drawn onto
+ this image and EFI_HII_DRAW_FLAG_CLIP is implied.
+ If this points to a NULL on entry, then a buffer
+ will be allocated to hold the generated image and
+ the pointer updated on exit. It is the caller's
+ responsibility to free this buffer.
+ @param BltX Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+ @param BltY Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+
+ @retval EFI_SUCCESS The image was successfully drawn.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
+ @retval EFI_INVALID_PARAMETER The Image or Blt was NULL.
+ @retval EFI_INVALID_PARAMETER Any combination of Flags is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiDrawImage (
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,
+ IN EFI_HII_DRAW_FLAGS Flags,
+ IN CONST EFI_IMAGE_INPUT *Image,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ BOOLEAN Transparent;
+ EFI_IMAGE_OUTPUT *ImageOut;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+ UINTN BufferLen;
+ UINT16 Width;
+ UINT16 Height;
+ UINTN Xpos;
+ UINTN Ypos;
+ UINTN OffsetY1;
+ UINTN OffsetY2;
+ EFI_FONT_DISPLAY_INFO *FontInfo;
+ UINTN Index;
+
+ if ((This == NULL) || (Image == NULL) || (Blt == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((Flags & EFI_HII_DRAW_FLAG_CLIP) == EFI_HII_DRAW_FLAG_CLIP) && (*Blt == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_TRANSPARENT) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FontInfo = NULL;
+
+ //
+ // Check whether the image will be drawn transparently or opaquely.
+ //
+ Transparent = FALSE;
+ if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_TRANS) {
+ Transparent = TRUE;
+ } else if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_OPAQUE) {
+ Transparent = FALSE;
+ } else {
+ //
+ // Now EFI_HII_DRAW_FLAG_DEFAULT is set, whether image will be drawn depending
+ // on the image's transparency setting.
+ //
+ if ((Image->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {
+ Transparent = TRUE;
+ }
+ }
+
+ //
+ // Image cannot be drawn transparently if Blt points to NULL on entry.
+ // Currently output to Screen transparently is not supported, either.
+ //
+ if (Transparent) {
+ if (*Blt == NULL) {
+ return EFI_INVALID_PARAMETER;
+ } else if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // When Blt points to a non-NULL on entry, this image will be drawn onto
+ // this bitmap or screen pointed by "*Blt" and EFI_HII_DRAW_FLAG_CLIP is implied.
+ // Otherwise a new bitmap will be allocated to hold this image.
+ //
+ if (*Blt != NULL) {
+ //
+ // Make sure the BltX and BltY is inside the Blt area.
+ //
+ if ((BltX >= (*Blt)->Width) || (BltY >= (*Blt)->Height)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Clip the image by (Width, Height)
+ //
+
+ Width = Image->Width;
+ Height = Image->Height;
+
+ if (Width > (*Blt)->Width - (UINT16)BltX) {
+ Width = (*Blt)->Width - (UINT16)BltX;
+ }
+
+ if (Height > (*Blt)->Height - (UINT16)BltY) {
+ Height = (*Blt)->Height - (UINT16)BltY;
+ }
+
+ //
+ // Prepare the buffer for the temporary image.
+ // Make sure the buffer size doesn't overflow UINTN.
+ //
+ BufferLen = Width * Height;
+ if (BufferLen > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BufferLen *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ BltBuffer = AllocateZeroPool (BufferLen);
+ if (BltBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if ((Width == Image->Width) && (Height == Image->Height)) {
+ CopyMem (BltBuffer, Image->Bitmap, BufferLen);
+ } else {
+ for (Ypos = 0; Ypos < Height; Ypos++) {
+ OffsetY1 = Image->Width * Ypos;
+ OffsetY2 = Width * Ypos;
+ for (Xpos = 0; Xpos < Width; Xpos++) {
+ BltBuffer[OffsetY2 + Xpos] = Image->Bitmap[OffsetY1 + Xpos];
+ }
+ }
+ }
+
+ //
+ // Draw the image to existing bitmap or screen depending on flag.
+ //
+ if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
+ //
+ // Caller should make sure the current UGA console is grarphic mode.
+ //
+
+ //
+ // Write the image directly to the output device specified by Screen.
+ //
+ Status = (*Blt)->Image.Screen->Blt (
+ (*Blt)->Image.Screen,
+ BltBuffer,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ BltX,
+ BltY,
+ Width,
+ Height,
+ 0
+ );
+ } else {
+ //
+ // Draw the image onto the existing bitmap specified by Bitmap.
+ //
+ Status = ImageToBlt (
+ BltBuffer,
+ BltX,
+ BltY,
+ Width,
+ Height,
+ Transparent,
+ Blt
+ );
+ }
+
+ FreePool (BltBuffer);
+ return Status;
+ } else {
+ //
+ // Allocate a new bitmap to hold the incoming image.
+ //
+
+ //
+ // Make sure the final width and height doesn't overflow UINT16.
+ //
+ if ((BltX > (UINTN)MAX_UINT16 - Image->Width) || (BltY > (UINTN)MAX_UINT16 - Image->Height)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Width = Image->Width + (UINT16)BltX;
+ Height = Image->Height + (UINT16)BltY;
+
+ //
+ // Make sure the output image size doesn't overflow UINTN.
+ //
+ BufferLen = Width * Height;
+ if (BufferLen > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BufferLen *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ BltBuffer = AllocateZeroPool (BufferLen);
+ if (BltBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ImageOut = (EFI_IMAGE_OUTPUT *)AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
+ if (ImageOut == NULL) {
+ FreePool (BltBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ImageOut->Width = Width;
+ ImageOut->Height = Height;
+ ImageOut->Image.Bitmap = BltBuffer;
+
+ //
+ // BUGBUG: Now all the "blank" pixels are filled with system default background
+ // color. Not sure if it need to be updated or not.
+ //
+ Status = GetSystemFont (Private, &FontInfo, NULL);
+ if (EFI_ERROR (Status)) {
+ FreePool (BltBuffer);
+ FreePool (ImageOut);
+ return Status;
+ }
+
+ ASSERT (FontInfo != NULL);
+ for (Index = 0; Index < (UINTN)Width * Height; Index++) {
+ BltBuffer[Index] = FontInfo->BackgroundColor;
+ }
+
+ FreePool (FontInfo);
+
+ //
+ // Draw the incoming image to the new created image.
+ //
+ *Blt = ImageOut;
+ return ImageToBlt (
+ Image->Bitmap,
+ BltX,
+ BltY,
+ Image->Width,
+ Image->Height,
+ Transparent,
+ Blt
+ );
+ }
+}
+
+/**
+ This function renders an image to a bitmap or the screen using the specified
+ color and options. It draws the image on an existing bitmap, allocates a new
+ bitmap or uses the screen. The images can be clipped.
+
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+ @param Flags Describes how the image is to be drawn.
+ @param PackageList The package list in the HII database to search for
+ the specified image.
+ @param ImageId The image's id, which is unique within
+ PackageList.
+ @param Blt If this points to a non-NULL on entry, this points
+ to the image, which is Width pixels wide and
+ Height pixels high. The image will be drawn onto
+ this image and
+ EFI_HII_DRAW_FLAG_CLIP is implied. If this points
+ to a NULL on entry, then a buffer will be
+ allocated to hold the generated image and the
+ pointer updated on exit. It is the caller's
+ responsibility to free this buffer.
+ @param BltX Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+ @param BltY Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+
+ @retval EFI_SUCCESS The image was successfully drawn.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
+ @retval EFI_INVALID_PARAMETER The Blt was NULL.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the database.
+ The specified PackageList is not in the database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiDrawImageId (
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,
+ IN EFI_HII_DRAW_FLAGS Flags,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY
+ )
+{
+ EFI_STATUS Status;
+ EFI_IMAGE_INPUT Image;
+
+ //
+ // Check input parameter.
+ //
+ if ((This == NULL) || (Blt == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get the specified Image.
+ //
+ Status = HiiGetImage (This, PackageList, ImageId, &Image);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Draw this image.
+ //
+ Status = HiiDrawImage (This, Flags, &Image, Blt, BltX, BltY);
+ if (Image.Bitmap != NULL) {
+ FreePool (Image.Bitmap);
+ }
+
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/ImageEx.c b/MdeModulePkg/Universal/HiiDatabaseDxe/ImageEx.c
index f394e1333c..16300cb6ab 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/ImageEx.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/ImageEx.c
@@ -1,429 +1,429 @@
-/** @file
-Implementation for EFI_HII_IMAGE_EX_PROTOCOL.
-
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "HiiDatabase.h"
-
-/**
- The prototype of this extension function is the same with EFI_HII_IMAGE_PROTOCOL.NewImage().
- This protocol invokes EFI_HII_IMAGE_PROTOCOL.NewImage() implicitly.
-
- @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
- @param PackageList Handle of the package list where this image will
- be added.
- @param ImageId On return, contains the new image id, which is
- unique within PackageList.
- @param Image Points to the image.
-
- @retval EFI_SUCCESS The new image was added successfully.
- @retval EFI_NOT_FOUND The PackageList could not be found.
- @retval EFI_OUT_OF_RESOURCES Could not add the image due to lack of resources.
- @retval EFI_INVALID_PARAMETER Image is NULL or ImageId is NULL.
-**/
-EFI_STATUS
-EFIAPI
-HiiNewImageEx (
- IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- OUT EFI_IMAGE_ID *ImageId,
- IN CONST EFI_IMAGE_INPUT *Image
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
-
- Private = HII_IMAGE_EX_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- return HiiNewImage (&Private->HiiImage, PackageList, ImageId, Image);
-}
-
-/**
- Return the information about the image, associated with the package list.
- The prototype of this extension function is the same with EFI_HII_IMAGE_PROTOCOL.GetImage().
-
- This function is similar to EFI_HII_IMAGE_PROTOCOL.GetImage().The difference is that
- this function will locate all EFI_HII_IMAGE_DECODER_PROTOCOL instances installed in the
- system if the decoder of the certain image type is not supported by the
- EFI_HII_IMAGE_EX_PROTOCOL. The function will attempt to decode the image to the
- EFI_IMAGE_INPUT using the first EFI_HII_IMAGE_DECODER_PROTOCOL instance that
- supports the requested image type.
-
- @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
- @param PackageList The package list in the HII database to search for the
- specified image.
- @param ImageId The image's id, which is unique within PackageList.
- @param Image Points to the image.
-
- @retval EFI_SUCCESS The new image was returned successfully.
- @retval EFI_NOT_FOUND The image specified by ImageId is not available. The specified
- PackageList is not in the Database.
- @retval EFI_INVALID_PARAMETER Image was NULL or ImageId was 0.
- @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there
- was not enough memory.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetImageEx (
- IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_IMAGE_ID ImageId,
- OUT EFI_IMAGE_INPUT *Image
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
-
- Private = HII_IMAGE_EX_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- return IGetImage (&Private->DatabaseList, PackageList, ImageId, Image, FALSE);
-}
-
-/**
- Change the information about the image.
-
- Same with EFI_HII_IMAGE_PROTOCOL.SetImage(),this protocol invokes
- EFI_HII_IMAGE_PROTOCOL.SetImage()implicitly.
-
- @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
- @param PackageList The package list containing the images.
- @param ImageId The image's id, which is unique within PackageList.
- @param Image Points to the image.
-
- @retval EFI_SUCCESS The new image was successfully updated.
- @retval EFI_NOT_FOUND The image specified by ImageId is not in the
- database. The specified PackageList is not in
- the database.
- @retval EFI_INVALID_PARAMETER The Image was NULL, the ImageId was 0 or
- the Image->Bitmap was NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiSetImageEx (
- IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_IMAGE_ID ImageId,
- IN CONST EFI_IMAGE_INPUT *Image
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
-
- Private = HII_IMAGE_EX_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- return HiiSetImage (&Private->HiiImage, PackageList, ImageId, Image);
-}
-
-/**
- Renders an image to a bitmap or to the display.
-
- The prototype of this extension function is the same with
- EFI_HII_IMAGE_PROTOCOL.DrawImage(). This protocol invokes
- EFI_HII_IMAGE_PROTOCOL.DrawImage() implicitly.
-
- @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
- @param Flags Describes how the image is to be drawn.
- @param Image Points to the image to be displayed.
- @param Blt If this points to a non-NULL on entry, this points
- to the image, which is Width pixels wide and
- Height pixels high. The image will be drawn onto
- this image and EFI_HII_DRAW_FLAG_CLIP is implied.
- If this points to a NULL on entry, then a buffer
- will be allocated to hold the generated image and
- the pointer updated on exit. It is the caller's
- responsibility to free this buffer.
- @param BltX Specifies the offset from the left and top edge of
- the output image of the first pixel in the image.
- @param BltY Specifies the offset from the left and top edge of
- the output image of the first pixel in the image.
-
- @retval EFI_SUCCESS The image was successfully drawn.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
- @retval EFI_INVALID_PARAMETER The Image or Blt was NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiDrawImageEx (
- IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
- IN EFI_HII_DRAW_FLAGS Flags,
- IN CONST EFI_IMAGE_INPUT *Image,
- IN OUT EFI_IMAGE_OUTPUT **Blt,
- IN UINTN BltX,
- IN UINTN BltY
- )
-{
- HII_DATABASE_PRIVATE_DATA *Private;
-
- Private = HII_IMAGE_EX_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- return HiiDrawImage (&Private->HiiImage, Flags, Image, Blt, BltX, BltY);
-}
-
-/**
- Renders an image to a bitmap or the screen containing the contents of the specified
- image.
-
- This function is similar to EFI_HII_IMAGE_PROTOCOL.DrawImageId(). The difference is that
- this function will locate all EFI_HII_IMAGE_DECODER_PROTOCOL instances installed in the
- system if the decoder of the certain image type is not supported by the
- EFI_HII_IMAGE_EX_PROTOCOL. The function will attempt to decode the image to the
- EFI_IMAGE_INPUT using the first EFI_HII_IMAGE_DECODER_PROTOCOL instance that
- supports the requested image type.
-
- @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
- @param Flags Describes how the image is to be drawn.
- @param PackageList The package list in the HII database to search for
- the specified image.
- @param ImageId The image's id, which is unique within PackageList.
- @param Blt If this points to a non-NULL on entry, this points
- to the image, which is Width pixels wide and
- Height pixels high. The image will be drawn onto
- this image and EFI_HII_DRAW_FLAG_CLIP is implied.
- If this points to a NULL on entry, then a buffer
- will be allocated to hold the generated image
- and the pointer updated on exit. It is the caller's
- responsibility to free this buffer.
- @param BltX Specifies the offset from the left and top edge of
- the output image of the first pixel in the image.
- @param BltY Specifies the offset from the left and top edge of
- the output image of the first pixel in the image.
-
- @retval EFI_SUCCESS The image was successfully drawn.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
- @retval EFI_INVALID_PARAMETER The Blt was NULL or ImageId was 0.
- @retval EFI_NOT_FOUND The image specified by ImageId is not in the database.
- The specified PackageList is not in the database.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiDrawImageIdEx (
- IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
- IN EFI_HII_DRAW_FLAGS Flags,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_IMAGE_ID ImageId,
- IN OUT EFI_IMAGE_OUTPUT **Blt,
- IN UINTN BltX,
- IN UINTN BltY
- )
-{
- EFI_STATUS Status;
- EFI_IMAGE_INPUT Image;
-
- //
- // Check input parameter.
- //
- if ((This == NULL) || (Blt == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Get the specified Image.
- //
- Status = HiiGetImageEx (This, PackageList, ImageId, &Image);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Draw this image.
- //
- Status = HiiDrawImageEx (This, Flags, &Image, Blt, BltX, BltY);
- if (Image.Bitmap != NULL) {
- FreePool (Image.Bitmap);
- }
-
- return Status;
-}
-
-/**
- Return the first HII image decoder instance which supports the DecoderName.
-
- @param BlockType The image block type.
-
- @retval Pointer to the HII image decoder instance.
-**/
-EFI_HII_IMAGE_DECODER_PROTOCOL *
-LocateHiiImageDecoder (
- UINT8 BlockType
- )
-{
- EFI_STATUS Status;
- EFI_HII_IMAGE_DECODER_PROTOCOL *Decoder;
- EFI_HANDLE *Handles;
- UINTN HandleNum;
- UINTN Index;
- EFI_GUID *DecoderNames;
- UINT16 NumberOfDecoderName;
- UINT16 DecoderNameIndex;
- EFI_GUID *DecoderName;
-
- switch (BlockType) {
- case EFI_HII_IIBT_IMAGE_JPEG:
- DecoderName = &gEfiHiiImageDecoderNameJpegGuid;
- break;
-
- case EFI_HII_IIBT_IMAGE_PNG:
- DecoderName = &gEfiHiiImageDecoderNamePngGuid;
- break;
-
- default:
- ASSERT (FALSE);
- return NULL;
- }
-
- Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiHiiImageDecoderProtocolGuid, NULL, &HandleNum, &Handles);
- if (EFI_ERROR (Status)) {
- return NULL;
- }
-
- for (Index = 0; Index < HandleNum; Index++) {
- Status = gBS->HandleProtocol (Handles[Index], &gEfiHiiImageDecoderProtocolGuid, (VOID **)&Decoder);
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- Status = Decoder->GetImageDecoderName (Decoder, &DecoderNames, &NumberOfDecoderName);
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- for (DecoderNameIndex = 0; DecoderNameIndex < NumberOfDecoderName; DecoderNameIndex++) {
- if (CompareGuid (DecoderName, &DecoderNames[DecoderNameIndex])) {
- return Decoder;
- }
- }
- }
-
- return NULL;
-}
-
-/**
- This function returns the image information to EFI_IMAGE_OUTPUT. Only the width
- and height are returned to the EFI_IMAGE_OUTPUT instead of decoding the image
- to the buffer. This function is used to get the geometry of the image. This function
- will try to locate all of the EFI_HII_IMAGE_DECODER_PROTOCOL installed on the
- system if the decoder of image type is not supported by the EFI_HII_IMAGE_EX_PROTOCOL.
-
- @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
- @param PackageList Handle of the package list where this image will
- be searched.
- @param ImageId The image's id, which is unique within PackageList.
- @param Image Points to the image.
-
- @retval EFI_SUCCESS The new image was returned successfully.
- @retval EFI_NOT_FOUND The image specified by ImageId is not in the
- database. The specified PackageList is not in the database.
- @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
- hold the image.
- @retval EFI_INVALID_PARAMETER The Image was NULL or the ImageId was 0.
- @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there
- was not enough memory.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetImageInfo (
- IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_IMAGE_ID ImageId,
- OUT EFI_IMAGE_OUTPUT *Image
- )
-{
- EFI_STATUS Status;
- HII_DATABASE_PRIVATE_DATA *Private;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
- HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
- EFI_HII_IMAGE_BLOCK *CurrentImageBlock;
- EFI_HII_IMAGE_DECODER_PROTOCOL *Decoder;
- EFI_HII_IMAGE_DECODER_IMAGE_INFO_HEADER *ImageInfo;
-
- if ((Image == NULL) || (ImageId == 0)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = HII_IMAGE_EX_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- PackageListNode = LocatePackageList (&Private->DatabaseList, PackageList);
- if (PackageListNode == NULL) {
- return EFI_NOT_FOUND;
- }
-
- ImagePackage = PackageListNode->ImagePkg;
- if (ImagePackage == NULL) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Find the image block specified by ImageId
- //
- CurrentImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &ImageId);
- if (CurrentImageBlock == NULL) {
- return EFI_NOT_FOUND;
- }
-
- switch (CurrentImageBlock->BlockType) {
- case EFI_HII_IIBT_IMAGE_JPEG:
- case EFI_HII_IIBT_IMAGE_PNG:
- Decoder = LocateHiiImageDecoder (CurrentImageBlock->BlockType);
- if (Decoder == NULL) {
- return EFI_UNSUPPORTED;
- }
-
- //
- // Use the common block code since the definition of two structures is the same.
- //
- ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Data) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Data));
- ASSERT (
- sizeof (((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Data) ==
- sizeof (((EFI_HII_IIBT_PNG_BLOCK *)CurrentImageBlock)->Data)
- );
- ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Size) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Size));
- ASSERT (
- sizeof (((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Size) ==
- sizeof (((EFI_HII_IIBT_PNG_BLOCK *)CurrentImageBlock)->Size)
- );
- Status = Decoder->GetImageInfo (
- Decoder,
- ((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Data,
- ((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Size,
- &ImageInfo
- );
-
- //
- // Spec requires to use the first capable image decoder instance.
- // The first image decoder instance may fail to decode the image.
- //
- if (!EFI_ERROR (Status)) {
- Image->Height = ImageInfo->ImageHeight;
- Image->Width = ImageInfo->ImageWidth;
- Image->Image.Bitmap = NULL;
- FreePool (ImageInfo);
- }
-
- return Status;
-
- case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
- case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
- case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
- case EFI_HII_IIBT_IMAGE_1BIT:
- case EFI_HII_IIBT_IMAGE_4BIT:
- case EFI_HII_IIBT_IMAGE_8BIT:
- //
- // Use the common block code since the definition of these structures is the same.
- //
- Image->Width = ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width);
- Image->Height = ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height);
- Image->Image.Bitmap = NULL;
- return EFI_SUCCESS;
-
- case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
- case EFI_HII_IIBT_IMAGE_24BIT:
- Image->Width = ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width);
- Image->Height = ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height);
- Image->Image.Bitmap = NULL;
- return EFI_SUCCESS;
-
- default:
- return EFI_NOT_FOUND;
- }
-}
+/** @file
+Implementation for EFI_HII_IMAGE_EX_PROTOCOL.
+
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "HiiDatabase.h"
+
+/**
+ The prototype of this extension function is the same with EFI_HII_IMAGE_PROTOCOL.NewImage().
+ This protocol invokes EFI_HII_IMAGE_PROTOCOL.NewImage() implicitly.
+
+ @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
+ @param PackageList Handle of the package list where this image will
+ be added.
+ @param ImageId On return, contains the new image id, which is
+ unique within PackageList.
+ @param Image Points to the image.
+
+ @retval EFI_SUCCESS The new image was added successfully.
+ @retval EFI_NOT_FOUND The PackageList could not be found.
+ @retval EFI_OUT_OF_RESOURCES Could not add the image due to lack of resources.
+ @retval EFI_INVALID_PARAMETER Image is NULL or ImageId is NULL.
+**/
+EFI_STATUS
+EFIAPI
+HiiNewImageEx (
+ IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ OUT EFI_IMAGE_ID *ImageId,
+ IN CONST EFI_IMAGE_INPUT *Image
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+
+ Private = HII_IMAGE_EX_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ return HiiNewImage (&Private->HiiImage, PackageList, ImageId, Image);
+}
+
+/**
+ Return the information about the image, associated with the package list.
+ The prototype of this extension function is the same with EFI_HII_IMAGE_PROTOCOL.GetImage().
+
+ This function is similar to EFI_HII_IMAGE_PROTOCOL.GetImage().The difference is that
+ this function will locate all EFI_HII_IMAGE_DECODER_PROTOCOL instances installed in the
+ system if the decoder of the certain image type is not supported by the
+ EFI_HII_IMAGE_EX_PROTOCOL. The function will attempt to decode the image to the
+ EFI_IMAGE_INPUT using the first EFI_HII_IMAGE_DECODER_PROTOCOL instance that
+ supports the requested image type.
+
+ @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
+ @param PackageList The package list in the HII database to search for the
+ specified image.
+ @param ImageId The image's id, which is unique within PackageList.
+ @param Image Points to the image.
+
+ @retval EFI_SUCCESS The new image was returned successfully.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not available. The specified
+ PackageList is not in the Database.
+ @retval EFI_INVALID_PARAMETER Image was NULL or ImageId was 0.
+ @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there
+ was not enough memory.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetImageEx (
+ IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ OUT EFI_IMAGE_INPUT *Image
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+
+ Private = HII_IMAGE_EX_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ return IGetImage (&Private->DatabaseList, PackageList, ImageId, Image, FALSE);
+}
+
+/**
+ Change the information about the image.
+
+ Same with EFI_HII_IMAGE_PROTOCOL.SetImage(),this protocol invokes
+ EFI_HII_IMAGE_PROTOCOL.SetImage()implicitly.
+
+ @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
+ @param PackageList The package list containing the images.
+ @param ImageId The image's id, which is unique within PackageList.
+ @param Image Points to the image.
+
+ @retval EFI_SUCCESS The new image was successfully updated.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the
+ database. The specified PackageList is not in
+ the database.
+ @retval EFI_INVALID_PARAMETER The Image was NULL, the ImageId was 0 or
+ the Image->Bitmap was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiSetImageEx (
+ IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ IN CONST EFI_IMAGE_INPUT *Image
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+
+ Private = HII_IMAGE_EX_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ return HiiSetImage (&Private->HiiImage, PackageList, ImageId, Image);
+}
+
+/**
+ Renders an image to a bitmap or to the display.
+
+ The prototype of this extension function is the same with
+ EFI_HII_IMAGE_PROTOCOL.DrawImage(). This protocol invokes
+ EFI_HII_IMAGE_PROTOCOL.DrawImage() implicitly.
+
+ @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
+ @param Flags Describes how the image is to be drawn.
+ @param Image Points to the image to be displayed.
+ @param Blt If this points to a non-NULL on entry, this points
+ to the image, which is Width pixels wide and
+ Height pixels high. The image will be drawn onto
+ this image and EFI_HII_DRAW_FLAG_CLIP is implied.
+ If this points to a NULL on entry, then a buffer
+ will be allocated to hold the generated image and
+ the pointer updated on exit. It is the caller's
+ responsibility to free this buffer.
+ @param BltX Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+ @param BltY Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+
+ @retval EFI_SUCCESS The image was successfully drawn.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
+ @retval EFI_INVALID_PARAMETER The Image or Blt was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiDrawImageEx (
+ IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
+ IN EFI_HII_DRAW_FLAGS Flags,
+ IN CONST EFI_IMAGE_INPUT *Image,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+
+ Private = HII_IMAGE_EX_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ return HiiDrawImage (&Private->HiiImage, Flags, Image, Blt, BltX, BltY);
+}
+
+/**
+ Renders an image to a bitmap or the screen containing the contents of the specified
+ image.
+
+ This function is similar to EFI_HII_IMAGE_PROTOCOL.DrawImageId(). The difference is that
+ this function will locate all EFI_HII_IMAGE_DECODER_PROTOCOL instances installed in the
+ system if the decoder of the certain image type is not supported by the
+ EFI_HII_IMAGE_EX_PROTOCOL. The function will attempt to decode the image to the
+ EFI_IMAGE_INPUT using the first EFI_HII_IMAGE_DECODER_PROTOCOL instance that
+ supports the requested image type.
+
+ @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
+ @param Flags Describes how the image is to be drawn.
+ @param PackageList The package list in the HII database to search for
+ the specified image.
+ @param ImageId The image's id, which is unique within PackageList.
+ @param Blt If this points to a non-NULL on entry, this points
+ to the image, which is Width pixels wide and
+ Height pixels high. The image will be drawn onto
+ this image and EFI_HII_DRAW_FLAG_CLIP is implied.
+ If this points to a NULL on entry, then a buffer
+ will be allocated to hold the generated image
+ and the pointer updated on exit. It is the caller's
+ responsibility to free this buffer.
+ @param BltX Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+ @param BltY Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+
+ @retval EFI_SUCCESS The image was successfully drawn.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
+ @retval EFI_INVALID_PARAMETER The Blt was NULL or ImageId was 0.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the database.
+ The specified PackageList is not in the database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiDrawImageIdEx (
+ IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
+ IN EFI_HII_DRAW_FLAGS Flags,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY
+ )
+{
+ EFI_STATUS Status;
+ EFI_IMAGE_INPUT Image;
+
+ //
+ // Check input parameter.
+ //
+ if ((This == NULL) || (Blt == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get the specified Image.
+ //
+ Status = HiiGetImageEx (This, PackageList, ImageId, &Image);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Draw this image.
+ //
+ Status = HiiDrawImageEx (This, Flags, &Image, Blt, BltX, BltY);
+ if (Image.Bitmap != NULL) {
+ FreePool (Image.Bitmap);
+ }
+
+ return Status;
+}
+
+/**
+ Return the first HII image decoder instance which supports the DecoderName.
+
+ @param BlockType The image block type.
+
+ @retval Pointer to the HII image decoder instance.
+**/
+EFI_HII_IMAGE_DECODER_PROTOCOL *
+LocateHiiImageDecoder (
+ UINT8 BlockType
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_IMAGE_DECODER_PROTOCOL *Decoder;
+ EFI_HANDLE *Handles;
+ UINTN HandleNum;
+ UINTN Index;
+ EFI_GUID *DecoderNames;
+ UINT16 NumberOfDecoderName;
+ UINT16 DecoderNameIndex;
+ EFI_GUID *DecoderName;
+
+ switch (BlockType) {
+ case EFI_HII_IIBT_IMAGE_JPEG:
+ DecoderName = &gEfiHiiImageDecoderNameJpegGuid;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_PNG:
+ DecoderName = &gEfiHiiImageDecoderNamePngGuid;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ return NULL;
+ }
+
+ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiHiiImageDecoderProtocolGuid, NULL, &HandleNum, &Handles);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ for (Index = 0; Index < HandleNum; Index++) {
+ Status = gBS->HandleProtocol (Handles[Index], &gEfiHiiImageDecoderProtocolGuid, (VOID **)&Decoder);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Status = Decoder->GetImageDecoderName (Decoder, &DecoderNames, &NumberOfDecoderName);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ for (DecoderNameIndex = 0; DecoderNameIndex < NumberOfDecoderName; DecoderNameIndex++) {
+ if (CompareGuid (DecoderName, &DecoderNames[DecoderNameIndex])) {
+ return Decoder;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ This function returns the image information to EFI_IMAGE_OUTPUT. Only the width
+ and height are returned to the EFI_IMAGE_OUTPUT instead of decoding the image
+ to the buffer. This function is used to get the geometry of the image. This function
+ will try to locate all of the EFI_HII_IMAGE_DECODER_PROTOCOL installed on the
+ system if the decoder of image type is not supported by the EFI_HII_IMAGE_EX_PROTOCOL.
+
+ @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance.
+ @param PackageList Handle of the package list where this image will
+ be searched.
+ @param ImageId The image's id, which is unique within PackageList.
+ @param Image Points to the image.
+
+ @retval EFI_SUCCESS The new image was returned successfully.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the
+ database. The specified PackageList is not in the database.
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
+ hold the image.
+ @retval EFI_INVALID_PARAMETER The Image was NULL or the ImageId was 0.
+ @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there
+ was not enough memory.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetImageInfo (
+ IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ OUT EFI_IMAGE_OUTPUT *Image
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
+ EFI_HII_IMAGE_BLOCK *CurrentImageBlock;
+ EFI_HII_IMAGE_DECODER_PROTOCOL *Decoder;
+ EFI_HII_IMAGE_DECODER_IMAGE_INFO_HEADER *ImageInfo;
+
+ if ((Image == NULL) || (ImageId == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_IMAGE_EX_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ PackageListNode = LocatePackageList (&Private->DatabaseList, PackageList);
+ if (PackageListNode == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ ImagePackage = PackageListNode->ImagePkg;
+ if (ImagePackage == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Find the image block specified by ImageId
+ //
+ CurrentImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &ImageId);
+ if (CurrentImageBlock == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ switch (CurrentImageBlock->BlockType) {
+ case EFI_HII_IIBT_IMAGE_JPEG:
+ case EFI_HII_IIBT_IMAGE_PNG:
+ Decoder = LocateHiiImageDecoder (CurrentImageBlock->BlockType);
+ if (Decoder == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Use the common block code since the definition of two structures is the same.
+ //
+ ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Data) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Data));
+ ASSERT (
+ sizeof (((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Data) ==
+ sizeof (((EFI_HII_IIBT_PNG_BLOCK *)CurrentImageBlock)->Data)
+ );
+ ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Size) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Size));
+ ASSERT (
+ sizeof (((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Size) ==
+ sizeof (((EFI_HII_IIBT_PNG_BLOCK *)CurrentImageBlock)->Size)
+ );
+ Status = Decoder->GetImageInfo (
+ Decoder,
+ ((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Data,
+ ((EFI_HII_IIBT_JPEG_BLOCK *)CurrentImageBlock)->Size,
+ &ImageInfo
+ );
+
+ //
+ // Spec requires to use the first capable image decoder instance.
+ // The first image decoder instance may fail to decode the image.
+ //
+ if (!EFI_ERROR (Status)) {
+ Image->Height = ImageInfo->ImageHeight;
+ Image->Width = ImageInfo->ImageWidth;
+ Image->Image.Bitmap = NULL;
+ FreePool (ImageInfo);
+ }
+
+ return Status;
+
+ case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
+ case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
+ case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
+ case EFI_HII_IIBT_IMAGE_1BIT:
+ case EFI_HII_IIBT_IMAGE_4BIT:
+ case EFI_HII_IIBT_IMAGE_8BIT:
+ //
+ // Use the common block code since the definition of these structures is the same.
+ //
+ Image->Width = ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width);
+ Image->Height = ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height);
+ Image->Image.Bitmap = NULL;
+ return EFI_SUCCESS;
+
+ case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
+ case EFI_HII_IIBT_IMAGE_24BIT:
+ Image->Width = ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Width);
+ Image->Height = ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *)CurrentImageBlock)->Bitmap.Height);
+ Image->Image.Bitmap = NULL;
+ return EFI_SUCCESS;
+
+ default:
+ return EFI_NOT_FOUND;
+ }
+}
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/String.c b/MdeModulePkg/Universal/HiiDatabaseDxe/String.c
index e3fceed7c4..29308163cd 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/String.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/String.c
@@ -1,2120 +1,2120 @@
-/** @file
-Implementation for EFI_HII_STRING_PROTOCOL.
-
-
-Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>
-(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "HiiDatabase.h"
-
-CHAR16 mLanguageWindow[16] = {
- 0x0000, 0x0080, 0x0100, 0x0300,
- 0x2000, 0x2080, 0x2100, 0x3000,
- 0x0080, 0x00C0, 0x0400, 0x0600,
- 0x0900, 0x3040, 0x30A0, 0xFF00
-};
-
-/**
- This function checks whether a global font info is referred by local
- font info list or not. (i.e. HII_FONT_INFO is generated.) If not, create
- a HII_FONT_INFO to refer it locally.
-
- This is a internal function.
-
-
- @param Private Hii database private structure.
- @param StringPackage HII string package instance.
- @param FontId Font identifer, which must be unique within the string package.
- @param DuplicateEnable If true, duplicate HII_FONT_INFO which refers to
- the same EFI_FONT_INFO is permitted. Otherwise it
- is not allowed.
- @param GlobalFontInfo Input a global font info which specify a
- EFI_FONT_INFO.
- @param LocalFontInfo Output a local font info which refers to a
- EFI_FONT_INFO.
-
- @retval TRUE Already referred before calling this function.
- @retval FALSE Not referred before calling this function.
-
-**/
-BOOLEAN
-ReferFontInfoLocally (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
- IN UINT8 FontId,
- IN BOOLEAN DuplicateEnable,
- IN HII_GLOBAL_FONT_INFO *GlobalFontInfo,
- OUT HII_FONT_INFO **LocalFontInfo
- )
-{
- HII_FONT_INFO *LocalFont;
- LIST_ENTRY *Link;
-
- ASSERT (Private != NULL && StringPackage != NULL && GlobalFontInfo != NULL && LocalFontInfo != NULL);
-
- if (!DuplicateEnable) {
- for (Link = StringPackage->FontInfoList.ForwardLink;
- Link != &StringPackage->FontInfoList;
- Link = Link->ForwardLink
- )
- {
- LocalFont = CR (Link, HII_FONT_INFO, Entry, HII_FONT_INFO_SIGNATURE);
- if (LocalFont->GlobalEntry == &GlobalFontInfo->Entry) {
- //
- // Already referred by local font info list, return directly.
- //
- *LocalFontInfo = LocalFont;
- return TRUE;
- }
- }
- }
-
- // FontId identifies EFI_FONT_INFO in local string package uniquely.
- // GlobalEntry points to a HII_GLOBAL_FONT_INFO which identifies
- // EFI_FONT_INFO uniquely in whole hii database.
- //
- LocalFont = (HII_FONT_INFO *)AllocateZeroPool (sizeof (HII_FONT_INFO));
- ASSERT (LocalFont != NULL);
-
- LocalFont->Signature = HII_FONT_INFO_SIGNATURE;
- LocalFont->FontId = FontId;
- LocalFont->GlobalEntry = &GlobalFontInfo->Entry;
- InsertTailList (&StringPackage->FontInfoList, &LocalFont->Entry);
-
- *LocalFontInfo = LocalFont;
- return FALSE;
-}
-
-/**
- Convert Ascii string text to unicode string test.
-
- This is a internal function.
-
-
- @param StringDest Buffer to store the string text. If it is NULL,
- only the size will be returned.
- @param StringSrc Points to current null-terminated string.
- @param BufferSize Length of the buffer.
-
- @retval EFI_SUCCESS The string text was outputted successfully.
- @retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string
- text. BufferSize is updated to the required buffer
- size.
-
-**/
-EFI_STATUS
-ConvertToUnicodeText (
- OUT EFI_STRING StringDest,
- IN CHAR8 *StringSrc,
- IN OUT UINTN *BufferSize
- )
-{
- UINTN StringSize;
- UINTN Index;
-
- ASSERT (StringSrc != NULL && BufferSize != NULL);
-
- StringSize = AsciiStrSize (StringSrc) * 2;
- if ((*BufferSize < StringSize) || (StringDest == NULL)) {
- *BufferSize = StringSize;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- for (Index = 0; Index < AsciiStrLen (StringSrc); Index++) {
- StringDest[Index] = (CHAR16)StringSrc[Index];
- }
-
- StringDest[Index] = 0;
- return EFI_SUCCESS;
-}
-
-/**
- Calculate the size of StringSrc and output it. If StringDest is not NULL,
- copy string text from src to dest.
-
- This is a internal function.
-
- @param StringDest Buffer to store the string text. If it is NULL,
- only the size will be returned.
- @param StringSrc Points to current null-terminated string.
- @param BufferSize Length of the buffer.
-
- @retval EFI_SUCCESS The string text was outputted successfully.
- @retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string
- text. BufferSize is updated to the required buffer
- size.
-
-**/
-EFI_STATUS
-GetUnicodeStringTextOrSize (
- OUT EFI_STRING StringDest OPTIONAL,
- IN UINT8 *StringSrc,
- IN OUT UINTN *BufferSize
- )
-{
- UINTN StringSize;
- UINT8 *StringPtr;
-
- ASSERT (StringSrc != NULL && BufferSize != NULL);
-
- StringSize = sizeof (CHAR16);
- StringPtr = StringSrc;
- while (ReadUnaligned16 ((UINT16 *)StringPtr) != 0) {
- StringSize += sizeof (CHAR16);
- StringPtr += sizeof (CHAR16);
- }
-
- if (*BufferSize < StringSize) {
- *BufferSize = StringSize;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- if (StringDest != NULL) {
- CopyMem (StringDest, StringSrc, StringSize);
- }
-
- *BufferSize = StringSize;
- return EFI_SUCCESS;
-}
-
-/**
- Copy string font info to a buffer.
-
- This is a internal function.
-
- @param StringPackage Hii string package instance.
- @param FontId Font identifier which is unique in a string
- package.
- @param StringFontInfo Buffer to record the output font info. It's
- caller's responsibility to free this buffer.
-
- @retval EFI_SUCCESS The string font is outputted successfully.
- @retval EFI_NOT_FOUND The specified font id does not exist.
-
-**/
-EFI_STATUS
-GetStringFontInfo (
- IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
- IN UINT8 FontId,
- OUT EFI_FONT_INFO **StringFontInfo
- )
-{
- LIST_ENTRY *Link;
- HII_FONT_INFO *FontInfo;
- HII_GLOBAL_FONT_INFO *GlobalFont;
-
- ASSERT (StringFontInfo != NULL && StringPackage != NULL);
-
- for (Link = StringPackage->FontInfoList.ForwardLink; Link != &StringPackage->FontInfoList; Link = Link->ForwardLink) {
- FontInfo = CR (Link, HII_FONT_INFO, Entry, HII_FONT_INFO_SIGNATURE);
- if (FontInfo->FontId == FontId) {
- GlobalFont = CR (FontInfo->GlobalEntry, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);
- *StringFontInfo = (EFI_FONT_INFO *)AllocateZeroPool (GlobalFont->FontInfoSize);
- if (*StringFontInfo == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- CopyMem (*StringFontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize);
- return EFI_SUCCESS;
- }
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- Parse all string blocks to find a String block specified by StringId.
- If StringId = (EFI_STRING_ID) (-1), find out all EFI_HII_SIBT_FONT blocks
- within this string package and backup its information. If LastStringId is
- specified, the string id of last string block will also be output.
- If StringId = 0, output the string id of last string block (EFI_HII_SIBT_STRING).
-
- @param Private Hii database private structure.
- @param StringPackage Hii string package instance.
- @param StringId The string's id, which is unique within
- PackageList.
- @param BlockType Output the block type of found string block.
- @param StringBlockAddr Output the block address of found string block.
- @param StringTextOffset Offset, relative to the found block address, of
- the string text information.
- @param LastStringId Output the last string id when StringId = 0 or StringId = -1.
- @param StartStringId The first id in the skip block which StringId in the block.
-
- @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
-FindStringBlock (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
- IN EFI_STRING_ID StringId,
- OUT UINT8 *BlockType OPTIONAL,
- OUT UINT8 **StringBlockAddr OPTIONAL,
- OUT UINTN *StringTextOffset OPTIONAL,
- OUT EFI_STRING_ID *LastStringId OPTIONAL,
- OUT EFI_STRING_ID *StartStringId OPTIONAL
- )
-{
- UINT8 *BlockHdr;
- EFI_STRING_ID CurrentStringId;
- UINTN BlockSize;
- UINTN Index;
- UINT8 *StringTextPtr;
- UINTN Offset;
- HII_FONT_INFO *LocalFont;
- EFI_FONT_INFO *FontInfo;
- HII_GLOBAL_FONT_INFO *GlobalFont;
- UINTN FontInfoSize;
- UINT16 StringCount;
- UINT16 SkipCount;
- EFI_HII_FONT_STYLE FontStyle;
- UINT16 FontSize;
- UINT8 Length8;
- EFI_HII_SIBT_EXT2_BLOCK Ext2;
- UINT8 FontId;
- UINT32 Length32;
- UINTN StringSize;
- CHAR16 Zero;
-
- ASSERT (StringPackage != NULL);
- ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);
-
- CurrentStringId = 1;
- StringSize = 0;
-
- if ((StringId != (EFI_STRING_ID)(-1)) && (StringId != 0)) {
- ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);
- if (StringId > StringPackage->MaxStringId) {
- return EFI_NOT_FOUND;
- }
- } else {
- ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
- if ((StringId == 0) && (LastStringId != NULL)) {
- *LastStringId = StringPackage->MaxStringId;
- return EFI_SUCCESS;
- }
- }
-
- ZeroMem (&Zero, sizeof (CHAR16));
-
- //
- // 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;
- 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;
- 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 (CurrentStringId == StringId) {
- ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);
- *BlockType = *BlockHdr;
- *StringBlockAddr = BlockHdr;
- *StringTextOffset = StringTextPtr - BlockHdr;
- return EFI_SUCCESS;
- }
-
- 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 (CurrentStringId == StringId) {
- ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);
- *BlockType = *BlockHdr;
- *StringBlockAddr = BlockHdr;
- *StringTextOffset = StringTextPtr - BlockHdr;
- return EFI_SUCCESS;
- }
-
- 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.
- //
- GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
- 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 StrSize to store the size of the specified string, including the NULL
- // terminator.
- //
- GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
- 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++) {
- GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
- BlockSize += StringSize;
- if (CurrentStringId == StringId) {
- ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);
- *BlockType = *BlockHdr;
- *StringBlockAddr = BlockHdr;
- *StringTextOffset = StringTextPtr - BlockHdr;
- return EFI_SUCCESS;
- }
-
- 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++) {
- GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
- BlockSize += StringSize;
- if (CurrentStringId == StringId) {
- ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);
- *BlockType = *BlockHdr;
- *StringBlockAddr = BlockHdr;
- *StringTextOffset = StringTextPtr - BlockHdr;
- return EFI_SUCCESS;
- }
-
- StringTextPtr = StringTextPtr + StringSize;
- CurrentStringId++;
- }
-
- break;
-
- case EFI_HII_SIBT_DUPLICATE:
- if (CurrentStringId == StringId) {
- //
- // Incoming StringId is an id of a duplicate string block.
- // Update the StringId to be the previous string block.
- // Go back to the header of string block to search.
- //
- CopyMem (
- &StringId,
- BlockHdr + sizeof (EFI_HII_STRING_BLOCK),
- sizeof (EFI_STRING_ID)
- );
- ASSERT (StringId != CurrentStringId);
- CurrentStringId = 1;
- BlockSize = 0;
- } else {
- 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));
- if ((Ext2.BlockType2 == EFI_HII_SIBT_FONT) && (StringId == (EFI_STRING_ID)(-1))) {
- //
- // Find the relationship between global font info and the font info of
- // this EFI_HII_SIBT_FONT block then backup its information in local package.
- //
- BlockHdr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);
- CopyMem (&FontId, BlockHdr, sizeof (UINT8));
- BlockHdr++;
- CopyMem (&FontSize, BlockHdr, sizeof (UINT16));
- BlockHdr += sizeof (UINT16);
- CopyMem (&FontStyle, BlockHdr, sizeof (EFI_HII_FONT_STYLE));
- BlockHdr += sizeof (EFI_HII_FONT_STYLE);
- GetUnicodeStringTextOrSize (NULL, BlockHdr, &StringSize);
-
- FontInfoSize = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + StringSize;
- FontInfo = (EFI_FONT_INFO *)AllocateZeroPool (FontInfoSize);
- if (FontInfo == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- FontInfo->FontStyle = FontStyle;
- FontInfo->FontSize = FontSize;
- CopyMem (FontInfo->FontName, BlockHdr, StringSize);
-
- //
- // If find the corresponding global font info, save the relationship.
- // Otherwise ignore this EFI_HII_SIBT_FONT block.
- //
- if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont)) {
- ReferFontInfoLocally (Private, StringPackage, FontId, TRUE, GlobalFont, &LocalFont);
- }
-
- //
- // Since string package tool set FontId initially to 0 and increases it
- // progressively by one, StringPackage->FondId always represents an unique
- // and available FontId.
- //
- StringPackage->FontId++;
-
- FreePool (FontInfo);
- }
-
- 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 ((StringId > 0) && (StringId != (EFI_STRING_ID)(-1))) {
- ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);
- *BlockType = *BlockHdr;
- *StringBlockAddr = BlockHdr;
- *StringTextOffset = Offset;
-
- if (StringId == CurrentStringId - 1) {
- //
- // if only one skip item, return EFI_NOT_FOUND.
- //
- if ((*BlockType == EFI_HII_SIBT_SKIP2) || (*BlockType == EFI_HII_SIBT_SKIP1)) {
- return EFI_NOT_FOUND;
- } else {
- return EFI_SUCCESS;
- }
- }
-
- if (StringId < CurrentStringId - 1) {
- return EFI_NOT_FOUND;
- }
- }
-
- BlockHdr = StringPackage->StringBlock + BlockSize;
- if (StartStringId != NULL) {
- *StartStringId = CurrentStringId;
- }
- }
-
- //
- // Get last string ID
- //
- if ((StringId == (EFI_STRING_ID)(-1)) && (LastStringId != NULL)) {
- *LastStringId = (EFI_STRING_ID)(CurrentStringId - 1);
- return EFI_SUCCESS;
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- Parse all string blocks to get a string specified by StringId.
-
- This is a internal function.
-
- @param Private Hii database private structure.
- @param StringPackage Hii string package instance.
- @param StringId The string's id, which is unique within
- PackageList.
- @param String Points to retrieved null-terminated string.
- @param StringSize On entry, points to the size of the buffer pointed
- to by String, in bytes. On return, points to the
- length of the string, in bytes.
- @param StringFontInfo If not NULL, allocate a buffer to record the
- output font info. It's caller's responsibility to
- free this buffer.
-
- @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_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to
- hold the string.
-
-**/
-EFI_STATUS
-GetStringWorker (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
- IN EFI_STRING_ID StringId,
- OUT EFI_STRING String,
- IN OUT UINTN *StringSize OPTIONAL,
- OUT EFI_FONT_INFO **StringFontInfo OPTIONAL
- )
-{
- UINT8 *StringTextPtr;
- UINT8 BlockType;
- UINT8 *StringBlockAddr;
- UINTN StringTextOffset;
- EFI_STATUS Status;
- UINT8 FontId;
-
- ASSERT (StringPackage != NULL);
- ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
-
- //
- // Find the specified string block
- //
- Status = FindStringBlock (
- Private,
- StringPackage,
- StringId,
- &BlockType,
- &StringBlockAddr,
- &StringTextOffset,
- NULL,
- NULL
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (StringSize == NULL) {
- //
- // String text buffer is not requested
- //
- return EFI_SUCCESS;
- }
-
- //
- // Get the string text.
- //
- StringTextPtr = StringBlockAddr + StringTextOffset;
- switch (BlockType) {
- case EFI_HII_SIBT_STRING_SCSU:
- case EFI_HII_SIBT_STRING_SCSU_FONT:
- case EFI_HII_SIBT_STRINGS_SCSU:
- case EFI_HII_SIBT_STRINGS_SCSU_FONT:
- Status = ConvertToUnicodeText (String, (CHAR8 *)StringTextPtr, StringSize);
- break;
- case EFI_HII_SIBT_STRING_UCS2:
- case EFI_HII_SIBT_STRING_UCS2_FONT:
- case EFI_HII_SIBT_STRINGS_UCS2:
- case EFI_HII_SIBT_STRINGS_UCS2_FONT:
- Status = GetUnicodeStringTextOrSize (String, StringTextPtr, StringSize);
- break;
- default:
- return EFI_NOT_FOUND;
- }
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Get the string font. The FontId 0 is the default font for those string blocks which
- // do not specify a font identifier. If default font is not specified, return NULL.
- //
- if (StringFontInfo != NULL) {
- switch (BlockType) {
- case EFI_HII_SIBT_STRING_SCSU_FONT:
- case EFI_HII_SIBT_STRINGS_SCSU_FONT:
- case EFI_HII_SIBT_STRING_UCS2_FONT:
- case EFI_HII_SIBT_STRINGS_UCS2_FONT:
- FontId = *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK));
- break;
- default:
- FontId = 0;
- }
-
- Status = GetStringFontInfo (StringPackage, FontId, StringFontInfo);
- if (Status == EFI_NOT_FOUND) {
- *StringFontInfo = NULL;
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- If GetStringBlock find the StringId's string is not saved in the exist string block,
- this function will create the UCS2 string block to save the string; also split the
- skip block into two or one skip block.
-
- This is a internal function.
-
- @param StringPackage Hii string package instance.
- @param StartStringId The first id in the skip block which StringId in the block.
- @param StringId The string's id, which is unique within
- PackageList.
- @param BlockType Output the block type of found string block.
- @param StringBlockAddr Output the block address of found string block.
- @param FontBlock whether this string block has font info.
-
- @retval EFI_SUCCESS The string font is outputted successfully.
- @retval EFI_OUT_OF_RESOURCES NO resource for the memory to save the new string block.
-
-**/
-EFI_STATUS
-InsertLackStringBlock (
- IN OUT HII_STRING_PACKAGE_INSTANCE *StringPackage,
- IN EFI_STRING_ID StartStringId,
- IN EFI_STRING_ID StringId,
- IN OUT UINT8 *BlockType,
- IN OUT UINT8 **StringBlockAddr,
- IN BOOLEAN FontBlock
- )
-{
- UINT8 *BlockPtr;
- UINT8 *StringBlock;
- UINT32 SkipLen;
- UINT32 OldBlockSize;
- UINT32 NewBlockSize;
- UINT32 FrontSkipNum;
- UINT32 NewUCSBlockLen;
- UINT8 *OldStringAddr;
- UINT32 IdCount;
-
- FrontSkipNum = 0;
- SkipLen = 0;
- OldStringAddr = *StringBlockAddr;
-
- ASSERT (*BlockType == EFI_HII_SIBT_SKIP1 || *BlockType == EFI_HII_SIBT_SKIP2);
- //
- // Old skip block size.
- //
- if (*BlockType == EFI_HII_SIBT_SKIP1) {
- SkipLen = sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
- IdCount = *(UINT8 *)(OldStringAddr + sizeof (EFI_HII_STRING_BLOCK));
- } else {
- SkipLen = sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
- IdCount = *(UINT16 *)(OldStringAddr + sizeof (EFI_HII_STRING_BLOCK));
- }
-
- //
- // New create UCS or UCS2 block size.
- //
- if (FontBlock) {
- NewUCSBlockLen = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK);
- } else {
- NewUCSBlockLen = sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);
- }
-
- OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
-
- if (StartStringId == StringId) {
- //
- // New block + [Skip block]
- //
- if (IdCount > 1) {
- NewBlockSize = OldBlockSize + NewUCSBlockLen;
- } else {
- NewBlockSize = OldBlockSize + NewUCSBlockLen - SkipLen;
- }
- } else if (StartStringId + IdCount - 1 == StringId) {
- //
- // Skip block + New block
- //
- NewBlockSize = OldBlockSize + NewUCSBlockLen;
- FrontSkipNum = StringId - StartStringId;
- } else {
- //
- // Skip block + New block + [Skip block]
- //
- NewBlockSize = OldBlockSize + NewUCSBlockLen + SkipLen;
- FrontSkipNum = StringId - StartStringId;
- }
-
- StringBlock = (UINT8 *)AllocateZeroPool (NewBlockSize);
- if (StringBlock == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Copy old block in front of skip block.
- //
- CopyMem (StringBlock, StringPackage->StringBlock, OldStringAddr - StringPackage->StringBlock);
- BlockPtr = StringBlock + (OldStringAddr - StringPackage->StringBlock);
-
- if (FrontSkipNum > 0) {
- *BlockPtr = *BlockType;
- if (*BlockType == EFI_HII_SIBT_SKIP1) {
- *(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT8)FrontSkipNum;
- } else {
- *(UINT16 *)(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT16)FrontSkipNum;
- }
-
- BlockPtr += SkipLen;
- }
-
- //
- // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
- //
- *StringBlockAddr = BlockPtr;
- if (FontBlock) {
- *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;
- } else {
- *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
- }
-
- BlockPtr += NewUCSBlockLen;
-
- if (IdCount > FrontSkipNum + 1) {
- *BlockPtr = *BlockType;
- if (*BlockType == EFI_HII_SIBT_SKIP1) {
- *(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT8)(IdCount - FrontSkipNum - 1);
- } else {
- *(UINT16 *)(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT16)(IdCount - FrontSkipNum - 1);
- }
-
- BlockPtr += SkipLen;
- }
-
- //
- // Append a EFI_HII_SIBT_END block to the end.
- //
- CopyMem (BlockPtr, OldStringAddr + SkipLen, OldBlockSize - (OldStringAddr - StringPackage->StringBlock) - SkipLen);
-
- if (FontBlock) {
- *BlockType = EFI_HII_SIBT_STRING_UCS2_FONT;
- } else {
- *BlockType = EFI_HII_SIBT_STRING_UCS2;
- }
-
- FreePool (StringPackage->StringBlock);
- StringPackage->StringBlock = StringBlock;
- StringPackage->StringPkgHdr->Header.Length += NewBlockSize - OldBlockSize;
-
- return EFI_SUCCESS;
-}
-
-/**
- Parse all string blocks to set a String specified by StringId.
-
- This is a internal function.
-
- @param Private HII database driver private structure.
- @param StringPackage HII string package instance.
- @param StringId The string's id, which is unique within
- PackageList.
- @param String Points to the new null-terminated string.
- @param StringFontInfo Points to the input font info.
-
- @retval EFI_SUCCESS The string was updated successfully.
- @retval EFI_NOT_FOUND The string specified by StringId is not in the
- database.
- @retval EFI_INVALID_PARAMETER The String or Language was NULL.
- @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in
- current database.
- @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
- task.
-
-**/
-EFI_STATUS
-SetStringWorker (
- IN HII_DATABASE_PRIVATE_DATA *Private,
- IN OUT HII_STRING_PACKAGE_INSTANCE *StringPackage,
- IN EFI_STRING_ID StringId,
- IN EFI_STRING String,
- IN EFI_FONT_INFO *StringFontInfo OPTIONAL
- )
-{
- UINT8 *StringTextPtr;
- UINT8 BlockType;
- UINT8 *StringBlockAddr;
- UINTN StringTextOffset;
- EFI_STATUS Status;
- UINT8 *Block;
- UINT8 *BlockPtr;
- UINTN BlockSize;
- UINTN OldBlockSize;
- HII_FONT_INFO *LocalFont;
- HII_GLOBAL_FONT_INFO *GlobalFont;
- BOOLEAN Referred;
- EFI_HII_SIBT_EXT2_BLOCK Ext2;
- UINTN StringSize;
- UINTN TmpSize;
- EFI_STRING_ID StartStringId;
-
- StartStringId = 0;
- StringSize = 0;
- ASSERT (Private != NULL && StringPackage != NULL && String != NULL);
- ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
- //
- // Find the specified string block
- //
- Status = FindStringBlock (
- Private,
- StringPackage,
- StringId,
- &BlockType,
- &StringBlockAddr,
- &StringTextOffset,
- NULL,
- &StartStringId
- );
- if (EFI_ERROR (Status) && ((BlockType == EFI_HII_SIBT_SKIP1) || (BlockType == EFI_HII_SIBT_SKIP2))) {
- Status = InsertLackStringBlock (
- StringPackage,
- StartStringId,
- StringId,
- &BlockType,
- &StringBlockAddr,
- (BOOLEAN)(StringFontInfo != NULL)
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (StringFontInfo != NULL) {
- StringTextOffset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);
- } else {
- StringTextOffset = sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16);
- }
- }
-
- LocalFont = NULL;
- GlobalFont = NULL;
- Referred = FALSE;
-
- //
- // The input StringFontInfo should exist in current database if specified.
- //
- if (StringFontInfo != NULL) {
- if (!IsFontInfoExisted (Private, StringFontInfo, NULL, NULL, &GlobalFont)) {
- return EFI_INVALID_PARAMETER;
- } else {
- Referred = ReferFontInfoLocally (
- Private,
- StringPackage,
- StringPackage->FontId,
- FALSE,
- GlobalFont,
- &LocalFont
- );
- if (!Referred) {
- StringPackage->FontId++;
- }
- }
-
- //
- // Update the FontId of the specified string block to input font info.
- //
- switch (BlockType) {
- case EFI_HII_SIBT_STRING_SCSU_FONT:
- case EFI_HII_SIBT_STRINGS_SCSU_FONT:
- case EFI_HII_SIBT_STRING_UCS2_FONT:
- case EFI_HII_SIBT_STRINGS_UCS2_FONT:
- *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK)) = LocalFont->FontId;
- break;
- default:
- //
- // When modify the font info of these blocks, the block type should be updated
- // to contain font info thus the whole structure should be revised.
- // It is recommended to use tool to modify the block type not in the code.
- //
- return EFI_UNSUPPORTED;
- }
- }
-
- OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
-
- //
- // Set the string text and font.
- //
- StringTextPtr = StringBlockAddr + StringTextOffset;
- switch (BlockType) {
- case EFI_HII_SIBT_STRING_SCSU:
- case EFI_HII_SIBT_STRING_SCSU_FONT:
- case EFI_HII_SIBT_STRINGS_SCSU:
- case EFI_HII_SIBT_STRINGS_SCSU_FONT:
- BlockSize = OldBlockSize + StrLen (String);
- BlockSize -= AsciiStrSize ((CHAR8 *)StringTextPtr);
- Block = AllocateZeroPool (BlockSize);
- if (Block == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock);
- BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock);
-
- while (*String != 0) {
- *BlockPtr++ = (CHAR8)*String++;
- }
-
- *BlockPtr++ = 0;
-
- TmpSize = OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - AsciiStrSize ((CHAR8 *)StringTextPtr);
- CopyMem (
- BlockPtr,
- StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr),
- TmpSize
- );
-
- ZeroMem (StringPackage->StringBlock, OldBlockSize);
- FreePool (StringPackage->StringBlock);
- StringPackage->StringBlock = Block;
- StringPackage->StringPkgHdr->Header.Length += (UINT32)(BlockSize - OldBlockSize);
- break;
-
- case EFI_HII_SIBT_STRING_UCS2:
- case EFI_HII_SIBT_STRING_UCS2_FONT:
- case EFI_HII_SIBT_STRINGS_UCS2:
- case EFI_HII_SIBT_STRINGS_UCS2_FONT:
- //
- // Use StrSize to store the size of the specified string, including the NULL
- // terminator.
- //
- GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
-
- BlockSize = OldBlockSize + StrSize (String) - StringSize;
- Block = AllocateZeroPool (BlockSize);
- if (Block == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock);
- BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock);
-
- CopyMem (BlockPtr, String, StrSize (String));
- BlockPtr += StrSize (String);
-
- CopyMem (
- BlockPtr,
- StringTextPtr + StringSize,
- OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - StringSize
- );
-
- ZeroMem (StringPackage->StringBlock, OldBlockSize);
- FreePool (StringPackage->StringBlock);
- StringPackage->StringBlock = Block;
- StringPackage->StringPkgHdr->Header.Length += (UINT32)(BlockSize - OldBlockSize);
- break;
-
- default:
- return EFI_NOT_FOUND;
- }
-
- //
- // Insert a new EFI_HII_SIBT_FONT_BLOCK to the header of string block, if incoming
- // StringFontInfo does not exist in current string package.
- //
- // This new block does not impact on the value of StringId.
- //
- //
- if ((StringFontInfo == NULL) || Referred) {
- return EFI_SUCCESS;
- }
-
- OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
- BlockSize = OldBlockSize + sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16) +
- StrSize (GlobalFont->FontInfo->FontName);
-
- Block = AllocateZeroPool (BlockSize);
- if (Block == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- BlockPtr = Block;
- Ext2.Header.BlockType = EFI_HII_SIBT_EXT2;
- Ext2.BlockType2 = EFI_HII_SIBT_FONT;
- Ext2.Length = (UINT16)(BlockSize - OldBlockSize);
- CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
- BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);
-
- *BlockPtr = LocalFont->FontId;
- BlockPtr++;
- CopyMem (BlockPtr, &GlobalFont->FontInfo->FontSize, sizeof (UINT16));
- BlockPtr += sizeof (UINT16);
- CopyMem (BlockPtr, &GlobalFont->FontInfo->FontStyle, sizeof (UINT32));
- BlockPtr += sizeof (UINT32);
- CopyMem (
- BlockPtr,
- GlobalFont->FontInfo->FontName,
- StrSize (GlobalFont->FontInfo->FontName)
- );
- BlockPtr += StrSize (GlobalFont->FontInfo->FontName);
-
- CopyMem (BlockPtr, StringPackage->StringBlock, OldBlockSize);
-
- ZeroMem (StringPackage->StringBlock, OldBlockSize);
- FreePool (StringPackage->StringBlock);
- StringPackage->StringBlock = Block;
- StringPackage->StringPkgHdr->Header.Length += Ext2.Length;
-
- return EFI_SUCCESS;
-}
-
-/**
- This function adds the string String to the group of strings owned by PackageList, with the
- specified font information StringFontInfo and returns a new string id.
- The new string identifier is guaranteed to be unique within the package list.
- That new string identifier is reserved for all languages in the package list.
-
-
- @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
- @param PackageList Handle of the package list where this string will
- be added.
- @param StringId On return, contains the new strings id, which is
- unique within PackageList.
- @param Language Points to the language for the new string.
- @param LanguageName Points to the printable language name to associate
- with the passed in Language field.If LanguageName
- is not NULL and the string package header's
- LanguageName associated with a given Language is
- not zero, the LanguageName being passed in will
- be ignored.
- @param String Points to the new null-terminated string.
- @param StringFontInfo Points to the new string's font information or
- NULL if the string should have the default system
- font, size and style.
-
- @retval EFI_SUCCESS The new string was added successfully.
- @retval EFI_NOT_FOUND The specified PackageList could not be found in
- database.
- @retval EFI_OUT_OF_RESOURCES Could not add the string due to lack of resources.
- @retval EFI_INVALID_PARAMETER String is NULL or StringId is NULL or Language is
- NULL.
- @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in
- current database.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiNewString (
- IN CONST EFI_HII_STRING_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- OUT EFI_STRING_ID *StringId,
- IN CONST CHAR8 *Language,
- IN CONST CHAR16 *LanguageName OPTIONAL,
- IN CONST EFI_STRING String,
- IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL
- )
-{
- EFI_STATUS Status;
- LIST_ENTRY *Link;
- HII_DATABASE_PRIVATE_DATA *Private;
- HII_DATABASE_RECORD *DatabaseRecord;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
- HII_STRING_PACKAGE_INSTANCE *StringPackage;
- UINT32 HeaderSize;
- UINT32 BlockSize;
- UINT32 OldBlockSize;
- UINT8 *StringBlock;
- UINT8 *BlockPtr;
- UINT32 Ucs2BlockSize;
- UINT32 FontBlockSize;
- UINT32 Ucs2FontBlockSize;
- EFI_HII_SIBT_EXT2_BLOCK Ext2;
- HII_FONT_INFO *LocalFont;
- HII_GLOBAL_FONT_INFO *GlobalFont;
- EFI_STRING_ID NewStringId;
- EFI_STRING_ID NextStringId;
- EFI_STRING_ID Index;
- HII_STRING_PACKAGE_INSTANCE *MatchStringPackage;
- BOOLEAN NewStringPackageCreated;
-
- if ((This == NULL) || (String == NULL) || (StringId == NULL) || (Language == NULL) || (PackageList == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (!IsHiiHandleValid (PackageList)) {
- return EFI_NOT_FOUND;
- }
-
- Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- GlobalFont = NULL;
-
- //
- // If StringFontInfo specify a paritcular font, it should exist in current database.
- //
- if (StringFontInfo != NULL) {
- if (!IsFontInfoExisted (Private, (EFI_FONT_INFO *)StringFontInfo, NULL, NULL, &GlobalFont)) {
- return EFI_INVALID_PARAMETER;
- }
- }
-
- //
- // Get the matching package list.
- //
- PackageListNode = NULL;
- for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
- DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- if (DatabaseRecord->Handle == PackageList) {
- PackageListNode = DatabaseRecord->PackageList;
- break;
- }
- }
-
- if (PackageListNode == NULL) {
- return EFI_NOT_FOUND;
- }
-
- EfiAcquireLock (&mHiiDatabaseLock);
-
- Status = EFI_SUCCESS;
- NewStringPackageCreated = FALSE;
- NewStringId = 0;
- NextStringId = 0;
- StringPackage = NULL;
- MatchStringPackage = NULL;
- for (Link = PackageListNode->StringPkgHdr.ForwardLink;
- Link != &PackageListNode->StringPkgHdr;
- Link = Link->ForwardLink
- )
- {
- StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
- //
- // Create a string block and corresponding font block if exists, then append them
- // to the end of the string package.
- //
- Status = FindStringBlock (
- Private,
- StringPackage,
- 0,
- NULL,
- NULL,
- NULL,
- &NextStringId,
- NULL
- );
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- //
- // Make sure that new StringId is same in all String Packages for the different language.
- //
- if ((NewStringId != 0) && (NewStringId != NextStringId)) {
- ASSERT (FALSE);
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- NewStringId = NextStringId;
- //
- // Get the matched string package with language.
- //
- if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *)Language)) {
- MatchStringPackage = StringPackage;
- } else {
- OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
- //
- // Create a blank EFI_HII_SIBT_STRING_UCS2_BLOCK to reserve new string ID.
- //
- Ucs2BlockSize = (UINT32)sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);
-
- StringBlock = (UINT8 *)AllocateZeroPool (OldBlockSize + Ucs2BlockSize);
- if (StringBlock == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- //
- // Copy original string blocks, except the EFI_HII_SIBT_END.
- //
- CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
- //
- // Create a blank EFI_HII_SIBT_STRING_UCS2 block
- //
- BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
- *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
- BlockPtr += sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);
-
- //
- // Append a EFI_HII_SIBT_END block to the end.
- //
- *BlockPtr = EFI_HII_SIBT_END;
- ZeroMem (StringPackage->StringBlock, OldBlockSize);
- FreePool (StringPackage->StringBlock);
- StringPackage->StringBlock = StringBlock;
- StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize;
- PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize;
- }
- }
-
- if (NewStringId == 0) {
- //
- // No string package is found.
- // Create new string package. StringId 1 is reserved for Language Name string.
- //
- *StringId = 2;
- } else {
- //
- // Set new StringId
- //
- *StringId = (EFI_STRING_ID)(NewStringId + 1);
- }
-
- if (MatchStringPackage != NULL) {
- StringPackage = MatchStringPackage;
- } else {
- //
- // LanguageName is required to create a new string package.
- //
- if (LanguageName == NULL) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- StringPackage = AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));
- if (StringPackage == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;
- StringPackage->MaxStringId = *StringId;
- StringPackage->FontId = 0;
- InitializeListHead (&StringPackage->FontInfoList);
-
- //
- // Fill in the string package header
- //
- HeaderSize = (UINT32)(AsciiStrSize ((CHAR8 *)Language) - 1 + sizeof (EFI_HII_STRING_PACKAGE_HDR));
- StringPackage->StringPkgHdr = AllocateZeroPool (HeaderSize);
- if (StringPackage->StringPkgHdr == NULL) {
- FreePool (StringPackage);
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- StringPackage->StringPkgHdr->Header.Type = EFI_HII_PACKAGE_STRINGS;
- StringPackage->StringPkgHdr->HdrSize = HeaderSize;
- StringPackage->StringPkgHdr->StringInfoOffset = HeaderSize;
- CopyMem (StringPackage->StringPkgHdr->LanguageWindow, mLanguageWindow, 16 * sizeof (CHAR16));
- StringPackage->StringPkgHdr->LanguageName = 1;
- AsciiStrCpyS (StringPackage->StringPkgHdr->Language, (HeaderSize - OFFSET_OF (EFI_HII_STRING_PACKAGE_HDR, Language)) / sizeof (CHAR8), (CHAR8 *)Language);
-
- //
- // Calculate the length of the string blocks, including string block to record
- // printable language full name and EFI_HII_SIBT_END_BLOCK.
- //
- Ucs2BlockSize = (UINT32)(StrSize ((CHAR16 *)LanguageName) +
- (*StringId - 1) * sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16));
-
- BlockSize = Ucs2BlockSize + sizeof (EFI_HII_SIBT_END_BLOCK);
- StringPackage->StringBlock = (UINT8 *)AllocateZeroPool (BlockSize);
- if (StringPackage->StringBlock == NULL) {
- FreePool (StringPackage->StringPkgHdr);
- FreePool (StringPackage);
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- //
- // Insert the string block of printable language full name
- //
- BlockPtr = StringPackage->StringBlock;
- *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
- BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
- CopyMem (BlockPtr, (EFI_STRING)LanguageName, StrSize ((EFI_STRING)LanguageName));
- BlockPtr += StrSize ((EFI_STRING)LanguageName);
- for (Index = 2; Index <= *StringId - 1; Index++) {
- *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
- BlockPtr += sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);
- }
-
- //
- // Insert the end block
- //
- *BlockPtr = EFI_HII_SIBT_END;
-
- //
- // Append this string package node to string package array in this package list.
- //
- StringPackage->StringPkgHdr->Header.Length = HeaderSize + BlockSize;
- PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;
- InsertTailList (&PackageListNode->StringPkgHdr, &StringPackage->StringEntry);
- NewStringPackageCreated = TRUE;
- }
-
- OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
-
- if (StringFontInfo == NULL) {
- //
- // Create a EFI_HII_SIBT_STRING_UCS2_BLOCK since font info is not specified.
- //
- Ucs2BlockSize = (UINT32)(StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK)
- - sizeof (CHAR16));
-
- StringBlock = (UINT8 *)AllocateZeroPool (OldBlockSize + Ucs2BlockSize);
- if (StringBlock == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- //
- // Copy original string blocks, except the EFI_HII_SIBT_END.
- //
- CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
- //
- // Create a EFI_HII_SIBT_STRING_UCS2 block
- //
- BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
- *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
- BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
- CopyMem (BlockPtr, (EFI_STRING)String, StrSize ((EFI_STRING)String));
- BlockPtr += StrSize ((EFI_STRING)String);
-
- //
- // Append a EFI_HII_SIBT_END block to the end.
- //
- *BlockPtr = EFI_HII_SIBT_END;
- ZeroMem (StringPackage->StringBlock, OldBlockSize);
- FreePool (StringPackage->StringBlock);
- StringPackage->StringBlock = StringBlock;
- StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize;
- PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize;
- } else {
- //
- // StringFontInfo is specified here. If there is a EFI_HII_SIBT_FONT_BLOCK
- // which refers to this font info, create a EFI_HII_SIBT_STRING_UCS2_FONT block
- // only. Otherwise create a EFI_HII_SIBT_FONT block with a EFI_HII_SIBT_STRING
- // _UCS2_FONT block.
- //
- Ucs2FontBlockSize = (UINT32)(StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) -
- sizeof (CHAR16));
- if (ReferFontInfoLocally (Private, StringPackage, StringPackage->FontId, FALSE, GlobalFont, &LocalFont)) {
- //
- // Create a EFI_HII_SIBT_STRING_UCS2_FONT block only.
- //
- StringBlock = (UINT8 *)AllocateZeroPool (OldBlockSize + Ucs2FontBlockSize);
- if (StringBlock == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- //
- // Copy original string blocks, except the EFI_HII_SIBT_END.
- //
- CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
- //
- // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
- //
- BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
- *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;
- BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
- *BlockPtr = LocalFont->FontId;
- BlockPtr++;
- CopyMem (BlockPtr, (EFI_STRING)String, StrSize ((EFI_STRING)String));
- BlockPtr += StrSize ((EFI_STRING)String);
-
- //
- // Append a EFI_HII_SIBT_END block to the end.
- //
- *BlockPtr = EFI_HII_SIBT_END;
- ZeroMem (StringPackage->StringBlock, OldBlockSize);
- FreePool (StringPackage->StringBlock);
- StringPackage->StringBlock = StringBlock;
- StringPackage->StringPkgHdr->Header.Length += Ucs2FontBlockSize;
- PackageListNode->PackageListHdr.PackageLength += Ucs2FontBlockSize;
- } else {
- //
- // EFI_HII_SIBT_FONT_BLOCK does not exist in current string package, so
- // create a EFI_HII_SIBT_FONT block to record the font info, then generate
- // a EFI_HII_SIBT_STRING_UCS2_FONT block to record the incoming string.
- //
- FontBlockSize = (UINT32)(StrSize (((EFI_FONT_INFO *)StringFontInfo)->FontName) +
- sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16));
- StringBlock = (UINT8 *)AllocateZeroPool (OldBlockSize + FontBlockSize + Ucs2FontBlockSize);
- if (StringBlock == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- //
- // Copy original string blocks, except the EFI_HII_SIBT_END.
- //
- CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
-
- //
- // Create a EFI_HII_SIBT_FONT block firstly and then backup its info in string
- // package instance for future reference.
- //
- BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
-
- Ext2.Header.BlockType = EFI_HII_SIBT_EXT2;
- Ext2.BlockType2 = EFI_HII_SIBT_FONT;
- Ext2.Length = (UINT16)FontBlockSize;
- CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
- BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);
-
- *BlockPtr = LocalFont->FontId;
- BlockPtr++;
- CopyMem (BlockPtr, &((EFI_FONT_INFO *)StringFontInfo)->FontSize, sizeof (UINT16));
- BlockPtr += sizeof (UINT16);
- CopyMem (BlockPtr, &((EFI_FONT_INFO *)StringFontInfo)->FontStyle, sizeof (EFI_HII_FONT_STYLE));
- BlockPtr += sizeof (EFI_HII_FONT_STYLE);
- CopyMem (
- BlockPtr,
- &((EFI_FONT_INFO *)StringFontInfo)->FontName,
- StrSize (((EFI_FONT_INFO *)StringFontInfo)->FontName)
- );
- BlockPtr += StrSize (((EFI_FONT_INFO *)StringFontInfo)->FontName);
- //
- // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
- //
- *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;
- BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
- *BlockPtr = LocalFont->FontId;
- BlockPtr++;
- CopyMem (BlockPtr, (EFI_STRING)String, StrSize ((EFI_STRING)String));
- BlockPtr += StrSize ((EFI_STRING)String);
-
- //
- // Append a EFI_HII_SIBT_END block to the end.
- //
- *BlockPtr = EFI_HII_SIBT_END;
- ZeroMem (StringPackage->StringBlock, OldBlockSize);
- FreePool (StringPackage->StringBlock);
- StringPackage->StringBlock = StringBlock;
- StringPackage->StringPkgHdr->Header.Length += FontBlockSize + Ucs2FontBlockSize;
- PackageListNode->PackageListHdr.PackageLength += FontBlockSize + Ucs2FontBlockSize;
-
- //
- // Increase the FontId to make it unique since we already add
- // a EFI_HII_SIBT_FONT block to this string package.
- //
- StringPackage->FontId++;
- }
- }
-
-Done:
- if (!EFI_ERROR (Status) && NewStringPackageCreated) {
- //
- // Trigger any registered notification function for new string package
- //
- Status = InvokeRegisteredFunction (
- Private,
- EFI_HII_DATABASE_NOTIFY_NEW_PACK,
- (VOID *)StringPackage,
- EFI_HII_PACKAGE_STRINGS,
- PackageList
- );
- }
-
- if (!EFI_ERROR (Status)) {
- //
- // Update MaxString Id to new StringId
- //
- for (Link = PackageListNode->StringPkgHdr.ForwardLink;
- Link != &PackageListNode->StringPkgHdr;
- Link = Link->ForwardLink
- )
- {
- StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
- StringPackage->MaxStringId = *StringId;
- }
- } else if (NewStringPackageCreated) {
- //
- // Free the allocated new string Package when new string can't be added.
- //
- RemoveEntryList (&StringPackage->StringEntry);
- FreePool (StringPackage->StringBlock);
- FreePool (StringPackage->StringPkgHdr);
- FreePool (StringPackage);
- }
-
- //
- // The contents of HiiDataBase may updated,need to check.
- //
- //
- // Check whether need to get the contents of HiiDataBase.
- // Only after ReadyToBoot to do the export.
- //
- if (gExportAfterReadyToBoot) {
- if (!EFI_ERROR (Status)) {
- HiiGetDatabaseInfo (&Private->HiiDatabase);
- }
- }
-
- EfiReleaseLock (&mHiiDatabaseLock);
-
- return Status;
-}
-
-/**
- This function retrieves the string specified by StringId which is associated
- with the specified PackageList in the language Language and copies it into
- the buffer specified by String.
-
- @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
- @param Language Points to the language for the retrieved string.
- @param PackageList The package list in the HII database to search for
- the specified string.
- @param StringId The string's id, which is unique within
- PackageList.
- @param String Points to the new null-terminated string.
- @param StringSize On entry, points to the size of the buffer pointed
- to by String, in bytes. On return, points to the
- length of the string, in bytes.
- @param StringFontInfo If not NULL, points to the string's font
- information. It's caller's responsibility to free
- this buffer.
-
- @retval EFI_SUCCESS The string was returned successfully.
- @retval EFI_NOT_FOUND The string specified by StringId is not available.
- @retval EFI_NOT_FOUND The string specified by StringId is available but
- not in the specified language.
- The specified PackageList is not in the database.
- @retval EFI_INVALID_LANGUAGE - The string specified by StringId is available but
- @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to
- hold the string.
- @retval EFI_INVALID_PARAMETER The Language or StringSize was NULL.
- @retval EFI_INVALID_PARAMETER The value referenced by StringSize was not zero and String was NULL.
- @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the
- request.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetString (
- IN CONST EFI_HII_STRING_PROTOCOL *This,
- IN CONST CHAR8 *Language,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_STRING_ID StringId,
- OUT EFI_STRING String,
- IN OUT UINTN *StringSize,
- OUT EFI_FONT_INFO **StringFontInfo OPTIONAL
- )
-{
- EFI_STATUS Status;
- LIST_ENTRY *Link;
- HII_DATABASE_PRIVATE_DATA *Private;
- HII_DATABASE_RECORD *DatabaseRecord;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
- HII_STRING_PACKAGE_INSTANCE *StringPackage;
-
- if ((This == NULL) || (Language == NULL) || (StringId < 1) || (StringSize == NULL) || (PackageList == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((String == NULL) && (*StringSize != 0)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (!IsHiiHandleValid (PackageList)) {
- return EFI_NOT_FOUND;
- }
-
- Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- PackageListNode = NULL;
-
- for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
- DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- if (DatabaseRecord->Handle == PackageList) {
- PackageListNode = DatabaseRecord->PackageList;
- break;
- }
- }
-
- if (PackageListNode != NULL) {
- //
- // First search: to match the StringId in the specified language.
- //
- for (Link = PackageListNode->StringPkgHdr.ForwardLink;
- Link != &PackageListNode->StringPkgHdr;
- Link = Link->ForwardLink
- )
- {
- StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
- if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *)Language)) {
- Status = GetStringWorker (Private, StringPackage, StringId, String, StringSize, StringFontInfo);
- if (Status != EFI_NOT_FOUND) {
- return Status;
- }
- }
- }
-
- //
- // Second search: to match the StringId in other available languages if exist.
- //
- for (Link = PackageListNode->StringPkgHdr.ForwardLink;
- Link != &PackageListNode->StringPkgHdr;
- Link = Link->ForwardLink
- )
- {
- StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
- Status = GetStringWorker (Private, StringPackage, StringId, NULL, NULL, NULL);
- if (!EFI_ERROR (Status)) {
- return EFI_INVALID_LANGUAGE;
- }
- }
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- This function updates the string specified by StringId in the specified PackageList to the text
- specified by String and, optionally, the font information specified by StringFontInfo.
-
- @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
- @param PackageList The package list containing the strings.
- @param StringId The string's id, which is unique within
- PackageList.
- @param Language Points to the language for the updated string.
- @param String Points to the new null-terminated string.
- @param StringFontInfo Points to the string's font information or NULL if
- the string font information is not changed.
-
- @retval EFI_SUCCESS The string was updated successfully.
- @retval EFI_NOT_FOUND The string specified by StringId is not in the
- database.
- @retval EFI_INVALID_PARAMETER The String or Language was NULL.
- @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in
- current database.
- @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
- task.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiSetString (
- IN CONST EFI_HII_STRING_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- IN EFI_STRING_ID StringId,
- IN CONST CHAR8 *Language,
- IN CONST EFI_STRING String,
- IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL
- )
-{
- EFI_STATUS Status;
- LIST_ENTRY *Link;
- HII_DATABASE_PRIVATE_DATA *Private;
- HII_DATABASE_RECORD *DatabaseRecord;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
- HII_STRING_PACKAGE_INSTANCE *StringPackage;
- UINT32 OldPackageLen;
-
- if ((This == NULL) || (Language == NULL) || (StringId < 1) || (String == NULL) || (PackageList == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (!IsHiiHandleValid (PackageList)) {
- return EFI_NOT_FOUND;
- }
-
- EfiAcquireLock (&mHiiDatabaseLock);
-
- Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
- PackageListNode = NULL;
-
- for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
- DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- if (DatabaseRecord->Handle == PackageList) {
- PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(DatabaseRecord->PackageList);
- }
- }
-
- if (PackageListNode != NULL) {
- for (Link = PackageListNode->StringPkgHdr.ForwardLink;
- Link != &PackageListNode->StringPkgHdr;
- Link = Link->ForwardLink
- )
- {
- StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
- if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *)Language)) {
- OldPackageLen = StringPackage->StringPkgHdr->Header.Length;
- Status = SetStringWorker (
- Private,
- StringPackage,
- StringId,
- (EFI_STRING)String,
- (EFI_FONT_INFO *)StringFontInfo
- );
- if (EFI_ERROR (Status)) {
- EfiReleaseLock (&mHiiDatabaseLock);
- return Status;
- }
-
- PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length - OldPackageLen;
- //
- // Check whether need to get the contents of HiiDataBase.
- // Only after ReadyToBoot to do the export.
- //
- if (gExportAfterReadyToBoot) {
- HiiGetDatabaseInfo (&Private->HiiDatabase);
- }
-
- EfiReleaseLock (&mHiiDatabaseLock);
- return EFI_SUCCESS;
- }
- }
- }
-
- EfiReleaseLock (&mHiiDatabaseLock);
- return EFI_NOT_FOUND;
-}
-
-/**
- This function returns the list of supported languages, in the format specified
- in Appendix M of UEFI 2.1 spec.
-
- @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
- @param PackageList The package list to examine.
- @param Languages Points to the buffer to hold the returned
- null-terminated ASCII string.
- @param LanguagesSize On entry, points to the size of the buffer pointed
- to by Languages, in bytes. On return, points to
- the length of Languages, in bytes.
-
- @retval EFI_SUCCESS The languages were returned successfully.
- @retval EFI_INVALID_PARAMETER The LanguagesSize was NULL.
- @retval EFI_INVALID_PARAMETER The value referenced by LanguagesSize is not zero and Languages is NULL.
- @retval EFI_BUFFER_TOO_SMALL The LanguagesSize is too small to hold the list of
- supported languages. LanguageSize is updated to
- contain the required size.
- @retval EFI_NOT_FOUND Could not find string package in specified
- packagelist.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetLanguages (
- IN CONST EFI_HII_STRING_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- IN OUT CHAR8 *Languages,
- IN OUT UINTN *LanguagesSize
- )
-{
- LIST_ENTRY *Link;
- HII_DATABASE_PRIVATE_DATA *Private;
- HII_DATABASE_RECORD *DatabaseRecord;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
- HII_STRING_PACKAGE_INSTANCE *StringPackage;
- UINTN ResultSize;
-
- if ((This == NULL) || (LanguagesSize == NULL) || (PackageList == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((*LanguagesSize != 0) && (Languages == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (!IsHiiHandleValid (PackageList)) {
- return EFI_NOT_FOUND;
- }
-
- Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
-
- PackageListNode = NULL;
- for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
- DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- if (DatabaseRecord->Handle == PackageList) {
- PackageListNode = DatabaseRecord->PackageList;
- break;
- }
- }
-
- if (PackageListNode == NULL) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Search the languages in the specified packagelist.
- //
- ResultSize = 0;
- for (Link = PackageListNode->StringPkgHdr.ForwardLink;
- Link != &PackageListNode->StringPkgHdr;
- Link = Link->ForwardLink
- )
- {
- StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
- ResultSize += AsciiStrSize (StringPackage->StringPkgHdr->Language);
- if (ResultSize <= *LanguagesSize) {
- AsciiStrCpyS (Languages, *LanguagesSize / sizeof (CHAR8), StringPackage->StringPkgHdr->Language);
- Languages += AsciiStrSize (StringPackage->StringPkgHdr->Language);
- *(Languages - 1) = L';';
- }
- }
-
- if (ResultSize == 0) {
- return EFI_NOT_FOUND;
- }
-
- if (*LanguagesSize < ResultSize) {
- *LanguagesSize = ResultSize;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- *(Languages - 1) = 0;
- return EFI_SUCCESS;
-}
-
-/**
- Each string package has associated with it a single primary language and zero
- or more secondary languages. This routine returns the secondary languages
- associated with a package list.
-
- @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
- @param PackageList The package list to examine.
- @param PrimaryLanguage Points to the null-terminated ASCII string that specifies
- the primary language. Languages are specified in the
- format specified in Appendix M of the UEFI 2.0 specification.
- @param SecondaryLanguages Points to the buffer to hold the returned null-terminated
- ASCII string that describes the list of
- secondary languages for the specified
- PrimaryLanguage. If there are no secondary
- languages, the function returns successfully, but
- this is set to NULL.
- @param SecondaryLanguagesSize On entry, points to the size of the buffer pointed
- to by SecondaryLanguages, in bytes. On return,
- points to the length of SecondaryLanguages in bytes.
-
- @retval EFI_SUCCESS Secondary languages were correctly returned.
- @retval EFI_INVALID_PARAMETER PrimaryLanguage or SecondaryLanguagesSize was NULL.
- @retval EFI_INVALID_PARAMETER The value referenced by SecondaryLanguagesSize is not
- zero and SecondaryLanguages is NULL.
- @retval EFI_BUFFER_TOO_SMALL The buffer specified by SecondaryLanguagesSize is
- too small to hold the returned information.
- SecondaryLanguageSize is updated to hold the size of
- the buffer required.
- @retval EFI_INVALID_LANGUAGE The language specified by PrimaryLanguage is not
- present in the specified package list.
- @retval EFI_NOT_FOUND The specified PackageList is not in the Database.
-
-**/
-EFI_STATUS
-EFIAPI
-HiiGetSecondaryLanguages (
- IN CONST EFI_HII_STRING_PROTOCOL *This,
- IN EFI_HII_HANDLE PackageList,
- IN CONST CHAR8 *PrimaryLanguage,
- IN OUT CHAR8 *SecondaryLanguages,
- IN OUT UINTN *SecondaryLanguagesSize
- )
-{
- LIST_ENTRY *Link;
- LIST_ENTRY *Link1;
- HII_DATABASE_PRIVATE_DATA *Private;
- HII_DATABASE_RECORD *DatabaseRecord;
- HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
- HII_STRING_PACKAGE_INSTANCE *StringPackage;
- CHAR8 *Languages;
- UINTN ResultSize;
-
- if ((This == NULL) || (PackageList == NULL) || (PrimaryLanguage == NULL) || (SecondaryLanguagesSize == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((SecondaryLanguages == NULL) && (*SecondaryLanguagesSize != 0)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (!IsHiiHandleValid (PackageList)) {
- return EFI_NOT_FOUND;
- }
-
- Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
-
- PackageListNode = NULL;
- for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
- DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
- if (DatabaseRecord->Handle == PackageList) {
- PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(DatabaseRecord->PackageList);
- break;
- }
- }
-
- if (PackageListNode == NULL) {
- return EFI_NOT_FOUND;
- }
-
- Languages = NULL;
- ResultSize = 0;
- for (Link1 = PackageListNode->StringPkgHdr.ForwardLink;
- Link1 != &PackageListNode->StringPkgHdr;
- Link1 = Link1->ForwardLink
- )
- {
- StringPackage = CR (Link1, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
- if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *)PrimaryLanguage)) {
- Languages = StringPackage->StringPkgHdr->Language;
- //
- // Language is a series of ';' terminated strings, first one is primary
- // language and following with other secondary languages or NULL if no
- // secondary languages any more.
- //
- Languages = AsciiStrStr (Languages, ";");
- if (Languages == NULL) {
- break;
- }
-
- Languages++;
-
- ResultSize = AsciiStrSize (Languages);
- if (ResultSize <= *SecondaryLanguagesSize) {
- AsciiStrCpyS (SecondaryLanguages, *SecondaryLanguagesSize / sizeof (CHAR8), Languages);
- } else {
- *SecondaryLanguagesSize = ResultSize;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- return EFI_SUCCESS;
- }
- }
-
- return EFI_INVALID_LANGUAGE;
-}
-
-/**
- Converts the ascii character of the string from uppercase to lowercase.
- This is a internal function.
-
- @param ConfigString String to be converted
-
-**/
-VOID
-EFIAPI
-AsciiHiiToLower (
- IN CHAR8 *ConfigString
- )
-{
- ASSERT (ConfigString != NULL);
-
- //
- // Convert all hex digits in range [A-F] in the configuration header to [a-f]
- //
- for ( ; *ConfigString != '\0'; ConfigString++) {
- if ((*ConfigString >= 'A') && (*ConfigString <= 'Z')) {
- *ConfigString = (CHAR8)(*ConfigString - 'A' + 'a');
- }
- }
-}
-
-/**
- Compare whether two names of languages are identical.
-
- @param Language1 Name of language 1 from StringPackage
- @param Language2 Name of language 2 to be compared with language 1.
-
- @retval TRUE same
- @retval FALSE not same
-
-**/
-BOOLEAN
-HiiCompareLanguage (
- IN CHAR8 *Language1,
- IN CHAR8 *Language2
- )
-{
- UINTN Index;
- UINTN StrLen;
- CHAR8 *Lan1;
- CHAR8 *Lan2;
-
- //
- // Convert to lower to compare.
- //
- StrLen = AsciiStrSize (Language1);
- Lan1 = AllocateZeroPool (StrLen);
- ASSERT (Lan1 != NULL);
- AsciiStrCpyS (Lan1, StrLen / sizeof (CHAR8), Language1);
- AsciiHiiToLower (Lan1);
-
- StrLen = AsciiStrSize (Language2);
- Lan2 = AllocateZeroPool (StrLen);
- ASSERT (Lan2 != NULL);
- AsciiStrCpyS (Lan2, StrLen / sizeof (CHAR8), Language2);
- AsciiHiiToLower (Lan2);
-
- //
- // Compare the Primary Language in Language1 to Language2
- //
- for (Index = 0; Lan1[Index] != 0 && Lan1[Index] != ';'; Index++) {
- if (Lan1[Index] != Lan2[Index]) {
- //
- // Return FALSE if any characters are different.
- //
- FreePool (Lan1);
- FreePool (Lan2);
- return FALSE;
- }
- }
-
- FreePool (Lan1);
- FreePool (Lan2);
-
- //
- // Only return TRUE if Language2[Index] is a Null-terminator which means
- // the Primary Language in Language1 is the same length as Language2. If
- // Language2[Index] is not a Null-terminator, then Language2 is longer than
- // the Primary Language in Language1, and FALSE must be returned.
- //
- return (BOOLEAN)(Language2[Index] == 0);
-}
+/** @file
+Implementation for EFI_HII_STRING_PROTOCOL.
+
+
+Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "HiiDatabase.h"
+
+CHAR16 mLanguageWindow[16] = {
+ 0x0000, 0x0080, 0x0100, 0x0300,
+ 0x2000, 0x2080, 0x2100, 0x3000,
+ 0x0080, 0x00C0, 0x0400, 0x0600,
+ 0x0900, 0x3040, 0x30A0, 0xFF00
+};
+
+/**
+ This function checks whether a global font info is referred by local
+ font info list or not. (i.e. HII_FONT_INFO is generated.) If not, create
+ a HII_FONT_INFO to refer it locally.
+
+ This is a internal function.
+
+
+ @param Private Hii database private structure.
+ @param StringPackage HII string package instance.
+ @param FontId Font identifer, which must be unique within the string package.
+ @param DuplicateEnable If true, duplicate HII_FONT_INFO which refers to
+ the same EFI_FONT_INFO is permitted. Otherwise it
+ is not allowed.
+ @param GlobalFontInfo Input a global font info which specify a
+ EFI_FONT_INFO.
+ @param LocalFontInfo Output a local font info which refers to a
+ EFI_FONT_INFO.
+
+ @retval TRUE Already referred before calling this function.
+ @retval FALSE Not referred before calling this function.
+
+**/
+BOOLEAN
+ReferFontInfoLocally (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
+ IN UINT8 FontId,
+ IN BOOLEAN DuplicateEnable,
+ IN HII_GLOBAL_FONT_INFO *GlobalFontInfo,
+ OUT HII_FONT_INFO **LocalFontInfo
+ )
+{
+ HII_FONT_INFO *LocalFont;
+ LIST_ENTRY *Link;
+
+ ASSERT (Private != NULL && StringPackage != NULL && GlobalFontInfo != NULL && LocalFontInfo != NULL);
+
+ if (!DuplicateEnable) {
+ for (Link = StringPackage->FontInfoList.ForwardLink;
+ Link != &StringPackage->FontInfoList;
+ Link = Link->ForwardLink
+ )
+ {
+ LocalFont = CR (Link, HII_FONT_INFO, Entry, HII_FONT_INFO_SIGNATURE);
+ if (LocalFont->GlobalEntry == &GlobalFontInfo->Entry) {
+ //
+ // Already referred by local font info list, return directly.
+ //
+ *LocalFontInfo = LocalFont;
+ return TRUE;
+ }
+ }
+ }
+
+ // FontId identifies EFI_FONT_INFO in local string package uniquely.
+ // GlobalEntry points to a HII_GLOBAL_FONT_INFO which identifies
+ // EFI_FONT_INFO uniquely in whole hii database.
+ //
+ LocalFont = (HII_FONT_INFO *)AllocateZeroPool (sizeof (HII_FONT_INFO));
+ ASSERT (LocalFont != NULL);
+
+ LocalFont->Signature = HII_FONT_INFO_SIGNATURE;
+ LocalFont->FontId = FontId;
+ LocalFont->GlobalEntry = &GlobalFontInfo->Entry;
+ InsertTailList (&StringPackage->FontInfoList, &LocalFont->Entry);
+
+ *LocalFontInfo = LocalFont;
+ return FALSE;
+}
+
+/**
+ Convert Ascii string text to unicode string test.
+
+ This is a internal function.
+
+
+ @param StringDest Buffer to store the string text. If it is NULL,
+ only the size will be returned.
+ @param StringSrc Points to current null-terminated string.
+ @param BufferSize Length of the buffer.
+
+ @retval EFI_SUCCESS The string text was outputted successfully.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string
+ text. BufferSize is updated to the required buffer
+ size.
+
+**/
+EFI_STATUS
+ConvertToUnicodeText (
+ OUT EFI_STRING StringDest,
+ IN CHAR8 *StringSrc,
+ IN OUT UINTN *BufferSize
+ )
+{
+ UINTN StringSize;
+ UINTN Index;
+
+ ASSERT (StringSrc != NULL && BufferSize != NULL);
+
+ StringSize = AsciiStrSize (StringSrc) * 2;
+ if ((*BufferSize < StringSize) || (StringDest == NULL)) {
+ *BufferSize = StringSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ for (Index = 0; Index < AsciiStrLen (StringSrc); Index++) {
+ StringDest[Index] = (CHAR16)StringSrc[Index];
+ }
+
+ StringDest[Index] = 0;
+ return EFI_SUCCESS;
+}
+
+/**
+ Calculate the size of StringSrc and output it. If StringDest is not NULL,
+ copy string text from src to dest.
+
+ This is a internal function.
+
+ @param StringDest Buffer to store the string text. If it is NULL,
+ only the size will be returned.
+ @param StringSrc Points to current null-terminated string.
+ @param BufferSize Length of the buffer.
+
+ @retval EFI_SUCCESS The string text was outputted successfully.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string
+ text. BufferSize is updated to the required buffer
+ size.
+
+**/
+EFI_STATUS
+GetUnicodeStringTextOrSize (
+ OUT EFI_STRING StringDest OPTIONAL,
+ IN UINT8 *StringSrc,
+ IN OUT UINTN *BufferSize
+ )
+{
+ UINTN StringSize;
+ UINT8 *StringPtr;
+
+ ASSERT (StringSrc != NULL && BufferSize != NULL);
+
+ StringSize = sizeof (CHAR16);
+ StringPtr = StringSrc;
+ while (ReadUnaligned16 ((UINT16 *)StringPtr) != 0) {
+ StringSize += sizeof (CHAR16);
+ StringPtr += sizeof (CHAR16);
+ }
+
+ if (*BufferSize < StringSize) {
+ *BufferSize = StringSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (StringDest != NULL) {
+ CopyMem (StringDest, StringSrc, StringSize);
+ }
+
+ *BufferSize = StringSize;
+ return EFI_SUCCESS;
+}
+
+/**
+ Copy string font info to a buffer.
+
+ This is a internal function.
+
+ @param StringPackage Hii string package instance.
+ @param FontId Font identifier which is unique in a string
+ package.
+ @param StringFontInfo Buffer to record the output font info. It's
+ caller's responsibility to free this buffer.
+
+ @retval EFI_SUCCESS The string font is outputted successfully.
+ @retval EFI_NOT_FOUND The specified font id does not exist.
+
+**/
+EFI_STATUS
+GetStringFontInfo (
+ IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
+ IN UINT8 FontId,
+ OUT EFI_FONT_INFO **StringFontInfo
+ )
+{
+ LIST_ENTRY *Link;
+ HII_FONT_INFO *FontInfo;
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+
+ ASSERT (StringFontInfo != NULL && StringPackage != NULL);
+
+ for (Link = StringPackage->FontInfoList.ForwardLink; Link != &StringPackage->FontInfoList; Link = Link->ForwardLink) {
+ FontInfo = CR (Link, HII_FONT_INFO, Entry, HII_FONT_INFO_SIGNATURE);
+ if (FontInfo->FontId == FontId) {
+ GlobalFont = CR (FontInfo->GlobalEntry, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);
+ *StringFontInfo = (EFI_FONT_INFO *)AllocateZeroPool (GlobalFont->FontInfoSize);
+ if (*StringFontInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (*StringFontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize);
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Parse all string blocks to find a String block specified by StringId.
+ If StringId = (EFI_STRING_ID) (-1), find out all EFI_HII_SIBT_FONT blocks
+ within this string package and backup its information. If LastStringId is
+ specified, the string id of last string block will also be output.
+ If StringId = 0, output the string id of last string block (EFI_HII_SIBT_STRING).
+
+ @param Private Hii database private structure.
+ @param StringPackage Hii string package instance.
+ @param StringId The string's id, which is unique within
+ PackageList.
+ @param BlockType Output the block type of found string block.
+ @param StringBlockAddr Output the block address of found string block.
+ @param StringTextOffset Offset, relative to the found block address, of
+ the string text information.
+ @param LastStringId Output the last string id when StringId = 0 or StringId = -1.
+ @param StartStringId The first id in the skip block which StringId in the block.
+
+ @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
+FindStringBlock (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
+ IN EFI_STRING_ID StringId,
+ OUT UINT8 *BlockType OPTIONAL,
+ OUT UINT8 **StringBlockAddr OPTIONAL,
+ OUT UINTN *StringTextOffset OPTIONAL,
+ OUT EFI_STRING_ID *LastStringId OPTIONAL,
+ OUT EFI_STRING_ID *StartStringId OPTIONAL
+ )
+{
+ UINT8 *BlockHdr;
+ EFI_STRING_ID CurrentStringId;
+ UINTN BlockSize;
+ UINTN Index;
+ UINT8 *StringTextPtr;
+ UINTN Offset;
+ HII_FONT_INFO *LocalFont;
+ EFI_FONT_INFO *FontInfo;
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+ UINTN FontInfoSize;
+ UINT16 StringCount;
+ UINT16 SkipCount;
+ EFI_HII_FONT_STYLE FontStyle;
+ UINT16 FontSize;
+ UINT8 Length8;
+ EFI_HII_SIBT_EXT2_BLOCK Ext2;
+ UINT8 FontId;
+ UINT32 Length32;
+ UINTN StringSize;
+ CHAR16 Zero;
+
+ ASSERT (StringPackage != NULL);
+ ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);
+
+ CurrentStringId = 1;
+ StringSize = 0;
+
+ if ((StringId != (EFI_STRING_ID)(-1)) && (StringId != 0)) {
+ ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);
+ if (StringId > StringPackage->MaxStringId) {
+ return EFI_NOT_FOUND;
+ }
+ } else {
+ ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
+ if ((StringId == 0) && (LastStringId != NULL)) {
+ *LastStringId = StringPackage->MaxStringId;
+ return EFI_SUCCESS;
+ }
+ }
+
+ ZeroMem (&Zero, sizeof (CHAR16));
+
+ //
+ // 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;
+ 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;
+ 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 (CurrentStringId == StringId) {
+ ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);
+ *BlockType = *BlockHdr;
+ *StringBlockAddr = BlockHdr;
+ *StringTextOffset = StringTextPtr - BlockHdr;
+ return EFI_SUCCESS;
+ }
+
+ 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 (CurrentStringId == StringId) {
+ ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);
+ *BlockType = *BlockHdr;
+ *StringBlockAddr = BlockHdr;
+ *StringTextOffset = StringTextPtr - BlockHdr;
+ return EFI_SUCCESS;
+ }
+
+ 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.
+ //
+ GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
+ 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 StrSize to store the size of the specified string, including the NULL
+ // terminator.
+ //
+ GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
+ 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++) {
+ GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
+ BlockSize += StringSize;
+ if (CurrentStringId == StringId) {
+ ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);
+ *BlockType = *BlockHdr;
+ *StringBlockAddr = BlockHdr;
+ *StringTextOffset = StringTextPtr - BlockHdr;
+ return EFI_SUCCESS;
+ }
+
+ 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++) {
+ GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
+ BlockSize += StringSize;
+ if (CurrentStringId == StringId) {
+ ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);
+ *BlockType = *BlockHdr;
+ *StringBlockAddr = BlockHdr;
+ *StringTextOffset = StringTextPtr - BlockHdr;
+ return EFI_SUCCESS;
+ }
+
+ StringTextPtr = StringTextPtr + StringSize;
+ CurrentStringId++;
+ }
+
+ break;
+
+ case EFI_HII_SIBT_DUPLICATE:
+ if (CurrentStringId == StringId) {
+ //
+ // Incoming StringId is an id of a duplicate string block.
+ // Update the StringId to be the previous string block.
+ // Go back to the header of string block to search.
+ //
+ CopyMem (
+ &StringId,
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK),
+ sizeof (EFI_STRING_ID)
+ );
+ ASSERT (StringId != CurrentStringId);
+ CurrentStringId = 1;
+ BlockSize = 0;
+ } else {
+ 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));
+ if ((Ext2.BlockType2 == EFI_HII_SIBT_FONT) && (StringId == (EFI_STRING_ID)(-1))) {
+ //
+ // Find the relationship between global font info and the font info of
+ // this EFI_HII_SIBT_FONT block then backup its information in local package.
+ //
+ BlockHdr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);
+ CopyMem (&FontId, BlockHdr, sizeof (UINT8));
+ BlockHdr++;
+ CopyMem (&FontSize, BlockHdr, sizeof (UINT16));
+ BlockHdr += sizeof (UINT16);
+ CopyMem (&FontStyle, BlockHdr, sizeof (EFI_HII_FONT_STYLE));
+ BlockHdr += sizeof (EFI_HII_FONT_STYLE);
+ GetUnicodeStringTextOrSize (NULL, BlockHdr, &StringSize);
+
+ FontInfoSize = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + StringSize;
+ FontInfo = (EFI_FONT_INFO *)AllocateZeroPool (FontInfoSize);
+ if (FontInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FontInfo->FontStyle = FontStyle;
+ FontInfo->FontSize = FontSize;
+ CopyMem (FontInfo->FontName, BlockHdr, StringSize);
+
+ //
+ // If find the corresponding global font info, save the relationship.
+ // Otherwise ignore this EFI_HII_SIBT_FONT block.
+ //
+ if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont)) {
+ ReferFontInfoLocally (Private, StringPackage, FontId, TRUE, GlobalFont, &LocalFont);
+ }
+
+ //
+ // Since string package tool set FontId initially to 0 and increases it
+ // progressively by one, StringPackage->FondId always represents an unique
+ // and available FontId.
+ //
+ StringPackage->FontId++;
+
+ FreePool (FontInfo);
+ }
+
+ 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 ((StringId > 0) && (StringId != (EFI_STRING_ID)(-1))) {
+ ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);
+ *BlockType = *BlockHdr;
+ *StringBlockAddr = BlockHdr;
+ *StringTextOffset = Offset;
+
+ if (StringId == CurrentStringId - 1) {
+ //
+ // if only one skip item, return EFI_NOT_FOUND.
+ //
+ if ((*BlockType == EFI_HII_SIBT_SKIP2) || (*BlockType == EFI_HII_SIBT_SKIP1)) {
+ return EFI_NOT_FOUND;
+ } else {
+ return EFI_SUCCESS;
+ }
+ }
+
+ if (StringId < CurrentStringId - 1) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ BlockHdr = StringPackage->StringBlock + BlockSize;
+ if (StartStringId != NULL) {
+ *StartStringId = CurrentStringId;
+ }
+ }
+
+ //
+ // Get last string ID
+ //
+ if ((StringId == (EFI_STRING_ID)(-1)) && (LastStringId != NULL)) {
+ *LastStringId = (EFI_STRING_ID)(CurrentStringId - 1);
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Parse all string blocks to get a string specified by StringId.
+
+ This is a internal function.
+
+ @param Private Hii database private structure.
+ @param StringPackage Hii string package instance.
+ @param StringId The string's id, which is unique within
+ PackageList.
+ @param String Points to retrieved null-terminated string.
+ @param StringSize On entry, points to the size of the buffer pointed
+ to by String, in bytes. On return, points to the
+ length of the string, in bytes.
+ @param StringFontInfo If not NULL, allocate a buffer to record the
+ output font info. It's caller's responsibility to
+ free this buffer.
+
+ @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_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to
+ hold the string.
+
+**/
+EFI_STATUS
+GetStringWorker (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
+ IN EFI_STRING_ID StringId,
+ OUT EFI_STRING String,
+ IN OUT UINTN *StringSize OPTIONAL,
+ OUT EFI_FONT_INFO **StringFontInfo OPTIONAL
+ )
+{
+ UINT8 *StringTextPtr;
+ UINT8 BlockType;
+ UINT8 *StringBlockAddr;
+ UINTN StringTextOffset;
+ EFI_STATUS Status;
+ UINT8 FontId;
+
+ ASSERT (StringPackage != NULL);
+ ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
+
+ //
+ // Find the specified string block
+ //
+ Status = FindStringBlock (
+ Private,
+ StringPackage,
+ StringId,
+ &BlockType,
+ &StringBlockAddr,
+ &StringTextOffset,
+ NULL,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (StringSize == NULL) {
+ //
+ // String text buffer is not requested
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Get the string text.
+ //
+ StringTextPtr = StringBlockAddr + StringTextOffset;
+ switch (BlockType) {
+ case EFI_HII_SIBT_STRING_SCSU:
+ case EFI_HII_SIBT_STRING_SCSU_FONT:
+ case EFI_HII_SIBT_STRINGS_SCSU:
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:
+ Status = ConvertToUnicodeText (String, (CHAR8 *)StringTextPtr, StringSize);
+ break;
+ case EFI_HII_SIBT_STRING_UCS2:
+ case EFI_HII_SIBT_STRING_UCS2_FONT:
+ case EFI_HII_SIBT_STRINGS_UCS2:
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:
+ Status = GetUnicodeStringTextOrSize (String, StringTextPtr, StringSize);
+ break;
+ default:
+ return EFI_NOT_FOUND;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the string font. The FontId 0 is the default font for those string blocks which
+ // do not specify a font identifier. If default font is not specified, return NULL.
+ //
+ if (StringFontInfo != NULL) {
+ switch (BlockType) {
+ case EFI_HII_SIBT_STRING_SCSU_FONT:
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:
+ case EFI_HII_SIBT_STRING_UCS2_FONT:
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:
+ FontId = *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK));
+ break;
+ default:
+ FontId = 0;
+ }
+
+ Status = GetStringFontInfo (StringPackage, FontId, StringFontInfo);
+ if (Status == EFI_NOT_FOUND) {
+ *StringFontInfo = NULL;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ If GetStringBlock find the StringId's string is not saved in the exist string block,
+ this function will create the UCS2 string block to save the string; also split the
+ skip block into two or one skip block.
+
+ This is a internal function.
+
+ @param StringPackage Hii string package instance.
+ @param StartStringId The first id in the skip block which StringId in the block.
+ @param StringId The string's id, which is unique within
+ PackageList.
+ @param BlockType Output the block type of found string block.
+ @param StringBlockAddr Output the block address of found string block.
+ @param FontBlock whether this string block has font info.
+
+ @retval EFI_SUCCESS The string font is outputted successfully.
+ @retval EFI_OUT_OF_RESOURCES NO resource for the memory to save the new string block.
+
+**/
+EFI_STATUS
+InsertLackStringBlock (
+ IN OUT HII_STRING_PACKAGE_INSTANCE *StringPackage,
+ IN EFI_STRING_ID StartStringId,
+ IN EFI_STRING_ID StringId,
+ IN OUT UINT8 *BlockType,
+ IN OUT UINT8 **StringBlockAddr,
+ IN BOOLEAN FontBlock
+ )
+{
+ UINT8 *BlockPtr;
+ UINT8 *StringBlock;
+ UINT32 SkipLen;
+ UINT32 OldBlockSize;
+ UINT32 NewBlockSize;
+ UINT32 FrontSkipNum;
+ UINT32 NewUCSBlockLen;
+ UINT8 *OldStringAddr;
+ UINT32 IdCount;
+
+ FrontSkipNum = 0;
+ SkipLen = 0;
+ OldStringAddr = *StringBlockAddr;
+
+ ASSERT (*BlockType == EFI_HII_SIBT_SKIP1 || *BlockType == EFI_HII_SIBT_SKIP2);
+ //
+ // Old skip block size.
+ //
+ if (*BlockType == EFI_HII_SIBT_SKIP1) {
+ SkipLen = sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
+ IdCount = *(UINT8 *)(OldStringAddr + sizeof (EFI_HII_STRING_BLOCK));
+ } else {
+ SkipLen = sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
+ IdCount = *(UINT16 *)(OldStringAddr + sizeof (EFI_HII_STRING_BLOCK));
+ }
+
+ //
+ // New create UCS or UCS2 block size.
+ //
+ if (FontBlock) {
+ NewUCSBlockLen = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK);
+ } else {
+ NewUCSBlockLen = sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);
+ }
+
+ OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
+
+ if (StartStringId == StringId) {
+ //
+ // New block + [Skip block]
+ //
+ if (IdCount > 1) {
+ NewBlockSize = OldBlockSize + NewUCSBlockLen;
+ } else {
+ NewBlockSize = OldBlockSize + NewUCSBlockLen - SkipLen;
+ }
+ } else if (StartStringId + IdCount - 1 == StringId) {
+ //
+ // Skip block + New block
+ //
+ NewBlockSize = OldBlockSize + NewUCSBlockLen;
+ FrontSkipNum = StringId - StartStringId;
+ } else {
+ //
+ // Skip block + New block + [Skip block]
+ //
+ NewBlockSize = OldBlockSize + NewUCSBlockLen + SkipLen;
+ FrontSkipNum = StringId - StartStringId;
+ }
+
+ StringBlock = (UINT8 *)AllocateZeroPool (NewBlockSize);
+ if (StringBlock == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Copy old block in front of skip block.
+ //
+ CopyMem (StringBlock, StringPackage->StringBlock, OldStringAddr - StringPackage->StringBlock);
+ BlockPtr = StringBlock + (OldStringAddr - StringPackage->StringBlock);
+
+ if (FrontSkipNum > 0) {
+ *BlockPtr = *BlockType;
+ if (*BlockType == EFI_HII_SIBT_SKIP1) {
+ *(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT8)FrontSkipNum;
+ } else {
+ *(UINT16 *)(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT16)FrontSkipNum;
+ }
+
+ BlockPtr += SkipLen;
+ }
+
+ //
+ // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
+ //
+ *StringBlockAddr = BlockPtr;
+ if (FontBlock) {
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;
+ } else {
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
+ }
+
+ BlockPtr += NewUCSBlockLen;
+
+ if (IdCount > FrontSkipNum + 1) {
+ *BlockPtr = *BlockType;
+ if (*BlockType == EFI_HII_SIBT_SKIP1) {
+ *(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT8)(IdCount - FrontSkipNum - 1);
+ } else {
+ *(UINT16 *)(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT16)(IdCount - FrontSkipNum - 1);
+ }
+
+ BlockPtr += SkipLen;
+ }
+
+ //
+ // Append a EFI_HII_SIBT_END block to the end.
+ //
+ CopyMem (BlockPtr, OldStringAddr + SkipLen, OldBlockSize - (OldStringAddr - StringPackage->StringBlock) - SkipLen);
+
+ if (FontBlock) {
+ *BlockType = EFI_HII_SIBT_STRING_UCS2_FONT;
+ } else {
+ *BlockType = EFI_HII_SIBT_STRING_UCS2;
+ }
+
+ FreePool (StringPackage->StringBlock);
+ StringPackage->StringBlock = StringBlock;
+ StringPackage->StringPkgHdr->Header.Length += NewBlockSize - OldBlockSize;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Parse all string blocks to set a String specified by StringId.
+
+ This is a internal function.
+
+ @param Private HII database driver private structure.
+ @param StringPackage HII string package instance.
+ @param StringId The string's id, which is unique within
+ PackageList.
+ @param String Points to the new null-terminated string.
+ @param StringFontInfo Points to the input font info.
+
+ @retval EFI_SUCCESS The string was updated successfully.
+ @retval EFI_NOT_FOUND The string specified by StringId is not in the
+ database.
+ @retval EFI_INVALID_PARAMETER The String or Language was NULL.
+ @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in
+ current database.
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
+ task.
+
+**/
+EFI_STATUS
+SetStringWorker (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN OUT HII_STRING_PACKAGE_INSTANCE *StringPackage,
+ IN EFI_STRING_ID StringId,
+ IN EFI_STRING String,
+ IN EFI_FONT_INFO *StringFontInfo OPTIONAL
+ )
+{
+ UINT8 *StringTextPtr;
+ UINT8 BlockType;
+ UINT8 *StringBlockAddr;
+ UINTN StringTextOffset;
+ EFI_STATUS Status;
+ UINT8 *Block;
+ UINT8 *BlockPtr;
+ UINTN BlockSize;
+ UINTN OldBlockSize;
+ HII_FONT_INFO *LocalFont;
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+ BOOLEAN Referred;
+ EFI_HII_SIBT_EXT2_BLOCK Ext2;
+ UINTN StringSize;
+ UINTN TmpSize;
+ EFI_STRING_ID StartStringId;
+
+ StartStringId = 0;
+ StringSize = 0;
+ ASSERT (Private != NULL && StringPackage != NULL && String != NULL);
+ ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
+ //
+ // Find the specified string block
+ //
+ Status = FindStringBlock (
+ Private,
+ StringPackage,
+ StringId,
+ &BlockType,
+ &StringBlockAddr,
+ &StringTextOffset,
+ NULL,
+ &StartStringId
+ );
+ if (EFI_ERROR (Status) && ((BlockType == EFI_HII_SIBT_SKIP1) || (BlockType == EFI_HII_SIBT_SKIP2))) {
+ Status = InsertLackStringBlock (
+ StringPackage,
+ StartStringId,
+ StringId,
+ &BlockType,
+ &StringBlockAddr,
+ (BOOLEAN)(StringFontInfo != NULL)
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (StringFontInfo != NULL) {
+ StringTextOffset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);
+ } else {
+ StringTextOffset = sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16);
+ }
+ }
+
+ LocalFont = NULL;
+ GlobalFont = NULL;
+ Referred = FALSE;
+
+ //
+ // The input StringFontInfo should exist in current database if specified.
+ //
+ if (StringFontInfo != NULL) {
+ if (!IsFontInfoExisted (Private, StringFontInfo, NULL, NULL, &GlobalFont)) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ Referred = ReferFontInfoLocally (
+ Private,
+ StringPackage,
+ StringPackage->FontId,
+ FALSE,
+ GlobalFont,
+ &LocalFont
+ );
+ if (!Referred) {
+ StringPackage->FontId++;
+ }
+ }
+
+ //
+ // Update the FontId of the specified string block to input font info.
+ //
+ switch (BlockType) {
+ case EFI_HII_SIBT_STRING_SCSU_FONT:
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:
+ case EFI_HII_SIBT_STRING_UCS2_FONT:
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:
+ *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK)) = LocalFont->FontId;
+ break;
+ default:
+ //
+ // When modify the font info of these blocks, the block type should be updated
+ // to contain font info thus the whole structure should be revised.
+ // It is recommended to use tool to modify the block type not in the code.
+ //
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
+
+ //
+ // Set the string text and font.
+ //
+ StringTextPtr = StringBlockAddr + StringTextOffset;
+ switch (BlockType) {
+ case EFI_HII_SIBT_STRING_SCSU:
+ case EFI_HII_SIBT_STRING_SCSU_FONT:
+ case EFI_HII_SIBT_STRINGS_SCSU:
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:
+ BlockSize = OldBlockSize + StrLen (String);
+ BlockSize -= AsciiStrSize ((CHAR8 *)StringTextPtr);
+ Block = AllocateZeroPool (BlockSize);
+ if (Block == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock);
+ BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock);
+
+ while (*String != 0) {
+ *BlockPtr++ = (CHAR8)*String++;
+ }
+
+ *BlockPtr++ = 0;
+
+ TmpSize = OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - AsciiStrSize ((CHAR8 *)StringTextPtr);
+ CopyMem (
+ BlockPtr,
+ StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr),
+ TmpSize
+ );
+
+ ZeroMem (StringPackage->StringBlock, OldBlockSize);
+ FreePool (StringPackage->StringBlock);
+ StringPackage->StringBlock = Block;
+ StringPackage->StringPkgHdr->Header.Length += (UINT32)(BlockSize - OldBlockSize);
+ break;
+
+ case EFI_HII_SIBT_STRING_UCS2:
+ case EFI_HII_SIBT_STRING_UCS2_FONT:
+ case EFI_HII_SIBT_STRINGS_UCS2:
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:
+ //
+ // Use StrSize to store the size of the specified string, including the NULL
+ // terminator.
+ //
+ GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
+
+ BlockSize = OldBlockSize + StrSize (String) - StringSize;
+ Block = AllocateZeroPool (BlockSize);
+ if (Block == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock);
+ BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock);
+
+ CopyMem (BlockPtr, String, StrSize (String));
+ BlockPtr += StrSize (String);
+
+ CopyMem (
+ BlockPtr,
+ StringTextPtr + StringSize,
+ OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - StringSize
+ );
+
+ ZeroMem (StringPackage->StringBlock, OldBlockSize);
+ FreePool (StringPackage->StringBlock);
+ StringPackage->StringBlock = Block;
+ StringPackage->StringPkgHdr->Header.Length += (UINT32)(BlockSize - OldBlockSize);
+ break;
+
+ default:
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Insert a new EFI_HII_SIBT_FONT_BLOCK to the header of string block, if incoming
+ // StringFontInfo does not exist in current string package.
+ //
+ // This new block does not impact on the value of StringId.
+ //
+ //
+ if ((StringFontInfo == NULL) || Referred) {
+ return EFI_SUCCESS;
+ }
+
+ OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
+ BlockSize = OldBlockSize + sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16) +
+ StrSize (GlobalFont->FontInfo->FontName);
+
+ Block = AllocateZeroPool (BlockSize);
+ if (Block == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BlockPtr = Block;
+ Ext2.Header.BlockType = EFI_HII_SIBT_EXT2;
+ Ext2.BlockType2 = EFI_HII_SIBT_FONT;
+ Ext2.Length = (UINT16)(BlockSize - OldBlockSize);
+ CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
+ BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);
+
+ *BlockPtr = LocalFont->FontId;
+ BlockPtr++;
+ CopyMem (BlockPtr, &GlobalFont->FontInfo->FontSize, sizeof (UINT16));
+ BlockPtr += sizeof (UINT16);
+ CopyMem (BlockPtr, &GlobalFont->FontInfo->FontStyle, sizeof (UINT32));
+ BlockPtr += sizeof (UINT32);
+ CopyMem (
+ BlockPtr,
+ GlobalFont->FontInfo->FontName,
+ StrSize (GlobalFont->FontInfo->FontName)
+ );
+ BlockPtr += StrSize (GlobalFont->FontInfo->FontName);
+
+ CopyMem (BlockPtr, StringPackage->StringBlock, OldBlockSize);
+
+ ZeroMem (StringPackage->StringBlock, OldBlockSize);
+ FreePool (StringPackage->StringBlock);
+ StringPackage->StringBlock = Block;
+ StringPackage->StringPkgHdr->Header.Length += Ext2.Length;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function adds the string String to the group of strings owned by PackageList, with the
+ specified font information StringFontInfo and returns a new string id.
+ The new string identifier is guaranteed to be unique within the package list.
+ That new string identifier is reserved for all languages in the package list.
+
+
+ @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
+ @param PackageList Handle of the package list where this string will
+ be added.
+ @param StringId On return, contains the new strings id, which is
+ unique within PackageList.
+ @param Language Points to the language for the new string.
+ @param LanguageName Points to the printable language name to associate
+ with the passed in Language field.If LanguageName
+ is not NULL and the string package header's
+ LanguageName associated with a given Language is
+ not zero, the LanguageName being passed in will
+ be ignored.
+ @param String Points to the new null-terminated string.
+ @param StringFontInfo Points to the new string's font information or
+ NULL if the string should have the default system
+ font, size and style.
+
+ @retval EFI_SUCCESS The new string was added successfully.
+ @retval EFI_NOT_FOUND The specified PackageList could not be found in
+ database.
+ @retval EFI_OUT_OF_RESOURCES Could not add the string due to lack of resources.
+ @retval EFI_INVALID_PARAMETER String is NULL or StringId is NULL or Language is
+ NULL.
+ @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in
+ current database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiNewString (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ OUT EFI_STRING_ID *StringId,
+ IN CONST CHAR8 *Language,
+ IN CONST CHAR16 *LanguageName OPTIONAL,
+ IN CONST EFI_STRING String,
+ IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+ UINT32 HeaderSize;
+ UINT32 BlockSize;
+ UINT32 OldBlockSize;
+ UINT8 *StringBlock;
+ UINT8 *BlockPtr;
+ UINT32 Ucs2BlockSize;
+ UINT32 FontBlockSize;
+ UINT32 Ucs2FontBlockSize;
+ EFI_HII_SIBT_EXT2_BLOCK Ext2;
+ HII_FONT_INFO *LocalFont;
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+ EFI_STRING_ID NewStringId;
+ EFI_STRING_ID NextStringId;
+ EFI_STRING_ID Index;
+ HII_STRING_PACKAGE_INSTANCE *MatchStringPackage;
+ BOOLEAN NewStringPackageCreated;
+
+ if ((This == NULL) || (String == NULL) || (StringId == NULL) || (Language == NULL) || (PackageList == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ GlobalFont = NULL;
+
+ //
+ // If StringFontInfo specify a paritcular font, it should exist in current database.
+ //
+ if (StringFontInfo != NULL) {
+ if (!IsFontInfoExisted (Private, (EFI_FONT_INFO *)StringFontInfo, NULL, NULL, &GlobalFont)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Get the matching package list.
+ //
+ PackageListNode = NULL;
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (DatabaseRecord->Handle == PackageList) {
+ PackageListNode = DatabaseRecord->PackageList;
+ break;
+ }
+ }
+
+ if (PackageListNode == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ EfiAcquireLock (&mHiiDatabaseLock);
+
+ Status = EFI_SUCCESS;
+ NewStringPackageCreated = FALSE;
+ NewStringId = 0;
+ NextStringId = 0;
+ StringPackage = NULL;
+ MatchStringPackage = NULL;
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;
+ Link != &PackageListNode->StringPkgHdr;
+ Link = Link->ForwardLink
+ )
+ {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ //
+ // Create a string block and corresponding font block if exists, then append them
+ // to the end of the string package.
+ //
+ Status = FindStringBlock (
+ Private,
+ StringPackage,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ &NextStringId,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Make sure that new StringId is same in all String Packages for the different language.
+ //
+ if ((NewStringId != 0) && (NewStringId != NextStringId)) {
+ ASSERT (FALSE);
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ NewStringId = NextStringId;
+ //
+ // Get the matched string package with language.
+ //
+ if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *)Language)) {
+ MatchStringPackage = StringPackage;
+ } else {
+ OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
+ //
+ // Create a blank EFI_HII_SIBT_STRING_UCS2_BLOCK to reserve new string ID.
+ //
+ Ucs2BlockSize = (UINT32)sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);
+
+ StringBlock = (UINT8 *)AllocateZeroPool (OldBlockSize + Ucs2BlockSize);
+ if (StringBlock == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Copy original string blocks, except the EFI_HII_SIBT_END.
+ //
+ CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
+ //
+ // Create a blank EFI_HII_SIBT_STRING_UCS2 block
+ //
+ BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
+ BlockPtr += sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);
+
+ //
+ // Append a EFI_HII_SIBT_END block to the end.
+ //
+ *BlockPtr = EFI_HII_SIBT_END;
+ ZeroMem (StringPackage->StringBlock, OldBlockSize);
+ FreePool (StringPackage->StringBlock);
+ StringPackage->StringBlock = StringBlock;
+ StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize;
+ PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize;
+ }
+ }
+
+ if (NewStringId == 0) {
+ //
+ // No string package is found.
+ // Create new string package. StringId 1 is reserved for Language Name string.
+ //
+ *StringId = 2;
+ } else {
+ //
+ // Set new StringId
+ //
+ *StringId = (EFI_STRING_ID)(NewStringId + 1);
+ }
+
+ if (MatchStringPackage != NULL) {
+ StringPackage = MatchStringPackage;
+ } else {
+ //
+ // LanguageName is required to create a new string package.
+ //
+ if (LanguageName == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ StringPackage = AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));
+ if (StringPackage == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;
+ StringPackage->MaxStringId = *StringId;
+ StringPackage->FontId = 0;
+ InitializeListHead (&StringPackage->FontInfoList);
+
+ //
+ // Fill in the string package header
+ //
+ HeaderSize = (UINT32)(AsciiStrSize ((CHAR8 *)Language) - 1 + sizeof (EFI_HII_STRING_PACKAGE_HDR));
+ StringPackage->StringPkgHdr = AllocateZeroPool (HeaderSize);
+ if (StringPackage->StringPkgHdr == NULL) {
+ FreePool (StringPackage);
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ StringPackage->StringPkgHdr->Header.Type = EFI_HII_PACKAGE_STRINGS;
+ StringPackage->StringPkgHdr->HdrSize = HeaderSize;
+ StringPackage->StringPkgHdr->StringInfoOffset = HeaderSize;
+ CopyMem (StringPackage->StringPkgHdr->LanguageWindow, mLanguageWindow, 16 * sizeof (CHAR16));
+ StringPackage->StringPkgHdr->LanguageName = 1;
+ AsciiStrCpyS (StringPackage->StringPkgHdr->Language, (HeaderSize - OFFSET_OF (EFI_HII_STRING_PACKAGE_HDR, Language)) / sizeof (CHAR8), (CHAR8 *)Language);
+
+ //
+ // Calculate the length of the string blocks, including string block to record
+ // printable language full name and EFI_HII_SIBT_END_BLOCK.
+ //
+ Ucs2BlockSize = (UINT32)(StrSize ((CHAR16 *)LanguageName) +
+ (*StringId - 1) * sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16));
+
+ BlockSize = Ucs2BlockSize + sizeof (EFI_HII_SIBT_END_BLOCK);
+ StringPackage->StringBlock = (UINT8 *)AllocateZeroPool (BlockSize);
+ if (StringPackage->StringBlock == NULL) {
+ FreePool (StringPackage->StringPkgHdr);
+ FreePool (StringPackage);
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Insert the string block of printable language full name
+ //
+ BlockPtr = StringPackage->StringBlock;
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
+ BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
+ CopyMem (BlockPtr, (EFI_STRING)LanguageName, StrSize ((EFI_STRING)LanguageName));
+ BlockPtr += StrSize ((EFI_STRING)LanguageName);
+ for (Index = 2; Index <= *StringId - 1; Index++) {
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
+ BlockPtr += sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);
+ }
+
+ //
+ // Insert the end block
+ //
+ *BlockPtr = EFI_HII_SIBT_END;
+
+ //
+ // Append this string package node to string package array in this package list.
+ //
+ StringPackage->StringPkgHdr->Header.Length = HeaderSize + BlockSize;
+ PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;
+ InsertTailList (&PackageListNode->StringPkgHdr, &StringPackage->StringEntry);
+ NewStringPackageCreated = TRUE;
+ }
+
+ OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
+
+ if (StringFontInfo == NULL) {
+ //
+ // Create a EFI_HII_SIBT_STRING_UCS2_BLOCK since font info is not specified.
+ //
+ Ucs2BlockSize = (UINT32)(StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK)
+ - sizeof (CHAR16));
+
+ StringBlock = (UINT8 *)AllocateZeroPool (OldBlockSize + Ucs2BlockSize);
+ if (StringBlock == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Copy original string blocks, except the EFI_HII_SIBT_END.
+ //
+ CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
+ //
+ // Create a EFI_HII_SIBT_STRING_UCS2 block
+ //
+ BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
+ BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
+ CopyMem (BlockPtr, (EFI_STRING)String, StrSize ((EFI_STRING)String));
+ BlockPtr += StrSize ((EFI_STRING)String);
+
+ //
+ // Append a EFI_HII_SIBT_END block to the end.
+ //
+ *BlockPtr = EFI_HII_SIBT_END;
+ ZeroMem (StringPackage->StringBlock, OldBlockSize);
+ FreePool (StringPackage->StringBlock);
+ StringPackage->StringBlock = StringBlock;
+ StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize;
+ PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize;
+ } else {
+ //
+ // StringFontInfo is specified here. If there is a EFI_HII_SIBT_FONT_BLOCK
+ // which refers to this font info, create a EFI_HII_SIBT_STRING_UCS2_FONT block
+ // only. Otherwise create a EFI_HII_SIBT_FONT block with a EFI_HII_SIBT_STRING
+ // _UCS2_FONT block.
+ //
+ Ucs2FontBlockSize = (UINT32)(StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) -
+ sizeof (CHAR16));
+ if (ReferFontInfoLocally (Private, StringPackage, StringPackage->FontId, FALSE, GlobalFont, &LocalFont)) {
+ //
+ // Create a EFI_HII_SIBT_STRING_UCS2_FONT block only.
+ //
+ StringBlock = (UINT8 *)AllocateZeroPool (OldBlockSize + Ucs2FontBlockSize);
+ if (StringBlock == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Copy original string blocks, except the EFI_HII_SIBT_END.
+ //
+ CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
+ //
+ // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
+ //
+ BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;
+ BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
+ *BlockPtr = LocalFont->FontId;
+ BlockPtr++;
+ CopyMem (BlockPtr, (EFI_STRING)String, StrSize ((EFI_STRING)String));
+ BlockPtr += StrSize ((EFI_STRING)String);
+
+ //
+ // Append a EFI_HII_SIBT_END block to the end.
+ //
+ *BlockPtr = EFI_HII_SIBT_END;
+ ZeroMem (StringPackage->StringBlock, OldBlockSize);
+ FreePool (StringPackage->StringBlock);
+ StringPackage->StringBlock = StringBlock;
+ StringPackage->StringPkgHdr->Header.Length += Ucs2FontBlockSize;
+ PackageListNode->PackageListHdr.PackageLength += Ucs2FontBlockSize;
+ } else {
+ //
+ // EFI_HII_SIBT_FONT_BLOCK does not exist in current string package, so
+ // create a EFI_HII_SIBT_FONT block to record the font info, then generate
+ // a EFI_HII_SIBT_STRING_UCS2_FONT block to record the incoming string.
+ //
+ FontBlockSize = (UINT32)(StrSize (((EFI_FONT_INFO *)StringFontInfo)->FontName) +
+ sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16));
+ StringBlock = (UINT8 *)AllocateZeroPool (OldBlockSize + FontBlockSize + Ucs2FontBlockSize);
+ if (StringBlock == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Copy original string blocks, except the EFI_HII_SIBT_END.
+ //
+ CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
+
+ //
+ // Create a EFI_HII_SIBT_FONT block firstly and then backup its info in string
+ // package instance for future reference.
+ //
+ BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
+
+ Ext2.Header.BlockType = EFI_HII_SIBT_EXT2;
+ Ext2.BlockType2 = EFI_HII_SIBT_FONT;
+ Ext2.Length = (UINT16)FontBlockSize;
+ CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
+ BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);
+
+ *BlockPtr = LocalFont->FontId;
+ BlockPtr++;
+ CopyMem (BlockPtr, &((EFI_FONT_INFO *)StringFontInfo)->FontSize, sizeof (UINT16));
+ BlockPtr += sizeof (UINT16);
+ CopyMem (BlockPtr, &((EFI_FONT_INFO *)StringFontInfo)->FontStyle, sizeof (EFI_HII_FONT_STYLE));
+ BlockPtr += sizeof (EFI_HII_FONT_STYLE);
+ CopyMem (
+ BlockPtr,
+ &((EFI_FONT_INFO *)StringFontInfo)->FontName,
+ StrSize (((EFI_FONT_INFO *)StringFontInfo)->FontName)
+ );
+ BlockPtr += StrSize (((EFI_FONT_INFO *)StringFontInfo)->FontName);
+ //
+ // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
+ //
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;
+ BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
+ *BlockPtr = LocalFont->FontId;
+ BlockPtr++;
+ CopyMem (BlockPtr, (EFI_STRING)String, StrSize ((EFI_STRING)String));
+ BlockPtr += StrSize ((EFI_STRING)String);
+
+ //
+ // Append a EFI_HII_SIBT_END block to the end.
+ //
+ *BlockPtr = EFI_HII_SIBT_END;
+ ZeroMem (StringPackage->StringBlock, OldBlockSize);
+ FreePool (StringPackage->StringBlock);
+ StringPackage->StringBlock = StringBlock;
+ StringPackage->StringPkgHdr->Header.Length += FontBlockSize + Ucs2FontBlockSize;
+ PackageListNode->PackageListHdr.PackageLength += FontBlockSize + Ucs2FontBlockSize;
+
+ //
+ // Increase the FontId to make it unique since we already add
+ // a EFI_HII_SIBT_FONT block to this string package.
+ //
+ StringPackage->FontId++;
+ }
+ }
+
+Done:
+ if (!EFI_ERROR (Status) && NewStringPackageCreated) {
+ //
+ // Trigger any registered notification function for new string package
+ //
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_NEW_PACK,
+ (VOID *)StringPackage,
+ EFI_HII_PACKAGE_STRINGS,
+ PackageList
+ );
+ }
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Update MaxString Id to new StringId
+ //
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;
+ Link != &PackageListNode->StringPkgHdr;
+ Link = Link->ForwardLink
+ )
+ {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ StringPackage->MaxStringId = *StringId;
+ }
+ } else if (NewStringPackageCreated) {
+ //
+ // Free the allocated new string Package when new string can't be added.
+ //
+ RemoveEntryList (&StringPackage->StringEntry);
+ FreePool (StringPackage->StringBlock);
+ FreePool (StringPackage->StringPkgHdr);
+ FreePool (StringPackage);
+ }
+
+ //
+ // The contents of HiiDataBase may updated,need to check.
+ //
+ //
+ // Check whether need to get the contents of HiiDataBase.
+ // Only after ReadyToBoot to do the export.
+ //
+ if (gExportAfterReadyToBoot) {
+ if (!EFI_ERROR (Status)) {
+ HiiGetDatabaseInfo (&Private->HiiDatabase);
+ }
+ }
+
+ EfiReleaseLock (&mHiiDatabaseLock);
+
+ return Status;
+}
+
+/**
+ This function retrieves the string specified by StringId which is associated
+ with the specified PackageList in the language Language and copies it into
+ the buffer specified by String.
+
+ @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
+ @param Language Points to the language for the retrieved string.
+ @param PackageList The package list in the HII database to search for
+ the specified string.
+ @param StringId The string's id, which is unique within
+ PackageList.
+ @param String Points to the new null-terminated string.
+ @param StringSize On entry, points to the size of the buffer pointed
+ to by String, in bytes. On return, points to the
+ length of the string, in bytes.
+ @param StringFontInfo If not NULL, points to the string's font
+ information. It's caller's responsibility to free
+ this buffer.
+
+ @retval EFI_SUCCESS The string was returned successfully.
+ @retval EFI_NOT_FOUND The string specified by StringId is not available.
+ @retval EFI_NOT_FOUND The string specified by StringId is available but
+ not in the specified language.
+ The specified PackageList is not in the database.
+ @retval EFI_INVALID_LANGUAGE - The string specified by StringId is available but
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to
+ hold the string.
+ @retval EFI_INVALID_PARAMETER The Language or StringSize was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by StringSize was not zero and String was NULL.
+ @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the
+ request.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetString (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN CONST CHAR8 *Language,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_STRING_ID StringId,
+ OUT EFI_STRING String,
+ IN OUT UINTN *StringSize,
+ OUT EFI_FONT_INFO **StringFontInfo OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+
+ if ((This == NULL) || (Language == NULL) || (StringId < 1) || (StringSize == NULL) || (PackageList == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((String == NULL) && (*StringSize != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ PackageListNode = NULL;
+
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (DatabaseRecord->Handle == PackageList) {
+ PackageListNode = DatabaseRecord->PackageList;
+ break;
+ }
+ }
+
+ if (PackageListNode != NULL) {
+ //
+ // First search: to match the StringId in the specified language.
+ //
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;
+ Link != &PackageListNode->StringPkgHdr;
+ Link = Link->ForwardLink
+ )
+ {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *)Language)) {
+ Status = GetStringWorker (Private, StringPackage, StringId, String, StringSize, StringFontInfo);
+ if (Status != EFI_NOT_FOUND) {
+ return Status;
+ }
+ }
+ }
+
+ //
+ // Second search: to match the StringId in other available languages if exist.
+ //
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;
+ Link != &PackageListNode->StringPkgHdr;
+ Link = Link->ForwardLink
+ )
+ {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ Status = GetStringWorker (Private, StringPackage, StringId, NULL, NULL, NULL);
+ if (!EFI_ERROR (Status)) {
+ return EFI_INVALID_LANGUAGE;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ This function updates the string specified by StringId in the specified PackageList to the text
+ specified by String and, optionally, the font information specified by StringFontInfo.
+
+ @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
+ @param PackageList The package list containing the strings.
+ @param StringId The string's id, which is unique within
+ PackageList.
+ @param Language Points to the language for the updated string.
+ @param String Points to the new null-terminated string.
+ @param StringFontInfo Points to the string's font information or NULL if
+ the string font information is not changed.
+
+ @retval EFI_SUCCESS The string was updated successfully.
+ @retval EFI_NOT_FOUND The string specified by StringId is not in the
+ database.
+ @retval EFI_INVALID_PARAMETER The String or Language was NULL.
+ @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in
+ current database.
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
+ task.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiSetString (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_STRING_ID StringId,
+ IN CONST CHAR8 *Language,
+ IN CONST EFI_STRING String,
+ IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+ UINT32 OldPackageLen;
+
+ if ((This == NULL) || (Language == NULL) || (StringId < 1) || (String == NULL) || (PackageList == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ EfiAcquireLock (&mHiiDatabaseLock);
+
+ Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ PackageListNode = NULL;
+
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (DatabaseRecord->Handle == PackageList) {
+ PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(DatabaseRecord->PackageList);
+ }
+ }
+
+ if (PackageListNode != NULL) {
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;
+ Link != &PackageListNode->StringPkgHdr;
+ Link = Link->ForwardLink
+ )
+ {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *)Language)) {
+ OldPackageLen = StringPackage->StringPkgHdr->Header.Length;
+ Status = SetStringWorker (
+ Private,
+ StringPackage,
+ StringId,
+ (EFI_STRING)String,
+ (EFI_FONT_INFO *)StringFontInfo
+ );
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return Status;
+ }
+
+ PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length - OldPackageLen;
+ //
+ // Check whether need to get the contents of HiiDataBase.
+ // Only after ReadyToBoot to do the export.
+ //
+ if (gExportAfterReadyToBoot) {
+ HiiGetDatabaseInfo (&Private->HiiDatabase);
+ }
+
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_NOT_FOUND;
+}
+
+/**
+ This function returns the list of supported languages, in the format specified
+ in Appendix M of UEFI 2.1 spec.
+
+ @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
+ @param PackageList The package list to examine.
+ @param Languages Points to the buffer to hold the returned
+ null-terminated ASCII string.
+ @param LanguagesSize On entry, points to the size of the buffer pointed
+ to by Languages, in bytes. On return, points to
+ the length of Languages, in bytes.
+
+ @retval EFI_SUCCESS The languages were returned successfully.
+ @retval EFI_INVALID_PARAMETER The LanguagesSize was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by LanguagesSize is not zero and Languages is NULL.
+ @retval EFI_BUFFER_TOO_SMALL The LanguagesSize is too small to hold the list of
+ supported languages. LanguageSize is updated to
+ contain the required size.
+ @retval EFI_NOT_FOUND Could not find string package in specified
+ packagelist.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetLanguages (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN OUT CHAR8 *Languages,
+ IN OUT UINTN *LanguagesSize
+ )
+{
+ LIST_ENTRY *Link;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+ UINTN ResultSize;
+
+ if ((This == NULL) || (LanguagesSize == NULL) || (PackageList == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*LanguagesSize != 0) && (Languages == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ PackageListNode = NULL;
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (DatabaseRecord->Handle == PackageList) {
+ PackageListNode = DatabaseRecord->PackageList;
+ break;
+ }
+ }
+
+ if (PackageListNode == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Search the languages in the specified packagelist.
+ //
+ ResultSize = 0;
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;
+ Link != &PackageListNode->StringPkgHdr;
+ Link = Link->ForwardLink
+ )
+ {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ ResultSize += AsciiStrSize (StringPackage->StringPkgHdr->Language);
+ if (ResultSize <= *LanguagesSize) {
+ AsciiStrCpyS (Languages, *LanguagesSize / sizeof (CHAR8), StringPackage->StringPkgHdr->Language);
+ Languages += AsciiStrSize (StringPackage->StringPkgHdr->Language);
+ *(Languages - 1) = L';';
+ }
+ }
+
+ if (ResultSize == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (*LanguagesSize < ResultSize) {
+ *LanguagesSize = ResultSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *(Languages - 1) = 0;
+ return EFI_SUCCESS;
+}
+
+/**
+ Each string package has associated with it a single primary language and zero
+ or more secondary languages. This routine returns the secondary languages
+ associated with a package list.
+
+ @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
+ @param PackageList The package list to examine.
+ @param PrimaryLanguage Points to the null-terminated ASCII string that specifies
+ the primary language. Languages are specified in the
+ format specified in Appendix M of the UEFI 2.0 specification.
+ @param SecondaryLanguages Points to the buffer to hold the returned null-terminated
+ ASCII string that describes the list of
+ secondary languages for the specified
+ PrimaryLanguage. If there are no secondary
+ languages, the function returns successfully, but
+ this is set to NULL.
+ @param SecondaryLanguagesSize On entry, points to the size of the buffer pointed
+ to by SecondaryLanguages, in bytes. On return,
+ points to the length of SecondaryLanguages in bytes.
+
+ @retval EFI_SUCCESS Secondary languages were correctly returned.
+ @retval EFI_INVALID_PARAMETER PrimaryLanguage or SecondaryLanguagesSize was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by SecondaryLanguagesSize is not
+ zero and SecondaryLanguages is NULL.
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by SecondaryLanguagesSize is
+ too small to hold the returned information.
+ SecondaryLanguageSize is updated to hold the size of
+ the buffer required.
+ @retval EFI_INVALID_LANGUAGE The language specified by PrimaryLanguage is not
+ present in the specified package list.
+ @retval EFI_NOT_FOUND The specified PackageList is not in the Database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetSecondaryLanguages (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN CONST CHAR8 *PrimaryLanguage,
+ IN OUT CHAR8 *SecondaryLanguages,
+ IN OUT UINTN *SecondaryLanguagesSize
+ )
+{
+ LIST_ENTRY *Link;
+ LIST_ENTRY *Link1;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+ CHAR8 *Languages;
+ UINTN ResultSize;
+
+ if ((This == NULL) || (PackageList == NULL) || (PrimaryLanguage == NULL) || (SecondaryLanguagesSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((SecondaryLanguages == NULL) && (*SecondaryLanguagesSize != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ PackageListNode = NULL;
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (DatabaseRecord->Handle == PackageList) {
+ PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(DatabaseRecord->PackageList);
+ break;
+ }
+ }
+
+ if (PackageListNode == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Languages = NULL;
+ ResultSize = 0;
+ for (Link1 = PackageListNode->StringPkgHdr.ForwardLink;
+ Link1 != &PackageListNode->StringPkgHdr;
+ Link1 = Link1->ForwardLink
+ )
+ {
+ StringPackage = CR (Link1, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *)PrimaryLanguage)) {
+ Languages = StringPackage->StringPkgHdr->Language;
+ //
+ // Language is a series of ';' terminated strings, first one is primary
+ // language and following with other secondary languages or NULL if no
+ // secondary languages any more.
+ //
+ Languages = AsciiStrStr (Languages, ";");
+ if (Languages == NULL) {
+ break;
+ }
+
+ Languages++;
+
+ ResultSize = AsciiStrSize (Languages);
+ if (ResultSize <= *SecondaryLanguagesSize) {
+ AsciiStrCpyS (SecondaryLanguages, *SecondaryLanguagesSize / sizeof (CHAR8), Languages);
+ } else {
+ *SecondaryLanguagesSize = ResultSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_INVALID_LANGUAGE;
+}
+
+/**
+ Converts the ascii character of the string from uppercase to lowercase.
+ This is a internal function.
+
+ @param ConfigString String to be converted
+
+**/
+VOID
+EFIAPI
+AsciiHiiToLower (
+ IN CHAR8 *ConfigString
+ )
+{
+ ASSERT (ConfigString != NULL);
+
+ //
+ // Convert all hex digits in range [A-F] in the configuration header to [a-f]
+ //
+ for ( ; *ConfigString != '\0'; ConfigString++) {
+ if ((*ConfigString >= 'A') && (*ConfigString <= 'Z')) {
+ *ConfigString = (CHAR8)(*ConfigString - 'A' + 'a');
+ }
+ }
+}
+
+/**
+ Compare whether two names of languages are identical.
+
+ @param Language1 Name of language 1 from StringPackage
+ @param Language2 Name of language 2 to be compared with language 1.
+
+ @retval TRUE same
+ @retval FALSE not same
+
+**/
+BOOLEAN
+HiiCompareLanguage (
+ IN CHAR8 *Language1,
+ IN CHAR8 *Language2
+ )
+{
+ UINTN Index;
+ UINTN StrLen;
+ CHAR8 *Lan1;
+ CHAR8 *Lan2;
+
+ //
+ // Convert to lower to compare.
+ //
+ StrLen = AsciiStrSize (Language1);
+ Lan1 = AllocateZeroPool (StrLen);
+ ASSERT (Lan1 != NULL);
+ AsciiStrCpyS (Lan1, StrLen / sizeof (CHAR8), Language1);
+ AsciiHiiToLower (Lan1);
+
+ StrLen = AsciiStrSize (Language2);
+ Lan2 = AllocateZeroPool (StrLen);
+ ASSERT (Lan2 != NULL);
+ AsciiStrCpyS (Lan2, StrLen / sizeof (CHAR8), Language2);
+ AsciiHiiToLower (Lan2);
+
+ //
+ // Compare the Primary Language in Language1 to Language2
+ //
+ for (Index = 0; Lan1[Index] != 0 && Lan1[Index] != ';'; Index++) {
+ if (Lan1[Index] != Lan2[Index]) {
+ //
+ // Return FALSE if any characters are different.
+ //
+ FreePool (Lan1);
+ FreePool (Lan2);
+ return FALSE;
+ }
+ }
+
+ FreePool (Lan1);
+ FreePool (Lan2);
+
+ //
+ // Only return TRUE if Language2[Index] is a Null-terminator which means
+ // the Primary Language in Language1 is the same length as Language2. If
+ // Language2[Index] is not a Null-terminator, then Language2 is longer than
+ // the Primary Language in Language1, and FALSE must be returned.
+ //
+ return (BOOLEAN)(Language2[Index] == 0);
+}