summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/HiiDatabaseDxe
diff options
context:
space:
mode:
authorqwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524>2008-01-21 14:39:56 +0000
committerqwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524>2008-01-21 14:39:56 +0000
commit93e3992d1ea50fb30c48f498d257d4e66252dd9b (patch)
treeb76adcd31d2017cd76317f21be967ad3cb05305e /MdeModulePkg/Universal/HiiDatabaseDxe
parentf79314fa8f44a79e862d2877e5a9b1a3a9f96791 (diff)
downloadedk2-93e3992d1ea50fb30c48f498d257d4e66252dd9b.zip
edk2-93e3992d1ea50fb30c48f498d257d4e66252dd9b.tar.gz
edk2-93e3992d1ea50fb30c48f498d257d4e66252dd9b.tar.bz2
UEFI HII: Merge UEFI HII support changes from branch.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@4599 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Universal/HiiDatabaseDxe')
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c2116
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/Database.c3727
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/Font.c2395
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h1694
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.msa79
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf75
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c197
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/Image.c1509
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.c284
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.h121
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/String.c1606
11 files changed, 13803 insertions, 0 deletions
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
new file mode 100644
index 0000000..15a55d7
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
@@ -0,0 +1,2116 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ConfigRouting.c
+
+Abstract:
+
+ Implementation for EFI_HII_CONFIG_ROUTING_PROTOCOL.
+
+Revision History
+
+
+**/
+
+
+#include "HiiDatabase.h"
+
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+
+STATIC
+CHAR16
+NibbleToHexCharPrivate (
+ IN UINT8 Nibble
+ )
+/*++
+
+ Routine Description:
+ Converts the low nibble of a byte to hex unicode character.
+
+ Arguments:
+ Nibble - lower nibble of a byte.
+
+ Returns:
+ Hex unicode character between L'0' to L'f'.
+
+--*/
+{
+ Nibble &= 0x0F;
+
+ if (Nibble <= 0x9) {
+ return (CHAR16)(Nibble + L'0');
+ }
+
+ return (CHAR16)(Nibble - 0xA + L'a');
+}
+
+
+/**
+ Converts Unicode string to binary buffer.
+ The conversion may be partial.
+ The first character in the string that is not hex digit stops the conversion.
+ At a minimum, any blob of data could be represented as a hex string.
+
+ @param Buf Pointer to buffer that receives the data.
+ @param Len Length in bytes of the buffer to hold converted
+ data. If routine return with EFI_SUCCESS,
+ containing length of converted data. If routine
+ return with EFI_BUFFER_TOO_SMALL, containg length
+ of buffer desired.
+ @param Str String to be converted from.
+ @param ConvertedStrLen Length of the Hex String consumed.
+
+ @retval EFI_SUCCESS Routine Success.
+ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold converted data.
+
+**/
+STATIC
+EFI_STATUS
+HexStringToBufPrivate (
+ IN OUT UINT8 *Buf,
+ IN OUT UINTN *Len,
+ IN CHAR16 *Str,
+ OUT UINTN *ConvertedStrLen OPTIONAL
+ )
+{
+ UINTN HexCnt;
+ UINTN Idx;
+ UINTN BufferLength;
+ UINT8 Digit;
+ UINT8 Byte;
+
+ //
+ // Find out how many hex characters the string has.
+ //
+ for (Idx = 0, HexCnt = 0; R8_IsHexDigit (&Digit, Str[Idx]); Idx++, HexCnt++);
+
+ if (HexCnt == 0) {
+ *Len = 0;
+ return EFI_SUCCESS;
+ }
+ //
+ // Two Unicode characters make up 1 buffer byte. Round up.
+ //
+ BufferLength = (HexCnt + 1) / 2;
+
+ //
+ // Test if buffer is passed enough.
+ //
+ if (BufferLength > (*Len)) {
+ *Len = BufferLength;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *Len = BufferLength;
+
+ for (Idx = 0; Idx < HexCnt; Idx++) {
+
+ R8_IsHexDigit (&Digit, Str[Idx]);
+
+ //
+ // For odd charaters, write the lower nibble for each buffer byte,
+ // and for even characters, the upper nibble.
+ //
+ if ((Idx & 1) == 0) {
+ Byte = (UINT8) (Digit << 4);
+ } else {
+ Byte = Buf[Idx / 2];
+ Byte &= 0xF0;
+ Byte = (UINT8) (Byte | Digit);
+ }
+
+ Buf[Idx / 2] = Byte;
+ }
+
+ if (ConvertedStrLen != NULL) {
+ *ConvertedStrLen = HexCnt;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Converts binary buffer to Unicode string.
+ At a minimum, any blob of data could be represented as a hex string.
+
+ @param Str Pointer to the string.
+ @param HexStringBufferLength Length in bytes of buffer to hold the hex string.
+ Includes tailing '\0' character. If routine return
+ with EFI_SUCCESS, containing length of hex string
+ buffer. If routine return with
+ EFI_BUFFER_TOO_SMALL, containg length of hex
+ string buffer desired.
+ @param Buf Buffer to be converted from.
+ @param Len Length in bytes of the buffer to be converted.
+ @param Flag If TRUE, encode the data in the same order as the
+ it resides in the Buf. Else encode it in the
+ reverse direction.
+
+ @retval EFI_SUCCESS Routine success.
+ @retval EFI_BUFFER_TOO_SMALL The hex string buffer is too small.
+
+**/
+STATIC
+EFI_STATUS
+BufToHexStringPrivate (
+ IN OUT CHAR16 *Str,
+ IN OUT UINTN *HexStringBufferLength,
+ IN UINT8 *Buf,
+ IN UINTN Len,
+ IN BOOLEAN Flag
+ )
+{
+ UINTN Idx;
+ UINT8 Byte;
+ UINTN StrLen;
+
+ //
+ // Make sure string is either passed or allocate enough.
+ // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer.
+ // Plus the Unicode termination character.
+ //
+ StrLen = Len * 2;
+ if ((*HexStringBufferLength) < (StrLen + 1) * sizeof (CHAR16)) {
+ *HexStringBufferLength = (StrLen + 1) * sizeof (CHAR16);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *HexStringBufferLength = (StrLen + 1) * sizeof (CHAR16);
+
+ //
+ // Ends the string.
+ //
+ Str[StrLen] = 0;
+
+ for (Idx = 0; Idx < Len; Idx++) {
+
+ Byte = Buf[Idx];
+ if (Flag) {
+ Str[Idx * 2] = NibbleToHexCharPrivate ((UINT8)(Byte >> 4));
+ Str[Idx * 2 + 1] = NibbleToHexCharPrivate (Byte);
+ } else {
+ Str[StrLen - 1 - Idx * 2] = NibbleToHexCharPrivate (Byte);
+ Str[StrLen - 2 - Idx * 2] = NibbleToHexCharPrivate ((UINT8)(Byte >> 4));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ Calculate the number of Unicode characters of the incoming Configuration string,
+ not including NULL terminator.
+
+ @param String String in <MultiConfigRequest> or
+ <MultiConfigResp> format.
+
+ @return The number of Unicode characters.
+
+**/
+STATIC
+UINTN
+CalculateConfigStringLen (
+ IN EFI_STRING String
+ )
+{
+ UINTN Length;
+
+ //
+ // "GUID=" should be the first element of incoming string.
+ //
+ ASSERT (String != NULL);
+ ASSERT (StrnCmp (String, L"GUID=", StrLen (L"GUID=")) == 0);
+
+ Length = StrLen (L"GUID=");
+ String += Length;
+
+ //
+ // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
+ // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
+ //
+ while (*String != 0 && StrnCmp (String, L"&GUID=", StrLen (L"&GUID=")) != 0) {
+ Length++;
+ String++;
+ }
+
+ return Length;
+}
+
+
+/**
+ Convert the hex UNICODE %02x encoding of a UEFI device path to binary
+ from <PathHdr> of <ConfigHdr>.
+
+ @param String UEFI configuration string
+ @param DevicePath binary of a UEFI device path.
+
+ @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
+ @retval EFI_SUCCESS The device path is retrieved and translated to
+ binary format.
+
+**/
+STATIC
+EFI_STATUS
+GetDevicePath (
+ IN EFI_STRING String,
+ OUT UINT8 **DevicePath
+ )
+{
+ UINTN Length;
+ EFI_STRING PathHdr;
+ EFI_STRING DevicePathString;
+
+ if (String == NULL || DevicePath == 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;
+ }
+
+ String += StrLen (L"PATH=");
+ 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++);
+ DevicePathString = (EFI_STRING) AllocateZeroPool ((Length + 1) * sizeof (CHAR16));
+ if (DevicePathString == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ StrnCpy (DevicePathString, PathHdr, Length);
+ *(DevicePathString + Length) = 0;
+
+ //
+ // 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.
+ // Two Unicode characters make up 1 buffer byte.
+ //
+ Length /= 2;
+ *DevicePath = (UINT8 *) AllocateZeroPool (Length);
+ if (*DevicePath == NULL) {
+ SafeFreePool (DevicePathString);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HexStringToBufPrivate (*DevicePath, &Length, DevicePathString, NULL);
+
+ SafeFreePool (DevicePathString);
+
+ return EFI_SUCCESS;
+
+}
+
+
+/**
+ Extract Storage from all Form Packages in current hii database.
+
+ @param HiiDatabase EFI_HII_DATABASE_PROTOCOL instance.
+ @param StorageListHead Storage link List head.
+
+ @retval EFI_NOT_FOUND There is no form package in current hii database.
+ @retval EFI_INVALID_PARAMETER Any parameter is invalid.
+ @retval EFI_SUCCESS All existing storage is exported.
+
+**/
+STATIC
+EFI_STATUS
+ExportAllStorage (
+ IN EFI_HII_DATABASE_PROTOCOL *HiiDatabase,
+ IN OUT LIST_ENTRY *StorageListHead
+)
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ UINTN HandleCount;
+ EFI_HII_HANDLE *HandleBuffer;
+ UINTN Index;
+ UINTN Index2;
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
+ EFI_HII_PACKAGE_HEADER *Package;
+ UINT8 *OpCodeData;
+ UINT8 Operand;
+ UINT32 Offset;
+ HII_FORMSET_STORAGE *Storage;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HANDLE DriverHandle;
+ CHAR8 *AsciiString;
+ UINT32 PackageListLength;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+
+ //
+ // Find the package list which contains Form package.
+ //
+ BufferSize = 0;
+ HandleBuffer = NULL;
+ Status = HiiListPackageLists (
+ HiiDatabase,
+ EFI_HII_PACKAGE_FORM,
+ NULL,
+ &BufferSize,
+ HandleBuffer
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HandleBuffer = AllocateZeroPool (BufferSize);
+ ASSERT (HandleBuffer != NULL);
+
+ Status = HiiListPackageLists (
+ HiiDatabase,
+ EFI_HII_PACKAGE_FORM,
+ NULL,
+ &BufferSize,
+ HandleBuffer
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ SafeFreePool (HandleBuffer);
+ return Status;
+ }
+
+ HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);
+ for (Index = 0; Index < HandleCount; Index++) {
+ HiiHandle = HandleBuffer[Index];
+
+ BufferSize = 0;
+ HiiPackageList = NULL;
+ Status = HiiExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HiiPackageList = AllocateZeroPool (BufferSize);
+ ASSERT (HiiPackageList != NULL);
+ Status = HiiExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
+ }
+ if (EFI_ERROR (Status)) {
+ SafeFreePool (HandleBuffer);
+ SafeFreePool (HiiPackageList);
+ return Status;
+ }
+
+ //
+ // Get Form package from this HII package List
+ //
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+ CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
+ Package = NULL;
+ ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ while (Offset < PackageListLength) {
+ Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+ if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {
+ break;
+ }
+ Offset += PackageHeader.Length;
+ }
+ if (Offset >= PackageListLength) {
+ //
+ // Error here: No Form package found in this Package List
+ //
+ ASSERT (FALSE);
+ }
+
+ //
+ // Search Storage definition in this Form package
+ //
+ Offset = sizeof (EFI_HII_PACKAGE_HEADER);
+ while (Offset < PackageHeader.Length) {
+ OpCodeData = ((UINT8 *) Package) + Offset;
+ Offset += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
+
+ Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
+
+ if ((Operand == EFI_IFR_VARSTORE_OP) ||
+ (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) ||
+ (Operand == EFI_IFR_VARSTORE_EFI_OP)) {
+
+ Storage = AllocateZeroPool (sizeof (HII_FORMSET_STORAGE));
+ ASSERT (Storage != NULL);
+ InsertTailList (StorageListHead, &Storage->Entry);
+
+ Storage->Signature = HII_FORMSET_STORAGE_SIGNATURE;
+ Storage->HiiHandle = HiiHandle;
+
+ Status = HiiGetPackageListHandle (HiiDatabase, HiiHandle, &DriverHandle);
+ if (EFI_ERROR (Status)) {
+ SafeFreePool (HandleBuffer);
+ SafeFreePool (HiiPackageList);
+ SafeFreePool (Storage);
+ return Status;
+ }
+ Storage->DriverHandle = DriverHandle;
+
+ if (Operand == EFI_IFR_VARSTORE_OP) {
+ Storage->Type = EFI_HII_VARSTORE_BUFFER;
+
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));
+ CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));
+
+ AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;
+ Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);
+ ASSERT (Storage->Name != NULL);
+ for (Index2 = 0; AsciiString[Index2] != 0; Index2++) {
+ Storage->Name[Index2] = (CHAR16) AsciiString[Index2];
+ }
+ //
+ // Append '\0' to the end of the unicode string.
+ //
+ Storage->Name[Index2] = 0;
+ } else if (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) {
+ Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;
+
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));
+ } else if (Operand == EFI_IFR_VARSTORE_EFI_OP) {
+ Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE;
+
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));
+ }
+ }
+ }
+
+ SafeFreePool (HiiPackageList);
+ }
+
+ SafeFreePool (HandleBuffer);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Generate a sub string then output it.
+
+ @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 hex
+ string and to be the content of the generated
+ string.
+ @param Flag If TRUE, convert the buffer data in the same order
+ as the it resides in the Buffer. Else convert it
+ in the reverse direction.
+ @param SubStr Points to the output string. It's caller's
+ responsibility to free this buffer.
+
+
+**/
+STATIC
+VOID
+GenerateSubStr (
+ IN CONST EFI_STRING String,
+ IN UINTN BufferLen,
+ IN UINT8 *Buffer,
+ IN BOOLEAN Flag,
+ OUT EFI_STRING *SubStr
+ )
+{
+ UINTN Length;
+ EFI_STRING Str;
+ EFI_STATUS Status;
+
+ ASSERT (String != NULL && SubStr != NULL);
+
+ if (Buffer == NULL) {
+ *SubStr = AllocateCopyPool (StrSize (String), String);
+ ASSERT (*SubStr != NULL);
+ return ;
+ }
+
+ Length = BufferLen * 2 + 1 + StrLen (String) + 1;
+ Str = AllocateZeroPool (Length * sizeof (CHAR16));
+ ASSERT (Str != NULL);
+
+ StrCpy (Str, String);
+ Length = (BufferLen * 2 + 1) * sizeof (CHAR16);
+
+ Status = BufToHexStringPrivate (
+ Str + StrLen (String),
+ &Length,
+ Buffer,
+ BufferLen,
+ Flag
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ StrCat (Str, L"&");
+
+ *SubStr = Str;
+}
+
+
+/**
+ Retrieve the <ConfigBody> from String then output it.
+
+ @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.
+
+**/
+STATIC
+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;
+ }
+
+ 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;
+ Result = AllocateCopyPool (Length * sizeof (CHAR16), String);
+ if (Result == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *(Result + Length - 1) = 0;
+ *ConfigBody = Result;
+ return EFI_SUCCESS;
+
+}
+
+
+#endif
+
+VOID *
+ReallocatePool (
+ IN VOID *OldPool,
+ IN UINTN OldSize,
+ IN UINTN NewSize
+ )
+/*++
+
+Routine Description:
+ Adjusts the size of a previously allocated buffer.
+
+Arguments:
+ OldPool - A pointer to the buffer whose size is being adjusted.
+ OldSize - The size of the current buffer.
+ NewSize - The size of the new buffer.
+
+Returns:
+ Points to the new buffer
+
+--*/
+{
+ VOID *NewPool;
+
+ NewPool = NULL;
+ if (NewSize) {
+ NewPool = AllocateZeroPool (NewSize);
+ }
+
+ if (OldPool) {
+ if (NewPool) {
+ CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);
+ }
+
+ gBS->FreePool (OldPool);
+ }
+
+ return NewPool;
+}
+
+
+/**
+ Append a string to a multi-string format.
+
+ @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
+
+**/
+STATIC
+EFI_STATUS
+AppendToMultiString (
+ IN OUT EFI_STRING *MultiString,
+ IN EFI_STRING AppendString
+ )
+{
+ UINTN AppendStringSize;
+ UINTN MultiStringSize;
+
+ if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AppendStringSize = StrSize (AppendString);
+ MultiStringSize = StrSize (*MultiString);
+
+ //
+ // 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 (
+ (VOID *) (*MultiString),
+ MultiStringSize,
+ MultiStringSize + AppendStringSize
+ );
+ }
+
+ //
+ // Append the incoming string
+ //
+ StrCat (*MultiString, 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>
+
+ @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 neccessary
+ structures.
+ @retval EFI_SUCCESS Value of <Number> is outputted in Number
+ successfully.
+
+**/
+STATIC
+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;
+
+ ASSERT (StringPtr != NULL && Number != NULL && Len != NULL);
+ ASSERT (*StringPtr != 0);
+
+ Buf = NULL;
+
+ TmpPtr = StringPtr;
+ while (*StringPtr != 0 && *StringPtr != L'&') {
+ StringPtr++;
+ }
+ *Len = StringPtr - TmpPtr;
+ Length = *Len + 1;
+
+ Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (EFI_STRING));
+ if (Str == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));
+ *(Str + *Len) = 0;
+
+ Length = (Length + 1) / 2;
+ Buf = (UINT8 *) AllocateZeroPool (Length);
+ if (Buf == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ Status = R8_HexStringToBuf (Buf, &Length, Str, NULL);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ *Number = Buf;
+ Status = EFI_SUCCESS;
+
+Exit:
+ SafeFreePool (Str);
+ return Status;
+}
+
+
+/**
+ 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
+ )
+{
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_STRING StringPtr;
+ EFI_STRING ConfigRequest;
+ UINTN Length;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *Database;
+ UINT8 *CurrentDevicePath;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+ EFI_STRING AccessProgress;
+ EFI_STRING AccessResults;
+ UINTN RemainSize;
+ EFI_STRING TmpPtr;
+
+ 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;
+
+ //
+ // 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;
+ }
+
+ //
+ // 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) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ *(ConfigRequest + Length) = 0;
+
+ //
+ // Get the UEFI device path
+ //
+ Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);
+ if (EFI_ERROR (Status)) {
+ SafeFreePool (ConfigRequest);
+ 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);
+ CurrentDevicePath = Database->PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
+ if (CurrentDevicePath != NULL) {
+ if (CompareMem (
+ DevicePath,
+ CurrentDevicePath,
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
+ ) == 0) {
+ DriverHandle = Database->DriverHandle;
+ break;
+ }
+ }
+ }
+
+ SafeFreePool (DevicePath);
+
+ if (DriverHandle == NULL) {
+ //
+ // Routing data does not match any known driver.
+ // Set Progress to the 'G' in "GUID" of the routing header.
+ //
+ *Progress = StringPtr;
+ SafeFreePool (ConfigRequest);
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Call corresponding ConfigAccess protocol to extract settings
+ //
+ Status = gBS->HandleProtocol (
+ DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ (VOID **) &ConfigAccess
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ 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.
+ //
+ RemainSize = StrSize (AccessProgress);
+ for (TmpPtr = StringPtr; CompareMem (TmpPtr, AccessProgress, RemainSize) != 0; TmpPtr++);
+ *Progress = TmpPtr;
+
+ SafeFreePool (ConfigRequest);
+ return Status;
+ }
+
+ //
+ // Attach this <ConfigAltResp> to a <MultiConfigAltResp>
+ //
+ ASSERT (*AccessProgress == 0);
+ Status = AppendToMultiString (Results, AccessResults);
+ ASSERT_EFI_ERROR (Status);
+ SafeFreePool (AccessResults);
+ AccessResults = NULL;
+ SafeFreePool (ConfigRequest);
+ ConfigRequest = NULL;
+
+ //
+ // Go to next <ConfigRequest> (skip '&').
+ //
+ StringPtr += Length;
+ if (*StringPtr == 0) {
+ *Progress = StringPtr;
+ break;
+ }
+
+ StringPtr++;
+
+ }
+
+ return EFI_SUCCESS;
+#else
+ return EFI_UNSUPPORTED;
+#endif
+
+}
+
+
+/**
+ 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 names in the Request string.
+ 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
+ )
+{
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ LIST_ENTRY StorageListHdr;
+ HII_FORMSET_STORAGE *Storage;
+ LIST_ENTRY *Link;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN Length;
+ EFI_STRING PathHdr;
+ UINTN PathHdrSize;
+ EFI_STRING ConfigRequest;
+ UINTN RequestSize;
+ EFI_STRING StringPtr;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+ EFI_STRING AccessProgress;
+ EFI_STRING AccessResults;
+ UINTN TmpSize;
+
+ if (This == NULL || Results == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ InitializeListHead (&StorageListHdr);
+
+ Status = ExportAllStorage (&Private->HiiDatabase, &StorageListHdr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // 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;
+ }
+
+ //
+ // Parsing all formset storages.
+ //
+ for (Link = StorageListHdr.ForwardLink; Link != &StorageListHdr; Link = Link->ForwardLink) {
+ Storage = CR (Link, HII_FORMSET_STORAGE, Entry, HII_FORMSET_STORAGE_SIGNATURE);
+ //
+ // Find the corresponding device path instance
+ //
+ Status = gBS->HandleProtocol (
+ Storage->DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Convert the device path binary to hex UNICODE %02x bytes in the same order
+ // as the device path resides in RAM memory.
+ //
+ Length = GetDevicePathSize (DevicePath);
+ PathHdrSize = (Length * 2 + 1) * sizeof (CHAR16);
+ PathHdr = (EFI_STRING) AllocateZeroPool (PathHdrSize);
+ if (PathHdr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = BufToHexStringPrivate (PathHdr, &PathHdrSize, (UINT8 *) DevicePath, Length, TRUE);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Generate a <ConfigRequest> with one <ConfigHdr> and zero <RequestElement>.
+ // It means extract all possible configurations from this specific driver.
+ //
+ TmpSize = StrLen (L"GUID=&NAME=&PATH=");
+ RequestSize = (TmpSize + sizeof (EFI_GUID) * 2 + StrLen (Storage->Name))
+ * sizeof (CHAR16) + PathHdrSize;
+ ConfigRequest = (EFI_STRING) AllocateZeroPool (RequestSize);
+ if (ConfigRequest == NULL) {
+ SafeFreePool (PathHdr);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Add <GuidHdr>
+ // <GuidHdr> ::= 'GUID='<Guid>
+ //
+ StringPtr = ConfigRequest;
+ StrnCpy (StringPtr, L"GUID=", StrLen (L"GUID="));
+ StringPtr += StrLen (L"GUID=");
+
+ Status = BufToHexStringPrivate (
+ StringPtr,
+ &RequestSize,
+ (UINT8 *) (&Storage->Guid),
+ sizeof (EFI_GUID),
+ FALSE
+ );
+ ASSERT_EFI_ERROR (Status);
+ StringPtr += RequestSize / 2 - 1;
+ ASSERT (*StringPtr == 0);
+ *StringPtr = L'&';
+ StringPtr++;
+
+ //
+ // Add <NameHdr>
+ // <NameHdr> ::= 'NAME='<String>
+ //
+ StrnCpy (StringPtr, L"NAME=", StrLen (L"NAME="));
+ StringPtr += StrLen (L"NAME=");
+ StrnCpy (StringPtr, Storage->Name, StrLen (Storage->Name));
+ StringPtr += StrLen (Storage->Name);
+ *StringPtr = L'&';
+ StringPtr++;
+
+ //
+ // Add <PathHdr>
+ // <PathHdr> ::= '<PATH=>'<UEFI binary represented as hex UNICODE %02x>
+ //
+ StrnCpy (StringPtr, L"PATH=", StrLen (L"PATH="));
+ StringPtr += StrLen (L"PATH=");
+ StrCpy (StringPtr, PathHdr);
+
+ SafeFreePool (PathHdr);
+ PathHdr = NULL;
+
+ //
+ // BUGBUG: The "Implementation note" of ExportConfig() in UEFI spec makes the
+ // code somewhat complex. Let's TBD here whether a <ConfigRequest> or a <ConfigHdr>
+ // is required to call ConfigAccess.ExtractConfig().
+ //
+ // Here we use <ConfigHdr> to call ConfigAccess instance. It requires ConfigAccess
+ // to handle such kind of "ConfigRequest". It is not supported till now.
+ //
+ // Either the ExportConfig will be updated or the ConfigAccess.ExtractConfig()
+ // will be updated as soon as the decision is made.
+
+ //
+ // Route the request to corresponding ConfigAccess protocol to extract settings.
+ //
+ Status = gBS->HandleProtocol (
+ Storage->DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ (VOID **) &ConfigAccess
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = ConfigAccess->ExtractConfig (
+ ConfigAccess,
+ ConfigRequest,
+ &AccessProgress,
+ &AccessResults
+ );
+ if (EFI_ERROR (Status)) {
+ SafeFreePool (ConfigRequest);
+ SafeFreePool (AccessResults);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Attach this <ConfigAltResp> to a <MultiConfigAltResp>
+ //
+ ASSERT (*AccessProgress == 0);
+ Status = AppendToMultiString (Results, AccessResults);
+ ASSERT_EFI_ERROR (Status);
+ SafeFreePool (AccessResults);
+ AccessResults = NULL;
+ SafeFreePool (ConfigRequest);
+ ConfigRequest = NULL;
+
+ }
+
+ //
+ // Free the exported storage resource
+ //
+ while (!IsListEmpty (&StorageListHdr)) {
+ Storage = CR (
+ StorageListHdr.ForwardLink,
+ HII_FORMSET_STORAGE,
+ Entry,
+ HII_FORMSET_STORAGE_SIGNATURE
+ );
+ RemoveEntryList (&Storage->Entry);
+ SafeFreePool (Storage->Name);
+ SafeFreePool (Storage);
+ }
+
+ return EFI_SUCCESS;
+#else
+ return EFI_UNSUPPORTED;
+#endif
+}
+
+
+/**
+ 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
+HiiConfigRoutingRoutConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ )
+{
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_STRING StringPtr;
+ EFI_STRING ConfigResp;
+ UINTN Length;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *Database;
+ UINT8 *CurrentDevicePath;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+ EFI_STRING AccessProgress;
+ UINTN RemainSize;
+ EFI_STRING TmpPtr;
+
+ 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;
+
+ //
+ // 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)) {
+ SafeFreePool (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);
+ CurrentDevicePath = Database->PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
+ if (CurrentDevicePath != NULL) {
+ if (CompareMem (
+ DevicePath,
+ CurrentDevicePath,
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
+ ) == 0) {
+ DriverHandle = Database->DriverHandle;
+ break;
+ }
+ }
+ }
+
+ SafeFreePool (DevicePath);
+
+ if (DriverHandle == NULL) {
+ //
+ // Routing data does not match any known driver.
+ // Set Progress to the 'G' in "GUID" of the routing header.
+ //
+ *Progress = StringPtr;
+ SafeFreePool (ConfigResp);
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Call corresponding ConfigAccess protocol to route settings
+ //
+ Status = gBS->HandleProtocol (
+ DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ (VOID **) &ConfigAccess
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = ConfigAccess->RouteConfig (
+ ConfigAccess,
+ ConfigResp,
+ &AccessProgress
+ );
+
+ if (EFI_ERROR (Status)) {
+ //
+ // AccessProgress indicates the parsing progress on <ConfigResp>.
+ // Map it to the progress on <MultiConfigResp> then return it.
+ //
+ RemainSize = StrSize (AccessProgress);
+ for (TmpPtr = StringPtr; CompareMem (TmpPtr, AccessProgress, RemainSize) != 0; TmpPtr++);
+ *Progress = TmpPtr;
+
+ SafeFreePool (ConfigResp);
+ return Status;
+ }
+
+ SafeFreePool (ConfigResp);
+ ConfigResp = NULL;
+
+ //
+ // Go to next <ConfigResp> (skip '&').
+ //
+ StringPtr += Length;
+ if (*StringPtr == 0) {
+ *Progress = StringPtr;
+ break;
+ }
+
+ StringPtr++;
+
+ }
+
+ return EFI_SUCCESS;
+#else
+ return EFI_UNSUPPORTED;
+#endif
+}
+
+
+/**
+ 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_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;
+
+ 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;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+ while (*StringPtr++ != L'&');
+
+ //
+ // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
+ //
+ Length = StringPtr - ConfigRequest;
+ CopyMem (*Config, ConfigRequest, Length * sizeof (CHAR16));
+
+ //
+ // 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 (Status == EFI_OUT_OF_RESOURCES) {
+ *Progress = ConfigRequest;
+ goto Exit;
+ }
+ Offset = 0;
+ CopyMem (
+ &Offset,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
+ );
+ SafeFreePool (TmpBuffer);
+
+ StringPtr += Length;
+ if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
+ *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+ StringPtr += StrLen (L"&WIDTH=");
+
+ //
+ // Get Width
+ //
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ *Progress = ConfigRequest;
+ goto Exit;
+ }
+ Width = 0;
+ CopyMem (
+ &Width,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
+ );
+ SafeFreePool (TmpBuffer);
+
+ StringPtr += Length;
+ if (*StringPtr != 0 && *StringPtr != L'&') {
+ *Progress = StringPtr - Length - StrLen (L"&WIDTH=");
+ 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;
+ }
+
+ Status = R8_BufToHexString (ValueStr, &Length, Value, Width);
+ ASSERT_EFI_ERROR (Status);
+ SafeFreePool (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;
+ StrCat (ConfigElement, L"VALUE=");
+ StrCat (ConfigElement, ValueStr);
+
+ AppendToMultiString (Config, ConfigElement);
+
+ SafeFreePool (ConfigElement);
+ SafeFreePool (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;
+ }
+
+ *Progress = StringPtr;
+ return EFI_SUCCESS;
+
+Exit:
+
+ SafeFreePool (*Config);
+ SafeFreePool (ValueStr);
+ SafeFreePool (Value);
+ SafeFreePool (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 index of the last
+ modified byte in the Block.
+ @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>.
+
+**/
+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;
+ UINTN Length;
+ EFI_STATUS Status;
+ UINT8 *TmpBuffer;
+ UINTN Offset;
+ UINTN Width;
+ UINT8 *Value;
+ UINTN BufferSize;
+
+ if (This == NULL || BlockSize == NULL || Progress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (ConfigResp == NULL || Block == NULL) {
+ *Progress = ConfigResp;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ ASSERT (Private != NULL);
+
+ StringPtr = ConfigResp;
+ BufferSize = *BlockSize;
+ Value = NULL;
+
+ //
+ // 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'&');
+
+ //
+ // 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) {
+ StringPtr += StrLen (L"OFFSET=");
+ //
+ // Get Offset
+ //
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ *Progress = ConfigResp;
+ goto Exit;
+ }
+ Offset = 0;
+ CopyMem (
+ &Offset,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
+ );
+ SafeFreePool (TmpBuffer);
+
+ StringPtr += Length;
+ if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
+ *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+ StringPtr += StrLen (L"&WIDTH=");
+
+ //
+ // Get Width
+ //
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ *Progress = ConfigResp;
+ goto Exit;
+ }
+ Width = 0;
+ CopyMem (
+ &Width,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
+ );
+ SafeFreePool (TmpBuffer);
+
+ StringPtr += Length;
+ if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
+ *Progress = StringPtr - Length - StrLen (L"&WIDTH=");
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+ StringPtr += StrLen (L"&VALUE=");
+
+ //
+ // Get Value
+ //
+ Status = GetValueOfNumber (StringPtr, &Value, &Length);
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ *Progress = ConfigResp;
+ goto Exit;
+ }
+
+ StringPtr += Length;
+ if (*StringPtr != 0 && *StringPtr != L'&') {
+ *Progress = StringPtr - Length - 7;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ //
+ // Update the Block with configuration info
+ //
+
+ if (Offset + Width > BufferSize) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ CopyMem (Block + Offset, Value, Width);
+ *BlockSize = Offset + Width - 1;
+
+ SafeFreePool (Value);
+ Value = NULL;
+
+ //
+ // If '\0', parsing is finished. Otherwise skip '&' to continue
+ //
+ if (*StringPtr == 0) {
+ break;
+ }
+
+ StringPtr++;
+ }
+
+ if (*StringPtr != 0) {
+ *Progress = StringPtr - 1;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ *Progress = StringPtr;
+ return EFI_SUCCESS;
+
+Exit:
+
+ SafeFreePool (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.
+
+ @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
+ )
+{
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+
+ EFI_STATUS Status;
+ EFI_STRING StringPtr;
+ EFI_STRING HdrStart = NULL;
+ EFI_STRING HdrEnd = NULL;
+ EFI_STRING TmpPtr;
+ UINTN Length;
+ EFI_STRING GuidStr = NULL;
+ EFI_STRING NameStr = NULL;
+ EFI_STRING PathStr = NULL;
+ EFI_STRING AltIdStr = NULL;
+ EFI_STRING Result = NULL;
+ BOOLEAN GuidFlag = FALSE;
+ BOOLEAN NameFlag = FALSE;
+ BOOLEAN 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), (UINT8 *) Guid, FALSE, &GuidStr);
+ GenerateSubStr (
+ L"PATH=",
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
+ (UINT8 *) DevicePath,
+ TRUE,
+ &PathStr
+ );
+ if (AltCfgId != NULL) {
+ GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (UINT8 *) AltCfgId, FALSE, &AltIdStr);
+ }
+ if (Name != NULL) {
+ Length = StrLen (Name);
+ Length += StrLen (L"NAME=&") + 1;
+ NameStr = AllocateZeroPool (Length * sizeof (CHAR16));
+ if (NameStr == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ StrCpy (NameStr, L"NAME=");
+ StrCat (NameStr, Name);
+ StrCat (NameStr, L"&");
+ } else {
+ GenerateSubStr (L"NAME=", 0, NULL, FALSE, &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;
+ }
+ }
+ 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 {
+ Status = OutputConfigBody (StringPtr, &Result);
+ goto Exit;
+ }
+ }
+ }
+
+ Status = EFI_NOT_FOUND;
+
+Exit:
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Copy the <ConfigHdr> and <ConfigBody>
+ //
+ Length = HdrEnd - HdrStart + StrLen (Result);
+ *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
+ if (*AltCfgResp == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);
+ StrCat (*AltCfgResp, Result);
+ Status = EFI_SUCCESS;
+ }
+ }
+
+ SafeFreePool (GuidStr);
+ SafeFreePool (NameStr);
+ SafeFreePool (PathStr);
+ SafeFreePool (AltIdStr);
+ SafeFreePool (Result);
+
+ return Status;
+
+#else
+ return EFI_UNSUPPORTED;
+#endif
+
+}
+
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
new file mode 100644
index 0000000..a24c59b
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
@@ -0,0 +1,3727 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Database.c
+
+Abstract:
+
+ Implementation for EFI_HII_DATABASE_PROTOCOL.
+
+Revision History
+
+
+**/
+
+
+#include "HiiDatabase.h"
+
+//
+// Global variables
+//
+STATIC EFI_GUID mHiiDatabaseNotifyGuid = HII_DATABASE_NOTIFY_GUID;
+
+
+/**
+ This function generates a HII_DATABASE_RECORD node and adds into hii database.
+
+ @param Private hii database private structure
+ @param DatabaseRecord 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.
+
+**/
+STATIC
+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) {
+ SafeFreePool (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) {
+ SafeFreePool (DatabaseRecord->PackageList);
+ SafeFreePool (DatabaseRecord);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ HiiHandle->Signature = HII_HANDLE_SIGNATURE;
+ //
+ // Backup the number of Hii handles
+ //
+ Private->HiiHandleCount++;
+ HiiHandle->Key = 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
+
+ @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.
+
+ @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.
+
+**/
+STATIC
+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_FORM:
+ 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
+ );
+ }
+ }
+
+ SafeFreePool (Buffer);
+ Buffer = NULL;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function insert a GUID package to a package list node.
+
+ @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 pacakge
+
+ @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.
+
+**/
+STATIC
+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) {
+ SafeFreePool (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.
+
+ @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.
+
+**/
+STATIC
+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.
+
+ @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.
+
+**/
+STATIC
+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;
+ SafeFreePool (Package->GuidPkg);
+ SafeFreePool (Package);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function insert a Form package to a package list node.
+
+ @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.
+
+**/
+STATIC
+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) {
+ SafeFreePool (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;
+
+ 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.
+
+ @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.
+
+**/
+STATIC
+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 (PackageLength + *ResultSize + UsedSize <= BufferSize) {
+ //
+ // Invoke registered notification if exists
+ //
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
+ (VOID *) FormPackage,
+ EFI_HII_PACKAGE_FORM,
+ 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.
+
+ @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.
+
+**/
+STATIC
+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_FORM,
+ Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RemoveEntryList (&Package->IfrEntry);
+ PackageList->PackageListHdr.PackageLength -= Package->FormPkgHdr.Length;
+ SafeFreePool (Package->IfrData);
+ SafeFreePool (Package);
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ This function insert a String package to a package list node.
+
+ @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.
+
+**/
+STATIC
+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;
+ }
+ AsciiStrCpy (Language, (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 (R8_EfiLibCompareLanguage (Language, StringPackage->StringPkgHdr->Language)) {
+ SafeFreePool (Language);
+ return EFI_UNSUPPORTED;
+ }
+ }
+ SafeFreePool (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, 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:
+
+ SafeFreePool (StringPackage->StringBlock);
+ SafeFreePool (StringPackage->StringPkgHdr);
+ SafeFreePool (StringPackage);
+ return Status;
+
+}
+
+
+/**
+ This function exports String packages to a buffer.
+
+ @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.
+
+**/
+STATIC
+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.
+
+ @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.
+
+**/
+STATIC
+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;
+ SafeFreePool (Package->StringBlock);
+ SafeFreePool (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);
+ SafeFreePool (FontInfo);
+ }
+
+ SafeFreePool (Package);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function insert a Font package to a package list node.
+
+ @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.
+
+**/
+STATIC
+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;
+ StrCpy (FontInfo->FontName, 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:
+
+ SafeFreePool (FontPkgHdr);
+ SafeFreePool (FontInfo);
+ SafeFreePool (FontPackage->GlyphBlock);
+ SafeFreePool (FontPackage);
+ SafeFreePool (GlobalFont);
+
+ return Status;
+
+}
+
+
+/**
+ This function exports Font packages to a buffer.
+
+ @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.
+
+**/
+STATIC
+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.
+
+ @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.
+
+**/
+STATIC
+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;
+ SafeFreePool (Package->GlyphBlock);
+ SafeFreePool (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);
+ SafeFreePool (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);
+ SafeFreePool (GlobalFont->FontInfo);
+ SafeFreePool (GlobalFont);
+ break;
+ }
+ }
+
+ SafeFreePool (Package);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function insert a Image package to a package list node.
+
+ @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.
+
+**/
+STATIC
+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) {
+ SafeFreePool (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 = (UINT8 *) AllocateZeroPool (ImageSize);
+ if (ImagePackage->ImageBlock == NULL) {
+ SafeFreePool (ImagePackage->PaletteBlock);
+ SafeFreePool (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.
+
+ @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.
+
+**/
+STATIC
+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.
+
+ @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.
+
+**/
+STATIC
+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;
+
+ SafeFreePool (Package->ImageBlock);
+ SafeFreePool (Package->PaletteBlock);
+ SafeFreePool (Package);
+
+ PackageList->ImagePkg = NULL;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function insert a Simple Font package to a package list node.
+
+ @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.
+
+**/
+STATIC
+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:
+
+ SafeFreePool (SimpleFontPackage->SimpleFontPkgHdr);
+ SafeFreePool (SimpleFontPackage);
+ return Status;
+}
+
+
+/**
+ This function exports SimpleFont packages to a buffer.
+
+ @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.
+
+**/
+STATIC
+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.
+
+ @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.
+
+**/
+STATIC
+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;
+ SafeFreePool (Package->SimpleFontPkgHdr);
+ SafeFreePool (Package);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function insert a Device path package to a package list node.
+
+ @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.
+
+**/
+STATIC
+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.
+
+ @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.
+
+**/
+STATIC
+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.
+
+ @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.
+
+**/
+STATIC
+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;
+
+ SafeFreePool (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.
+
+ @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.
+
+**/
+STATIC
+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.
+
+ @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.
+
+**/
+STATIC
+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:
+
+ SafeFreePool (KeyboardLayoutPackage->KeyboardPkg);
+ SafeFreePool (KeyboardLayoutPackage);
+
+ return Status;
+}
+
+
+/**
+ This function exports Keyboard Layout packages to a buffer.
+
+ @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.
+
+**/
+STATIC
+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.
+
+ @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.
+
+**/
+STATIC
+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;
+ SafeFreePool (Package->KeyboardPkg);
+ SafeFreePool (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.
+
+ @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.
+
+**/
+STATIC
+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;
+
+ //
+ // 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_FORM:
+ Status = InsertFormPackage (
+ PackageHdrPtr,
+ NotifyType,
+ DatabaseRecord->PackageList,
+ &FormPackage
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *) FormPackage,
+ (UINT8) (PackageHeader.Type),
+ DatabaseRecord->Handle
+ );
+ 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;
+ }
+ Status = InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *) StringPackage,
+ (UINT8) (PackageHeader.Type),
+ DatabaseRecord->Handle
+ );
+ 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));
+ }
+
+ return Status;
+}
+
+
+/**
+ This function exports a package list to a buffer. It is the worker function
+ of HiiExportPackageList.
+
+ @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.
+
+**/
+STATIC
+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 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.
+ @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,
+ 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
+ )
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Build a PackageList node
+ //
+ Status = GenerateHiiDatabaseRecord (Private, &DatabaseRecord);
+ if (EFI_ERROR (Status)) {
+ 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)) {
+ 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;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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 PackageList could not be found 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 || !IsHiiHandleValid (Handle)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ 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)) {
+ return Status;
+ }
+ Status = RemoveFormPackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = RemoveKeyboardLayoutPackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = RemoveStringPackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = RemoveFontPackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = RemoveImagePackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = RemoveSimpleFontPackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = RemoveDevicePathPackage (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ 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;
+ SafeFreePool (HiiHandle);
+ SafeFreePool (Node->PackageList);
+ SafeFreePool (Node);
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ 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 Handle or PackageList was NULL.
+ @retval EFI_NOT_FOUND The Handle was not valid or could not be found 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 || Handle == 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;
+
+ //
+ // 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_FORM:
+ 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)) {
+ 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
+ //
+ return AddPackages (Private, EFI_HII_DATABASE_NOTIFY_ADD_PACK, PackageList, Node);
+ }
+ }
+
+ 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 outputed successfully.
+ @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 Handle or HandleBufferLength was 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_FORM:
+ 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;
+ //
+ // Pesudo-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 specifiecd Handle could not be found in the
+ current database.
+ @retval EFI_INVALID_PARAMETER Handle or Buffer or BufferSize 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 || Handle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*BufferSize > 0 && Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (!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,
+ &mHiiDatabaseNotifyGuid,
+ 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 NotifyHandle 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 || NotificationHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gBS->OpenProtocol (
+ NotificationHandle,
+ &mHiiDatabaseNotifyGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ 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,
+ &mHiiDatabaseNotifyGuid,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ SafeFreePool (Notify);
+ Notify = NULL;
+
+ 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 KeyGuidBuffer or KeyGuidBufferLength was 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 + Index, 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));
+ SafeFreePool(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
new file mode 100644
index 0000000..a5363d4
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c
@@ -0,0 +1,2395 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Font.c
+
+Abstract:
+
+ Implementation for EFI_HII_FONT_PROTOCOL.
+
+Revision History
+
+
+**/
+
+
+#include "HiiDatabase.h"
+
+static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors[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.
+
+ @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.
+
+**/
+STATIC
+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;
+ 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.
+
+ @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.
+
+**/
+STATIC
+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.
+
+ @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.
+
+**/
+STATIC
+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->OffsetY = NARROW_BASELINE;
+ 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->OffsetY = WIDE_BASELINE;
+ 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;
+}
+
+STATIC
+VOID
+NarrowGlyphToBlt (
+ IN UINT8 *GlyphBuffer,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
+ IN UINTN ImageWidth,
+ IN UINTN ImageHeight,
+ IN BOOLEAN Transparent,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
+ )
+{
+ UINT8 X;
+ UINT8 Y;
+ 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;
+
+ ASSERT (Width <= ImageWidth && Height <= ImageHeight);
+
+ Buffer = *Origin;
+
+ for (Y = 0; Y < Height; Y++) {
+ for (X = 0; X < Width; X++) {
+ if ((GlyphBuffer[Y] & (1 << X)) != 0) {
+ Buffer[Y * ImageWidth + (Width - X - 1)] = Foreground;
+ } else {
+ if (!Transparent) {
+ Buffer[Y * ImageWidth + (Width - X - 1)] = Background;
+ }
+ }
+ }
+ }
+
+ *Origin = Buffer + Width;
+}
+
+
+/**
+ Convert bitmap data of the glyph to blt structure.
+
+ @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 Width Width of the character or character cell, in
+ pixels.
+ @param Height Height of the character or character cell, in
+ pixels.
+ @param Transparent If TRUE, the Background color is ignored and all
+ "off" pixels in the character's drawn wil use the
+ pixel value from BltBuffer.
+ @param BltBuffer Points to the blt buffer.
+
+
+**/
+STATIC
+VOID
+GlyphToBlt (
+ IN UINT8 *GlyphBuffer,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
+ IN UINTN ImageWidth,
+ IN UINTN ImageHeight,
+ IN BOOLEAN Transparent,
+ IN EFI_HII_GLYPH_INFO Cell,
+ IN UINT8 Attributes,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
+ )
+{
+ UINT8 X;
+ UINT8 Y;
+ UINT8 Data;
+ UINT8 Index;
+ UINTN OffsetY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+
+ ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL);
+ ASSERT (Cell.Width <= ImageWidth && Cell.Height <= ImageHeight);
+
+ BltBuffer = *Origin;
+
+ //
+ // 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 (Y = 0; Y < Cell.Height; Y++) {
+ OffsetY = BITMAP_LEN_1_BIT (Cell.Width, Y);
+
+ //
+ // All bits in these bytes are meaningful.
+ //
+ for (X = 0; X < Cell.Width / 8; X++) {
+ Data = *(GlyphBuffer + OffsetY + X);
+ for (Index = 0; Index < 8; Index++) {
+ if ((Data & (1 << Index)) != 0) {
+ BltBuffer[Y * ImageWidth + X * 8 + (8 - Index - 1)] = Foreground;
+ } else {
+ if (!Transparent) {
+ BltBuffer[Y * ImageWidth + X * 8 + (8 - Index - 1)] = Background;
+ }
+ }
+ }
+ }
+
+ if (Cell.Width % 8 != 0) {
+ //
+ // There are some padding bits in this byte. Ignore them.
+ //
+ Data = *(GlyphBuffer + OffsetY + X);
+ for (Index = 0; Index < Cell.Width % 8; Index++) {
+ if ((Data & (1 << (8 - Index - 1))) != 0) {
+ BltBuffer[Y * ImageWidth + X * 8 + Index] = Foreground;
+ } else {
+ if (!Transparent) {
+ BltBuffer[Y * ImageWidth + X * 8 + Index] = Background;
+ }
+ }
+ }
+ } // end of if (Width % 8...)
+
+ } // end of for (Y=0...)
+
+ *Origin = BltBuffer + Cell.Width;
+}
+
+
+/**
+ Convert bitmap data of the glyph to blt structure.
+
+ @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 Width Width of the character or character cell, in
+ pixels.
+ @param Height Height of the character or character cell, in
+ pixels.
+ @param Transparent If TRUE, the Background color is ignored and all
+ "off" pixels in the character's drawn wil 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.
+
+**/
+STATIC
+VOID
+GlyphToImage (
+ IN UINT8 *GlyphBuffer,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
+ IN UINTN ImageWidth,
+ IN UINTN ImageHeight,
+ IN BOOLEAN Transparent,
+ IN EFI_HII_GLYPH_INFO Cell,
+ IN UINT8 Attributes,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
+ )
+{
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Buffer;
+
+ ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL);
+ ASSERT (Cell.Width <= ImageWidth && Cell.Height <= ImageHeight);
+
+ 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.Width;
+ GlyphToBlt (
+ GlyphBuffer,
+ Foreground,
+ Background,
+ ImageWidth,
+ ImageHeight,
+ 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,
+ ImageHeight,
+ Transparent,
+ Origin
+ );
+
+ NarrowGlyphToBlt (
+ GlyphBuffer + EFI_GLYPH_HEIGHT,
+ Foreground,
+ Background,
+ ImageWidth,
+ ImageHeight,
+ 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,
+ ImageHeight,
+ 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,
+ ImageHeight,
+ Transparent,
+ Cell,
+ Attributes,
+ Origin
+ );
+ }
+}
+
+
+/**
+ Write the output parameters of FindGlyphBlock().
+
+ @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 responsiblity 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.
+
+**/
+STATIC
+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 || BufferLen < 1 || InputCell == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Cell != NULL) {
+ CopyMem (Cell, InputCell, sizeof (EFI_HII_GLYPH_INFO));
+ }
+
+ if (GlyphBuffer != NULL) {
+ *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 responsiblity 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;
+
+ ASSERT (FontPackage != NULL);
+ ASSERT (FontPackage->Signature == HII_FONT_PACKAGE_SIGNATURE);
+
+ 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;
+ }
+ }
+
+ 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;
+ }
+ }
+ 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 += *(BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8));
+ break;
+ case EFI_HII_GIBT_EXT2:
+ CopyMem (
+ &Length16,
+ BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8),
+ sizeof (UINT16)
+ );
+ BlockPtr += Length16;
+ break;
+ case EFI_HII_GIBT_EXT4:
+ CopyMem (
+ &Length32,
+ 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)
+ );
+ BufferLen = BITMAP_LEN_1_BIT (LocalCell.Width, LocalCell.Height);
+ if (CharCurrent == CharValue) {
+ return WriteOutputParam (
+ 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);
+
+ 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;
+ }
+ 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;
+ }
+ 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)) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Copy a Font Name to a new created EFI_FONT_INFO structure.
+
+ @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.
+
+**/
+STATIC
+EFI_STATUS
+SaveFontName (
+ IN EFI_STRING FontName,
+ OUT EFI_FONT_INFO **FontInfo
+ )
+{
+ UINTN FontInfoLen;
+
+ ASSERT (FontName != NULL && FontInfo != NULL);
+
+ FontInfoLen = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + StrSize (FontName);
+ *FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoLen);
+ if (*FontInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StrCpy ((*FontInfo)->FontName, 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;
+
+ 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".
+ //
+ InfoSize = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + StrSize (L"sysdefault");
+ Info = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (InfoSize);
+ if (Info == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Info->ForegroundColor = mEfiColors[Private->Attribute & 0x0f];
+ Info->BackgroundColor = mEfiColors[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;
+ StrCpy (Info->FontInfo.FontName, 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.
+
+ @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 when incoming StringInfo does not match the
+ default. Points to NULL if matches. It's
+ caller's reponsibility to free this buffer.
+ @param SystemInfoLen If not NULL, output the length of default system
+ info.
+
+ @retval TRUE Yes, it points to system default.
+ @retval FALSE No.
+
+**/
+STATIC
+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;
+
+ ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
+
+ if (StringInfo == NULL && SystemInfo == NULL) {
+ return TRUE;
+ }
+
+ //
+ // Check whether incoming string font and color matches system default.
+ //
+ Status = GetSystemFont (Private, &SystemDefault, &DefaultLen);
+ ASSERT_EFI_ERROR (Status);
+
+ if (SystemInfo != NULL) {
+ *SystemInfo = SystemDefault;
+ } else {
+ SafeFreePool (SystemDefault);
+ }
+
+ if (SystemInfoLen != NULL) {
+ *SystemInfoLen = DefaultLen;
+ }
+
+ if (StringInfo == NULL ||
+ (StringInfo != NULL && CompareMem (SystemDefault, StringInfo, DefaultLen) == 0)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/**
+ 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 globa 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 repensents 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 sytem 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.
+
+ @param Char Unicode character
+
+ @retval 0 Yes, it is a line break.
+ @retval 1 Yes, it is a hyphen that desires a line break
+ after this character.
+ @retval 2 Yes, it is a dash that desires a line break
+ before and after it.
+ @retval -1 No, it is not a link break.
+
+**/
+STATIC
+INT8
+IsLineBreak (
+ IN CHAR16 Char
+ )
+{
+ UINT8 Byte1;
+ UINT8 Byte2;
+
+ //
+ // In little endian, Byte1 is the low byte of Char, Byte2 is the high byte of Char.
+ //
+ Byte1 = *((UINT8 *) (&Char));
+ Byte2 = *(((UINT8 *) (&Char) + 1));
+
+ if (Byte2 == 0x20) {
+ switch (Byte1) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x08:
+ case 0x09:
+ case 0x0A:
+ case 0x0B:
+ case 0x28:
+ case 0x29:
+ case 0x5F:
+ return 0;
+ case 0x10:
+ case 0x12:
+ case 0x13:
+ return 1;
+ case 0x14:
+ //
+ // BUGBUG: Does it really require line break before it and after it?
+ //
+ return 2;
+ }
+ } else if (Byte2 == 0x00) {
+ switch (Byte1) {
+ case 0x20:
+ case 0x0C:
+ case 0x0D:
+ return 0;
+ }
+ }
+
+ switch (Char) {
+ case 0x1680:
+ return 0;
+ case 0x058A:
+ case 0x0F0B:
+ case 0x1361:
+ case 0x17D5:
+ return 1;
+ }
+
+ 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,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.
+
+**/
+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 BaseLineOffset;
+ UINT16 MaxRowNum;
+ UINT16 RowIndex;
+ UINTN Index;
+ UINTN Index1;
+ EFI_FONT_DISPLAY_INFO *StringInfoOut;
+ EFI_FONT_DISPLAY_INFO *SystemDefault;
+ EFI_FONT_HANDLE FontHandle;
+ EFI_STRING StringIn;
+ EFI_STRING StringIn2;
+ UINT16 Height;
+ 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;
+
+ //
+ // 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_CLEAN_X)) == EFI_HII_OUT_FLAG_CLEAN_X) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLEAN_Y)) == EFI_HII_OUT_FLAG_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_CLEAN_X)) == (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLEAN_X)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ GlyphBuf = (UINT8 **) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (UINT8 *));
+ ASSERT (GlyphBuf != NULL);
+ Cell = (EFI_HII_GLYPH_INFO *) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (EFI_HII_GLYPH_INFO));
+ ASSERT (Cell != NULL);
+ Attributes = (UINT8 *) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (UINT8));
+ ASSERT (Attributes != NULL);
+
+ RowInfo = NULL;
+ Status = EFI_SUCCESS;
+ StringIn2 = NULL;
+ SystemDefault = 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) {
+ FontInfo = NULL;
+ Height = SystemDefault->FontInfo.FontSize;
+ Foreground = SystemDefault->ForegroundColor;
+ Background = SystemDefault->BackgroundColor;
+
+ } else {
+ 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;
+ Foreground = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->ForegroundColor;
+ Background = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->BackgroundColor;
+
+ } else {
+ FontInfo = &StringInfoOut->FontInfo;
+ Height = StringInfoOut->FontInfo.FontSize;
+ Foreground = StringInfoOut->ForegroundColor;
+ Background = StringInfoOut->BackgroundColor;
+ }
+ }
+
+ //
+ // Parse the string to be displayed to drop some ignored characters.
+ //
+
+ StringPtr = String;
+ StringIn = NULL;
+
+ //
+ // 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 wth Unicode character 0xFFFD.
+ //
+ StringIn2 = AllocateZeroPool (StrSize (StringPtr));
+ if (StringIn2 == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ Index = 0;
+ StringTmp = StringIn2;
+
+ while (*StringPtr != 0 && Index < MAX_STRING_LENGTH) {
+ 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) {
+ SafeFreePool (GlyphBuf[Index]);
+ GlyphBuf[Index] = NULL;
+ StringPtr++;
+ } 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;
+ goto Exit;
+ }
+ *StringTmp++ = *StringPtr++;
+ Index++;
+ }
+ } else if (EFI_ERROR (Status)) {
+ goto Exit;
+ } else {
+ *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.
+ //
+ if (*Blt != NULL) {
+ Image = *Blt;
+ BufferPtr = Image->Image.Bitmap + Image->Width * BltY + BltX;
+ MaxRowNum = (UINT16) (Image->Height / Height);
+ if (Image->Height % Height != 0) {
+ 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);
+ if ((Flags & EFI_HII_OUT_FLAG_CLEAN_Y) == EFI_HII_OUT_FLAG_CLEAN_Y) {
+ //
+ // Don't draw at all if there is only one row and
+ // the row's bottom-most on pixel cannot fit.
+ //
+ if (MaxRowNum == 1 && SysFontFlag) {
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+ }
+
+ for (RowIndex = 0, Index = 0; RowIndex < MaxRowNum && StringPtr[Index] != 0; ) {
+ LineWidth = 0;
+ LineHeight = 0;
+ BaseLineOffset = 0;
+ LineBreak = FALSE;
+
+ //
+ // Calculate how many characters there are in a row.
+ //
+ RowInfo[RowIndex].StartIndex = Index;
+
+ while (LineWidth + BltX < Image->Width && StringPtr[Index] != 0) {
+ LineWidth += (UINTN) Cell[Index].AdvanceX;
+ if (LineHeight < Cell[Index].Height) {
+ LineHeight = (UINTN) Cell[Index].Height;
+ }
+ BaseLineOffset += (UINTN) Cell[Index].OffsetY;
+
+ if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0 &&
+ (Flags & EFI_HII_OUT_FLAG_WRAP) == 0 &&
+ IsLineBreak (StringPtr[Index]) > 0) {
+ //
+ // It is a line break that ends this row.
+ //
+ Index++;
+ break;
+ }
+
+ Index++;
+ }
+
+ //
+ // If this character is the last character of a row, we need not
+ // draw its (AdvanceX - Width) for next character.
+ //
+ Index--;
+ if (!SysFontFlag) {
+ LineWidth -= (UINTN) (Cell[Index].AdvanceX - Cell[Index].Width);
+ }
+
+ //
+ // 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) {
+ if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0) {
+ for (Index1 = RowInfo[RowIndex].EndIndex; Index1 >= RowInfo[RowIndex].StartIndex; Index1--) {
+ if (IsLineBreak (StringPtr[Index1]) > 0) {
+ LineBreak = TRUE;
+ RowInfo[RowIndex].EndIndex = Index1 - 1;
+ break;
+ }
+ }
+ }
+ //
+ // 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) {
+ Flags &= (~ (EFI_HII_OUT_FLAGS) EFI_HII_OUT_FLAG_WRAP);
+ Flags |= EFI_HII_OUT_FLAG_CLEAN_X;
+ }
+ }
+
+ //
+ // 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_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 > 0) {
+ RowInfo[RowIndex].EndIndex = Index - 1;
+ RowInfo[RowIndex].LineWidth = LineWidth - Cell[Index].AdvanceX;
+ RowInfo[RowIndex].BaselineOffset = BaseLineOffset - Cell[Index].OffsetY;
+ if (LineHeight > Cell[Index - 1].Height) {
+ LineHeight = Cell[Index - 1].Height;
+ }
+ RowInfo[RowIndex].LineHeight = LineHeight;
+ } else {
+ //
+ // There is only one column and it can not be drawn so that return directly.
+ //
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+ }
+
+ //
+ // 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 && Image->Height < LineHeight) {
+ LineHeight = Image->Height;
+ if ((Flags & EFI_HII_OUT_FLAG_CLEAN_Y) == EFI_HII_OUT_FLAG_CLEAN_Y) {
+ //
+ // Don't draw at all if the row's bottom-most on pixel cannot fit.
+ //
+ break;
+ }
+ }
+
+ //
+ // Draw it to screen or existing bitmap depending on whether
+ // EFI_HII_DIRECT_TO_SCREEN is set.
+ //
+ if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
+ BltBuffer = AllocateZeroPool (RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ if (BltBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ BufferPtr = BltBuffer;
+ for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {
+ GlyphToImage (
+ GlyphBuf[Index1],
+ Foreground,
+ Background,
+ RowInfo[RowIndex].LineWidth,
+ RowInfo[RowIndex].LineHeight,
+ Transparent,
+ Cell[Index1],
+ Attributes[Index1],
+ &BufferPtr
+ );
+ if (ColumnInfoArray != NULL) {
+ if (Index1 == RowInfo[RowIndex].StartIndex) {
+ *ColumnInfoArray = 0;
+ } else {
+ *ColumnInfoArray = Cell[Index1 -1].AdvanceX;
+ }
+ ColumnInfoArray++;
+ }
+ }
+ 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)) {
+ SafeFreePool (BltBuffer);
+ goto Exit;
+ }
+
+ SafeFreePool (BltBuffer);
+
+ } else {
+ for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {
+ GlyphToImage (
+ GlyphBuf[Index1],
+ Foreground,
+ Background,
+ Image->Width,
+ Image->Height,
+ Transparent,
+ Cell[Index1],
+ Attributes[Index1],
+ &BufferPtr
+ );
+ if (ColumnInfoArray != NULL) {
+ if (Index1 == RowInfo[RowIndex].StartIndex) {
+ *ColumnInfoArray = 0;
+ } else {
+ *ColumnInfoArray = Cell[Index1 -1].AdvanceX;
+ }
+ ColumnInfoArray++;
+ }
+ }
+ //
+ // Jump to next row
+ //
+ BufferPtr += BltX + Image->Width * (LineHeight - 1);
+ }
+
+ Index++;
+ RowIndex++;
+
+ }
+
+ //
+ // Write output parameters.
+ //
+ RowInfoSize = RowIndex * sizeof (EFI_HII_ROW_INFO);
+ if (RowInfoArray != NULL) {
+ *RowInfoArray = AllocateZeroPool (RowInfoSize);
+ if (*RowInfoArray == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ CopyMem (*RowInfoArray, RowInfo, RowInfoSize);
+ }
+ if (RowInfoArraySize != NULL) {
+ *RowInfoArraySize = RowIndex;
+ }
+
+ } else {
+ //
+ // 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) {
+ SafeFreePool (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;
+ Status = HiiStringToImage (
+ This,
+ Flags,
+ String,
+ StringInfo,
+ &Image,
+ BltX,
+ BltY,
+ RowInfoArray,
+ RowInfoArraySize,
+ ColumnInfoArray
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *Blt = Image;
+ }
+
+ Status = EFI_SUCCESS;
+
+Exit:
+
+ for (Index = 0; Index < MAX_STRING_LENGTH; Index++) {
+ SafeFreePool (GlyphBuf[Index]);
+ }
+ SafeFreePool (StringIn);
+ SafeFreePool (StringIn2);
+ SafeFreePool (StringInfoOut);
+ SafeFreePool (RowInfo);
+ SafeFreePool (SystemDefault);
+ SafeFreePool (GlyphBuf);
+ SafeFreePool (Cell);
+ SafeFreePool (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,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 PackageList was NULL.
+
+**/
+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_STRING String;
+ UINTN StringSize;
+
+ if (This == NULL || PackageList == NULL || Blt == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Get the string to be displayed.
+ //
+
+ StringSize = MAX_STRING_LENGTH;
+ String = (EFI_STRING) AllocateZeroPool (StringSize);
+ if (String == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = Private->HiiString.GetString (
+ &Private->HiiString,
+ Language,
+ PackageList,
+ StringId,
+ String,
+ &StringSize,
+ NULL
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ SafeFreePool (String);
+ String = (EFI_STRING) AllocateZeroPool (StringSize);
+ if (String == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = Private->HiiString.GetString (
+ &Private->HiiString,
+ Language,
+ PackageList,
+ StringId,
+ String,
+ &StringSize,
+ NULL
+ );
+
+ }
+
+ if (EFI_ERROR (Status)) {
+ SafeFreePool (String);
+ return Status;
+ }
+
+ return HiiStringToImage (
+ This,
+ Flags,
+ String,
+ StringInfo,
+ Blt,
+ BltX,
+ BltY,
+ RowInfoArray,
+ RowInfoArraySize,
+ ColumnInfoArray
+ );
+
+}
+
+
+/**
+ 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;
+
+ 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;
+ }
+ FontInfo = &StringInfoOut->FontInfo;
+ Foreground = StringInfoOut->ForegroundColor;
+ Background = StringInfoOut->BackgroundColor;
+ } else {
+ 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;
+
+ Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ if (Image->Image.Bitmap == NULL) {
+ SafeFreePool (Image);
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ BltBuffer = Image->Image.Bitmap;
+ GlyphToImage (
+ GlyphBuffer,
+ Foreground,
+ Background,
+ Image->Width,
+ Image->Height,
+ 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;
+ }
+ }
+
+ SafeFreePool (SystemDefault);
+ SafeFreePool (StringInfoOut);
+ SafeFreePool (String);
+ SafeFreePool (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.
+ @param StringInfoOut Upon return, contains the matching font¡¯s
+ information. If NULL, then no information is
+ returned. It's caller's responsibility to free
+ this buffer.
+ @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_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,
+ 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 || StringInfoIn == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // 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;
+ }
+
+ FontInfo = NULL;
+ LocalFontHandle = NULL;
+ if (FontHandle != NULL) {
+ LocalFontHandle = *FontHandle;
+ }
+
+ //
+ // Get default system display info, if StringInfoIn points to
+ // system display info, return it directly.
+ //
+ Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ if (IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfoIn, &SystemDefault, &StringInfoOutLen)) {
+ if (StringInfoOut != NULL) {
+ *StringInfoOut = AllocateCopyPool (StringInfoOutLen, (EFI_FONT_DISPLAY_INFO *) StringInfoIn);
+ if (*StringInfoOut == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ LocalFontHandle = NULL;
+ goto Exit;
+ }
+ }
+
+ LocalFontHandle = Private->FontInfoList.ForwardLink;
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+
+ //
+ // 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;
+ } else if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_STYLE) == EFI_FONT_INFO_SYS_STYLE) {
+ InfoOut.FontInfo.FontStyle = SystemDefault->FontInfo.FontStyle;
+ } else if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) == EFI_FONT_INFO_SYS_FORE_COLOR) {
+ InfoOut.ForegroundColor = SystemDefault->ForegroundColor;
+ } else if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) == EFI_FONT_INFO_SYS_BACK_COLOR) {
+ InfoOut.BackgroundColor = SystemDefault->BackgroundColor;
+ }
+
+ FontInfo->FontSize = InfoOut.FontInfo.FontSize;
+ FontInfo->FontStyle = InfoOut.FontInfo.FontStyle;
+
+ if (IsFontInfoExisted (Private, FontInfo, &InfoOut.FontInfoMask, LocalFontHandle, &GlobalFont)) {
+ if (String != NULL) {
+ //
+ // Test to guarantee all characters are available in the found font.
+ //
+ 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;
+ }
+ } else {
+ LocalFontHandle = NULL;
+ }
+
+ Status = EFI_NOT_FOUND;
+
+Exit:
+
+ if (FontHandle != NULL) {
+ *FontHandle = LocalFontHandle;
+ }
+
+ SafeFreePool (SystemDefault);
+ SafeFreePool (FontInfo);
+ return Status;
+}
+
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
new file mode 100644
index 0000000..cf3519b
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
@@ -0,0 +1,1694 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ HiiDatabase.h
+
+Abstract:
+
+ Private structures definitions in HiiDatabase.
+
+Revision History
+
+
+**/
+
+#ifndef __HII_DATABASE_PRIVATE_H__
+#define __HII_DATABASE_PRIVATE_H__
+
+#include <PiDxe.h>
+
+#include <Protocol/ConsoleControl.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/HiiFont.h>
+#include <Protocol/HiiImage.h>
+#include <Protocol/HiiString.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/SimpleTextOut.h>
+
+#include <Guid/HiiKeyBoardLayout.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>
+
+#define HII_DATABASE_NOTIFY_GUID \
+ { \
+ 0xc1c76, 0xd79e, 0x42fe, 0x86, 0xb, 0x8b, 0xe8, 0x7b, 0x3e, 0x7a, 0x78 \
+ }
+
+#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)
+
+//
+// Storage types
+//
+#define EFI_HII_VARSTORE_BUFFER 0
+#define EFI_HII_VARSTORE_NAME_VALUE 1
+#define EFI_HII_VARSTORE_EFI_VARIABLE 2
+
+#define HII_FORMSET_STORAGE_SIGNATURE EFI_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;
+
+#define HII_FORMSET_STORAGE_FROM_LINK(a) CR (a, HII_FORMSET_STORAGE, Link, HII_FORMSET_STORAGE_SIGNATURE)
+
+
+//
+// String Package definitions
+//
+#define HII_STRING_PACKAGE_SIGNATURE EFI_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;
+} HII_STRING_PACKAGE_INSTANCE;
+
+//
+// Form Package definitions
+//
+#define HII_IFR_PACKAGE_SIGNATURE EFI_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 EFI_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 EFI_SIGNATURE_32 ('h','i','f','p')
+typedef struct _HII_FONT_PACKAGE_INSTANCE {
+ UINTN Signature;
+ EFI_HII_FONT_PACKAGE_HDR *FontPkgHdr;
+ UINT8 *GlyphBlock;
+ LIST_ENTRY FontEntry;
+ LIST_ENTRY GlyphInfoList;
+} HII_FONT_PACKAGE_INSTANCE;
+
+#define HII_GLYPH_INFO_SIGNATURE EFI_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 EFI_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 EFI_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;
+ UINT8 *ImageBlock;
+ UINT8 *PaletteBlock;
+} HII_IMAGE_PACKAGE_INSTANCE;
+
+//
+// Keyboard Layout Pacakge definitions
+//
+#define HII_KB_LAYOUT_PACKAGE_SIGNATURE EFI_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 EFI_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 EFI_SIGNATURE_32 ('h','i','h','l')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Handle;
+ UINTN Key;
+} HII_HANDLE;
+
+#define HII_DATABASE_RECORD_SIGNATURE EFI_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 EFI_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 EFI_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;
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+ EFI_HII_IMAGE_PROTOCOL HiiImage;
+#endif
+ EFI_HII_STRING_PROTOCOL HiiString;
+ EFI_HII_DATABASE_PROTOCOL HiiDatabase;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL ConfigRouting;
+ 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_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 \
+ )
+
+//
+// Internal function prototypes.
+//
+
+/**
+ 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 globa 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
+ )
+;
+
+
+/**
+ 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 StringId = 0, output the string id of last string block (EFI_HII_SIBT_END).
+
+ @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.
+
+ @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
+ )
+;
+
+
+/**
+ 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 responsiblity 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_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,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 was NULL.
+
+**/
+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,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 was NULL.
+
+**/
+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.
+ @param StringInfoOut Upon return, contains the matching font¡¯s
+ information. If NULL, then no information is
+ returned. It's caller's responsibility to free
+ this buffer.
+ @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_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,
+ OUT EFI_FONT_DISPLAY_INFO **StringInfoOut,
+ IN CONST EFI_STRING String OPTIONAL
+ )
+;
+
+//
+// EFI_HII_IMAGE_PROTOCOL interfaces
+//
+
+
+/**
+ 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.
+ @param ImageSize On entry, points to the size of the buffer
+ pointed to by Image, in bytes. On return, points
+ to the length of the image, in bytes.
+
+ @retval EFI_SUCCESS The new image was returned successfully.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not available.
+ @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.
+
+**/
+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,
+ OUT UINTN *ImageSize
+ )
+;
+
+
+/**
+ 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.
+ @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 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 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 was NULL.
+ @retval EFI_NOT_FOUND The specified packagelist could not be found in
+ current 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_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.
+ @retval EFI_NOT_FOUND 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 String or Language or StringSize 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 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 Languages or LanguagesSize was 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 FirstLanguage Points to the primary language.
+ @param SecondaryLanguages Points to the buffer to hold the returned list of
+ secondary languages for the specified
+ FirstLanguage. If there are no secondary
+ languages, the function returns successfully,
+ but this is set to NULL.
+ @param SecondaryLanguageSize On entry, points to the size of the buffer
+ pointed to by SecondLanguages, in bytes. On
+ return, points to the length of SecondLanguages
+ in bytes.
+
+ @retval EFI_SUCCESS Secondary languages were correctly returned.
+ @retval EFI_INVALID_PARAMETER FirstLanguage or SecondLanguages or
+ SecondLanguagesSize was NULL.
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by SecondLanguagesSize is
+ too small to hold the returned information.
+ SecondLanguageSize is updated to hold the size of
+ the buffer required.
+ @retval EFI_NOT_FOUND The language specified by FirstLanguage is not
+ present in the specified package list.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetSecondaryLanguages (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN CONST CHAR8 *FirstLanguage,
+ IN OUT CHAR8 *SecondLanguages,
+ IN OUT UINTN *SecondLanguagesSize
+ )
+;
+
+//
+// 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.
+ @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,
+ 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 PackageList could not be found 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
+ )
+;
+
+
+/**
+ 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 Handle or PackageList was NULL.
+ @retval EFI_NOT_FOUND The Handle was not valid or could not be found 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 outputed successfully.
+ @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 Handle or HandleBufferLength was 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 specifiecd Handle could not be found in the
+ current database.
+ @retval EFI_INVALID_PARAMETER Handle or Buffer or BufferSize 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 NotifyHandle The handle of the notification function being
+ unregistered.
+
+ @retval EFI_SUCCESS Notification is unregistered successfully.
+ @retval EFI_INVALID_PARAMETER The Handle is invalid.
+
+**/
+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 KeyGuidBuffer or KeyGuidBufferLength was
+ 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 names in the Request string.
+ 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
+HiiConfigRoutingRoutConfig (
+ 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 index of the last
+ modified byte in the Block.
+ @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>.
+
+**/
+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
+ )
+;
+
+
+//
+// Global variables
+//
+extern EFI_EVENT gHiiKeyboardLayoutChanged;
+
+#include "R8Lib.h"
+
+#endif
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.msa b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.msa
new file mode 100644
index 0000000..2b3cf9b
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.msa
@@ -0,0 +1,79 @@
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>HiiDatabase</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>348C4D62-BFBD-4882-9ECE-C80BB1C4783B</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component name for module HiiDatabase</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>
+ <License>All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>HiiDatabase</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DevicePathLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>R8Lib.c</Filename>
+ <Filename>R8Lib.h</Filename>
+ <Filename>Font.c</Filename>
+ <Filename>Database.c</Filename>
+ <Filename>String.c</Filename>
+ <Filename>ConfigRouting.c</Filename>
+ <Filename>HiiDatabase.dxs</Filename>
+ <Filename>HiiDatabase.h</Filename>
+ <Filename>Image.c</Filename>
+ <Filename>HiiDatabaseEntry.c</Filename>
+ <Filename>CVS\TortoiseCVS.Status</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiConsoleControlProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <ModuleEntryPoint>InitializeHiiDatabase</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea> \ No newline at end of file
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
new file mode 100644
index 0000000..2bafb25
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
@@ -0,0 +1,75 @@
+#/** @file
+# Component name for module HiiDatabase
+#
+# FIX ME!
+# Copyright (c) 2007, Intel Corporation. All rights reserved.
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = HiiDatabase
+ FILE_GUID = 348C4D62-BFBD-4882-9ECE-C80BB1C4783B
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x0002000A
+
+ ENTRY_POINT = InitializeHiiDatabase
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ HiiDatabaseEntry.c
+ Image.c
+ HiiDatabase.h
+ ConfigRouting.c
+ String.c
+ Database.c
+ Font.c
+ R8Lib.h
+ R8Lib.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+ MemoryAllocationLib
+ DevicePathLib
+ BaseLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ DebugLib
+
+
+[Protocols]
+ gEfiConsoleControlProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiHiiStringProtocolGuid
+ gEfiHiiImageProtocolGuid
+ gEfiHiiConfigRoutingProtocolGuid
+ gEfiHiiDatabaseProtocolGuid
+ gEfiHiiFontProtocolGuid
+ gEfiHiiConfigAccessProtocolGuid
+
+
+[Depex]
+ TRUE
+
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c
new file mode 100644
index 0000000..99084db
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c
@@ -0,0 +1,197 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ HiiDatabaseEntry.c
+
+Abstract:
+
+ This file contains the entry code to the HII database, which is defined by
+ UEFI 2.1 specification.
+
+Revision History
+
+
+**/
+
+
+#include "HiiDatabase.h"
+
+//
+// Global variables
+//
+EFI_EVENT gHiiKeyboardLayoutChanged;
+STATIC EFI_GUID gHiiSetKbdLayoutEventGuid = EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID;
+
+STATIC 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
+ },
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+ {
+ HiiNewImage,
+ HiiGetImage,
+ HiiSetImage,
+ HiiDrawImage,
+ HiiDrawImageId
+ },
+#endif
+ {
+ HiiNewString,
+ HiiGetString,
+ HiiSetString,
+ HiiGetLanguages,
+ HiiGetSecondaryLanguages
+ },
+ {
+ HiiNewPackageList,
+ HiiRemovePackageList,
+ HiiUpdatePackageList,
+ HiiListPackageLists,
+ HiiExportPackageLists,
+ HiiRegisterPackageNotify,
+ HiiUnregisterPackageNotify,
+ HiiFindKeyboardLayouts,
+ HiiGetKeyboardLayout,
+ HiiSetKeyboardLayout,
+ HiiGetPackageListHandle
+ },
+ {
+ HiiConfigRoutingExtractConfig,
+ HiiConfigRoutingExportConfig,
+ HiiConfigRoutingRoutConfig,
+ HiiBlockToConfig,
+ HiiConfigToBlock,
+ HiiGetAltCfg
+ },
+ {
+ (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
+};
+
+//@MT: EFI_DRIVER_ENTRY_POINT (InitializeHiiDatabase)
+
+EFI_STATUS
+EFIAPI
+InitializeHiiDatabase (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ Initialize HII Database
+
+Arguments:
+ (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
+
+Returns:
+ EFI_SUCCESS -
+ other -
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+
+ //@MT: EfiInitializeDriverLib (ImageHandle, SystemTable);
+
+ //
+ // 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.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+
+ //
+ // If there was no error, assume there is an installation and fail to load
+ //
+ if (!EFI_ERROR (Status)) {
+ if (HandleBuffer != NULL) {
+ gBS->FreePool (HandleBuffer);
+ }
+ return EFI_DEVICE_ERROR;
+ }
+
+ 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 (
+ 0,
+ 0,
+ NULL,
+ NULL,
+ &gHiiSetKbdLayoutEventGuid,
+ &gHiiKeyboardLayoutChanged
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Handle = NULL;
+ return gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiHiiFontProtocolGuid,
+ &mPrivate.HiiFont,
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+ &gEfiHiiImageProtocolGuid,
+ &mPrivate.HiiImage,
+#endif
+ &gEfiHiiStringProtocolGuid,
+ &mPrivate.HiiString,
+ &gEfiHiiDatabaseProtocolGuid,
+ &mPrivate.HiiDatabase,
+ &gEfiHiiConfigRoutingProtocolGuid,
+ &mPrivate.ConfigRouting,
+ NULL
+ );
+}
+
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
new file mode 100644
index 0000000..06d783a
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
@@ -0,0 +1,1509 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Image.c
+
+Abstract:
+
+ Implementation for EFI_HII_IMAGE_PROTOCOL.
+
+Revision History
+
+
+**/
+
+
+#include "HiiDatabase.h"
+
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+
+STATIC
+UINT8*
+GetImageIdOrAddress (
+ IN UINT8 *ImageBlock,
+ IN OUT EFI_IMAGE_ID *ImageId
+ )
+/*++
+
+ Routine Description:
+ 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.
+
+ Arguments:
+ ImageBlock - Points to the beginning of a series of image blocks stored in order.
+ 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.
+
+ Returns:
+ The image block address when input ImageId is not zero; otherwise return NULL.
+
+--*/
+{
+ EFI_IMAGE_ID ImageIdCurrent;
+ UINT8 *ImageBlockHdr;
+ UINT8 Length8;
+ UINT16 Length16;
+ UINT32 Length32;
+ EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit;
+ EFI_HII_IIBT_IMAGE_4BIT_BLOCK Iibt4bit;
+ EFI_HII_IIBT_IMAGE_8BIT_BLOCK Iibt8bit;
+ UINT16 Width;
+ UINT16 Height;
+
+ ASSERT (ImageBlock != NULL && ImageId != NULL);
+
+ ImageBlockHdr = ImageBlock;
+ ImageIdCurrent = 1;
+
+ while (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->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 (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType == EFI_HII_IIBT_DUPLICATE) {
+ CopyMem (ImageId, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (EFI_IMAGE_ID));
+ ASSERT (*ImageId != ImageIdCurrent);
+ ImageBlock = ImageBlockHdr;
+ ImageIdCurrent = 1;
+ continue;
+ }
+
+ return ImageBlock;
+ }
+ if (*ImageId < ImageIdCurrent) {
+ //
+ // Can not find the specified image block in this image.
+ //
+ return NULL;
+ }
+ }
+ switch (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType) {
+ case EFI_HII_IIBT_EXT1:
+ Length8 = *(ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8));
+ ImageBlock += Length8;
+ ImageIdCurrent++;
+ break;
+ case EFI_HII_IIBT_EXT2:
+ CopyMem (
+ &Length16,
+ ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8),
+ sizeof (UINT16)
+ );
+ ImageBlock += Length16;
+ ImageIdCurrent++;
+ break;
+ case EFI_HII_IIBT_EXT4:
+ CopyMem (
+ &Length32,
+ ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8),
+ sizeof (UINT32)
+ );
+ ImageBlock += Length32;
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_1BIT:
+ case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
+ CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));
+ ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_1_BIT (Iibt1bit.Bitmap.Width, Iibt1bit.Bitmap.Height);
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_4BIT:
+ case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
+ CopyMem (&Iibt4bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK));
+ ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_4_BIT (Iibt4bit.Bitmap.Width, Iibt4bit.Bitmap.Height);
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_8BIT:
+ case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
+ CopyMem (&Iibt8bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK));
+ ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_8_BIT (Iibt8bit.Bitmap.Width, Iibt8bit.Bitmap.Height);
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_24BIT:
+ case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
+ CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));
+ CopyMem (
+ &Height,
+ ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),
+ sizeof (UINT16)
+ );
+ ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
+ BITMAP_LEN_24_BIT (Width, Height);
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_DUPLICATE:
+ ImageBlock += sizeof (EFI_HII_IIBT_DUPLICATE_BLOCK);
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_JPEG:
+ CopyMem (&Length32, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT32));
+ ImageBlock += Length32;
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_SKIP1:
+ Length8 = *(ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK));
+ ImageBlock += sizeof (EFI_HII_IIBT_SKIP1_BLOCK);
+ ImageIdCurrent = (UINT16) (ImageIdCurrent + Length8);
+ break;
+
+ case EFI_HII_IIBT_SKIP2:
+ CopyMem (&Length16, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));
+ ImageBlock += sizeof (EFI_HII_IIBT_SKIP2_BLOCK);
+ ImageIdCurrent = (UINT16) (ImageIdCurrent + Length16);
+ break;
+
+ default:
+ //
+ // Unknown image blocks can not be skipped, processing halts.
+ //
+ ASSERT (FALSE);
+ }
+ }
+
+ //
+ // When ImageId is zero, return the imageid of last image block: EFI_HII_IIBT_END_BLOCK.
+ //
+ if (*ImageId == 0) {
+ *ImageId = ImageIdCurrent;
+ return ImageBlock;
+ }
+
+ return NULL;
+}
+
+
+
+/**
+ Convert pixels from EFI_GRAPHICS_OUTPUT_BLT_PIXEL to EFI_HII_RGB_PIXEL style.
+
+ @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.
+
+
+**/
+STATIC
+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.
+
+ @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.
+
+
+**/
+STATIC
+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.
+
+ @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.
+
+
+**/
+STATIC
+VOID
+Output1bitPixel (
+ IN OUT EFI_IMAGE_INPUT *Image,
+ IN UINT8 *Data,
+ IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
+ )
+{
+ UINT16 X;
+ UINT16 Y;
+ UINTN OffsetY;
+ UINT8 Index;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[2];
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;
+ UINT16 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.
+ //
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
+ PaletteSize += sizeof (UINT16);
+ Palette = AllocateZeroPool (PaletteSize);
+ ASSERT (Palette != NULL);
+ CopyMem (Palette, PaletteInfo, PaletteSize);
+
+ ZeroMem (PaletteValue, sizeof (PaletteValue));
+ CopyRgbToGopPixel (&PaletteValue[0], &Palette->PaletteValue[0], 1);
+ CopyRgbToGopPixel (&PaletteValue[1], &Palette->PaletteValue[1], 1);
+ SafeFreePool (Palette);
+
+ //
+ // Convert the pixel from one bit to corresponding color.
+ //
+ for (Y = 0; Y < Image->Height; Y++) {
+ OffsetY = BITMAP_LEN_1_BIT (Image->Width, Y);
+ //
+ // All bits in these bytes are meaningful
+ //
+ for (X = 0; X < Image->Width / 8; X++) {
+ Byte = *(Data + OffsetY + X);
+ for (Index = 0; Index < 8; Index++) {
+ if ((Byte & (1 << Index)) != 0) {
+ BitMapPtr[Y * Image->Width + X * 8 + (8 - Index - 1)] = PaletteValue[1];
+ } else {
+ BitMapPtr[Y * Image->Width + X * 8 + (8 - Index - 1)] = PaletteValue[0];
+ }
+ }
+ }
+
+ if (Image->Width % 8 != 0) {
+ //
+ // Padding bits in this byte should be ignored.
+ //
+ Byte = *(Data + OffsetY + X);
+ for (Index = 0; Index < Image->Width % 8; Index++) {
+ if ((Byte & (1 << (8 - Index - 1))) != 0) {
+ BitMapPtr[Y * Image->Width + X * 8 + Index] = PaletteValue[1];
+ } else {
+ BitMapPtr[Y * Image->Width + X * 8 + Index] = PaletteValue[0];
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ Output pixels in "4 bit per pixel" format to an image.
+
+ @param Image Points to the image which will store the pixels.
+ @param Data Stores the value of output pixels, 0 ~ 15.
+ @param PaletteInfo PaletteInfo which stores the color of the output
+ pixels. Each entry corresponds to a color within
+ [0, 15].
+
+
+**/
+STATIC
+VOID
+Output4bitPixel (
+ IN OUT EFI_IMAGE_INPUT *Image,
+ IN UINT8 *Data,
+ IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
+ )
+{
+ UINT16 X;
+ UINT16 Y;
+ UINTN OffsetY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[16];
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;
+ UINT16 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.
+ //
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
+ PaletteSize += sizeof (UINT16);
+ Palette = AllocateZeroPool (PaletteSize);
+ ASSERT (Palette != NULL);
+ CopyMem (Palette, PaletteInfo, PaletteSize);
+ PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));
+
+ ZeroMem (PaletteValue, sizeof (PaletteValue));
+ CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, PaletteNum);
+ SafeFreePool (Palette);
+
+ //
+ // Convert the pixel from 4 bit to corresponding color.
+ //
+ for (Y = 0; Y < Image->Height; Y++) {
+ OffsetY = BITMAP_LEN_4_BIT (Image->Width, Y);
+ //
+ // All bits in these bytes are meaningful
+ //
+ for (X = 0; X < Image->Width / 2; X++) {
+ Byte = *(Data + OffsetY + X);
+ BitMapPtr[Y * Image->Width + X * 2] = PaletteValue[Byte >> 4];
+ BitMapPtr[Y * Image->Width + X * 2 + 1] = PaletteValue[Byte & 0x0F];
+ }
+
+ if (Image->Width % 2 != 0) {
+ //
+ // Padding bits in this byte should be ignored.
+ //
+ Byte = *(Data + OffsetY + X);
+ BitMapPtr[Y * Image->Width + X * 2] = PaletteValue[Byte >> 4];
+ }
+ }
+}
+
+
+/**
+ Output pixels in "8 bit per pixel" format to an image.
+
+ @param Image Points to the image which will store the pixels.
+ @param Data Stores the value of output pixels, 0 ~ 255.
+ @param PaletteInfo PaletteInfo which stores the color of the output
+ pixels. Each entry corresponds to a color within
+ [0, 255].
+
+
+**/
+STATIC
+VOID
+Output8bitPixel (
+ IN OUT EFI_IMAGE_INPUT *Image,
+ IN UINT8 *Data,
+ IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
+ )
+{
+ UINT16 X;
+ UINT16 Y;
+ UINTN OffsetY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[256];
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;
+ UINT16 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.
+ //
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
+ PaletteSize += sizeof (UINT16);
+ Palette = AllocateZeroPool (PaletteSize);
+ ASSERT (Palette != NULL);
+ CopyMem (Palette, PaletteInfo, PaletteSize);
+ PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));
+ ZeroMem (PaletteValue, sizeof (PaletteValue));
+ CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, PaletteNum);
+ SafeFreePool (Palette);
+
+ //
+ // Convert the pixel from 8 bits to corresponding color.
+ //
+ for (Y = 0; Y < Image->Height; Y++) {
+ OffsetY = BITMAP_LEN_8_BIT (Image->Width, Y);
+ //
+ // All bits are meaningful since the bitmap is 8 bits per pixel.
+ //
+ for (X = 0; X < Image->Width; X++) {
+ Byte = *(Data + OffsetY + X);
+ BitMapPtr[OffsetY + X] = PaletteValue[Byte];
+ }
+ }
+
+}
+
+
+/**
+ Output pixels in "24 bit per pixel" format to an image.
+
+ @param Image Points to the image which will store the pixels.
+ @param Data Stores the color of output pixels, allowing 16.8
+ millions colors.
+
+
+**/
+STATIC
+VOID
+Output24bitPixel (
+ IN OUT EFI_IMAGE_INPUT *Image,
+ IN EFI_HII_RGB_PIXEL *Data
+ )
+{
+ UINT16 Y;
+ UINTN OffsetY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
+
+ ASSERT (Image != NULL && Data != NULL);
+
+ BitMapPtr = Image->Bitmap;
+
+ for (Y = 0; Y < Image->Height; Y++) {
+ OffsetY = BITMAP_LEN_8_BIT (Image->Width, Y);
+ CopyRgbToGopPixel (&BitMapPtr[OffsetY], &Data[OffsetY], Image->Width);
+ }
+
+}
+
+
+/**
+ Convert the image from EFI_IMAGE_INPUT to EFI_IMAGE_OUTPUT format.
+
+ @param BltBuffer Buffer points to bitmap data of incoming 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.
+
+**/
+STATIC
+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 X;
+ UINTN Y;
+ 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 (Y = 0; Y < Height; Y++) {
+ OffsetY1 = Width * Y;
+ OffsetY2 = ImageOut->Width * (BltY + Y);
+ for (X = 0; X < Width; X++) {
+ SrcPixel = BltBuffer[OffsetY1 + X];
+ if (Transparent) {
+ if (CompareMem (&SrcPixel, &ZeroPixel, 3) != 0) {
+ ImageOut->Image.Bitmap[OffsetY2 + BltX + X] = SrcPixel;
+ }
+ } else {
+ ImageOut->Image.Bitmap[OffsetY2 + BltX + X] = SrcPixel;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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;
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
+ UINT8 *ImageBlock;
+ UINTN BlockSize;
+ UINT8 *NewBlock;
+ UINT8 *NewBlockPtr;
+ UINTN NewBlockSize;
+ EFI_IMAGE_INPUT *ImageIn;
+
+ if (This == NULL || ImageId == NULL || Image == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Get the specified 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;
+ }
+
+ ImageIn = (EFI_IMAGE_INPUT *) Image;
+
+ NewBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
+ BITMAP_LEN_24_BIT (ImageIn->Width, ImageIn->Height);
+
+ //
+ // 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.
+ //
+ BlockSize = ImagePackage->ImageBlockSize + NewBlockSize;
+ ImageBlock = (UINT8 *) AllocateZeroPool (BlockSize);
+ if (ImageBlock == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Copy the original content.
+ //
+ CopyMem (
+ ImageBlock,
+ ImagePackage->ImageBlock,
+ ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)
+ );
+ SafeFreePool (ImagePackage->ImageBlock);
+ ImagePackage->ImageBlock = ImageBlock;
+ ImageBlock += ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK);
+ //
+ // Temp memory to store new block.
+ //
+ NewBlock = AllocateZeroPool (NewBlockSize);
+ if (NewBlock == NULL) {
+ SafeFreePool (ImagePackage->ImageBlock);
+ ImagePackage->ImageBlock = NULL;
+ return EFI_OUT_OF_RESOURCES;
+ }
+ NewBlockPtr = NewBlock;
+
+ //
+ // Update the length record.
+ //
+ ImagePackage->ImageBlockSize = (UINT32) BlockSize;
+ ImagePackage->ImagePkgHdr.Header.Length += (UINT32) NewBlockSize;
+ PackageListNode->PackageListHdr.PackageLength += (UINT32) NewBlockSize;
+
+ } else {
+ //
+ // 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) {
+ 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;
+ BlockSize = sizeof (EFI_HII_IIBT_END_BLOCK) + NewBlockSize;
+ //
+ // Fill in image package header.
+ //
+ ImagePackage->ImagePkgHdr.Header.Length = (UINT32) BlockSize + sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
+ 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 = (UINT32) BlockSize;
+ ImagePackage->ImageBlock = (UINT8 *) AllocateZeroPool (BlockSize);
+ if (ImagePackage->ImageBlock == NULL) {
+ SafeFreePool (ImagePackage);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ImageBlock = ImagePackage->ImageBlock;
+
+ //
+ // Temp memory to store new block.
+ //
+ NewBlock = AllocateZeroPool (NewBlockSize);
+ if (NewBlock == NULL) {
+ SafeFreePool (ImagePackage->ImageBlock);
+ SafeFreePool (ImagePackage);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ NewBlockPtr = NewBlock;
+
+ //
+ // Insert this image package.
+ //
+ PackageListNode->ImagePkg = ImagePackage;
+ PackageListNode->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;
+ }
+
+ //
+ // Append the new block here
+ //
+ if (ImageIn->Flags == EFI_IMAGE_TRANSPARENT) {
+ *NewBlock = EFI_HII_IIBT_IMAGE_24BIT_TRANS;
+ } else {
+ *NewBlock = EFI_HII_IIBT_IMAGE_24BIT;
+ }
+ NewBlock++;
+ CopyMem (NewBlock, &ImageIn->Width, sizeof (UINT16));
+ NewBlock += sizeof (UINT16);
+ CopyMem (NewBlock, &ImageIn->Height, sizeof (UINT16));
+ NewBlock += sizeof (UINT16);
+ CopyGopToRgbPixel ((EFI_HII_RGB_PIXEL *) NewBlock, ImageIn->Bitmap, ImageIn->Width * ImageIn->Height);
+
+ CopyMem (ImageBlock, NewBlockPtr, NewBlockSize);
+ SafeFreePool (NewBlockPtr);
+
+ //
+ // Append the block end
+ //
+ ImageBlock += NewBlockSize;
+ ((EFI_HII_IIBT_END_BLOCK *) (ImageBlock))->Header.BlockType = EFI_HII_IIBT_END;
+
+ 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 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.
+ @param ImageSize On entry, points to the size of the buffer pointed
+ to by Image, in bytes. On return, points to the
+ length of the image, in bytes.
+
+ @retval EFI_SUCCESS The new image was returned successfully.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not available.
+ @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.
+
+**/
+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,
+ OUT UINTN *ImageSize
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
+ UINT8 *ImageBlock;
+ EFI_IMAGE_ID LocalImageId;
+ UINT8 BlockType;
+ EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit;
+ UINT16 Width;
+ UINT16 Height;
+ UINTN ImageLength;
+ BOOLEAN Flag;
+ UINT8 *PaletteInfo;
+ UINT8 PaletteIndex;
+ UINT16 PaletteSize;
+
+ if (This == NULL || ImageSize == NULL || Image == NULL || ImageId < 1 || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Get the specified package list and image package.
+ //
+ 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;
+ }
+ ImagePackage = PackageListNode->ImagePkg;
+ if (ImagePackage == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Find the image block specified by ImageId
+ //
+ LocalImageId = ImageId;
+ ImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &LocalImageId);
+ if (ImageBlock == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Flag = FALSE;
+ BlockType = *ImageBlock;
+
+ switch (BlockType) {
+ case EFI_HII_IIBT_IMAGE_JPEG:
+ //
+ // BUGBUG: need to be supported as soon as image tool is designed.
+ //
+ return EFI_UNSUPPORTED;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
+ case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
+ case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
+ Flag = TRUE;
+ //
+ // 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, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));
+ ImageLength = sizeof (EFI_IMAGE_INPUT) + sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) *
+ (Iibt1bit.Bitmap.Width * Iibt1bit.Bitmap.Height - 1);
+ if (*ImageSize < ImageLength) {
+ *ImageSize = ImageLength;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ ZeroMem (Image, ImageLength);
+
+ if (Flag) {
+ Image->Flags = EFI_IMAGE_TRANSPARENT;
+ }
+ 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 (BlockType == EFI_HII_IIBT_IMAGE_1BIT || BlockType == EFI_HII_IIBT_IMAGE_1BIT_TRANS) {
+ Output1bitPixel (
+ Image,
+ (UINT8 *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8)),
+ (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
+ );
+ } else if (BlockType == EFI_HII_IIBT_IMAGE_4BIT || BlockType == EFI_HII_IIBT_IMAGE_4BIT_TRANS) {
+ Output4bitPixel (
+ Image,
+ (UINT8 *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8)),
+ (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
+ );
+ } else {
+ Output8bitPixel (
+ Image,
+ (UINT8 *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8)),
+ (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
+ );
+ }
+
+ return EFI_SUCCESS;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
+ Flag = TRUE;
+ //
+ // fall through
+ //
+ case EFI_HII_IIBT_IMAGE_24BIT:
+ CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));
+ CopyMem (
+ &Height,
+ ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),
+ sizeof (UINT16)
+ );
+ ImageLength = sizeof (EFI_IMAGE_INPUT) +
+ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (Width * Height - 1);
+ if (*ImageSize < ImageLength) {
+ *ImageSize = ImageLength;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ ZeroMem (Image, ImageLength);
+
+ if (Flag) {
+ Image->Flags = EFI_IMAGE_TRANSPARENT;
+ }
+ Image->Width = Width;
+ Image->Height = Height;
+
+ //
+ // Output the bimap data directly.
+ //
+ Output24bitPixel (
+ Image,
+ (EFI_HII_RGB_PIXEL *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))
+ );
+ return EFI_SUCCESS;
+ break;
+
+ default:
+ return EFI_NOT_FOUND;
+ break;
+ }
+}
+
+
+/**
+ 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.
+ @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;
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
+ UINT8 *ImageBlock;
+ EFI_IMAGE_ID LocalImageId;
+ UINT8 BlockType;
+ EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit;
+ EFI_HII_IIBT_IMAGE_4BIT_BLOCK Iibt4bit;
+ EFI_HII_IIBT_IMAGE_8BIT_BLOCK Iibt8bit;
+ UINT16 Width;
+ UINT16 Height;
+ UINT32 BlockSize;
+ UINT32 NewBlockSize;
+ UINT32 OldBlockSize;
+ EFI_IMAGE_INPUT *ImageIn;
+ UINT8 *NewBlock;
+ UINT8 *NewBlockPtr;
+ UINT8 *Block;
+ UINT8 *BlockPtr;
+ UINT32 Part1Size;
+ UINT32 Part2Size;
+
+ if (This == NULL || Image == NULL || ImageId < 1 || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Get the specified package list and image package.
+ //
+ 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;
+ }
+ ImagePackage = PackageListNode->ImagePkg;
+ if (ImagePackage == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Find the image block specified by ImageId
+ //
+ LocalImageId = ImageId;
+ ImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &LocalImageId);
+ if (ImageBlock == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ BlockType = *ImageBlock;
+
+ //
+ // Get the size of original image block. Use some common block code here
+ // since the definition of some structures is the same.
+ //
+ switch (BlockType) {
+ case EFI_HII_IIBT_IMAGE_JPEG:
+ //
+ // BUGBUG: need to be supported as soon as image tool is designed.
+ //
+ return EFI_UNSUPPORTED;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_1BIT:
+ case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
+ CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_1_BIT (Iibt1bit.Bitmap.Width, Iibt1bit.Bitmap.Height);
+ break;
+ case EFI_HII_IIBT_IMAGE_4BIT:
+ case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
+ CopyMem (&Iibt4bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK));
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_4_BIT (Iibt4bit.Bitmap.Width, Iibt4bit.Bitmap.Height);
+ break;
+ case EFI_HII_IIBT_IMAGE_8BIT:
+ case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
+ CopyMem (&Iibt8bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK));
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_8_BIT (Iibt8bit.Bitmap.Width, Iibt8bit.Bitmap.Height);
+ break;
+ case EFI_HII_IIBT_IMAGE_24BIT:
+ case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
+ CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));
+ CopyMem (
+ &Height,
+ ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),
+ sizeof (UINT16)
+ );
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
+ BITMAP_LEN_24_BIT (Width , Height);
+ break;
+ default:
+ return EFI_NOT_FOUND;
+ break;
+ }
+
+ //
+ // Create the new image block according to input image.
+ //
+ ImageIn = (EFI_IMAGE_INPUT *) Image;
+ NewBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
+ BITMAP_LEN_24_BIT (ImageIn->Width, ImageIn->Height);
+ NewBlock = (UINT8 *) AllocateZeroPool (NewBlockSize);
+ if (NewBlock == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewBlockPtr = NewBlock;
+ if ((ImageIn->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {
+ *NewBlockPtr = EFI_HII_IIBT_IMAGE_24BIT_TRANS;
+ } else {
+ *NewBlockPtr = EFI_HII_IIBT_IMAGE_24BIT;
+ }
+ NewBlockPtr++;
+
+ CopyMem (NewBlockPtr, &ImageIn->Width, sizeof (UINT16));
+ NewBlockPtr += sizeof (UINT16);
+ CopyMem (NewBlockPtr, &ImageIn->Height, sizeof (UINT16));
+ NewBlockPtr += sizeof (UINT16);
+
+ CopyGopToRgbPixel ((EFI_HII_RGB_PIXEL *) NewBlockPtr, ImageIn->Bitmap, ImageIn->Width * ImageIn->Height);
+
+ //
+ // Adjust the image package to remove the original block firstly then add the new block.
+ //
+ BlockSize = ImagePackage->ImageBlockSize + NewBlockSize - OldBlockSize;
+ Block = (UINT8 *) AllocateZeroPool (BlockSize);
+ if (Block == NULL) {
+ SafeFreePool (NewBlock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BlockPtr = Block;
+ Part1Size = (UINT32) (ImageBlock - ImagePackage->ImageBlock);
+ Part2Size = ImagePackage->ImageBlockSize - Part1Size - OldBlockSize;
+ CopyMem (BlockPtr, ImagePackage->ImageBlock, Part1Size);
+ BlockPtr += Part1Size;
+ CopyMem (BlockPtr, NewBlock, NewBlockSize);
+ BlockPtr += NewBlockSize;
+ CopyMem (BlockPtr, ImageBlock + OldBlockSize, Part2Size);
+
+ SafeFreePool (ImagePackage->ImageBlock);
+ SafeFreePool (NewBlock);
+ ImagePackage->ImageBlock = Block;
+ ImagePackage->ImageBlockSize = BlockSize;
+ ImagePackage->ImagePkgHdr.Header.Length += NewBlockSize - OldBlockSize;
+ PackageListNode->PackageListHdr.PackageLength += NewBlockSize - OldBlockSize;
+
+ 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 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_INPUT *ImageIn;
+ EFI_IMAGE_OUTPUT *ImageOut;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+ UINTN BufferLen;
+ UINTN Width;
+ UINTN Height;
+ UINTN X;
+ UINTN Y;
+ UINTN OffsetY1;
+ UINTN OffsetY2;
+ EFI_FONT_DISPLAY_INFO *FontInfo;
+ UINTN Index;
+ EFI_CONSOLE_CONTROL_PROTOCOL *Console;
+
+ 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;
+ }
+
+ ImageIn = (EFI_IMAGE_INPUT *) Image;
+
+ //
+ // 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 ((ImageIn->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) {
+ //
+ // Clip the image by (Width, Height)
+ //
+
+ Width = ImageIn->Width;
+ Height = ImageIn->Height;
+
+ if (Width > (*Blt)->Width - BltX) {
+ Width = (*Blt)->Width - BltX;
+ }
+ if (Height > (*Blt)->Height - BltY) {
+ Height = (*Blt)->Height - BltY;
+ }
+
+ BufferLen = Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (BufferLen);
+ if (BltBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (Width == ImageIn->Width && Height == ImageIn->Height) {
+ CopyMem (BltBuffer, ImageIn->Bitmap, BufferLen);
+ } else {
+ for (Y = 0; Y < Height; Y++) {
+ OffsetY1 = ImageIn->Width * Y;
+ OffsetY2 = Width * Y;
+ for (X = 0; X < Width; X++) {
+ BltBuffer[OffsetY2 + X] = ImageIn->Bitmap[OffsetY1 + X];
+ }
+ }
+ }
+
+ //
+ // Draw the image to existing bitmap or screen depending on flag.
+ //
+ if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
+ Status = gBS->LocateProtocol (
+ &gEfiConsoleControlProtocolGuid,
+ NULL,
+ (VOID **) &Console
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Console->SetMode (Console, EfiConsoleControlScreenGraphics);
+ //
+ // 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
+ );
+
+ }
+
+ SafeFreePool (BltBuffer);
+ return Status;
+
+ } else {
+ //
+ // Allocate a new bitmap to hold the incoming image.
+ //
+ Width = ImageIn->Width + BltX;
+ Height = ImageIn->Height + BltY;
+
+ BufferLen = Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (BufferLen);
+ if (BltBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ImageOut = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
+ if (ImageOut == NULL) {
+ SafeFreePool (BltBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ImageOut->Width = (UINT16) Width;
+ ImageOut->Height = (UINT16) 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)) {
+ SafeFreePool (BltBuffer);
+ SafeFreePool (ImageOut);
+ return Status;
+ }
+ for (Index = 0; Index < Width * Height; Index++) {
+ BltBuffer[Index] = FontInfo->BackgroundColor;
+ }
+ SafeFreePool (FontInfo);
+
+ //
+ // Draw the incoming image to the new created image.
+ //
+ *Blt = ImageOut;
+ return ImageToBlt (
+ ImageIn->Bitmap,
+ BltX,
+ BltY,
+ ImageIn->Width,
+ ImageIn->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 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 was NULL.
+ @retval EFI_NOT_FOUND The specified packagelist could not be found in
+ current 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 ImageTemp;
+ EFI_IMAGE_INPUT *Image;
+ UINTN ImageSize;
+
+ //
+ // Check input parameter.
+ //
+ if (This == NULL || PackageList == NULL || Blt == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get the specified Image.
+ //
+ ImageSize = 0;
+ Status = HiiGetImage (This, PackageList, ImageId, &ImageTemp, &ImageSize);
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ return Status;
+ }
+
+ Image = (EFI_IMAGE_INPUT *) AllocateZeroPool (ImageSize);
+ if (Image == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = HiiGetImage (This, PackageList, ImageId, Image, &ImageSize);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Draw this image.
+ //
+ Status = HiiDrawImage (This, Flags, Image, Blt, BltX, BltY);
+ SafeFreePool (Image);
+ return Status;
+}
+
+#endif
+
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.c b/MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.c
new file mode 100644
index 0000000..5458b16
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.c
@@ -0,0 +1,284 @@
+/**@file
+ Copyright (c) 2007, Intel Corporation
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+**/
+
+#include "HiiDatabase.h"
+
+
+CHAR16
+NibbleToHexChar (
+ IN UINT8 Nibble
+ )
+/*++
+
+ Routine Description:
+ Converts the low nibble of a byte to hex unicode character.
+
+ Arguments:
+ Nibble - lower nibble of a byte.
+
+ Returns:
+ Hex unicode character.
+
+--*/
+{
+ Nibble &= 0x0F;
+ if (Nibble <= 0x9) {
+ return (CHAR16)(Nibble + L'0');
+ }
+
+ return (CHAR16)(Nibble - 0xA + L'A');
+}
+
+/**
+ Compare whether two names of languages are identical.
+
+ @param Language1 Name of language 1
+ @param Language2 Name of language 2
+
+ @retval TRUE same
+ @retval FALSE not same
+
+**/
+BOOLEAN
+R8_EfiLibCompareLanguage (
+ IN CHAR8 *Language1,
+ IN CHAR8 *Language2
+ )
+{
+ //
+ // Porting Guide:
+ // This library interface is simply obsolete.
+ // Include the source code to user code.
+ //
+ UINTN Index;
+
+ for (Index = 0; (Language1[Index] != 0) && (Language2[Index] != 0); Index++) {
+ if (Language1[Index] != Language2[Index]) {
+ return FALSE;
+ }
+ }
+
+ if (((Language1[Index] == 0) && (Language2[Index] == 0)) ||
+ ((Language1[Index] == 0) && (Language2[Index] != ';')) ||
+ ((Language1[Index] == ';') && (Language2[Index] != 0)) ||
+ ((Language1[Index] == ';') && (Language2[Index] != ';'))) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+
+/**
+ Converts binary buffer to Unicode string.
+ At a minimum, any blob of data could be represented as a hex string.
+
+ @param Str Pointer to the string.
+ @param HexStringBufferLength Length in bytes of buffer to hold the hex string.
+ Includes tailing '\0' character. If routine return
+ with EFI_SUCCESS, containing length of hex string
+ buffer. If routine return with
+ EFI_BUFFER_TOO_SMALL, containg length of hex
+ string buffer desired.
+ @param Buf Buffer to be converted from.
+ @param Len Length in bytes of the buffer to be converted.
+
+ @retval EFI_SUCCESS Routine success.
+ @retval EFI_BUFFER_TOO_SMALL The hex string buffer is too small.
+
+**/
+EFI_STATUS
+R8_BufToHexString (
+ IN OUT CHAR16 *Str,
+ IN OUT UINTN *HexStringBufferLength,
+ IN UINT8 *Buf,
+ IN UINTN Len
+ )
+{
+ //
+ // Porting Guide:
+ // This library interface is simply obsolete.
+ // Include the source code to user code.
+ //
+ UINTN Idx;
+ UINT8 Byte;
+ UINTN StrLen;
+
+ //
+ // Make sure string is either passed or allocate enough.
+ // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer.
+ // Plus the Unicode termination character.
+ //
+ StrLen = Len * 2;
+ if (StrLen > ((*HexStringBufferLength) - 1)) {
+ *HexStringBufferLength = StrLen + 1;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *HexStringBufferLength = StrLen + 1;
+ //
+ // Ends the string.
+ //
+ Str[StrLen] = L'\0';
+
+ for (Idx = 0; Idx < Len; Idx++) {
+
+ Byte = Buf[Idx];
+ Str[StrLen - 1 - Idx * 2] = NibbleToHexChar (Byte);
+ Str[StrLen - 2 - Idx * 2] = NibbleToHexChar ((UINT8)(Byte >> 4));
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+
+/**
+ Converts Unicode string to binary buffer.
+ The conversion may be partial.
+ The first character in the string that is not hex digit stops the conversion.
+ At a minimum, any blob of data could be represented as a hex string.
+
+ @param Buf Pointer to buffer that receives the data.
+ @param Len Length in bytes of the buffer to hold converted
+ data. If routine return with EFI_SUCCESS,
+ containing length of converted data. If routine
+ return with EFI_BUFFER_TOO_SMALL, containg length
+ of buffer desired.
+ @param Str String to be converted from.
+ @param ConvertedStrLen Length of the Hex String consumed.
+
+ @retval EFI_SUCCESS Routine Success.
+ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold converted data.
+
+**/
+EFI_STATUS
+R8_HexStringToBuf (
+ IN OUT UINT8 *Buf,
+ IN OUT UINTN *Len,
+ IN CHAR16 *Str,
+ OUT UINTN *ConvertedStrLen OPTIONAL
+ )
+{
+ //
+ // Porting Guide:
+ // This library interface is simply obsolete.
+ // Include the source code to user code.
+ //
+
+ UINTN HexCnt;
+ UINTN Idx;
+ UINTN BufferLength;
+ UINT8 Digit;
+ UINT8 Byte;
+
+ //
+ // Find out how many hex characters the string has.
+ //
+ for (Idx = 0, HexCnt = 0; R8_IsHexDigit (&Digit, Str[Idx]); Idx++, HexCnt++);
+
+ if (HexCnt == 0) {
+ *Len = 0;
+ return EFI_SUCCESS;
+ }
+ //
+ // Two Unicode characters make up 1 buffer byte. Round up.
+ //
+ BufferLength = (HexCnt + 1) / 2;
+
+ //
+ // Test if buffer is passed enough.
+ //
+ if (BufferLength > (*Len)) {
+ *Len = BufferLength;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *Len = BufferLength;
+
+ for (Idx = 0; Idx < HexCnt; Idx++) {
+
+ R8_IsHexDigit (&Digit, Str[HexCnt - 1 - Idx]);
+
+ //
+ // For odd charaters, write the lower nibble for each buffer byte,
+ // and for even characters, the upper nibble.
+ //
+ if ((Idx & 1) == 0) {
+ Byte = Digit;
+ } else {
+ Byte = Buf[Idx / 2];
+ Byte &= 0x0F;
+ Byte = (UINT8) (Byte | Digit << 4);
+ }
+
+ Buf[Idx / 2] = Byte;
+ }
+
+ if (ConvertedStrLen != NULL) {
+ *ConvertedStrLen = HexCnt;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+
+/**
+ Determines if a Unicode character is a hexadecimal digit.
+ The test is case insensitive.
+
+ @param Digit Pointer to byte that receives the value of the hex
+ character.
+ @param Char Unicode character to test.
+
+ @retval TRUE If the character is a hexadecimal digit.
+ @retval FALSE Otherwise.
+
+**/
+BOOLEAN
+R8_IsHexDigit (
+ OUT UINT8 *Digit,
+ IN CHAR16 Char
+ )
+{
+ //
+ // Porting Guide:
+ // This library interface is simply obsolete.
+ // Include the source code to user code.
+ //
+
+ if ((Char >= L'0') && (Char <= L'9')) {
+ *Digit = (UINT8) (Char - L'0');
+ return TRUE;
+ }
+
+ if ((Char >= L'A') && (Char <= L'F')) {
+ *Digit = (UINT8) (Char - L'A' + 0x0A);
+ return TRUE;
+ }
+
+ if ((Char >= L'a') && (Char <= L'f')) {
+ *Digit = (UINT8) (Char - L'a' + 0x0A);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.h b/MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.h
new file mode 100644
index 0000000..4e6e1a1
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.h
@@ -0,0 +1,121 @@
+/**@file
+ Copyright (c) 2007, Intel Corporation
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+**/
+
+#ifndef __R8_LIB_H__
+#define __R8_LIB_H__
+
+
+/**
+ Compare whether two names of languages are identical.
+
+ @param Language1 Name of language 1
+ @param Language2 Name of language 2
+
+ @retval TRUE same
+ @retval FALSE not same
+
+**/
+BOOLEAN
+R8_EfiLibCompareLanguage (
+ IN CHAR8 *Language1,
+ IN CHAR8 *Language2
+ )
+;
+
+
+
+
+/**
+ Converts binary buffer to Unicode string.
+ At a minimum, any blob of data could be represented as a hex string.
+
+ @param Str Pointer to the string.
+ @param HexStringBufferLength Length in bytes of buffer to hold the hex string.
+ Includes tailing '\0' character. If routine return
+ with EFI_SUCCESS, containing length of hex string
+ buffer. If routine return with
+ EFI_BUFFER_TOO_SMALL, containg length of hex
+ string buffer desired.
+ @param Buf Buffer to be converted from.
+ @param Len Length in bytes of the buffer to be converted.
+
+ @retval EFI_SUCCESS Routine success.
+ @retval EFI_BUFFER_TOO_SMALL The hex string buffer is too small.
+
+**/
+EFI_STATUS
+R8_BufToHexString (
+ IN OUT CHAR16 *Str,
+ IN OUT UINTN *HexStringBufferLength,
+ IN UINT8 *Buf,
+ IN UINTN Len
+ )
+;
+
+
+
+
+/**
+ Converts Unicode string to binary buffer.
+ The conversion may be partial.
+ The first character in the string that is not hex digit stops the conversion.
+ At a minimum, any blob of data could be represented as a hex string.
+
+ @param Buf Pointer to buffer that receives the data.
+ @param Len Length in bytes of the buffer to hold converted
+ data. If routine return with EFI_SUCCESS,
+ containing length of converted data. If routine
+ return with EFI_BUFFER_TOO_SMALL, containg length
+ of buffer desired.
+ @param Str String to be converted from.
+ @param ConvertedStrLen Length of the Hex String consumed.
+
+ @retval EFI_SUCCESS Routine Success.
+ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold converted data.
+
+**/
+EFI_STATUS
+R8_HexStringToBuf (
+ IN OUT UINT8 *Buf,
+ IN OUT UINTN *Len,
+ IN CHAR16 *Str,
+ OUT UINTN *ConvertedStrLen OPTIONAL
+ )
+;
+
+
+
+
+/**
+ Determines if a Unicode character is a hexadecimal digit.
+ The test is case insensitive.
+
+ @param Digit Pointer to byte that receives the value of the hex
+ character.
+ @param Char Unicode character to test.
+
+ @retval TRUE If the character is a hexadecimal digit.
+ @retval FALSE Otherwise.
+
+**/
+BOOLEAN
+R8_IsHexDigit (
+ OUT UINT8 *Digit,
+ IN CHAR16 Char
+ )
+;
+
+
+#endif
+
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/String.c b/MdeModulePkg/Universal/HiiDatabaseDxe/String.c
new file mode 100644
index 0000000..d408365
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/String.c
@@ -0,0 +1,1606 @@
+/** @file
+
+Copyright (c) 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ String.c
+
+Abstract:
+
+ Implementation for EFI_HII_STRING_PROTOCOL.
+
+Revision History
+
+
+**/
+
+
+#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.
+
+ @param Private Hii database private structure.
+ @param StringPackage HII string package instance.
+ @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.
+
+**/
+STATIC
+BOOLEAN
+ReferFontInfoLocally (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
+ 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;
+ }
+ }
+ }
+ //
+ // Since string package tool set FontId initially to 0 and increases it
+ // progressively by one, StringPackage->FondId always represents an unique
+ // and available FontId.
+ //
+ // 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 = StringPackage->FontId;
+ LocalFont->GlobalEntry = &GlobalFontInfo->Entry;
+ InsertTailList (&StringPackage->FontInfoList, &LocalFont->Entry);
+
+ StringPackage->FontId++;
+
+ *LocalFontInfo = LocalFont;
+ return FALSE;
+}
+
+
+/**
+ Convert Ascii string text to unicode string test.
+
+ @param StringSrc Points to current null-terminated Ascii string.
+ @param StringDest Buffer to store the converted string text.
+ @param BufferSize Length of the buffer.
+
+ @retval EFI_SUCCESS The string text was outputed successfully.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string
+ text. BufferSize is updated to the required buffer
+ size.
+
+**/
+STATIC
+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) {
+ *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.
+
+ @param StringSrc Points to current null-terminated string.
+ @param StringDest Buffer to store the string text.
+ @param BufferSize Length of the buffer.
+
+ @retval EFI_SUCCESS The string text was outputed successfully.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string
+ text. BufferSize is updated to the required buffer
+ size.
+
+**/
+STATIC
+EFI_STATUS
+GetUnicodeStringTextOrSize (
+ OUT EFI_STRING StringDest, OPTIONAL
+ IN UINT8 *StringSrc,
+ IN OUT UINTN *BufferSize
+ )
+{
+ UINTN StringSize;
+ CHAR16 Zero;
+ UINT8 *StringPtr;
+
+ ASSERT (StringSrc != NULL && BufferSize != NULL);
+
+ ZeroMem (&Zero, sizeof (CHAR16));
+ StringSize = sizeof (CHAR16);
+ StringPtr = StringSrc;
+ while (CompareMem (StringPtr, &Zero, sizeof (CHAR16)) != 0) {
+ StringSize += sizeof (CHAR16);
+ StringPtr += sizeof (CHAR16);
+ }
+
+ if (StringDest != NULL) {
+ if (*BufferSize < StringSize) {
+ *BufferSize = StringSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ CopyMem (StringDest, StringSrc, StringSize);
+ return EFI_SUCCESS;
+ }
+
+ *BufferSize = StringSize;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Copy string font info to a buffer.
+
+ @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 outputed successfully.
+ @retval EFI_NOT_FOUND The specified font id does not exist.
+
+**/
+STATIC
+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 StringId = 0, output the string id of last string block (EFI_HII_SIBT_END).
+
+ @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.
+
+ @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
+ )
+{
+ 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;
+ UINT32 Length32;
+ UINTN StringSize;
+ CHAR16 Zero;
+
+ ASSERT (StringPackage != NULL);
+ ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);
+
+ CurrentStringId = 1;
+
+ if (StringId != (EFI_STRING_ID) (-1) && StringId != 0) {
+ ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);
+ } else {
+ ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
+ }
+
+ 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 = 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) {
+ *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,
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
+ sizeof (UINT16)
+ );
+ StringTextPtr = 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) {
+ *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) {
+ *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,
+ 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) {
+ *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) (*(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,
+ 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) + sizeof (UINT8);
+ 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 (IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont)) {
+ //
+ // If find the corresponding global font info, save the relationship.
+ //
+ ReferFontInfoLocally (Private, StringPackage, TRUE, GlobalFont, &LocalFont);
+ }
+
+ //
+ // If can not find, ignore this EFI_HII_SIBT_FONT block.
+ //
+ SafeFreePool (FontInfo);
+ }
+
+ BlockSize += Ext2.Length;
+
+ break;
+
+ case EFI_HII_SIBT_EXT4:
+ CopyMem (
+ &Length32,
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
+ sizeof (UINT32)
+ );
+
+ BlockSize += Length32;
+ break;
+
+ default:
+ break;
+ }
+
+ if (StringId > 0) {
+ if (StringId == CurrentStringId - 1) {
+ *BlockType = *BlockHdr;
+ *StringBlockAddr = BlockHdr;
+ *StringTextOffset = Offset;
+ return EFI_SUCCESS;
+ }
+
+ if (StringId < CurrentStringId - 1) {
+ return EFI_NOT_FOUND;
+ }
+ }
+ BlockHdr = StringPackage->StringBlock + BlockSize;
+
+ }
+
+ if (StringId == (EFI_STRING_ID) (-1)) {
+ return EFI_SUCCESS;
+ }
+
+ if (StringId == 0 && LastStringId != NULL) {
+ *LastStringId = CurrentStringId;
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Parse all string blocks to get a string specified by StringId.
+
+ @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.
+
+**/
+STATIC
+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,
+ OUT EFI_FONT_INFO **StringFontInfo OPTIONAL
+ )
+{
+ UINT8 *StringTextPtr;
+ UINT8 BlockType;
+ UINT8 *StringBlockAddr;
+ UINTN StringTextOffset;
+ EFI_STATUS Status;
+ UINT8 FontId;
+
+ ASSERT (StringPackage != NULL && StringSize != 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
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // 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.
+ //
+ 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));
+ return GetStringFontInfo (StringPackage, FontId, StringFontInfo);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Parse all string blocks to set a String specified by StringId.
+
+ @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.
+
+**/
+STATIC
+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;
+
+
+ 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
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ LocalFont = NULL;
+ GlobalFont = NULL;
+ Referred = FALSE;
+
+ //
+ // Set the string font according to input font information.
+ //
+ if (StringFontInfo != NULL) {
+ //
+ // The input StringFontInfo should exist in current database
+ //
+ if (!IsFontInfoExisted (Private, StringFontInfo, NULL, NULL, &GlobalFont)) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ Referred = ReferFontInfoLocally (Private, StringPackage, FALSE, GlobalFont, &LocalFont);
+ }
+
+ //
+ // Update the FontId of the specified string block
+ //
+ 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:
+ return EFI_NOT_FOUND;
+ }
+
+ }
+
+ OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
+
+ //
+ // Set 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:
+ BlockSize = OldBlockSize + StrLen (String);
+ BlockSize -= AsciiStrLen ((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
+ );
+
+ SafeFreePool (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
+ );
+
+ SafeFreePool (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 += sizeof (UINT8);
+ 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);
+
+ SafeFreePool (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.
+
+ @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;
+ BOOLEAN Matched;
+ 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;
+
+ 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;
+ }
+
+ //
+ // Try to get the matching string package. Create a new string package when failed.
+ //
+ StringPackage = NULL;
+ Matched = FALSE;
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;
+ Link != &PackageListNode->StringPkgHdr;
+ Link = Link->ForwardLink
+ ) {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {
+ Matched = TRUE;
+ break;
+ }
+ }
+
+ if (!Matched) {
+ //
+ // LanguageName is required to create a new string package.
+ //
+ if (LanguageName == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ StringPackage = AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));
+ if (StringPackage == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;
+ 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) {
+ SafeFreePool (StringPackage);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ 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;
+ AsciiStrCpy (StringPackage->StringPkgHdr->Language, (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) +
+ 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) {
+ SafeFreePool (StringPackage->StringPkgHdr);
+ SafeFreePool (StringPackage);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // 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);
+
+ //
+ // 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);
+
+ }
+
+ //
+ // 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,
+ StringId
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ 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) {
+ 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 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;
+ SafeFreePool (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, FALSE, GlobalFont, &LocalFont)) {
+ //
+ // Create a EFI_HII_SIBT_STRING_UCS2_FONT block only.
+ //
+ StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2FontBlockSize);
+ 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 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 += sizeof (UINT8);
+ 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;
+ SafeFreePool (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) {
+ 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 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 += sizeof (UINT8);
+ 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)
+ );
+
+ //
+ // 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 += sizeof (UINT8);
+ 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;
+ SafeFreePool (StringPackage->StringBlock);
+ StringPackage->StringBlock = StringBlock;
+ StringPackage->StringPkgHdr->Header.Length += FontBlockSize + Ucs2FontBlockSize;
+ PackageListNode->PackageListHdr.PackageLength += FontBlockSize + Ucs2FontBlockSize;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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.
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to
+ hold the string.
+ @retval EFI_INVALID_PARAMETER The String or Language or StringSize 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) {
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;
+ Link != &PackageListNode->StringPkgHdr;
+ Link = Link->ForwardLink
+ ) {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {
+ Status = GetStringWorker (Private, StringPackage, StringId, String, StringSize, StringFontInfo);
+ if (Status != EFI_NOT_FOUND) {
+ return Status;
+ }
+ }
+ }
+ }
+
+ 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;
+ }
+
+ 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 (R8_EfiLibCompareLanguage (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)) {
+ return Status;
+ }
+ PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length - OldPackageLen;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ 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 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 Languages or LanguagesSize was 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 || Languages == NULL || LanguagesSize == NULL || PackageList == 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) {
+ AsciiStrCpy (Languages, 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 FirstLanguage Points to the primary language.
+ @param SecondaryLanguages Points to the buffer to hold the returned list of
+ secondary languages for the specified
+ FirstLanguage. If there are no secondary
+ languages, the function returns successfully, but
+ this is set to NULL.
+ @param SecondaryLanguageSize On entry, points to the size of the buffer pointed
+ to by SecondLanguages, in bytes. On return,
+ points to the length of SecondLanguages in bytes.
+
+ @retval EFI_SUCCESS Secondary languages were correctly returned.
+ @retval EFI_INVALID_PARAMETER FirstLanguage or SecondLanguages or
+ SecondLanguagesSize was NULL.
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by SecondLanguagesSize is
+ too small to hold the returned information.
+ SecondLanguageSize is updated to hold the size of
+ the buffer required.
+ @retval EFI_NOT_FOUND The language specified by FirstLanguage is not
+ present in the specified package list.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetSecondaryLanguages (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN CONST CHAR8 *FirstLanguage,
+ IN OUT CHAR8 *SecondLanguages,
+ IN OUT UINTN *SecondLanguagesSize
+ )
+{
+ 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 || FirstLanguage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (SecondLanguages == NULL || SecondLanguagesSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ Languages = NULL;
+ ResultSize = 0;
+
+ 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);
+ for (Link1 = PackageListNode->StringPkgHdr.ForwardLink;
+ Link1 != &PackageListNode->StringPkgHdr;
+ Link1 = Link1->ForwardLink
+ ) {
+ StringPackage = CR (Link1, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) FirstLanguage)) {
+ 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 <= *SecondLanguagesSize) {
+ AsciiStrCpy (SecondLanguages, Languages);
+ } else {
+ *SecondLanguagesSize = ResultSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+