Implementation for EFI_HII_STRING_PROTOCOL.\r
\r
\r
-Copyright (c) 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
@param StringSrc Points to current null-terminated string.\r
@param BufferSize Length of the buffer.\r
\r
- @retval EFI_SUCCESS The string text was outputed successfully.\r
+ @retval EFI_SUCCESS The string text was outputted successfully.\r
@retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string\r
text. BufferSize is updated to the required buffer\r
size.\r
@param StringSrc Points to current null-terminated string.\r
@param BufferSize Length of the buffer.\r
\r
- @retval EFI_SUCCESS The string text was outputed successfully.\r
+ @retval EFI_SUCCESS The string text was outputted successfully.\r
@retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string\r
text. BufferSize is updated to the required buffer\r
size.\r
@param StringFontInfo Buffer to record the output font info. It's\r
caller's responsibility to free this buffer.\r
\r
- @retval EFI_SUCCESS The string font is outputed successfully.\r
+ @retval EFI_SUCCESS The string font is outputted successfully.\r
@retval EFI_NOT_FOUND The specified font id does not exist.\r
\r
**/\r
/**\r
Parse all string blocks to find a String block specified by StringId.\r
If StringId = (EFI_STRING_ID) (-1), find out all EFI_HII_SIBT_FONT blocks\r
- within this string package and backup its information.\r
- If StringId = 0, output the string id of last string block (EFI_HII_SIBT_END).\r
-\r
- @param Private Hii database private structure.\r
- @param StringPackage Hii string package instance.\r
- @param StringId The string's id, which is unique within\r
- PackageList.\r
- @param BlockType Output the block type of found string block.\r
- @param StringBlockAddr Output the block address of found string block.\r
- @param StringTextOffset Offset, relative to the found block address, of\r
- the string text information.\r
- @param LastStringId Output the last string id when StringId = 0.\r
-\r
- @retval EFI_SUCCESS The string text and font is retrieved\r
- successfully.\r
- @retval EFI_NOT_FOUND The specified text or font info can not be found\r
- out.\r
- @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the\r
- task.\r
+ within this string package and backup its information. If LastStringId is\r
+ specified, the string id of last string block will also be output.\r
+ If StringId = 0, output the string id of last string block (EFI_HII_SIBT_STRING).\r
+\r
+ @param Private Hii database private structure.\r
+ @param StringPackage Hii string package instance.\r
+ @param StringId The string's id, which is unique within\r
+ PackageList.\r
+ @param BlockType Output the block type of found string block.\r
+ @param StringBlockAddr Output the block address of found string block.\r
+ @param StringTextOffset Offset, relative to the found block address, of\r
+ the string text information.\r
+ @param LastStringId Output the last string id when StringId = 0 or StringId = -1.\r
+ @param StartStringId The first id in the skip block which StringId in the block.\r
+\r
+ @retval EFI_SUCCESS The string text and font is retrieved\r
+ successfully.\r
+ @retval EFI_NOT_FOUND The specified text or font info can not be found\r
+ out.\r
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the\r
+ task.\r
\r
**/\r
EFI_STATUS\r
OUT UINT8 *BlockType, OPTIONAL\r
OUT UINT8 **StringBlockAddr, OPTIONAL\r
OUT UINTN *StringTextOffset, OPTIONAL\r
- OUT EFI_STRING_ID *LastStringId OPTIONAL\r
+ OUT EFI_STRING_ID *LastStringId, OPTIONAL\r
+ OUT EFI_STRING_ID *StartStringId OPTIONAL\r
)\r
{\r
UINT8 *BlockHdr;\r
ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);\r
\r
CurrentStringId = 1;\r
+ StringSize = 0;\r
\r
if (StringId != (EFI_STRING_ID) (-1) && StringId != 0) {\r
ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);\r
+ if (StringId > StringPackage->MaxStringId) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
} else {\r
ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);\r
+ if (StringId == 0 && LastStringId != NULL) {\r
+ *LastStringId = StringPackage->MaxStringId;\r
+ return EFI_SUCCESS;\r
+ }\r
}\r
\r
ZeroMem (&Zero, sizeof (CHAR16));\r
\r
case EFI_HII_SIBT_STRINGS_SCSU:\r
CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
- StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8);\r
+ StringTextPtr = (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8));\r
BlockSize += StringTextPtr - BlockHdr;\r
\r
for (Index = 0; Index < StringCount; Index++) {\r
BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);\r
if (CurrentStringId == StringId) {\r
+ ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);\r
*BlockType = *BlockHdr;\r
*StringBlockAddr = BlockHdr;\r
*StringTextOffset = StringTextPtr - BlockHdr;\r
case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
CopyMem (\r
&StringCount,\r
- BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),\r
+ (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
sizeof (UINT16)\r
);\r
- StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8);\r
+ StringTextPtr = (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8));\r
BlockSize += StringTextPtr - BlockHdr;\r
\r
for (Index = 0; Index < StringCount; Index++) {\r
BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);\r
if (CurrentStringId == StringId) {\r
+ ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);\r
*BlockType = *BlockHdr;\r
*StringBlockAddr = BlockHdr;\r
*StringTextOffset = StringTextPtr - BlockHdr;\r
GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);\r
BlockSize += StringSize;\r
if (CurrentStringId == StringId) {\r
+ ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);\r
*BlockType = *BlockHdr;\r
*StringBlockAddr = BlockHdr;\r
*StringTextOffset = StringTextPtr - BlockHdr;\r
BlockSize += Offset;\r
CopyMem (\r
&StringCount,\r
- BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),\r
+ (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
sizeof (UINT16)\r
);\r
for (Index = 0; Index < StringCount; Index++) {\r
GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);\r
BlockSize += StringSize;\r
if (CurrentStringId == StringId) {\r
+ ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);\r
*BlockType = *BlockHdr;\r
*StringBlockAddr = BlockHdr;\r
*StringTextOffset = StringTextPtr - BlockHdr;\r
break;\r
\r
case EFI_HII_SIBT_SKIP1:\r
- SkipCount = (UINT16) (*(BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));\r
+ SkipCount = (UINT16) (*(UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));\r
CurrentStringId = (UINT16) (CurrentStringId + SkipCount);\r
BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);\r
break;\r
case EFI_HII_SIBT_EXT1:\r
CopyMem (\r
&Length8,\r
- BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),\r
+ (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
sizeof (UINT8)\r
);\r
BlockSize += Length8;\r
//\r
BlockHdr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);\r
CopyMem (&FontId, BlockHdr, sizeof (UINT8));\r
- BlockHdr += sizeof (UINT8);\r
+ BlockHdr ++;\r
CopyMem (&FontSize, BlockHdr, sizeof (UINT16));\r
BlockHdr += sizeof (UINT16);\r
CopyMem (&FontStyle, BlockHdr, sizeof (EFI_HII_FONT_STYLE));\r
// Since string package tool set FontId initially to 0 and increases it\r
// progressively by one, StringPackage->FondId always represents an unique\r
// and available FontId.\r
- // \r
+ //\r
StringPackage->FontId++;\r
\r
FreePool (FontInfo);\r
case EFI_HII_SIBT_EXT4:\r
CopyMem (\r
&Length32,\r
- BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),\r
+ (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
sizeof (UINT32)\r
);\r
\r
break;\r
}\r
\r
- if (StringId > 0) {\r
+ if (StringId > 0 && StringId != (EFI_STRING_ID)(-1)) {\r
+ ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);\r
+ *BlockType = *BlockHdr;\r
+ *StringBlockAddr = BlockHdr;\r
+ *StringTextOffset = Offset;\r
+\r
if (StringId == CurrentStringId - 1) {\r
- *BlockType = *BlockHdr;\r
- *StringBlockAddr = BlockHdr;\r
- *StringTextOffset = Offset;\r
- return EFI_SUCCESS;\r
+ //\r
+ // if only one skip item, return EFI_NOT_FOUND.\r
+ //\r
+ if(*BlockType == EFI_HII_SIBT_SKIP2 || *BlockType == EFI_HII_SIBT_SKIP1) {\r
+ return EFI_NOT_FOUND;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
}\r
\r
if (StringId < CurrentStringId - 1) {\r
}\r
}\r
BlockHdr = StringPackage->StringBlock + BlockSize;\r
-\r
- }\r
-\r
- if (StringId == (EFI_STRING_ID) (-1)) {\r
- return EFI_SUCCESS;\r
+ if (StartStringId != NULL) {\r
+ *StartStringId = CurrentStringId;\r
+ }\r
}\r
\r
- if (StringId == 0 && LastStringId != NULL) {\r
- *LastStringId = CurrentStringId;\r
+ //\r
+ // Get last string ID\r
+ //\r
+ if (StringId == (EFI_STRING_ID) (-1) && LastStringId != NULL) {\r
+ *LastStringId = (EFI_STRING_ID) (CurrentStringId - 1);\r
return EFI_SUCCESS;\r
}\r
\r
IN HII_STRING_PACKAGE_INSTANCE *StringPackage,\r
IN EFI_STRING_ID StringId,\r
OUT EFI_STRING String,\r
- IN OUT UINTN *StringSize,\r
+ IN OUT UINTN *StringSize, OPTIONAL\r
OUT EFI_FONT_INFO **StringFontInfo OPTIONAL\r
)\r
{\r
EFI_STATUS Status;\r
UINT8 FontId;\r
\r
- ASSERT (StringPackage != NULL && StringSize != NULL);\r
+ ASSERT (StringPackage != NULL);\r
ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);\r
\r
//\r
&BlockType,\r
&StringBlockAddr,\r
&StringTextOffset,\r
+ NULL,\r
NULL\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
+ if (StringSize == NULL) {\r
+ //\r
+ // String text buffer is not requested\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
//\r
// Get the string text.\r
//\r
}\r
\r
//\r
- // Get the string font. The FontId 0 is the default font for those string blocks which \r
+ // Get the string font. The FontId 0 is the default font for those string blocks which\r
// do not specify a font identifier. If default font is not specified, return NULL.\r
//\r
if (StringFontInfo != NULL) {\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ If GetStringBlock find the StringId's string is not saved in the exist string block,\r
+ this function will create the UCS2 string block to save the string; also split the\r
+ skip block into two or one skip block.\r
+\r
+ This is a internal function.\r
+\r
+ @param StringPackage Hii string package instance.\r
+ @param StartStringId The first id in the skip block which StringId in the block.\r
+ @param StringId The string's id, which is unique within\r
+ PackageList.\r
+ @param BlockType Output the block type of found string block.\r
+ @param StringBlockAddr Output the block address of found string block.\r
+ @param FontBlock whether this string block has font info.\r
+\r
+ @retval EFI_SUCCESS The string font is outputted successfully.\r
+ @retval EFI_OUT_OF_RESOURCES NO resource for the memory to save the new string block.\r
+\r
+**/\r
+EFI_STATUS\r
+InsertLackStringBlock (\r
+ IN OUT HII_STRING_PACKAGE_INSTANCE *StringPackage,\r
+ IN EFI_STRING_ID StartStringId,\r
+ IN EFI_STRING_ID StringId,\r
+ IN OUT UINT8 *BlockType,\r
+ IN OUT UINT8 **StringBlockAddr,\r
+ IN BOOLEAN FontBlock\r
+ )\r
+{\r
+ UINT8 *BlockPtr;\r
+ UINT8 *StringBlock;\r
+ UINT32 SkipLen;\r
+ UINT32 OldBlockSize;\r
+ UINT32 NewBlockSize;\r
+ UINT32 FrontSkipNum;\r
+ UINT32 NewUCSBlockLen;\r
+ UINT8 *OldStringAddr;\r
+ UINT32 IdCount;\r
+\r
+ FrontSkipNum = 0;\r
+ SkipLen = 0;\r
+ OldStringAddr = *StringBlockAddr;\r
+\r
+ ASSERT (*BlockType == EFI_HII_SIBT_SKIP1 || *BlockType == EFI_HII_SIBT_SKIP2);\r
+ //\r
+ // Old skip block size.\r
+ //\r
+ if (*BlockType == EFI_HII_SIBT_SKIP1) {\r
+ SkipLen = sizeof (EFI_HII_SIBT_SKIP1_BLOCK);\r
+ IdCount = *(UINT8*)(OldStringAddr + sizeof (EFI_HII_STRING_BLOCK));\r
+ } else {\r
+ SkipLen = sizeof (EFI_HII_SIBT_SKIP2_BLOCK);\r
+ IdCount = *(UINT16*)(OldStringAddr + sizeof (EFI_HII_STRING_BLOCK));\r
+ }\r
+\r
+ //\r
+ // New create UCS or UCS2 block size.\r
+ //\r
+ if (FontBlock) {\r
+ NewUCSBlockLen = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK);\r
+ } else {\r
+ NewUCSBlockLen = sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);\r
+ }\r
+\r
+ OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;\r
+\r
+ if (StartStringId == StringId) {\r
+ //\r
+ // New block + [Skip block]\r
+ //\r
+ if (IdCount > 1) {\r
+ NewBlockSize = OldBlockSize + NewUCSBlockLen;\r
+ } else {\r
+ NewBlockSize = OldBlockSize + NewUCSBlockLen - SkipLen;\r
+ }\r
+ } else if (StartStringId + IdCount - 1 == StringId){\r
+ //\r
+ // Skip block + New block\r
+ //\r
+ NewBlockSize = OldBlockSize + NewUCSBlockLen;\r
+ FrontSkipNum = StringId - StartStringId;\r
+ } else {\r
+ //\r
+ // Skip block + New block + [Skip block]\r
+ //\r
+ NewBlockSize = OldBlockSize + NewUCSBlockLen + SkipLen;\r
+ FrontSkipNum = StringId - StartStringId;\r
+ }\r
+\r
+ StringBlock = (UINT8 *) AllocateZeroPool (NewBlockSize);\r
+ if (StringBlock == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Copy old block in front of skip block.\r
+ //\r
+ CopyMem (StringBlock, StringPackage->StringBlock, OldStringAddr - StringPackage->StringBlock);\r
+ BlockPtr = StringBlock + (OldStringAddr - StringPackage->StringBlock);\r
+\r
+ if (FrontSkipNum > 0) {\r
+ *BlockPtr = *BlockType;\r
+ if (*BlockType == EFI_HII_SIBT_SKIP1) {\r
+ *(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT8) FrontSkipNum;\r
+ } else {\r
+ *(UINT16 *)(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT16) FrontSkipNum;\r
+ }\r
+ BlockPtr += SkipLen;\r
+ }\r
+\r
+ //\r
+ // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK\r
+ //\r
+ *StringBlockAddr = BlockPtr;\r
+ if (FontBlock) {\r
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;\r
+ } else {\r
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2;\r
+ }\r
+ BlockPtr += NewUCSBlockLen;\r
+\r
+ if (IdCount > FrontSkipNum + 1) {\r
+ *BlockPtr = *BlockType;\r
+ if (*BlockType == EFI_HII_SIBT_SKIP1) {\r
+ *(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT8) (IdCount - FrontSkipNum - 1);\r
+ } else {\r
+ *(UINT16 *)(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT16) (IdCount - FrontSkipNum - 1);\r
+ }\r
+ BlockPtr += SkipLen;\r
+ }\r
+\r
+ //\r
+ // Append a EFI_HII_SIBT_END block to the end.\r
+ //\r
+ CopyMem (BlockPtr, OldStringAddr + SkipLen, OldBlockSize - (OldStringAddr - StringPackage->StringBlock) - SkipLen);\r
+\r
+ if (FontBlock) {\r
+ *BlockType = EFI_HII_SIBT_STRING_UCS2_FONT;\r
+ } else {\r
+ *BlockType = EFI_HII_SIBT_STRING_UCS2;\r
+ }\r
+ FreePool (StringPackage->StringBlock);\r
+ StringPackage->StringBlock = StringBlock;\r
+ StringPackage->StringPkgHdr->Header.Length += NewBlockSize - OldBlockSize;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
\r
/**\r
Parse all string blocks to set a String specified by StringId.\r
EFI_HII_SIBT_EXT2_BLOCK Ext2;\r
UINTN StringSize;\r
UINTN TmpSize;\r
+ EFI_STRING_ID StartStringId;\r
\r
-\r
+ StartStringId = 0;\r
+ StringSize = 0;\r
ASSERT (Private != NULL && StringPackage != NULL && String != NULL);\r
ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);\r
//\r
&BlockType,\r
&StringBlockAddr,\r
&StringTextOffset,\r
- NULL\r
+ NULL,\r
+ &StartStringId\r
);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ if (EFI_ERROR (Status) && (BlockType == EFI_HII_SIBT_SKIP1 || BlockType == EFI_HII_SIBT_SKIP2)) {\r
+ Status = InsertLackStringBlock(StringPackage,\r
+ StartStringId,\r
+ StringId,\r
+ &BlockType,\r
+ &StringBlockAddr,\r
+ (BOOLEAN)(StringFontInfo != NULL)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (StringFontInfo != NULL) {\r
+ StringTextOffset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);\r
+ } else {\r
+ StringTextOffset = sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16);\r
+ }\r
}\r
\r
LocalFont = NULL;\r
return EFI_INVALID_PARAMETER;\r
} else {\r
Referred = ReferFontInfoLocally (\r
- Private, \r
- StringPackage, \r
- StringPackage->FontId, \r
- FALSE, \r
- GlobalFont, \r
+ Private,\r
+ StringPackage,\r
+ StringPackage->FontId,\r
+ FALSE,\r
+ GlobalFont,\r
&LocalFont\r
);\r
if (!Referred) {\r
// Update the FontId of the specified string block to input font info.\r
//\r
switch (BlockType) {\r
- case EFI_HII_SIBT_STRING_SCSU_FONT: \r
+ case EFI_HII_SIBT_STRING_SCSU_FONT:\r
case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
case EFI_HII_SIBT_STRING_UCS2_FONT:\r
case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
// When modify the font info of these blocks, the block type should be updated\r
// to contain font info thus the whole structure should be revised.\r
// It is recommended to use tool to modify the block type not in the code.\r
- // \r
+ //\r
return EFI_UNSUPPORTED;\r
}\r
}\r
case EFI_HII_SIBT_STRINGS_SCSU:\r
case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
BlockSize = OldBlockSize + StrLen (String);\r
- BlockSize -= AsciiStrLen ((CHAR8 *) StringTextPtr);\r
+ BlockSize -= AsciiStrSize ((CHAR8 *) StringTextPtr);\r
Block = AllocateZeroPool (BlockSize);\r
if (Block == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
*BlockPtr++ = 0;\r
\r
- \r
+\r
TmpSize = OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - AsciiStrSize ((CHAR8 *) StringTextPtr);\r
CopyMem (\r
BlockPtr,\r
BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);\r
\r
*BlockPtr = LocalFont->FontId;\r
- BlockPtr += sizeof (UINT8);\r
+ BlockPtr ++;\r
CopyMem (BlockPtr, &GlobalFont->FontInfo->FontSize, sizeof (UINT16));\r
BlockPtr += sizeof (UINT16);\r
CopyMem (BlockPtr, &GlobalFont->FontInfo->FontStyle, sizeof (UINT32));\r
/**\r
This function adds the string String to the group of strings owned by PackageList, with the\r
specified font information StringFontInfo and returns a new string id.\r
+ The new string identifier is guaranteed to be unique within the package list.\r
+ That new string identifier is reserved for all languages in the package list.\r
+\r
\r
@param This A pointer to the EFI_HII_STRING_PROTOCOL instance.\r
@param PackageList Handle of the package list where this string will\r
{\r
EFI_STATUS Status;\r
LIST_ENTRY *Link;\r
- BOOLEAN Matched;\r
HII_DATABASE_PRIVATE_DATA *Private;\r
HII_DATABASE_RECORD *DatabaseRecord;\r
HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
EFI_HII_SIBT_EXT2_BLOCK Ext2;\r
HII_FONT_INFO *LocalFont;\r
HII_GLOBAL_FONT_INFO *GlobalFont;\r
+ EFI_STRING_ID NewStringId;\r
+ EFI_STRING_ID NextStringId;\r
+ EFI_STRING_ID Index;\r
+ HII_STRING_PACKAGE_INSTANCE *MatchStringPackage;\r
+ BOOLEAN NewStringPackageCreated;\r
+\r
\r
if (This == NULL || String == NULL || StringId == NULL || Language == NULL || PackageList == NULL) {\r
return EFI_INVALID_PARAMETER;\r
return EFI_NOT_FOUND;\r
}\r
\r
- //\r
- // Try to get the matching string package. Create a new string package when failed.\r
- //\r
+ EfiAcquireLock (&mHiiDatabaseLock);\r
+\r
+ Status = EFI_SUCCESS;\r
+ NewStringPackageCreated = FALSE;\r
+ NewStringId = 0;\r
+ NextStringId = 0;\r
StringPackage = NULL;\r
- Matched = FALSE;\r
+ MatchStringPackage = NULL;\r
for (Link = PackageListNode->StringPkgHdr.ForwardLink;\r
Link != &PackageListNode->StringPkgHdr;\r
Link = Link->ForwardLink\r
) {\r
StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
- if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {\r
- Matched = TRUE;\r
- break;\r
+ //\r
+ // Create a string block and corresponding font block if exists, then append them\r
+ // to the end of the string package.\r
+ //\r
+ Status = FindStringBlock (\r
+ Private,\r
+ StringPackage,\r
+ 0,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ &NextStringId,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Make sure that new StringId is same in all String Packages for the different language.\r
+ //\r
+ if (NewStringId != 0 && NewStringId != NextStringId) {\r
+ ASSERT (FALSE);\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
}\r
+ NewStringId = NextStringId;\r
+ //\r
+ // Get the matched string package with language.\r
+ //\r
+ if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {\r
+ MatchStringPackage = StringPackage;\r
+ } else {\r
+ OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;\r
+ //\r
+ // Create a blank EFI_HII_SIBT_STRING_UCS2_BLOCK to reserve new string ID.\r
+ //\r
+ Ucs2BlockSize = (UINT32) sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);\r
+\r
+ StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2BlockSize);\r
+ if (StringBlock == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Copy original string blocks, except the EFI_HII_SIBT_END.\r
+ //\r
+ CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));\r
+ //\r
+ // Create a blank EFI_HII_SIBT_STRING_UCS2 block\r
+ //\r
+ BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);\r
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2;\r
+ BlockPtr += sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);\r
+\r
+ //\r
+ // Append a EFI_HII_SIBT_END block to the end.\r
+ //\r
+ *BlockPtr = EFI_HII_SIBT_END;\r
+ FreePool (StringPackage->StringBlock);\r
+ StringPackage->StringBlock = StringBlock;\r
+ StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize;\r
+ PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize;\r
+ }\r
+ }\r
+ if (NewStringId == 0) {\r
+ //\r
+ // No string package is found.\r
+ // Create new string package. StringId 1 is reserved for Language Name string.\r
+ //\r
+ *StringId = 2;\r
+ } else {\r
+ //\r
+ // Set new StringId\r
+ //\r
+ *StringId = (EFI_STRING_ID) (NewStringId + 1);\r
}\r
\r
- if (!Matched) {\r
+ if (MatchStringPackage != NULL) {\r
+ StringPackage = MatchStringPackage;\r
+ } else {\r
//\r
// LanguageName is required to create a new string package.\r
//\r
if (LanguageName == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
}\r
\r
StringPackage = AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));\r
if (StringPackage == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
}\r
\r
- StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;\r
- StringPackage->FontId = 0;\r
+ StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;\r
+ StringPackage->MaxStringId = *StringId;\r
+ StringPackage->FontId = 0;\r
InitializeListHead (&StringPackage->FontInfoList);\r
\r
//\r
StringPackage->StringPkgHdr = AllocateZeroPool (HeaderSize);\r
if (StringPackage->StringPkgHdr == NULL) {\r
FreePool (StringPackage);\r
- return EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
}\r
StringPackage->StringPkgHdr->Header.Type = EFI_HII_PACKAGE_STRINGS;\r
StringPackage->StringPkgHdr->HdrSize = HeaderSize;\r
StringPackage->StringPkgHdr->StringInfoOffset = HeaderSize;\r
- CopyMem (StringPackage->StringPkgHdr->LanguageWindow, mLanguageWindow, 16 * sizeof (CHAR16));;\r
+ CopyMem (StringPackage->StringPkgHdr->LanguageWindow, mLanguageWindow, 16 * sizeof (CHAR16));\r
StringPackage->StringPkgHdr->LanguageName = 1;\r
- AsciiStrCpy (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language);\r
+ AsciiStrCpyS (StringPackage->StringPkgHdr->Language, (HeaderSize - OFFSET_OF(EFI_HII_STRING_PACKAGE_HDR,Language)) / sizeof (CHAR8), (CHAR8 *) Language);\r
\r
//\r
// Calculate the length of the string blocks, including string block to record\r
// printable language full name and EFI_HII_SIBT_END_BLOCK.\r
//\r
Ucs2BlockSize = (UINT32) (StrSize ((CHAR16 *) LanguageName) +\r
- sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16));\r
+ (*StringId - 1) * sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16));\r
\r
BlockSize = Ucs2BlockSize + sizeof (EFI_HII_SIBT_END_BLOCK);\r
StringPackage->StringBlock = (UINT8 *) AllocateZeroPool (BlockSize);\r
if (StringPackage->StringBlock == NULL) {\r
FreePool (StringPackage->StringPkgHdr);\r
FreePool (StringPackage);\r
- return EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
}\r
\r
//\r
BlockPtr += sizeof (EFI_HII_STRING_BLOCK);\r
CopyMem (BlockPtr, (EFI_STRING) LanguageName, StrSize ((EFI_STRING) LanguageName));\r
BlockPtr += StrSize ((EFI_STRING) LanguageName);\r
-\r
+ for (Index = 2; Index <= *StringId - 1; Index ++) {\r
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2;\r
+ BlockPtr += sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);\r
+ }\r
//\r
// Insert the end block\r
//\r
StringPackage->StringPkgHdr->Header.Length = HeaderSize + BlockSize;\r
PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;\r
InsertTailList (&PackageListNode->StringPkgHdr, &StringPackage->StringEntry);\r
-\r
- }\r
-\r
- //\r
- // Create a string block and corresponding font block if exists, then append them\r
- // to the end of the string package.\r
- //\r
- Status = FindStringBlock (\r
- Private,\r
- StringPackage,\r
- 0,\r
- NULL,\r
- NULL,\r
- NULL,\r
- StringId\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ NewStringPackageCreated = TRUE;\r
}\r
\r
OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;\r
//\r
// Create a EFI_HII_SIBT_STRING_UCS2_BLOCK since font info is not specified.\r
//\r
-\r
Ucs2BlockSize = (UINT32) (StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK)\r
- sizeof (CHAR16));\r
\r
StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2BlockSize);\r
if (StringBlock == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
}\r
//\r
// Copy original string blocks, except the EFI_HII_SIBT_END.\r
//\r
StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2FontBlockSize);\r
if (StringBlock == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
}\r
//\r
// Copy original string blocks, except the EFI_HII_SIBT_END.\r
*BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;\r
BlockPtr += sizeof (EFI_HII_STRING_BLOCK);\r
*BlockPtr = LocalFont->FontId;\r
- BlockPtr += sizeof (UINT8);\r
+ BlockPtr ++;\r
CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));\r
BlockPtr += StrSize ((EFI_STRING) String);\r
\r
sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16));\r
StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + FontBlockSize + Ucs2FontBlockSize);\r
if (StringBlock == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
}\r
//\r
// Copy original string blocks, except the EFI_HII_SIBT_END.\r
BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);\r
\r
*BlockPtr = LocalFont->FontId;\r
- BlockPtr += sizeof (UINT8);\r
+ BlockPtr ++;\r
CopyMem (BlockPtr, &((EFI_FONT_INFO *) StringFontInfo)->FontSize, sizeof (UINT16));\r
BlockPtr += sizeof (UINT16);\r
CopyMem (BlockPtr, &((EFI_FONT_INFO *) StringFontInfo)->FontStyle, sizeof (EFI_HII_FONT_STYLE));\r
&((EFI_FONT_INFO *) StringFontInfo)->FontName,\r
StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName)\r
);\r
-\r
+ BlockPtr += StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName);\r
//\r
// Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK\r
//\r
*BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;\r
BlockPtr += sizeof (EFI_HII_STRING_BLOCK);\r
*BlockPtr = LocalFont->FontId;\r
- BlockPtr += sizeof (UINT8);\r
+ BlockPtr ++;\r
CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));\r
BlockPtr += StrSize ((EFI_STRING) String);\r
\r
PackageListNode->PackageListHdr.PackageLength += FontBlockSize + Ucs2FontBlockSize;\r
\r
//\r
- // Increase the FontId to make it unique since we already add \r
+ // Increase the FontId to make it unique since we already add\r
// a EFI_HII_SIBT_FONT block to this string package.\r
//\r
StringPackage->FontId++;\r
}\r
}\r
\r
+Done:\r
+ if (!EFI_ERROR (Status) && NewStringPackageCreated) {\r
+ //\r
+ // Trigger any registered notification function for new string package\r
+ //\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ EFI_HII_DATABASE_NOTIFY_NEW_PACK,\r
+ (VOID *) StringPackage,\r
+ EFI_HII_PACKAGE_STRINGS,\r
+ PackageList\r
+ );\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Update MaxString Id to new StringId\r
+ //\r
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;\r
+ Link != &PackageListNode->StringPkgHdr;\r
+ Link = Link->ForwardLink\r
+ ) {\r
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+ StringPackage->MaxStringId = *StringId;\r
+ }\r
+ } else if (NewStringPackageCreated) {\r
+ //\r
+ // Free the allocated new string Package when new string can't be added.\r
+ //\r
+ RemoveEntryList (&StringPackage->StringEntry);\r
+ FreePool (StringPackage->StringBlock);\r
+ FreePool (StringPackage->StringPkgHdr);\r
+ FreePool (StringPackage);\r
+ }\r
//\r
- // Trigger any registered notification function\r
+ // The contents of HiiDataBase may updated,need to check.\r
//\r
- if (!Matched) { \r
- return InvokeRegisteredFunction (\r
- Private,\r
- EFI_HII_DATABASE_NOTIFY_NEW_PACK,\r
- (VOID *) StringPackage,\r
- EFI_HII_PACKAGE_STRINGS,\r
- PackageList\r
- );\r
+ //\r
+ // Check whether need to get the contents of HiiDataBase.\r
+ // Only after ReadyToBoot to do the export.\r
+ //\r
+ if (gExportAfterReadyToBoot) {\r
+ if (!EFI_ERROR (Status)) {\r
+ HiiGetDatabaseInfo(&Private->HiiDatabase);\r
+ }\r
}\r
\r
- return EFI_SUCCESS;\r
+ EfiReleaseLock (&mHiiDatabaseLock);\r
+\r
+ return Status;\r
}\r
\r
\r
@retval EFI_INVALID_LANGUAGE - The string specified by StringId is available but\r
@retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to\r
hold the string.\r
- @retval EFI_INVALID_PARAMETER The String or Language or StringSize was NULL.\r
+ @retval EFI_INVALID_PARAMETER The Language or StringSize was NULL.\r
+ @retval EFI_INVALID_PARAMETER The value referenced by StringSize was not zero and String was NULL.\r
@retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the\r
request.\r
\r
Link = Link->ForwardLink\r
) {\r
StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
- if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {\r
+ if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {\r
Status = GetStringWorker (Private, StringPackage, StringId, String, StringSize, StringFontInfo);\r
if (Status != EFI_NOT_FOUND) {\r
return Status;\r
//\r
// Second search: to match the StringId in other available languages if exist.\r
//\r
- for (Link = PackageListNode->StringPkgHdr.ForwardLink; \r
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;\r
Link != &PackageListNode->StringPkgHdr;\r
Link = Link->ForwardLink\r
) {\r
- StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE); \r
- Status = GetStringWorker (Private, StringPackage, StringId, String, StringSize, StringFontInfo);\r
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+ Status = GetStringWorker (Private, StringPackage, StringId, NULL, NULL, NULL);\r
if (!EFI_ERROR (Status)) {\r
return EFI_INVALID_LANGUAGE;\r
}\r
- } \r
+ }\r
}\r
\r
return EFI_NOT_FOUND;\r
return EFI_NOT_FOUND;\r
}\r
\r
+ EfiAcquireLock (&mHiiDatabaseLock);\r
+\r
Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
PackageListNode = NULL;\r
\r
Link = Link->ForwardLink\r
) {\r
StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
- if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {\r
+ if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {\r
OldPackageLen = StringPackage->StringPkgHdr->Header.Length;\r
Status = SetStringWorker (\r
Private,\r
(EFI_FONT_INFO *) StringFontInfo\r
);\r
if (EFI_ERROR (Status)) {\r
+ EfiReleaseLock (&mHiiDatabaseLock);\r
return Status;\r
}\r
PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length - OldPackageLen;\r
+ //\r
+ // Check whether need to get the contents of HiiDataBase.\r
+ // Only after ReadyToBoot to do the export.\r
+ //\r
+ if (gExportAfterReadyToBoot) {\r
+ HiiGetDatabaseInfo(&Private->HiiDatabase);\r
+ }\r
+ EfiReleaseLock (&mHiiDatabaseLock);\r
return EFI_SUCCESS;\r
}\r
}\r
}\r
\r
+ EfiReleaseLock (&mHiiDatabaseLock);\r
return EFI_NOT_FOUND;\r
}\r
\r
\r
@param This A pointer to the EFI_HII_STRING_PROTOCOL instance.\r
@param PackageList The package list to examine.\r
- @param Languages Points to the buffer to hold the returned string.\r
+ @param Languages Points to the buffer to hold the returned\r
+ null-terminated ASCII string.\r
@param LanguagesSize On entry, points to the size of the buffer pointed\r
to by Languages, in bytes. On return, points to\r
the length of Languages, in bytes.\r
\r
@retval EFI_SUCCESS The languages were returned successfully.\r
- @retval EFI_INVALID_PARAMETER The Languages or LanguagesSize was NULL.\r
+ @retval EFI_INVALID_PARAMETER The LanguagesSize was NULL.\r
+ @retval EFI_INVALID_PARAMETER The value referenced by LanguagesSize is not zero and Languages is NULL.\r
@retval EFI_BUFFER_TOO_SMALL The LanguagesSize is too small to hold the list of\r
supported languages. LanguageSize is updated to\r
contain the required size.\r
HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
UINTN ResultSize;\r
\r
- if (This == NULL || Languages == NULL || LanguagesSize == NULL || PackageList == NULL) {\r
+ if (This == NULL || LanguagesSize == NULL || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (*LanguagesSize != 0 && Languages == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
if (!IsHiiHandleValid (PackageList)) {\r
StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
ResultSize += AsciiStrSize (StringPackage->StringPkgHdr->Language);\r
if (ResultSize <= *LanguagesSize) {\r
- AsciiStrCpy (Languages, StringPackage->StringPkgHdr->Language);\r
+ AsciiStrCpyS (Languages, *LanguagesSize / sizeof (CHAR8), StringPackage->StringPkgHdr->Language);\r
Languages += AsciiStrSize (StringPackage->StringPkgHdr->Language);\r
*(Languages - 1) = L';';\r
}\r
\r
@param This A pointer to the EFI_HII_STRING_PROTOCOL instance.\r
@param PackageList The package list to examine.\r
- @param FirstLanguage Points to the primary language.\r
- @param SecondaryLanguages Points to the buffer to hold the returned list of\r
+ @param PrimaryLanguage Points to the null-terminated ASCII string that specifies\r
+ the primary language. Languages are specified in the\r
+ format specified in Appendix M of the UEFI 2.0 specification.\r
+ @param SecondaryLanguages Points to the buffer to hold the returned null-terminated\r
+ ASCII string that describes the list of\r
secondary languages for the specified\r
- FirstLanguage. If there are no secondary\r
- languages, the function returns successfully, but\r
+ PrimaryLanguage. If there are no secondary\r
+ languages, the function returns successfully, but\r
this is set to NULL.\r
@param SecondaryLanguagesSize On entry, points to the size of the buffer pointed\r
- to by SecondaryLanguages, in bytes. On return,\r
+ to by SecondaryLanguages, in bytes. On return,\r
points to the length of SecondaryLanguages in bytes.\r
\r
@retval EFI_SUCCESS Secondary languages were correctly returned.\r
- @retval EFI_INVALID_PARAMETER FirstLanguage or SecondaryLanguages or\r
- SecondaryLanguagesSize was NULL.\r
+ @retval EFI_INVALID_PARAMETER PrimaryLanguage or SecondaryLanguagesSize was NULL.\r
+ @retval EFI_INVALID_PARAMETER The value referenced by SecondaryLanguagesSize is not\r
+ zero and SecondaryLanguages is NULL.\r
@retval EFI_BUFFER_TOO_SMALL The buffer specified by SecondaryLanguagesSize is\r
too small to hold the returned information.\r
- SecondLanguageSize is updated to hold the size of\r
+ SecondaryLanguageSize is updated to hold the size of\r
the buffer required.\r
- @retval EFI_INVALID_LANGUAGE The language specified by FirstLanguage is not\r
- present in the specified package list.\r
- @retval EFI_NOT_FOUND The specified PackageList is not in the Database. \r
+ @retval EFI_INVALID_LANGUAGE The language specified by PrimaryLanguage is not\r
+ present in the specified package list.\r
+ @retval EFI_NOT_FOUND The specified PackageList is not in the Database.\r
\r
**/\r
EFI_STATUS\r
HiiGetSecondaryLanguages (\r
IN CONST EFI_HII_STRING_PROTOCOL *This,\r
IN EFI_HII_HANDLE PackageList,\r
- IN CONST CHAR8 *FirstLanguage,\r
+ IN CONST CHAR8 *PrimaryLanguage,\r
IN OUT CHAR8 *SecondaryLanguages,\r
IN OUT UINTN *SecondaryLanguagesSize\r
)\r
CHAR8 *Languages;\r
UINTN ResultSize;\r
\r
- if (This == NULL || PackageList == NULL || FirstLanguage == NULL) {\r
+ if (This == NULL || PackageList == NULL || PrimaryLanguage == NULL || SecondaryLanguagesSize == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- if (SecondaryLanguages == NULL || SecondaryLanguagesSize == NULL) {\r
+ if (SecondaryLanguages == NULL && *SecondaryLanguagesSize != 0) {\r
return EFI_INVALID_PARAMETER;\r
}\r
if (!IsHiiHandleValid (PackageList)) {\r
\r
Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
\r
- PackageListNode = NULL; \r
+ PackageListNode = NULL;\r
for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
if (DatabaseRecord->Handle == PackageList) {\r
if (PackageListNode == NULL) {\r
return EFI_NOT_FOUND;\r
}\r
- \r
+\r
Languages = NULL;\r
ResultSize = 0;\r
for (Link1 = PackageListNode->StringPkgHdr.ForwardLink;\r
Link1 = Link1->ForwardLink\r
) {\r
StringPackage = CR (Link1, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
- if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) FirstLanguage)) {\r
+ if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) PrimaryLanguage)) {\r
Languages = StringPackage->StringPkgHdr->Language;\r
//\r
// Language is a series of ';' terminated strings, first one is primary\r
\r
ResultSize = AsciiStrSize (Languages);\r
if (ResultSize <= *SecondaryLanguagesSize) {\r
- AsciiStrCpy (SecondaryLanguages, Languages);\r
+ AsciiStrCpyS (SecondaryLanguages, *SecondaryLanguagesSize / sizeof (CHAR8), Languages);\r
} else {\r
*SecondaryLanguagesSize = ResultSize;\r
return EFI_BUFFER_TOO_SMALL;\r
return EFI_INVALID_LANGUAGE;\r
}\r
\r
+/**\r
+ Converts the ascii character of the string from uppercase to lowercase.\r
+ This is a internal function.\r
+\r
+ @param ConfigString String to be converted\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+AsciiHiiToLower (\r
+ IN CHAR8 *ConfigString\r
+ )\r
+{\r
+ ASSERT (ConfigString != NULL);\r
+\r
+ //\r
+ // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
+ //\r
+ for (; *ConfigString != '\0'; ConfigString++) {\r
+ if ( *ConfigString >= 'A' && *ConfigString <= 'Z') {\r
+ *ConfigString = (CHAR8) (*ConfigString - 'A' + 'a');\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Compare whether two names of languages are identical.\r
+\r
+ @param Language1 Name of language 1 from StringPackage\r
+ @param Language2 Name of language 2 to be compared with language 1.\r
+\r
+ @retval TRUE same\r
+ @retval FALSE not same\r
+\r
+**/\r
+BOOLEAN\r
+HiiCompareLanguage (\r
+ IN CHAR8 *Language1,\r
+ IN CHAR8 *Language2\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN StrLen;\r
+ CHAR8 *Lan1;\r
+ CHAR8 *Lan2;\r
+\r
+ //\r
+ // Convert to lower to compare.\r
+ //\r
+ StrLen = AsciiStrSize (Language1);\r
+ Lan1 = AllocateZeroPool (StrLen);\r
+ ASSERT (Lan1 != NULL);\r
+ AsciiStrCpyS(Lan1, StrLen / sizeof (CHAR8), Language1);\r
+ AsciiHiiToLower (Lan1);\r
+\r
+ StrLen = AsciiStrSize (Language2);\r
+ Lan2 = AllocateZeroPool (StrLen);\r
+ ASSERT (Lan2 != NULL);\r
+ AsciiStrCpyS(Lan2, StrLen / sizeof (CHAR8), Language2);\r
+ AsciiHiiToLower (Lan2);\r
+\r
+ //\r
+ // Compare the Primary Language in Language1 to Language2\r
+ //\r
+ for (Index = 0; Lan1[Index] != 0 && Lan1[Index] != ';'; Index++) {\r
+ if (Lan1[Index] != Lan2[Index]) {\r
+ //\r
+ // Return FALSE if any characters are different.\r
+ //\r
+ FreePool (Lan1);\r
+ FreePool (Lan2);\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ FreePool (Lan1);\r
+ FreePool (Lan2);\r
+\r
+ //\r
+ // Only return TRUE if Language2[Index] is a Null-terminator which means\r
+ // the Primary Language in Language1 is the same length as Language2. If\r
+ // Language2[Index] is not a Null-terminator, then Language2 is longer than\r
+ // the Primary Language in Language1, and FALSE must be returned.\r
+ //\r
+ return (BOOLEAN) (Language2[Index] == 0);\r
+}\r