From 93e3992d1ea50fb30c48f498d257d4e66252dd9b Mon Sep 17 00:00:00 2001 From: qwang12 Date: Mon, 21 Jan 2008 14:39:56 +0000 Subject: 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 --- .../Universal/HiiDatabaseDxe/ConfigRouting.c | 2116 +++++++++++ MdeModulePkg/Universal/HiiDatabaseDxe/Database.c | 3727 ++++++++++++++++++++ MdeModulePkg/Universal/HiiDatabaseDxe/Font.c | 2395 +++++++++++++ .../Universal/HiiDatabaseDxe/HiiDatabase.h | 1694 +++++++++ .../Universal/HiiDatabaseDxe/HiiDatabase.msa | 79 + .../Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf | 75 + .../Universal/HiiDatabaseDxe/HiiDatabaseEntry.c | 197 ++ MdeModulePkg/Universal/HiiDatabaseDxe/Image.c | 1509 ++++++++ MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.c | 284 ++ MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.h | 121 + MdeModulePkg/Universal/HiiDatabaseDxe/String.c | 1606 +++++++++ 11 files changed, 13803 insertions(+) create mode 100644 MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c create mode 100644 MdeModulePkg/Universal/HiiDatabaseDxe/Database.c create mode 100644 MdeModulePkg/Universal/HiiDatabaseDxe/Font.c create mode 100644 MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h create mode 100644 MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.msa create mode 100644 MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf create mode 100644 MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c create mode 100644 MdeModulePkg/Universal/HiiDatabaseDxe/Image.c create mode 100644 MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.c create mode 100644 MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.h create mode 100644 MdeModulePkg/Universal/HiiDatabaseDxe/String.c (limited to 'MdeModulePkg/Universal/HiiDatabaseDxe') diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c new file mode 100644 index 0000000000..15a55d794a --- /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 or + 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 / should be "&GUID=". + // Will meet '\0' if there is only one /. + // + 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 of . + + @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 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 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 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 from String then output it. + + @param String A sub string of a configuration string in + 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 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 , + , or . 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 in format, i.e. the value of OFFSET + or WIDTH or VALUE. + ::= 'OFFSET='&'WIDTH='&'VALUE'= + + @param StringPtr String in format and points to the + first character of . + @param Number The output value. Caller takes the responsibility + to free memory. + @param Len Length of the , in characters. + + @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary + structures. + @retval EFI_SUCCESS Value of 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 + 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 + 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 should be + // , which is in '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 + // or most recent & before the error. + // + if (StringPtr == Request) { + *Progress = StringPtr; + } else { + *Progress = StringPtr - 1; + } + + // + // Process each of + // + 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 . + // Map it to the progress on then return it. + // + RemainSize = StrSize (AccessProgress); + for (TmpPtr = StringPtr; CompareMem (TmpPtr, AccessProgress, RemainSize) != 0; TmpPtr++); + *Progress = TmpPtr; + + SafeFreePool (ConfigRequest); + return Status; + } + + // + // Attach this to a + // + ASSERT (*AccessProgress == 0); + Status = AppendToMultiString (Results, AccessResults); + ASSERT_EFI_ERROR (Status); + SafeFreePool (AccessResults); + AccessResults = NULL; + SafeFreePool (ConfigRequest); + ConfigRequest = NULL; + + // + // Go to next (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 + 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 with one and zero . + // 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 + // ::= '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 + // ::= 'NAME=' + // + 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 + // ::= '' + // + 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 or a + // is required to call ConfigAccess.ExtractConfig(). + // + // Here we use 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 to a + // + 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 + 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 should be + // , which is in '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 + // or most recent & before the error. + // + if (StringPtr == Configuration) { + *Progress = StringPtr; + } else { + *Progress = StringPtr - 1; + } + + // + // Process each of + // + 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 . + // Map it to the progress on 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 (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 + 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 formatted string. + Block is left updated and Progress points at + the "&" preceding the first non-. + +**/ +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 + // + 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 and an additional '&' to + // + Length = StringPtr - ConfigRequest; + CopyMem (*Config, ConfigRequest, Length * sizeof (CHAR16)); + + // + // Parse each if exists + // Only format is supported by this help function. + // ::= 'OFFSET='&'WIDTH=' + // + while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) { + // + // Back up the header of one + // + 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 + 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 formatted name / + value pair. Block is left updated and + Progress points at the '&' preceding the first + non-. + +**/ +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 + // + 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 if exists + // Only format is supported by this help function. + // ::= 'OFFSET='&'WIDTH='&'VALUE=' + // + 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 + 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 + // + 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 + // + 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 or + // + 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 to get the 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 and + // + 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 0000000000..a24c59bdce --- /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 0000000000..a5363d43bd --- /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 0000000000..cf3519b853 --- /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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +#include +#include +#include +#include +#include +#include +#include + +#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 + 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 + 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 + 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 + 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 + 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 formatted string. + Block is left updated and Progress points at + the ¡®&¡¯ preceding the first non-. + +**/ +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 + 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 formatted name / + value pair. Block is left updated and + Progress points at the ¡®&¡¯ preceding the first + non-. + +**/ +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 + 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 0000000000..2b3cf9b460 --- /dev/null +++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.msa @@ -0,0 +1,79 @@ + + + HiiDatabase + DXE_DRIVER + 348C4D62-BFBD-4882-9ECE-C80BB1C4783B + 1.0 + 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. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + HiiDatabase + + + + DebugLib + + + BaseMemoryLib + + + UefiDriverEntryPoint + + + UefiBootServicesTableLib + + + BaseLib + + + DevicePathLib + + + MemoryAllocationLib + + + + R8Lib.c + R8Lib.h + Font.c + Database.c + String.c + ConfigRouting.c + HiiDatabase.dxs + HiiDatabase.h + Image.c + HiiDatabaseEntry.c + CVS\TortoiseCVS.Status + + + + + + + + gEfiDevicePathProtocolGuid + + + gEfiConsoleControlProtocolGuid + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00020000 + + InitializeHiiDatabase + + + \ 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 0000000000..2bafb25b18 --- /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 0000000000..99084db068 --- /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 0000000000..06d783a880 --- /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 0000000000..5458b16b61 --- /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 0000000000..4e6e1a1e61 --- /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 0000000000..d408365a89 --- /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; +} + -- cgit v1.2.3