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