diff options
| author | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
|---|---|---|
| committer | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
| commit | 7e2ccccace24636f29ddc210b94606abd4c7e42b (patch) | |
| tree | 545d43ea12671048956cafeb12303e84d601e571 /MdeModulePkg/Universal/HiiDatabaseDxe | |
| parent | 27b044605cd5f6b33a3d231576003850b3fe305b (diff) | |
| download | edk2-trunk.tar.xz | |
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'MdeModulePkg/Universal/HiiDatabaseDxe')
| -rw-r--r-- | MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c | 6840 | ||||
| -rw-r--r-- | MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c | 12892 | ||||
| -rw-r--r-- | MdeModulePkg/Universal/HiiDatabaseDxe/Database.c | 9444 | ||||
| -rw-r--r-- | MdeModulePkg/Universal/HiiDatabaseDxe/Font.c | 6036 | ||||
| -rw-r--r-- | MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h | 4680 | ||||
| -rw-r--r-- | MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.uni | 34 | ||||
| -rw-r--r-- | MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf | 188 | ||||
| -rw-r--r-- | MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c | 500 | ||||
| -rw-r--r-- | MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseExtra.uni | 28 | ||||
| -rw-r--r-- | MdeModulePkg/Universal/HiiDatabaseDxe/Image.c | 3166 | ||||
| -rw-r--r-- | MdeModulePkg/Universal/HiiDatabaseDxe/ImageEx.c | 858 | ||||
| -rw-r--r-- | MdeModulePkg/Universal/HiiDatabaseDxe/String.c | 4240 |
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); +} |
