| /** @file | |
| Implementation for EFI_HII_STRING_PROTOCOL. | |
| Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR> | |
| (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include "HiiDatabase.h" | |
| CHAR16 mLanguageWindow[16] = { | |
| 0x0000, 0x0080, 0x0100, 0x0300, | |
| 0x2000, 0x2080, 0x2100, 0x3000, | |
| 0x0080, 0x00C0, 0x0400, 0x0600, | |
| 0x0900, 0x3040, 0x30A0, 0xFF00 | |
| }; | |
| /** | |
| This function checks whether a global font info is referred by local | |
| font info list or not. (i.e. HII_FONT_INFO is generated.) If not, create | |
| a HII_FONT_INFO to refer it locally. | |
| This is a internal function. | |
| @param Private Hii database private structure. | |
| @param StringPackage HII string package instance. | |
| @param FontId Font identifer, which must be unique within the string package. | |
| @param DuplicateEnable If true, duplicate HII_FONT_INFO which refers to | |
| the same EFI_FONT_INFO is permitted. Otherwise it | |
| is not allowed. | |
| @param GlobalFontInfo Input a global font info which specify a | |
| EFI_FONT_INFO. | |
| @param LocalFontInfo Output a local font info which refers to a | |
| EFI_FONT_INFO. | |
| @retval TRUE Already referred before calling this function. | |
| @retval FALSE Not referred before calling this function. | |
| **/ | |
| BOOLEAN | |
| ReferFontInfoLocally ( | |
| IN HII_DATABASE_PRIVATE_DATA *Private, | |
| IN HII_STRING_PACKAGE_INSTANCE *StringPackage, | |
| IN UINT8 FontId, | |
| IN BOOLEAN DuplicateEnable, | |
| IN HII_GLOBAL_FONT_INFO *GlobalFontInfo, | |
| OUT HII_FONT_INFO **LocalFontInfo | |
| ) | |
| { | |
| HII_FONT_INFO *LocalFont; | |
| LIST_ENTRY *Link; | |
| ASSERT (Private != NULL && StringPackage != NULL && GlobalFontInfo != NULL && LocalFontInfo != NULL); | |
| if (!DuplicateEnable) { | |
| for (Link = StringPackage->FontInfoList.ForwardLink; | |
| Link != &StringPackage->FontInfoList; | |
| Link = Link->ForwardLink | |
| ) | |
| { | |
| LocalFont = CR (Link, HII_FONT_INFO, Entry, HII_FONT_INFO_SIGNATURE); | |
| if (LocalFont->GlobalEntry == &GlobalFontInfo->Entry) { | |
| // | |
| // Already referred by local font info list, return directly. | |
| // | |
| *LocalFontInfo = LocalFont; | |
| return TRUE; | |
| } | |
| } | |
| } | |
| // FontId identifies EFI_FONT_INFO in local string package uniquely. | |
| // GlobalEntry points to a HII_GLOBAL_FONT_INFO which identifies | |
| // EFI_FONT_INFO uniquely in whole hii database. | |
| // | |
| LocalFont = (HII_FONT_INFO *)AllocateZeroPool (sizeof (HII_FONT_INFO)); | |
| ASSERT (LocalFont != NULL); | |
| LocalFont->Signature = HII_FONT_INFO_SIGNATURE; | |
| LocalFont->FontId = FontId; | |
| LocalFont->GlobalEntry = &GlobalFontInfo->Entry; | |
| InsertTailList (&StringPackage->FontInfoList, &LocalFont->Entry); | |
| *LocalFontInfo = LocalFont; | |
| return FALSE; | |
| } | |
| /** | |
| Convert Ascii string text to unicode string test. | |
| This is a internal function. | |
| @param StringDest Buffer to store the string text. If it is NULL, | |
| only the size will be returned. | |
| @param StringSrc Points to current null-terminated string. | |
| @param BufferSize Length of the buffer. | |
| @retval EFI_SUCCESS The string text was outputted successfully. | |
| @retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string | |
| text. BufferSize is updated to the required buffer | |
| size. | |
| **/ | |
| EFI_STATUS | |
| ConvertToUnicodeText ( | |
| OUT EFI_STRING StringDest, | |
| IN CHAR8 *StringSrc, | |
| IN OUT UINTN *BufferSize | |
| ) | |
| { | |
| UINTN StringSize; | |
| UINTN Index; | |
| ASSERT (StringSrc != NULL && BufferSize != NULL); | |
| StringSize = AsciiStrSize (StringSrc) * 2; | |
| if ((*BufferSize < StringSize) || (StringDest == NULL)) { | |
| *BufferSize = StringSize; | |
| return EFI_BUFFER_TOO_SMALL; | |
| } | |
| for (Index = 0; Index < AsciiStrLen (StringSrc); Index++) { | |
| StringDest[Index] = (CHAR16)StringSrc[Index]; | |
| } | |
| StringDest[Index] = 0; | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Calculate the size of StringSrc and output it. If StringDest is not NULL, | |
| copy string text from src to dest. | |
| This is a internal function. | |
| @param StringDest Buffer to store the string text. If it is NULL, | |
| only the size will be returned. | |
| @param StringSrc Points to current null-terminated string. | |
| @param BufferSize Length of the buffer. | |
| @retval EFI_SUCCESS The string text was outputted successfully. | |
| @retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string | |
| text. BufferSize is updated to the required buffer | |
| size. | |
| **/ | |
| EFI_STATUS | |
| GetUnicodeStringTextOrSize ( | |
| OUT EFI_STRING StringDest OPTIONAL, | |
| IN UINT8 *StringSrc, | |
| IN OUT UINTN *BufferSize | |
| ) | |
| { | |
| UINTN StringSize; | |
| UINT8 *StringPtr; | |
| ASSERT (StringSrc != NULL && BufferSize != NULL); | |
| StringSize = sizeof (CHAR16); | |
| StringPtr = StringSrc; | |
| while (ReadUnaligned16 ((UINT16 *)StringPtr) != 0) { | |
| StringSize += sizeof (CHAR16); | |
| StringPtr += sizeof (CHAR16); | |
| } | |
| if (*BufferSize < StringSize) { | |
| *BufferSize = StringSize; | |
| return EFI_BUFFER_TOO_SMALL; | |
| } | |
| if (StringDest != NULL) { | |
| CopyMem (StringDest, StringSrc, StringSize); | |
| } | |
| *BufferSize = StringSize; | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Copy string font info to a buffer. | |
| This is a internal function. | |
| @param StringPackage Hii string package instance. | |
| @param FontId Font identifier which is unique in a string | |
| package. | |
| @param StringFontInfo Buffer to record the output font info. It's | |
| caller's responsibility to free this buffer. | |
| @retval EFI_SUCCESS The string font is outputted successfully. | |
| @retval EFI_NOT_FOUND The specified font id does not exist. | |
| **/ | |
| EFI_STATUS | |
| GetStringFontInfo ( | |
| IN HII_STRING_PACKAGE_INSTANCE *StringPackage, | |
| IN UINT8 FontId, | |
| OUT EFI_FONT_INFO **StringFontInfo | |
| ) | |
| { | |
| LIST_ENTRY *Link; | |
| HII_FONT_INFO *FontInfo; | |
| HII_GLOBAL_FONT_INFO *GlobalFont; | |
| ASSERT (StringFontInfo != NULL && StringPackage != NULL); | |
| for (Link = StringPackage->FontInfoList.ForwardLink; Link != &StringPackage->FontInfoList; Link = Link->ForwardLink) { | |
| FontInfo = CR (Link, HII_FONT_INFO, Entry, HII_FONT_INFO_SIGNATURE); | |
| if (FontInfo->FontId == FontId) { | |
| GlobalFont = CR (FontInfo->GlobalEntry, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE); | |
| *StringFontInfo = (EFI_FONT_INFO *)AllocateZeroPool (GlobalFont->FontInfoSize); | |
| if (*StringFontInfo == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| CopyMem (*StringFontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize); | |
| return EFI_SUCCESS; | |
| } | |
| } | |
| return EFI_NOT_FOUND; | |
| } | |
| /** | |
| Parse all string blocks to find a String block specified by StringId. | |
| If StringId = (EFI_STRING_ID) (-1), find out all EFI_HII_SIBT_FONT blocks | |
| within this string package and backup its information. If LastStringId is | |
| specified, the string id of last string block will also be output. | |
| If StringId = 0, output the string id of last string block (EFI_HII_SIBT_STRING). | |
| @param Private Hii database private structure. | |
| @param StringPackage Hii string package instance. | |
| @param StringId The string's id, which is unique within | |
| PackageList. | |
| @param BlockType Output the block type of found string block. | |
| @param StringBlockAddr Output the block address of found string block. | |
| @param StringTextOffset Offset, relative to the found block address, of | |
| the string text information. | |
| @param LastStringId Output the last string id when StringId = 0 or StringId = -1. | |
| @param StartStringId The first id in the skip block which StringId in the block. | |
| @retval EFI_SUCCESS The string text and font is retrieved | |
| successfully. | |
| @retval EFI_NOT_FOUND The specified text or font info can not be found | |
| out. | |
| @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the | |
| task. | |
| **/ | |
| EFI_STATUS | |
| FindStringBlock ( | |
| IN HII_DATABASE_PRIVATE_DATA *Private, | |
| IN HII_STRING_PACKAGE_INSTANCE *StringPackage, | |
| IN EFI_STRING_ID StringId, | |
| OUT UINT8 *BlockType OPTIONAL, | |
| OUT UINT8 **StringBlockAddr OPTIONAL, | |
| OUT UINTN *StringTextOffset OPTIONAL, | |
| OUT EFI_STRING_ID *LastStringId OPTIONAL, | |
| OUT EFI_STRING_ID *StartStringId OPTIONAL | |
| ) | |
| { | |
| UINT8 *BlockHdr; | |
| EFI_STRING_ID CurrentStringId; | |
| UINTN BlockSize; | |
| UINTN Index; | |
| UINT8 *StringTextPtr; | |
| UINTN Offset; | |
| HII_FONT_INFO *LocalFont; | |
| EFI_FONT_INFO *FontInfo; | |
| HII_GLOBAL_FONT_INFO *GlobalFont; | |
| UINTN FontInfoSize; | |
| UINT16 StringCount; | |
| UINT16 SkipCount; | |
| EFI_HII_FONT_STYLE FontStyle; | |
| UINT16 FontSize; | |
| UINT8 Length8; | |
| EFI_HII_SIBT_EXT2_BLOCK Ext2; | |
| UINT8 FontId; | |
| UINT32 Length32; | |
| UINTN StringSize; | |
| CHAR16 Zero; | |
| ASSERT (StringPackage != NULL); | |
| ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE); | |
| CurrentStringId = 1; | |
| StringSize = 0; | |
| if ((StringId != (EFI_STRING_ID)(-1)) && (StringId != 0)) { | |
| ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL); | |
| if (StringId > StringPackage->MaxStringId) { | |
| return EFI_NOT_FOUND; | |
| } | |
| } else { | |
| ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE); | |
| if ((StringId == 0) && (LastStringId != NULL)) { | |
| *LastStringId = StringPackage->MaxStringId; | |
| return EFI_SUCCESS; | |
| } | |
| } | |
| ZeroMem (&Zero, sizeof (CHAR16)); | |
| // | |
| // Parse the string blocks to get the string text and font. | |
| // | |
| BlockHdr = StringPackage->StringBlock; | |
| BlockSize = 0; | |
| Offset = 0; | |
| while (*BlockHdr != EFI_HII_SIBT_END) { | |
| switch (*BlockHdr) { | |
| case EFI_HII_SIBT_STRING_SCSU: | |
| Offset = sizeof (EFI_HII_STRING_BLOCK); | |
| StringTextPtr = BlockHdr + Offset; | |
| BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr); | |
| CurrentStringId++; | |
| break; | |
| case EFI_HII_SIBT_STRING_SCSU_FONT: | |
| Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8); | |
| StringTextPtr = BlockHdr + Offset; | |
| BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr); | |
| CurrentStringId++; | |
| break; | |
| case EFI_HII_SIBT_STRINGS_SCSU: | |
| CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16)); | |
| StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8)); | |
| BlockSize += StringTextPtr - BlockHdr; | |
| for (Index = 0; Index < StringCount; Index++) { | |
| BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr); | |
| if (CurrentStringId == StringId) { | |
| ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL); | |
| *BlockType = *BlockHdr; | |
| *StringBlockAddr = BlockHdr; | |
| *StringTextOffset = StringTextPtr - BlockHdr; | |
| return EFI_SUCCESS; | |
| } | |
| StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr); | |
| CurrentStringId++; | |
| } | |
| break; | |
| case EFI_HII_SIBT_STRINGS_SCSU_FONT: | |
| CopyMem ( | |
| &StringCount, | |
| (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)), | |
| sizeof (UINT16) | |
| ); | |
| StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8)); | |
| BlockSize += StringTextPtr - BlockHdr; | |
| for (Index = 0; Index < StringCount; Index++) { | |
| BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr); | |
| if (CurrentStringId == StringId) { | |
| ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL); | |
| *BlockType = *BlockHdr; | |
| *StringBlockAddr = BlockHdr; | |
| *StringTextOffset = StringTextPtr - BlockHdr; | |
| return EFI_SUCCESS; | |
| } | |
| StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr); | |
| CurrentStringId++; | |
| } | |
| break; | |
| case EFI_HII_SIBT_STRING_UCS2: | |
| Offset = sizeof (EFI_HII_STRING_BLOCK); | |
| StringTextPtr = BlockHdr + Offset; | |
| // | |
| // Use StringSize to store the size of the specified string, including the NULL | |
| // terminator. | |
| // | |
| GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize); | |
| BlockSize += Offset + StringSize; | |
| CurrentStringId++; | |
| break; | |
| case EFI_HII_SIBT_STRING_UCS2_FONT: | |
| Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16); | |
| StringTextPtr = BlockHdr + Offset; | |
| // | |
| // Use StrSize to store the size of the specified string, including the NULL | |
| // terminator. | |
| // | |
| GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize); | |
| BlockSize += Offset + StringSize; | |
| CurrentStringId++; | |
| break; | |
| case EFI_HII_SIBT_STRINGS_UCS2: | |
| Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16); | |
| StringTextPtr = BlockHdr + Offset; | |
| BlockSize += Offset; | |
| CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16)); | |
| for (Index = 0; Index < StringCount; Index++) { | |
| GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize); | |
| BlockSize += StringSize; | |
| if (CurrentStringId == StringId) { | |
| ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL); | |
| *BlockType = *BlockHdr; | |
| *StringBlockAddr = BlockHdr; | |
| *StringTextOffset = StringTextPtr - BlockHdr; | |
| return EFI_SUCCESS; | |
| } | |
| StringTextPtr = StringTextPtr + StringSize; | |
| CurrentStringId++; | |
| } | |
| break; | |
| case EFI_HII_SIBT_STRINGS_UCS2_FONT: | |
| Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16); | |
| StringTextPtr = BlockHdr + Offset; | |
| BlockSize += Offset; | |
| CopyMem ( | |
| &StringCount, | |
| (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)), | |
| sizeof (UINT16) | |
| ); | |
| for (Index = 0; Index < StringCount; Index++) { | |
| GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize); | |
| BlockSize += StringSize; | |
| if (CurrentStringId == StringId) { | |
| ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL); | |
| *BlockType = *BlockHdr; | |
| *StringBlockAddr = BlockHdr; | |
| *StringTextOffset = StringTextPtr - BlockHdr; | |
| return EFI_SUCCESS; | |
| } | |
| StringTextPtr = StringTextPtr + StringSize; | |
| CurrentStringId++; | |
| } | |
| break; | |
| case EFI_HII_SIBT_DUPLICATE: | |
| if (CurrentStringId == StringId) { | |
| // | |
| // Incoming StringId is an id of a duplicate string block. | |
| // Update the StringId to be the previous string block. | |
| // Go back to the header of string block to search. | |
| // | |
| CopyMem ( | |
| &StringId, | |
| BlockHdr + sizeof (EFI_HII_STRING_BLOCK), | |
| sizeof (EFI_STRING_ID) | |
| ); | |
| ASSERT (StringId != CurrentStringId); | |
| CurrentStringId = 1; | |
| BlockSize = 0; | |
| } else { | |
| BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK); | |
| CurrentStringId++; | |
| } | |
| break; | |
| case EFI_HII_SIBT_SKIP1: | |
| SkipCount = (UINT16)(*(UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK))); | |
| CurrentStringId = (UINT16)(CurrentStringId + SkipCount); | |
| BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK); | |
| break; | |
| case EFI_HII_SIBT_SKIP2: | |
| CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16)); | |
| CurrentStringId = (UINT16)(CurrentStringId + SkipCount); | |
| BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK); | |
| break; | |
| case EFI_HII_SIBT_EXT1: | |
| CopyMem ( | |
| &Length8, | |
| (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)), | |
| sizeof (UINT8) | |
| ); | |
| BlockSize += Length8; | |
| break; | |
| case EFI_HII_SIBT_EXT2: | |
| CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK)); | |
| if ((Ext2.BlockType2 == EFI_HII_SIBT_FONT) && (StringId == (EFI_STRING_ID)(-1))) { | |
| // | |
| // Find the relationship between global font info and the font info of | |
| // this EFI_HII_SIBT_FONT block then backup its information in local package. | |
| // | |
| BlockHdr += sizeof (EFI_HII_SIBT_EXT2_BLOCK); | |
| CopyMem (&FontId, BlockHdr, sizeof (UINT8)); | |
| BlockHdr++; | |
| CopyMem (&FontSize, BlockHdr, sizeof (UINT16)); | |
| BlockHdr += sizeof (UINT16); | |
| CopyMem (&FontStyle, BlockHdr, sizeof (EFI_HII_FONT_STYLE)); | |
| BlockHdr += sizeof (EFI_HII_FONT_STYLE); | |
| GetUnicodeStringTextOrSize (NULL, BlockHdr, &StringSize); | |
| FontInfoSize = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + StringSize; | |
| FontInfo = (EFI_FONT_INFO *)AllocateZeroPool (FontInfoSize); | |
| if (FontInfo == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| FontInfo->FontStyle = FontStyle; | |
| FontInfo->FontSize = FontSize; | |
| CopyMem (FontInfo->FontName, BlockHdr, StringSize); | |
| // | |
| // If find the corresponding global font info, save the relationship. | |
| // Otherwise ignore this EFI_HII_SIBT_FONT block. | |
| // | |
| if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont)) { | |
| ReferFontInfoLocally (Private, StringPackage, FontId, TRUE, GlobalFont, &LocalFont); | |
| } | |
| // | |
| // Since string package tool set FontId initially to 0 and increases it | |
| // progressively by one, StringPackage->FondId always represents an unique | |
| // and available FontId. | |
| // | |
| StringPackage->FontId++; | |
| FreePool (FontInfo); | |
| } | |
| BlockSize += Ext2.Length; | |
| break; | |
| case EFI_HII_SIBT_EXT4: | |
| CopyMem ( | |
| &Length32, | |
| (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)), | |
| sizeof (UINT32) | |
| ); | |
| BlockSize += Length32; | |
| break; | |
| default: | |
| break; | |
| } | |
| if ((StringId > 0) && (StringId != (EFI_STRING_ID)(-1))) { | |
| ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL); | |
| *BlockType = *BlockHdr; | |
| *StringBlockAddr = BlockHdr; | |
| *StringTextOffset = Offset; | |
| if (StringId == CurrentStringId - 1) { | |
| // | |
| // if only one skip item, return EFI_NOT_FOUND. | |
| // | |
| if ((*BlockType == EFI_HII_SIBT_SKIP2) || (*BlockType == EFI_HII_SIBT_SKIP1)) { | |
| return EFI_NOT_FOUND; | |
| } else { | |
| return EFI_SUCCESS; | |
| } | |
| } | |
| if (StringId < CurrentStringId - 1) { | |
| return EFI_NOT_FOUND; | |
| } | |
| } | |
| BlockHdr = StringPackage->StringBlock + BlockSize; | |
| if (StartStringId != NULL) { | |
| *StartStringId = CurrentStringId; | |
| } | |
| } | |
| // | |
| // Get last string ID | |
| // | |
| if ((StringId == (EFI_STRING_ID)(-1)) && (LastStringId != NULL)) { | |
| *LastStringId = (EFI_STRING_ID)(CurrentStringId - 1); | |
| return EFI_SUCCESS; | |
| } | |
| return EFI_NOT_FOUND; | |
| } | |
| /** | |
| Parse all string blocks to get a string specified by StringId. | |
| This is a internal function. | |
| @param Private Hii database private structure. | |
| @param StringPackage Hii string package instance. | |
| @param StringId The string's id, which is unique within | |
| PackageList. | |
| @param String Points to retrieved null-terminated string. | |
| @param StringSize On entry, points to the size of the buffer pointed | |
| to by String, in bytes. On return, points to the | |
| length of the string, in bytes. | |
| @param StringFontInfo If not NULL, allocate a buffer to record the | |
| output font info. It's caller's responsibility to | |
| free this buffer. | |
| @retval EFI_SUCCESS The string text and font is retrieved | |
| successfully. | |
| @retval EFI_NOT_FOUND The specified text or font info can not be found | |
| out. | |
| @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to | |
| hold the string. | |
| **/ | |
| EFI_STATUS | |
| GetStringWorker ( | |
| IN HII_DATABASE_PRIVATE_DATA *Private, | |
| IN HII_STRING_PACKAGE_INSTANCE *StringPackage, | |
| IN EFI_STRING_ID StringId, | |
| OUT EFI_STRING String, | |
| IN OUT UINTN *StringSize OPTIONAL, | |
| OUT EFI_FONT_INFO **StringFontInfo OPTIONAL | |
| ) | |
| { | |
| UINT8 *StringTextPtr; | |
| UINT8 BlockType; | |
| UINT8 *StringBlockAddr; | |
| UINTN StringTextOffset; | |
| EFI_STATUS Status; | |
| UINT8 FontId; | |
| ASSERT (StringPackage != NULL); | |
| ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE); | |
| // | |
| // Find the specified string block | |
| // | |
| Status = FindStringBlock ( | |
| Private, | |
| StringPackage, | |
| StringId, | |
| &BlockType, | |
| &StringBlockAddr, | |
| &StringTextOffset, | |
| NULL, | |
| NULL | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| if (StringSize == NULL) { | |
| // | |
| // String text buffer is not requested | |
| // | |
| return EFI_SUCCESS; | |
| } | |
| // | |
| // Get the string text. | |
| // | |
| StringTextPtr = StringBlockAddr + StringTextOffset; | |
| switch (BlockType) { | |
| case EFI_HII_SIBT_STRING_SCSU: | |
| case EFI_HII_SIBT_STRING_SCSU_FONT: | |
| case EFI_HII_SIBT_STRINGS_SCSU: | |
| case EFI_HII_SIBT_STRINGS_SCSU_FONT: | |
| Status = ConvertToUnicodeText (String, (CHAR8 *)StringTextPtr, StringSize); | |
| break; | |
| case EFI_HII_SIBT_STRING_UCS2: | |
| case EFI_HII_SIBT_STRING_UCS2_FONT: | |
| case EFI_HII_SIBT_STRINGS_UCS2: | |
| case EFI_HII_SIBT_STRINGS_UCS2_FONT: | |
| Status = GetUnicodeStringTextOrSize (String, StringTextPtr, StringSize); | |
| break; | |
| default: | |
| return EFI_NOT_FOUND; | |
| } | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // Get the string font. The FontId 0 is the default font for those string blocks which | |
| // do not specify a font identifier. If default font is not specified, return NULL. | |
| // | |
| if (StringFontInfo != NULL) { | |
| switch (BlockType) { | |
| case EFI_HII_SIBT_STRING_SCSU_FONT: | |
| case EFI_HII_SIBT_STRINGS_SCSU_FONT: | |
| case EFI_HII_SIBT_STRING_UCS2_FONT: | |
| case EFI_HII_SIBT_STRINGS_UCS2_FONT: | |
| FontId = *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK)); | |
| break; | |
| default: | |
| FontId = 0; | |
| } | |
| Status = GetStringFontInfo (StringPackage, FontId, StringFontInfo); | |
| if (Status == EFI_NOT_FOUND) { | |
| *StringFontInfo = NULL; | |
| } | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| If GetStringBlock find the StringId's string is not saved in the exist string block, | |
| this function will create the UCS2 string block to save the string; also split the | |
| skip block into two or one skip block. | |
| This is a internal function. | |
| @param StringPackage Hii string package instance. | |
| @param StartStringId The first id in the skip block which StringId in the block. | |
| @param StringId The string's id, which is unique within | |
| PackageList. | |
| @param BlockType Output the block type of found string block. | |
| @param StringBlockAddr Output the block address of found string block. | |
| @param FontBlock whether this string block has font info. | |
| @retval EFI_SUCCESS The string font is outputted successfully. | |
| @retval EFI_OUT_OF_RESOURCES NO resource for the memory to save the new string block. | |
| **/ | |
| EFI_STATUS | |
| InsertLackStringBlock ( | |
| IN OUT HII_STRING_PACKAGE_INSTANCE *StringPackage, | |
| IN EFI_STRING_ID StartStringId, | |
| IN EFI_STRING_ID StringId, | |
| IN OUT UINT8 *BlockType, | |
| IN OUT UINT8 **StringBlockAddr, | |
| IN BOOLEAN FontBlock | |
| ) | |
| { | |
| UINT8 *BlockPtr; | |
| UINT8 *StringBlock; | |
| UINT32 SkipLen; | |
| UINT32 OldBlockSize; | |
| UINT32 NewBlockSize; | |
| UINT32 FrontSkipNum; | |
| UINT32 NewUCSBlockLen; | |
| UINT8 *OldStringAddr; | |
| UINT32 IdCount; | |
| FrontSkipNum = 0; | |
| SkipLen = 0; | |
| OldStringAddr = *StringBlockAddr; | |
| ASSERT (*BlockType == EFI_HII_SIBT_SKIP1 || *BlockType == EFI_HII_SIBT_SKIP2); | |
| // | |
| // Old skip block size. | |
| // | |
| if (*BlockType == EFI_HII_SIBT_SKIP1) { | |
| SkipLen = sizeof (EFI_HII_SIBT_SKIP1_BLOCK); | |
| IdCount = *(UINT8 *)(OldStringAddr + sizeof (EFI_HII_STRING_BLOCK)); | |
| } else { | |
| SkipLen = sizeof (EFI_HII_SIBT_SKIP2_BLOCK); | |
| IdCount = *(UINT16 *)(OldStringAddr + sizeof (EFI_HII_STRING_BLOCK)); | |
| } | |
| // | |
| // New create UCS or UCS2 block size. | |
| // | |
| if (FontBlock) { | |
| NewUCSBlockLen = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK); | |
| } else { | |
| NewUCSBlockLen = sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK); | |
| } | |
| OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize; | |
| if (StartStringId == StringId) { | |
| // | |
| // New block + [Skip block] | |
| // | |
| if (IdCount > 1) { | |
| NewBlockSize = OldBlockSize + NewUCSBlockLen; | |
| } else { | |
| NewBlockSize = OldBlockSize + NewUCSBlockLen - SkipLen; | |
| } | |
| } else if (StartStringId + IdCount - 1 == StringId) { | |
| // | |
| // Skip block + New block | |
| // | |
| NewBlockSize = OldBlockSize + NewUCSBlockLen; | |
| FrontSkipNum = StringId - StartStringId; | |
| } else { | |
| // | |
| // Skip block + New block + [Skip block] | |
| // | |
| NewBlockSize = OldBlockSize + NewUCSBlockLen + SkipLen; | |
| FrontSkipNum = StringId - StartStringId; | |
| } | |
| StringBlock = (UINT8 *)AllocateZeroPool (NewBlockSize); | |
| if (StringBlock == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| // | |
| // Copy old block in front of skip block. | |
| // | |
| CopyMem (StringBlock, StringPackage->StringBlock, OldStringAddr - StringPackage->StringBlock); | |
| BlockPtr = StringBlock + (OldStringAddr - StringPackage->StringBlock); | |
| if (FrontSkipNum > 0) { | |
| *BlockPtr = *BlockType; | |
| if (*BlockType == EFI_HII_SIBT_SKIP1) { | |
| *(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT8)FrontSkipNum; | |
| } else { | |
| *(UINT16 *)(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT16)FrontSkipNum; | |
| } | |
| BlockPtr += SkipLen; | |
| } | |
| // | |
| // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK | |
| // | |
| *StringBlockAddr = BlockPtr; | |
| if (FontBlock) { | |
| *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT; | |
| } else { | |
| *BlockPtr = EFI_HII_SIBT_STRING_UCS2; | |
| } | |
| BlockPtr += NewUCSBlockLen; | |
| if (IdCount > FrontSkipNum + 1) { | |
| *BlockPtr = *BlockType; | |
| if (*BlockType == EFI_HII_SIBT_SKIP1) { | |
| *(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT8)(IdCount - FrontSkipNum - 1); | |
| } else { | |
| *(UINT16 *)(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT16)(IdCount - FrontSkipNum - 1); | |
| } | |
| BlockPtr += SkipLen; | |
| } | |
| // | |
| // Append a EFI_HII_SIBT_END block to the end. | |
| // | |
| CopyMem (BlockPtr, OldStringAddr + SkipLen, OldBlockSize - (OldStringAddr - StringPackage->StringBlock) - SkipLen); | |
| if (FontBlock) { | |
| *BlockType = EFI_HII_SIBT_STRING_UCS2_FONT; | |
| } else { | |
| *BlockType = EFI_HII_SIBT_STRING_UCS2; | |
| } | |
| FreePool (StringPackage->StringBlock); | |
| StringPackage->StringBlock = StringBlock; | |
| StringPackage->StringPkgHdr->Header.Length += NewBlockSize - OldBlockSize; | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Parse all string blocks to set a String specified by StringId. | |
| This is a internal function. | |
| @param Private HII database driver private structure. | |
| @param StringPackage HII string package instance. | |
| @param StringId The string's id, which is unique within | |
| PackageList. | |
| @param String Points to the new null-terminated string. | |
| @param StringFontInfo Points to the input font info. | |
| @retval EFI_SUCCESS The string was updated successfully. | |
| @retval EFI_NOT_FOUND The string specified by StringId is not in the | |
| database. | |
| @retval EFI_INVALID_PARAMETER The String or Language was NULL. | |
| @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in | |
| current database. | |
| @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the | |
| task. | |
| **/ | |
| EFI_STATUS | |
| SetStringWorker ( | |
| IN HII_DATABASE_PRIVATE_DATA *Private, | |
| IN OUT HII_STRING_PACKAGE_INSTANCE *StringPackage, | |
| IN EFI_STRING_ID StringId, | |
| IN EFI_STRING String, | |
| IN EFI_FONT_INFO *StringFontInfo OPTIONAL | |
| ) | |
| { | |
| UINT8 *StringTextPtr; | |
| UINT8 BlockType; | |
| UINT8 *StringBlockAddr; | |
| UINTN StringTextOffset; | |
| EFI_STATUS Status; | |
| UINT8 *Block; | |
| UINT8 *BlockPtr; | |
| UINTN BlockSize; | |
| UINTN OldBlockSize; | |
| HII_FONT_INFO *LocalFont; | |
| HII_GLOBAL_FONT_INFO *GlobalFont; | |
| BOOLEAN Referred; | |
| EFI_HII_SIBT_EXT2_BLOCK Ext2; | |
| UINTN StringSize; | |
| UINTN TmpSize; | |
| EFI_STRING_ID StartStringId; | |
| StartStringId = 0; | |
| StringSize = 0; | |
| ASSERT (Private != NULL && StringPackage != NULL && String != NULL); | |
| ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE); | |
| // | |
| // Find the specified string block | |
| // | |
| Status = FindStringBlock ( | |
| Private, | |
| StringPackage, | |
| StringId, | |
| &BlockType, | |
| &StringBlockAddr, | |
| &StringTextOffset, | |
| NULL, | |
| &StartStringId | |
| ); | |
| if (EFI_ERROR (Status) && ((BlockType == EFI_HII_SIBT_SKIP1) || (BlockType == EFI_HII_SIBT_SKIP2))) { | |
| Status = InsertLackStringBlock ( | |
| StringPackage, | |
| StartStringId, | |
| StringId, | |
| &BlockType, | |
| &StringBlockAddr, | |
| (BOOLEAN)(StringFontInfo != NULL) | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| if (StringFontInfo != NULL) { | |
| StringTextOffset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16); | |
| } else { | |
| StringTextOffset = sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16); | |
| } | |
| } | |
| LocalFont = NULL; | |
| GlobalFont = NULL; | |
| Referred = FALSE; | |
| // | |
| // The input StringFontInfo should exist in current database if specified. | |
| // | |
| if (StringFontInfo != NULL) { | |
| if (!IsFontInfoExisted (Private, StringFontInfo, NULL, NULL, &GlobalFont)) { | |
| return EFI_INVALID_PARAMETER; | |
| } else { | |
| Referred = ReferFontInfoLocally ( | |
| Private, | |
| StringPackage, | |
| StringPackage->FontId, | |
| FALSE, | |
| GlobalFont, | |
| &LocalFont | |
| ); | |
| if (!Referred) { | |
| StringPackage->FontId++; | |
| } | |
| } | |
| // | |
| // Update the FontId of the specified string block to input font info. | |
| // | |
| switch (BlockType) { | |
| case EFI_HII_SIBT_STRING_SCSU_FONT: | |
| case EFI_HII_SIBT_STRINGS_SCSU_FONT: | |
| case EFI_HII_SIBT_STRING_UCS2_FONT: | |
| case EFI_HII_SIBT_STRINGS_UCS2_FONT: | |
| *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK)) = LocalFont->FontId; | |
| break; | |
| default: | |
| // | |
| // When modify the font info of these blocks, the block type should be updated | |
| // to contain font info thus the whole structure should be revised. | |
| // It is recommended to use tool to modify the block type not in the code. | |
| // | |
| return EFI_UNSUPPORTED; | |
| } | |
| } | |
| OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize; | |
| // | |
| // Set the string text and font. | |
| // | |
| StringTextPtr = StringBlockAddr + StringTextOffset; | |
| switch (BlockType) { | |
| case EFI_HII_SIBT_STRING_SCSU: | |
| case EFI_HII_SIBT_STRING_SCSU_FONT: | |
| case EFI_HII_SIBT_STRINGS_SCSU: | |
| case EFI_HII_SIBT_STRINGS_SCSU_FONT: | |
| BlockSize = OldBlockSize + StrLen (String); | |
| BlockSize -= AsciiStrSize ((CHAR8 *)StringTextPtr); | |
| Block = AllocateZeroPool (BlockSize); | |
| if (Block == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock); | |
| BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock); | |
| while (*String != 0) { | |
| *BlockPtr++ = (CHAR8)*String++; | |
| } | |
| *BlockPtr++ = 0; | |
| TmpSize = OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - AsciiStrSize ((CHAR8 *)StringTextPtr); | |
| CopyMem ( | |
| BlockPtr, | |
| StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr), | |
| TmpSize | |
| ); | |
| ZeroMem (StringPackage->StringBlock, OldBlockSize); | |
| FreePool (StringPackage->StringBlock); | |
| StringPackage->StringBlock = Block; | |
| StringPackage->StringPkgHdr->Header.Length += (UINT32)(BlockSize - OldBlockSize); | |
| break; | |
| case EFI_HII_SIBT_STRING_UCS2: | |
| case EFI_HII_SIBT_STRING_UCS2_FONT: | |
| case EFI_HII_SIBT_STRINGS_UCS2: | |
| case EFI_HII_SIBT_STRINGS_UCS2_FONT: | |
| // | |
| // Use StrSize to store the size of the specified string, including the NULL | |
| // terminator. | |
| // | |
| GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize); | |
| BlockSize = OldBlockSize + StrSize (String) - StringSize; | |
| Block = AllocateZeroPool (BlockSize); | |
| if (Block == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock); | |
| BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock); | |
| CopyMem (BlockPtr, String, StrSize (String)); | |
| BlockPtr += StrSize (String); | |
| CopyMem ( | |
| BlockPtr, | |
| StringTextPtr + StringSize, | |
| OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - StringSize | |
| ); | |
| ZeroMem (StringPackage->StringBlock, OldBlockSize); | |
| FreePool (StringPackage->StringBlock); | |
| StringPackage->StringBlock = Block; | |
| StringPackage->StringPkgHdr->Header.Length += (UINT32)(BlockSize - OldBlockSize); | |
| break; | |
| default: | |
| return EFI_NOT_FOUND; | |
| } | |
| // | |
| // Insert a new EFI_HII_SIBT_FONT_BLOCK to the header of string block, if incoming | |
| // StringFontInfo does not exist in current string package. | |
| // | |
| // This new block does not impact on the value of StringId. | |
| // | |
| // | |
| if ((StringFontInfo == NULL) || Referred) { | |
| return EFI_SUCCESS; | |
| } | |
| OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize; | |
| BlockSize = OldBlockSize + sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16) + | |
| StrSize (GlobalFont->FontInfo->FontName); | |
| Block = AllocateZeroPool (BlockSize); | |
| if (Block == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| BlockPtr = Block; | |
| Ext2.Header.BlockType = EFI_HII_SIBT_EXT2; | |
| Ext2.BlockType2 = EFI_HII_SIBT_FONT; | |
| Ext2.Length = (UINT16)(BlockSize - OldBlockSize); | |
| CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK)); | |
| BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK); | |
| *BlockPtr = LocalFont->FontId; | |
| BlockPtr++; | |
| CopyMem (BlockPtr, &GlobalFont->FontInfo->FontSize, sizeof (UINT16)); | |
| BlockPtr += sizeof (UINT16); | |
| CopyMem (BlockPtr, &GlobalFont->FontInfo->FontStyle, sizeof (UINT32)); | |
| BlockPtr += sizeof (UINT32); | |
| CopyMem ( | |
| BlockPtr, | |
| GlobalFont->FontInfo->FontName, | |
| StrSize (GlobalFont->FontInfo->FontName) | |
| ); | |
| BlockPtr += StrSize (GlobalFont->FontInfo->FontName); | |
| CopyMem (BlockPtr, StringPackage->StringBlock, OldBlockSize); | |
| ZeroMem (StringPackage->StringBlock, OldBlockSize); | |
| FreePool (StringPackage->StringBlock); | |
| StringPackage->StringBlock = Block; | |
| StringPackage->StringPkgHdr->Header.Length += Ext2.Length; | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| This function adds the string String to the group of strings owned by PackageList, with the | |
| specified font information StringFontInfo and returns a new string id. | |
| The new string identifier is guaranteed to be unique within the package list. | |
| That new string identifier is reserved for all languages in the package list. | |
| @param This A pointer to the EFI_HII_STRING_PROTOCOL instance. | |
| @param PackageList Handle of the package list where this string will | |
| be added. | |
| @param StringId On return, contains the new strings id, which is | |
| unique within PackageList. | |
| @param Language Points to the language for the new string. | |
| @param LanguageName Points to the printable language name to associate | |
| with the passed in Language field.If LanguageName | |
| is not NULL and the string package header's | |
| LanguageName associated with a given Language is | |
| not zero, the LanguageName being passed in will | |
| be ignored. | |
| @param String Points to the new null-terminated string. | |
| @param StringFontInfo Points to the new string's font information or | |
| NULL if the string should have the default system | |
| font, size and style. | |
| @retval EFI_SUCCESS The new string was added successfully. | |
| @retval EFI_NOT_FOUND The specified PackageList could not be found in | |
| database. | |
| @retval EFI_OUT_OF_RESOURCES Could not add the string due to lack of resources. | |
| @retval EFI_INVALID_PARAMETER String is NULL or StringId is NULL or Language is | |
| NULL. | |
| @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in | |
| current database. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| HiiNewString ( | |
| IN CONST EFI_HII_STRING_PROTOCOL *This, | |
| IN EFI_HII_HANDLE PackageList, | |
| OUT EFI_STRING_ID *StringId, | |
| IN CONST CHAR8 *Language, | |
| IN CONST CHAR16 *LanguageName OPTIONAL, | |
| IN CONST EFI_STRING String, | |
| IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| LIST_ENTRY *Link; | |
| HII_DATABASE_PRIVATE_DATA *Private; | |
| HII_DATABASE_RECORD *DatabaseRecord; | |
| HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode; | |
| HII_STRING_PACKAGE_INSTANCE *StringPackage; | |
| UINT32 HeaderSize; | |
| UINT32 BlockSize; | |
| UINT32 OldBlockSize; | |
| UINT8 *StringBlock; | |
| UINT8 *BlockPtr; | |
| UINT32 Ucs2BlockSize; | |
| UINT32 FontBlockSize; | |
| UINT32 Ucs2FontBlockSize; | |
| EFI_HII_SIBT_EXT2_BLOCK Ext2; | |
| HII_FONT_INFO *LocalFont; | |
| HII_GLOBAL_FONT_INFO *GlobalFont; | |
| EFI_STRING_ID NewStringId; | |
| EFI_STRING_ID NextStringId; | |
| EFI_STRING_ID Index; | |
| HII_STRING_PACKAGE_INSTANCE *MatchStringPackage; | |
| BOOLEAN NewStringPackageCreated; | |
| if ((This == NULL) || (String == NULL) || (StringId == NULL) || (Language == NULL) || (PackageList == NULL)) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| if (!IsHiiHandleValid (PackageList)) { | |
| return EFI_NOT_FOUND; | |
| } | |
| Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This); | |
| GlobalFont = NULL; | |
| // | |
| // If StringFontInfo specify a paritcular font, it should exist in current database. | |
| // | |
| if (StringFontInfo != NULL) { | |
| if (!IsFontInfoExisted (Private, (EFI_FONT_INFO *)StringFontInfo, NULL, NULL, &GlobalFont)) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| } | |
| // | |
| // Get the matching package list. | |
| // | |
| PackageListNode = NULL; | |
| for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) { | |
| DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE); | |
| if (DatabaseRecord->Handle == PackageList) { | |
| PackageListNode = DatabaseRecord->PackageList; | |
| break; | |
| } | |
| } | |
| if (PackageListNode == NULL) { | |
| return EFI_NOT_FOUND; | |
| } | |
| EfiAcquireLock (&mHiiDatabaseLock); | |
| Status = EFI_SUCCESS; | |
| NewStringPackageCreated = FALSE; | |
| NewStringId = 0; | |
| NextStringId = 0; | |
| StringPackage = NULL; | |
| MatchStringPackage = NULL; | |
| for (Link = PackageListNode->StringPkgHdr.ForwardLink; | |
| Link != &PackageListNode->StringPkgHdr; | |
| Link = Link->ForwardLink | |
| ) | |
| { | |
| StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE); | |
| // | |
| // Create a string block and corresponding font block if exists, then append them | |
| // to the end of the string package. | |
| // | |
| Status = FindStringBlock ( | |
| Private, | |
| StringPackage, | |
| 0, | |
| NULL, | |
| NULL, | |
| NULL, | |
| &NextStringId, | |
| NULL | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| goto Done; | |
| } | |
| // | |
| // Make sure that new StringId is same in all String Packages for the different language. | |
| // | |
| if ((NewStringId != 0) && (NewStringId != NextStringId)) { | |
| ASSERT (FALSE); | |
| Status = EFI_INVALID_PARAMETER; | |
| goto Done; | |
| } | |
| NewStringId = NextStringId; | |
| // | |
| // Get the matched string package with language. | |
| // | |
| if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *)Language)) { | |
| MatchStringPackage = StringPackage; | |
| } else { | |
| OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize; | |
| // | |
| // Create a blank EFI_HII_SIBT_STRING_UCS2_BLOCK to reserve new string ID. | |
| // | |
| Ucs2BlockSize = (UINT32)sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK); | |
| StringBlock = (UINT8 *)AllocateZeroPool (OldBlockSize + Ucs2BlockSize); | |
| if (StringBlock == NULL) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto Done; | |
| } | |
| // | |
| // Copy original string blocks, except the EFI_HII_SIBT_END. | |
| // | |
| CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK)); | |
| // | |
| // Create a blank EFI_HII_SIBT_STRING_UCS2 block | |
| // | |
| BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK); | |
| *BlockPtr = EFI_HII_SIBT_STRING_UCS2; | |
| BlockPtr += sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK); | |
| // | |
| // Append a EFI_HII_SIBT_END block to the end. | |
| // | |
| *BlockPtr = EFI_HII_SIBT_END; | |
| ZeroMem (StringPackage->StringBlock, OldBlockSize); | |
| FreePool (StringPackage->StringBlock); | |
| StringPackage->StringBlock = StringBlock; | |
| StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize; | |
| PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize; | |
| } | |
| } | |
| if (NewStringId == 0) { | |
| // | |
| // No string package is found. | |
| // Create new string package. StringId 1 is reserved for Language Name string. | |
| // | |
| *StringId = 2; | |
| } else { | |
| // | |
| // Set new StringId | |
| // | |
| *StringId = (EFI_STRING_ID)(NewStringId + 1); | |
| } | |
| if (MatchStringPackage != NULL) { | |
| StringPackage = MatchStringPackage; | |
| } else { | |
| // | |
| // LanguageName is required to create a new string package. | |
| // | |
| if (LanguageName == NULL) { | |
| Status = EFI_INVALID_PARAMETER; | |
| goto Done; | |
| } | |
| StringPackage = AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE)); | |
| if (StringPackage == NULL) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto Done; | |
| } | |
| StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE; | |
| StringPackage->MaxStringId = *StringId; | |
| StringPackage->FontId = 0; | |
| InitializeListHead (&StringPackage->FontInfoList); | |
| // | |
| // Fill in the string package header | |
| // | |
| HeaderSize = (UINT32)(AsciiStrSize ((CHAR8 *)Language) - 1 + sizeof (EFI_HII_STRING_PACKAGE_HDR)); | |
| StringPackage->StringPkgHdr = AllocateZeroPool (HeaderSize); | |
| if (StringPackage->StringPkgHdr == NULL) { | |
| FreePool (StringPackage); | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto Done; | |
| } | |
| StringPackage->StringPkgHdr->Header.Type = EFI_HII_PACKAGE_STRINGS; | |
| StringPackage->StringPkgHdr->HdrSize = HeaderSize; | |
| StringPackage->StringPkgHdr->StringInfoOffset = HeaderSize; | |
| CopyMem (StringPackage->StringPkgHdr->LanguageWindow, mLanguageWindow, 16 * sizeof (CHAR16)); | |
| StringPackage->StringPkgHdr->LanguageName = 1; | |
| AsciiStrCpyS (StringPackage->StringPkgHdr->Language, (HeaderSize - OFFSET_OF (EFI_HII_STRING_PACKAGE_HDR, Language)) / sizeof (CHAR8), (CHAR8 *)Language); | |
| // | |
| // Calculate the length of the string blocks, including string block to record | |
| // printable language full name and EFI_HII_SIBT_END_BLOCK. | |
| // | |
| Ucs2BlockSize = (UINT32)(StrSize ((CHAR16 *)LanguageName) + | |
| (*StringId - 1) * sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16)); | |
| BlockSize = Ucs2BlockSize + sizeof (EFI_HII_SIBT_END_BLOCK); | |
| StringPackage->StringBlock = (UINT8 *)AllocateZeroPool (BlockSize); | |
| if (StringPackage->StringBlock == NULL) { | |
| FreePool (StringPackage->StringPkgHdr); | |
| FreePool (StringPackage); | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto Done; | |
| } | |
| // | |
| // Insert the string block of printable language full name | |
| // | |
| BlockPtr = StringPackage->StringBlock; | |
| *BlockPtr = EFI_HII_SIBT_STRING_UCS2; | |
| BlockPtr += sizeof (EFI_HII_STRING_BLOCK); | |
| CopyMem (BlockPtr, (EFI_STRING)LanguageName, StrSize ((EFI_STRING)LanguageName)); | |
| BlockPtr += StrSize ((EFI_STRING)LanguageName); | |
| for (Index = 2; Index <= *StringId - 1; Index++) { | |
| *BlockPtr = EFI_HII_SIBT_STRING_UCS2; | |
| BlockPtr += sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK); | |
| } | |
| // | |
| // Insert the end block | |
| // | |
| *BlockPtr = EFI_HII_SIBT_END; | |
| // | |
| // Append this string package node to string package array in this package list. | |
| // | |
| StringPackage->StringPkgHdr->Header.Length = HeaderSize + BlockSize; | |
| PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length; | |
| InsertTailList (&PackageListNode->StringPkgHdr, &StringPackage->StringEntry); | |
| NewStringPackageCreated = TRUE; | |
| } | |
| OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize; | |
| if (StringFontInfo == NULL) { | |
| // | |
| // Create a EFI_HII_SIBT_STRING_UCS2_BLOCK since font info is not specified. | |
| // | |
| Ucs2BlockSize = (UINT32)(StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) | |
| - sizeof (CHAR16)); | |
| StringBlock = (UINT8 *)AllocateZeroPool (OldBlockSize + Ucs2BlockSize); | |
| if (StringBlock == NULL) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto Done; | |
| } | |
| // | |
| // Copy original string blocks, except the EFI_HII_SIBT_END. | |
| // | |
| CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK)); | |
| // | |
| // Create a EFI_HII_SIBT_STRING_UCS2 block | |
| // | |
| BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK); | |
| *BlockPtr = EFI_HII_SIBT_STRING_UCS2; | |
| BlockPtr += sizeof (EFI_HII_STRING_BLOCK); | |
| CopyMem (BlockPtr, (EFI_STRING)String, StrSize ((EFI_STRING)String)); | |
| BlockPtr += StrSize ((EFI_STRING)String); | |
| // | |
| // Append a EFI_HII_SIBT_END block to the end. | |
| // | |
| *BlockPtr = EFI_HII_SIBT_END; | |
| ZeroMem (StringPackage->StringBlock, OldBlockSize); | |
| FreePool (StringPackage->StringBlock); | |
| StringPackage->StringBlock = StringBlock; | |
| StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize; | |
| PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize; | |
| } else { | |
| // | |
| // StringFontInfo is specified here. If there is a EFI_HII_SIBT_FONT_BLOCK | |
| // which refers to this font info, create a EFI_HII_SIBT_STRING_UCS2_FONT block | |
| // only. Otherwise create a EFI_HII_SIBT_FONT block with a EFI_HII_SIBT_STRING | |
| // _UCS2_FONT block. | |
| // | |
| Ucs2FontBlockSize = (UINT32)(StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - | |
| sizeof (CHAR16)); | |
| if (ReferFontInfoLocally (Private, StringPackage, StringPackage->FontId, FALSE, GlobalFont, &LocalFont)) { | |
| // | |
| // Create a EFI_HII_SIBT_STRING_UCS2_FONT block only. | |
| // | |
| StringBlock = (UINT8 *)AllocateZeroPool (OldBlockSize + Ucs2FontBlockSize); | |
| if (StringBlock == NULL) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto Done; | |
| } | |
| // | |
| // Copy original string blocks, except the EFI_HII_SIBT_END. | |
| // | |
| CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK)); | |
| // | |
| // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK | |
| // | |
| BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK); | |
| *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT; | |
| BlockPtr += sizeof (EFI_HII_STRING_BLOCK); | |
| *BlockPtr = LocalFont->FontId; | |
| BlockPtr++; | |
| CopyMem (BlockPtr, (EFI_STRING)String, StrSize ((EFI_STRING)String)); | |
| BlockPtr += StrSize ((EFI_STRING)String); | |
| // | |
| // Append a EFI_HII_SIBT_END block to the end. | |
| // | |
| *BlockPtr = EFI_HII_SIBT_END; | |
| ZeroMem (StringPackage->StringBlock, OldBlockSize); | |
| FreePool (StringPackage->StringBlock); | |
| StringPackage->StringBlock = StringBlock; | |
| StringPackage->StringPkgHdr->Header.Length += Ucs2FontBlockSize; | |
| PackageListNode->PackageListHdr.PackageLength += Ucs2FontBlockSize; | |
| } else { | |
| // | |
| // EFI_HII_SIBT_FONT_BLOCK does not exist in current string package, so | |
| // create a EFI_HII_SIBT_FONT block to record the font info, then generate | |
| // a EFI_HII_SIBT_STRING_UCS2_FONT block to record the incoming string. | |
| // | |
| FontBlockSize = (UINT32)(StrSize (((EFI_FONT_INFO *)StringFontInfo)->FontName) + | |
| sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16)); | |
| StringBlock = (UINT8 *)AllocateZeroPool (OldBlockSize + FontBlockSize + Ucs2FontBlockSize); | |
| if (StringBlock == NULL) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto Done; | |
| } | |
| // | |
| // Copy original string blocks, except the EFI_HII_SIBT_END. | |
| // | |
| CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK)); | |
| // | |
| // Create a EFI_HII_SIBT_FONT block firstly and then backup its info in string | |
| // package instance for future reference. | |
| // | |
| BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK); | |
| Ext2.Header.BlockType = EFI_HII_SIBT_EXT2; | |
| Ext2.BlockType2 = EFI_HII_SIBT_FONT; | |
| Ext2.Length = (UINT16)FontBlockSize; | |
| CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK)); | |
| BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK); | |
| *BlockPtr = LocalFont->FontId; | |
| BlockPtr++; | |
| CopyMem (BlockPtr, &((EFI_FONT_INFO *)StringFontInfo)->FontSize, sizeof (UINT16)); | |
| BlockPtr += sizeof (UINT16); | |
| CopyMem (BlockPtr, &((EFI_FONT_INFO *)StringFontInfo)->FontStyle, sizeof (EFI_HII_FONT_STYLE)); | |
| BlockPtr += sizeof (EFI_HII_FONT_STYLE); | |
| CopyMem ( | |
| BlockPtr, | |
| &((EFI_FONT_INFO *)StringFontInfo)->FontName, | |
| StrSize (((EFI_FONT_INFO *)StringFontInfo)->FontName) | |
| ); | |
| BlockPtr += StrSize (((EFI_FONT_INFO *)StringFontInfo)->FontName); | |
| // | |
| // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK | |
| // | |
| *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT; | |
| BlockPtr += sizeof (EFI_HII_STRING_BLOCK); | |
| *BlockPtr = LocalFont->FontId; | |
| BlockPtr++; | |
| CopyMem (BlockPtr, (EFI_STRING)String, StrSize ((EFI_STRING)String)); | |
| BlockPtr += StrSize ((EFI_STRING)String); | |
| // | |
| // Append a EFI_HII_SIBT_END block to the end. | |
| // | |
| *BlockPtr = EFI_HII_SIBT_END; | |
| ZeroMem (StringPackage->StringBlock, OldBlockSize); | |
| FreePool (StringPackage->StringBlock); | |
| StringPackage->StringBlock = StringBlock; | |
| StringPackage->StringPkgHdr->Header.Length += FontBlockSize + Ucs2FontBlockSize; | |
| PackageListNode->PackageListHdr.PackageLength += FontBlockSize + Ucs2FontBlockSize; | |
| // | |
| // Increase the FontId to make it unique since we already add | |
| // a EFI_HII_SIBT_FONT block to this string package. | |
| // | |
| StringPackage->FontId++; | |
| } | |
| } | |
| Done: | |
| if (!EFI_ERROR (Status) && NewStringPackageCreated) { | |
| // | |
| // Trigger any registered notification function for new string package | |
| // | |
| Status = InvokeRegisteredFunction ( | |
| Private, | |
| EFI_HII_DATABASE_NOTIFY_NEW_PACK, | |
| (VOID *)StringPackage, | |
| EFI_HII_PACKAGE_STRINGS, | |
| PackageList | |
| ); | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| // | |
| // Update MaxString Id to new StringId | |
| // | |
| for (Link = PackageListNode->StringPkgHdr.ForwardLink; | |
| Link != &PackageListNode->StringPkgHdr; | |
| Link = Link->ForwardLink | |
| ) | |
| { | |
| StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE); | |
| StringPackage->MaxStringId = *StringId; | |
| } | |
| } else if (NewStringPackageCreated) { | |
| // | |
| // Free the allocated new string Package when new string can't be added. | |
| // | |
| RemoveEntryList (&StringPackage->StringEntry); | |
| FreePool (StringPackage->StringBlock); | |
| FreePool (StringPackage->StringPkgHdr); | |
| FreePool (StringPackage); | |
| } | |
| // | |
| // The contents of HiiDataBase may updated,need to check. | |
| // | |
| // | |
| // Check whether need to get the contents of HiiDataBase. | |
| // Only after ReadyToBoot to do the export. | |
| // | |
| if (gExportAfterReadyToBoot) { | |
| if (!EFI_ERROR (Status)) { | |
| HiiGetDatabaseInfo (&Private->HiiDatabase); | |
| } | |
| } | |
| EfiReleaseLock (&mHiiDatabaseLock); | |
| return Status; | |
| } | |
| /** | |
| This function retrieves the string specified by StringId which is associated | |
| with the specified PackageList in the language Language and copies it into | |
| the buffer specified by String. | |
| @param This A pointer to the EFI_HII_STRING_PROTOCOL instance. | |
| @param Language Points to the language for the retrieved string. | |
| @param PackageList The package list in the HII database to search for | |
| the specified string. | |
| @param StringId The string's id, which is unique within | |
| PackageList. | |
| @param String Points to the new null-terminated string. | |
| @param StringSize On entry, points to the size of the buffer pointed | |
| to by String, in bytes. On return, points to the | |
| length of the string, in bytes. | |
| @param StringFontInfo If not NULL, points to the string's font | |
| information. It's caller's responsibility to free | |
| this buffer. | |
| @retval EFI_SUCCESS The string was returned successfully. | |
| @retval EFI_NOT_FOUND The string specified by StringId is not available. | |
| @retval EFI_NOT_FOUND The string specified by StringId is available but | |
| not in the specified language. | |
| The specified PackageList is not in the database. | |
| @retval EFI_INVALID_LANGUAGE - The string specified by StringId is available but | |
| @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to | |
| hold the string. | |
| @retval EFI_INVALID_PARAMETER The Language or StringSize was NULL. | |
| @retval EFI_INVALID_PARAMETER The value referenced by StringSize was not zero and String was NULL. | |
| @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the | |
| request. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| HiiGetString ( | |
| IN CONST EFI_HII_STRING_PROTOCOL *This, | |
| IN CONST CHAR8 *Language, | |
| IN EFI_HII_HANDLE PackageList, | |
| IN EFI_STRING_ID StringId, | |
| OUT EFI_STRING String, | |
| IN OUT UINTN *StringSize, | |
| OUT EFI_FONT_INFO **StringFontInfo OPTIONAL | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| LIST_ENTRY *Link; | |
| HII_DATABASE_PRIVATE_DATA *Private; | |
| HII_DATABASE_RECORD *DatabaseRecord; | |
| HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode; | |
| HII_STRING_PACKAGE_INSTANCE *StringPackage; | |
| if ((This == NULL) || (Language == NULL) || (StringId < 1) || (StringSize == NULL) || (PackageList == NULL)) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| if ((String == NULL) && (*StringSize != 0)) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| if (!IsHiiHandleValid (PackageList)) { | |
| return EFI_NOT_FOUND; | |
| } | |
| Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This); | |
| PackageListNode = NULL; | |
| for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) { | |
| DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE); | |
| if (DatabaseRecord->Handle == PackageList) { | |
| PackageListNode = DatabaseRecord->PackageList; | |
| break; | |
| } | |
| } | |
| if (PackageListNode != NULL) { | |
| // | |
| // First search: to match the StringId in the specified language. | |
| // | |
| for (Link = PackageListNode->StringPkgHdr.ForwardLink; | |
| Link != &PackageListNode->StringPkgHdr; | |
| Link = Link->ForwardLink | |
| ) | |
| { | |
| StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE); | |
| if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *)Language)) { | |
| Status = GetStringWorker (Private, StringPackage, StringId, String, StringSize, StringFontInfo); | |
| if (Status != EFI_NOT_FOUND) { | |
| return Status; | |
| } | |
| } | |
| } | |
| // | |
| // Second search: to match the StringId in other available languages if exist. | |
| // | |
| for (Link = PackageListNode->StringPkgHdr.ForwardLink; | |
| Link != &PackageListNode->StringPkgHdr; | |
| Link = Link->ForwardLink | |
| ) | |
| { | |
| StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE); | |
| Status = GetStringWorker (Private, StringPackage, StringId, NULL, NULL, NULL); | |
| if (!EFI_ERROR (Status)) { | |
| return EFI_INVALID_LANGUAGE; | |
| } | |
| } | |
| } | |
| return EFI_NOT_FOUND; | |
| } | |
| /** | |
| This function updates the string specified by StringId in the specified PackageList to the text | |
| specified by String and, optionally, the font information specified by StringFontInfo. | |
| @param This A pointer to the EFI_HII_STRING_PROTOCOL instance. | |
| @param PackageList The package list containing the strings. | |
| @param StringId The string's id, which is unique within | |
| PackageList. | |
| @param Language Points to the language for the updated string. | |
| @param String Points to the new null-terminated string. | |
| @param StringFontInfo Points to the string's font information or NULL if | |
| the string font information is not changed. | |
| @retval EFI_SUCCESS The string was updated successfully. | |
| @retval EFI_NOT_FOUND The string specified by StringId is not in the | |
| database. | |
| @retval EFI_INVALID_PARAMETER The String or Language was NULL. | |
| @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in | |
| current database. | |
| @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the | |
| task. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| HiiSetString ( | |
| IN CONST EFI_HII_STRING_PROTOCOL *This, | |
| IN EFI_HII_HANDLE PackageList, | |
| IN EFI_STRING_ID StringId, | |
| IN CONST CHAR8 *Language, | |
| IN CONST EFI_STRING String, | |
| IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| LIST_ENTRY *Link; | |
| HII_DATABASE_PRIVATE_DATA *Private; | |
| HII_DATABASE_RECORD *DatabaseRecord; | |
| HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode; | |
| HII_STRING_PACKAGE_INSTANCE *StringPackage; | |
| UINT32 OldPackageLen; | |
| if ((This == NULL) || (Language == NULL) || (StringId < 1) || (String == NULL) || (PackageList == NULL)) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| if (!IsHiiHandleValid (PackageList)) { | |
| return EFI_NOT_FOUND; | |
| } | |
| EfiAcquireLock (&mHiiDatabaseLock); | |
| Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This); | |
| PackageListNode = NULL; | |
| for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) { | |
| DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE); | |
| if (DatabaseRecord->Handle == PackageList) { | |
| PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(DatabaseRecord->PackageList); | |
| } | |
| } | |
| if (PackageListNode != NULL) { | |
| for (Link = PackageListNode->StringPkgHdr.ForwardLink; | |
| Link != &PackageListNode->StringPkgHdr; | |
| Link = Link->ForwardLink | |
| ) | |
| { | |
| StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE); | |
| if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *)Language)) { | |
| OldPackageLen = StringPackage->StringPkgHdr->Header.Length; | |
| Status = SetStringWorker ( | |
| Private, | |
| StringPackage, | |
| StringId, | |
| (EFI_STRING)String, | |
| (EFI_FONT_INFO *)StringFontInfo | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| EfiReleaseLock (&mHiiDatabaseLock); | |
| return Status; | |
| } | |
| PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length - OldPackageLen; | |
| // | |
| // Check whether need to get the contents of HiiDataBase. | |
| // Only after ReadyToBoot to do the export. | |
| // | |
| if (gExportAfterReadyToBoot) { | |
| HiiGetDatabaseInfo (&Private->HiiDatabase); | |
| } | |
| EfiReleaseLock (&mHiiDatabaseLock); | |
| return EFI_SUCCESS; | |
| } | |
| } | |
| } | |
| EfiReleaseLock (&mHiiDatabaseLock); | |
| return EFI_NOT_FOUND; | |
| } | |
| /** | |
| This function returns the list of supported languages, in the format specified | |
| in Appendix M of UEFI 2.1 spec. | |
| @param This A pointer to the EFI_HII_STRING_PROTOCOL instance. | |
| @param PackageList The package list to examine. | |
| @param Languages Points to the buffer to hold the returned | |
| null-terminated ASCII string. | |
| @param LanguagesSize On entry, points to the size of the buffer pointed | |
| to by Languages, in bytes. On return, points to | |
| the length of Languages, in bytes. | |
| @retval EFI_SUCCESS The languages were returned successfully. | |
| @retval EFI_INVALID_PARAMETER The LanguagesSize was NULL. | |
| @retval EFI_INVALID_PARAMETER The value referenced by LanguagesSize is not zero and Languages is NULL. | |
| @retval EFI_BUFFER_TOO_SMALL The LanguagesSize is too small to hold the list of | |
| supported languages. LanguageSize is updated to | |
| contain the required size. | |
| @retval EFI_NOT_FOUND Could not find string package in specified | |
| packagelist. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| HiiGetLanguages ( | |
| IN CONST EFI_HII_STRING_PROTOCOL *This, | |
| IN EFI_HII_HANDLE PackageList, | |
| IN OUT CHAR8 *Languages, | |
| IN OUT UINTN *LanguagesSize | |
| ) | |
| { | |
| LIST_ENTRY *Link; | |
| HII_DATABASE_PRIVATE_DATA *Private; | |
| HII_DATABASE_RECORD *DatabaseRecord; | |
| HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode; | |
| HII_STRING_PACKAGE_INSTANCE *StringPackage; | |
| UINTN ResultSize; | |
| if ((This == NULL) || (LanguagesSize == NULL) || (PackageList == NULL)) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| if ((*LanguagesSize != 0) && (Languages == NULL)) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| if (!IsHiiHandleValid (PackageList)) { | |
| return EFI_NOT_FOUND; | |
| } | |
| Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This); | |
| PackageListNode = NULL; | |
| for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) { | |
| DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE); | |
| if (DatabaseRecord->Handle == PackageList) { | |
| PackageListNode = DatabaseRecord->PackageList; | |
| break; | |
| } | |
| } | |
| if (PackageListNode == NULL) { | |
| return EFI_NOT_FOUND; | |
| } | |
| // | |
| // Search the languages in the specified packagelist. | |
| // | |
| ResultSize = 0; | |
| for (Link = PackageListNode->StringPkgHdr.ForwardLink; | |
| Link != &PackageListNode->StringPkgHdr; | |
| Link = Link->ForwardLink | |
| ) | |
| { | |
| StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE); | |
| ResultSize += AsciiStrSize (StringPackage->StringPkgHdr->Language); | |
| if (ResultSize <= *LanguagesSize) { | |
| AsciiStrCpyS (Languages, *LanguagesSize / sizeof (CHAR8), StringPackage->StringPkgHdr->Language); | |
| Languages += AsciiStrSize (StringPackage->StringPkgHdr->Language); | |
| *(Languages - 1) = L';'; | |
| } | |
| } | |
| if (ResultSize == 0) { | |
| return EFI_NOT_FOUND; | |
| } | |
| if (*LanguagesSize < ResultSize) { | |
| *LanguagesSize = ResultSize; | |
| return EFI_BUFFER_TOO_SMALL; | |
| } | |
| *(Languages - 1) = 0; | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Each string package has associated with it a single primary language and zero | |
| or more secondary languages. This routine returns the secondary languages | |
| associated with a package list. | |
| @param This A pointer to the EFI_HII_STRING_PROTOCOL instance. | |
| @param PackageList The package list to examine. | |
| @param PrimaryLanguage Points to the null-terminated ASCII string that specifies | |
| the primary language. Languages are specified in the | |
| format specified in Appendix M of the UEFI 2.0 specification. | |
| @param SecondaryLanguages Points to the buffer to hold the returned null-terminated | |
| ASCII string that describes the list of | |
| secondary languages for the specified | |
| PrimaryLanguage. If there are no secondary | |
| languages, the function returns successfully, but | |
| this is set to NULL. | |
| @param SecondaryLanguagesSize On entry, points to the size of the buffer pointed | |
| to by SecondaryLanguages, in bytes. On return, | |
| points to the length of SecondaryLanguages in bytes. | |
| @retval EFI_SUCCESS Secondary languages were correctly returned. | |
| @retval EFI_INVALID_PARAMETER PrimaryLanguage or SecondaryLanguagesSize was NULL. | |
| @retval EFI_INVALID_PARAMETER The value referenced by SecondaryLanguagesSize is not | |
| zero and SecondaryLanguages is NULL. | |
| @retval EFI_BUFFER_TOO_SMALL The buffer specified by SecondaryLanguagesSize is | |
| too small to hold the returned information. | |
| SecondaryLanguageSize is updated to hold the size of | |
| the buffer required. | |
| @retval EFI_INVALID_LANGUAGE The language specified by PrimaryLanguage is not | |
| present in the specified package list. | |
| @retval EFI_NOT_FOUND The specified PackageList is not in the Database. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| HiiGetSecondaryLanguages ( | |
| IN CONST EFI_HII_STRING_PROTOCOL *This, | |
| IN EFI_HII_HANDLE PackageList, | |
| IN CONST CHAR8 *PrimaryLanguage, | |
| IN OUT CHAR8 *SecondaryLanguages, | |
| IN OUT UINTN *SecondaryLanguagesSize | |
| ) | |
| { | |
| LIST_ENTRY *Link; | |
| LIST_ENTRY *Link1; | |
| HII_DATABASE_PRIVATE_DATA *Private; | |
| HII_DATABASE_RECORD *DatabaseRecord; | |
| HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode; | |
| HII_STRING_PACKAGE_INSTANCE *StringPackage; | |
| CHAR8 *Languages; | |
| UINTN ResultSize; | |
| if ((This == NULL) || (PackageList == NULL) || (PrimaryLanguage == NULL) || (SecondaryLanguagesSize == NULL)) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| if ((SecondaryLanguages == NULL) && (*SecondaryLanguagesSize != 0)) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| if (!IsHiiHandleValid (PackageList)) { | |
| return EFI_NOT_FOUND; | |
| } | |
| Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This); | |
| PackageListNode = NULL; | |
| for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) { | |
| DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE); | |
| if (DatabaseRecord->Handle == PackageList) { | |
| PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(DatabaseRecord->PackageList); | |
| break; | |
| } | |
| } | |
| if (PackageListNode == NULL) { | |
| return EFI_NOT_FOUND; | |
| } | |
| Languages = NULL; | |
| ResultSize = 0; | |
| for (Link1 = PackageListNode->StringPkgHdr.ForwardLink; | |
| Link1 != &PackageListNode->StringPkgHdr; | |
| Link1 = Link1->ForwardLink | |
| ) | |
| { | |
| StringPackage = CR (Link1, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE); | |
| if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *)PrimaryLanguage)) { | |
| Languages = StringPackage->StringPkgHdr->Language; | |
| // | |
| // Language is a series of ';' terminated strings, first one is primary | |
| // language and following with other secondary languages or NULL if no | |
| // secondary languages any more. | |
| // | |
| Languages = AsciiStrStr (Languages, ";"); | |
| if (Languages == NULL) { | |
| break; | |
| } | |
| Languages++; | |
| ResultSize = AsciiStrSize (Languages); | |
| if (ResultSize <= *SecondaryLanguagesSize) { | |
| AsciiStrCpyS (SecondaryLanguages, *SecondaryLanguagesSize / sizeof (CHAR8), Languages); | |
| } else { | |
| *SecondaryLanguagesSize = ResultSize; | |
| return EFI_BUFFER_TOO_SMALL; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| } | |
| return EFI_INVALID_LANGUAGE; | |
| } | |
| /** | |
| Converts the ascii character of the string from uppercase to lowercase. | |
| This is a internal function. | |
| @param ConfigString String to be converted | |
| **/ | |
| VOID | |
| EFIAPI | |
| AsciiHiiToLower ( | |
| IN CHAR8 *ConfigString | |
| ) | |
| { | |
| ASSERT (ConfigString != NULL); | |
| // | |
| // Convert all hex digits in range [A-F] in the configuration header to [a-f] | |
| // | |
| for ( ; *ConfigString != '\0'; ConfigString++) { | |
| if ((*ConfigString >= 'A') && (*ConfigString <= 'Z')) { | |
| *ConfigString = (CHAR8)(*ConfigString - 'A' + 'a'); | |
| } | |
| } | |
| } | |
| /** | |
| Compare whether two names of languages are identical. | |
| @param Language1 Name of language 1 from StringPackage | |
| @param Language2 Name of language 2 to be compared with language 1. | |
| @retval TRUE same | |
| @retval FALSE not same | |
| **/ | |
| BOOLEAN | |
| HiiCompareLanguage ( | |
| IN CHAR8 *Language1, | |
| IN CHAR8 *Language2 | |
| ) | |
| { | |
| UINTN Index; | |
| UINTN StrLen; | |
| CHAR8 *Lan1; | |
| CHAR8 *Lan2; | |
| // | |
| // Convert to lower to compare. | |
| // | |
| StrLen = AsciiStrSize (Language1); | |
| Lan1 = AllocateZeroPool (StrLen); | |
| ASSERT (Lan1 != NULL); | |
| AsciiStrCpyS (Lan1, StrLen / sizeof (CHAR8), Language1); | |
| AsciiHiiToLower (Lan1); | |
| StrLen = AsciiStrSize (Language2); | |
| Lan2 = AllocateZeroPool (StrLen); | |
| ASSERT (Lan2 != NULL); | |
| AsciiStrCpyS (Lan2, StrLen / sizeof (CHAR8), Language2); | |
| AsciiHiiToLower (Lan2); | |
| // | |
| // Compare the Primary Language in Language1 to Language2 | |
| // | |
| for (Index = 0; Lan1[Index] != 0 && Lan1[Index] != ';'; Index++) { | |
| if (Lan1[Index] != Lan2[Index]) { | |
| // | |
| // Return FALSE if any characters are different. | |
| // | |
| FreePool (Lan1); | |
| FreePool (Lan2); | |
| return FALSE; | |
| } | |
| } | |
| FreePool (Lan1); | |
| FreePool (Lan2); | |
| // | |
| // Only return TRUE if Language2[Index] is a Null-terminator which means | |
| // the Primary Language in Language1 is the same length as Language2. If | |
| // Language2[Index] is not a Null-terminator, then Language2 is longer than | |
| // the Primary Language in Language1, and FALSE must be returned. | |
| // | |
| return (BOOLEAN)(Language2[Index] == 0); | |
| } |