/** @file | |
Implementation for EFI_HII_STRING_PROTOCOL. | |
Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR> | |
This program and the accompanying materials | |
are licensed and made available under the terms and conditions of the BSD License | |
which accompanies this distribution. The full text of the license may be found at | |
http://opensource.org/licenses/bsd-license.php | |
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
**/ | |
#include "HiiDatabase.h" | |
CHAR16 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 outputed 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 outputed 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 outputed 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; | |
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 outputed 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 | |
); | |
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 | |
); | |
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); | |
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; | |
} | |
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; | |
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; | |
AsciiStrCpy (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language); | |
// | |
// Calculate the length of the string blocks, including string block to record | |
// printable language full name and EFI_HII_SIBT_END_BLOCK. | |
// | |
Ucs2BlockSize = (UINT32) (StrSize ((CHAR16 *) LanguageName) + | |
(*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; | |
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; | |
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; | |
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); | |
} | |
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; | |
} | |
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)) { | |
return Status; | |
} | |
PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length - OldPackageLen; | |
return EFI_SUCCESS; | |
} | |
} | |
} | |
return EFI_NOT_FOUND; | |
} | |
/** | |
This function returns the list of supported languages, in the format specified | |
in Appendix M of UEFI 2.1 spec. | |
@param This A pointer to the EFI_HII_STRING_PROTOCOL instance. | |
@param PackageList The package list to examine. | |
@param Languages Points to the buffer to hold the returned | |
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) { | |
AsciiStrCpy (Languages, StringPackage->StringPkgHdr->Language); | |
Languages += AsciiStrSize (StringPackage->StringPkgHdr->Language); | |
*(Languages - 1) = L';'; | |
} | |
} | |
if (ResultSize == 0) { | |
return EFI_NOT_FOUND; | |
} | |
if (*LanguagesSize < ResultSize) { | |
*LanguagesSize = ResultSize; | |
return EFI_BUFFER_TOO_SMALL; | |
} | |
*(Languages - 1) = 0; | |
return EFI_SUCCESS; | |
} | |
/** | |
Each string package has associated with it a single primary language and zero | |
or more secondary languages. This routine returns the secondary languages | |
associated with a package list. | |
@param This A pointer to the EFI_HII_STRING_PROTOCOL instance. | |
@param PackageList The package list to examine. | |
@param 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) { | |
AsciiStrCpy (SecondaryLanguages, 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); | |
AsciiStrCpy(Lan1, Language1); | |
AsciiHiiToLower (Lan1); | |
StrLen = AsciiStrSize (Language2); | |
Lan2 = AllocateZeroPool (StrLen); | |
ASSERT (Lan2 != NULL); | |
AsciiStrCpy(Lan2, 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); | |
} |