]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/HiiDatabaseDxe/String.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / String.c
index f6a4cdf02d028b2dd05c894487d645ac88f0c732..505e063d49c39dbda15a86ca578b7fd9b16be48d 100644 (file)
@@ -1,24 +1,10 @@
 /** @file\r
+Implementation for EFI_HII_STRING_PROTOCOL.\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
-\r
-Module Name:\r
-\r
-    String.c\r
-\r
-Abstract:\r
-\r
-    Implementation for EFI_HII_STRING_PROTOCOL.\r
-\r
-Revision History\r
 \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
@@ -38,6 +24,9 @@ CHAR16 mLanguageWindow[16] = {
   font info list or not. (i.e. HII_FONT_INFO is generated.) If not, create\r
   a HII_FONT_INFO to refer it locally.\r
 \r
+  This is a internal function.\r
+\r
+\r
   @param  Private                Hii database private structure.\r
   @param  StringPackage          HII string package instance.\r
   @param  FontId                Font identifer, which must be unique within the string package.\r
@@ -53,7 +42,6 @@ CHAR16 mLanguageWindow[16] = {
   @retval FALSE                  Not referred before calling this function.\r
 \r
 **/\r
-STATIC\r
 BOOLEAN\r
 ReferFontInfoLocally (\r
   IN  HII_DATABASE_PRIVATE_DATA   *Private,\r
@@ -104,17 +92,20 @@ ReferFontInfoLocally (
 /**\r
   Convert Ascii string text to unicode string test.\r
 \r
-  @param  StringSrc              Points to current null-terminated Ascii string.\r
-  @param  StringDest             Buffer to store the converted string text.\r
+  This is a internal function.\r
+\r
+\r
+  @param  StringDest             Buffer to store the string text. If it is NULL,\r
+                                 only the size will be returned.\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
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 ConvertToUnicodeText (\r
   OUT EFI_STRING       StringDest,\r
@@ -128,7 +119,7 @@ ConvertToUnicodeText (
   ASSERT (StringSrc != NULL && BufferSize != NULL);\r
 \r
   StringSize = AsciiStrSize (StringSrc) * 2;\r
-  if (*BufferSize < StringSize) {\r
+  if (*BufferSize < StringSize || StringDest == NULL) {\r
     *BufferSize = StringSize;\r
     return EFI_BUFFER_TOO_SMALL;\r
   }\r
@@ -146,17 +137,19 @@ ConvertToUnicodeText (
   Calculate the size of StringSrc and output it. If StringDest is not NULL,\r
   copy string text from src to dest.\r
 \r
+  This is a internal function.\r
+\r
+  @param  StringDest             Buffer to store the string text. If it is NULL,\r
+                                 only the size will be returned.\r
   @param  StringSrc              Points to current null-terminated string.\r
-  @param  StringDest             Buffer to store the string text.\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
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 GetUnicodeStringTextOrSize (\r
   OUT EFI_STRING       StringDest, OPTIONAL\r
@@ -165,15 +158,13 @@ GetUnicodeStringTextOrSize (
   )\r
 {\r
   UINTN  StringSize;\r
-  CHAR16 Zero;\r
   UINT8  *StringPtr;\r
 \r
   ASSERT (StringSrc != NULL && BufferSize != NULL);\r
 \r
-  ZeroMem (&Zero, sizeof (CHAR16));\r
   StringSize = sizeof (CHAR16);\r
   StringPtr  = StringSrc;\r
-  while (CompareMem (StringPtr, &Zero, sizeof (CHAR16)) != 0) {\r
+  while (ReadUnaligned16 ((UINT16 *) StringPtr) != 0) {\r
     StringSize += sizeof (CHAR16);\r
     StringPtr += sizeof (CHAR16);\r
   }\r
@@ -194,17 +185,18 @@ GetUnicodeStringTextOrSize (
 /**\r
   Copy string font info to a buffer.\r
 \r
+  This is a internal function.\r
+\r
   @param  StringPackage          Hii string package instance.\r
   @param  FontId                 Font identifier which is unique in a string\r
                                  package.\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
-STATIC\r
 EFI_STATUS\r
 GetStringFontInfo (\r
   IN  HII_STRING_PACKAGE_INSTANCE     *StringPackage,\r
@@ -238,25 +230,27 @@ GetStringFontInfo (
 /**\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
@@ -267,7 +261,8 @@ FindStringBlock (
   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
@@ -295,11 +290,19 @@ FindStringBlock (
   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
@@ -328,12 +331,13 @@ FindStringBlock (
 \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
@@ -347,15 +351,16 @@ FindStringBlock (
     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
@@ -399,6 +404,7 @@ FindStringBlock (
         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
@@ -415,13 +421,14 @@ FindStringBlock (
       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
@@ -454,7 +461,7 @@ FindStringBlock (
       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
@@ -468,7 +475,7 @@ FindStringBlock (
     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
@@ -483,7 +490,7 @@ FindStringBlock (
         //\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
@@ -511,10 +518,10 @@ FindStringBlock (
         // 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
-        SafeFreePool (FontInfo);\r
+        FreePool (FontInfo);\r
       }\r
 \r
       BlockSize += Ext2.Length;\r
@@ -524,7 +531,7 @@ FindStringBlock (
     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
@@ -535,12 +542,21 @@ FindStringBlock (
       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
@@ -548,15 +564,16 @@ FindStringBlock (
       }\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
@@ -567,6 +584,8 @@ FindStringBlock (
 /**\r
   Parse all string blocks to get a string specified by StringId.\r
 \r
+  This is a internal function.\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
@@ -587,14 +606,13 @@ FindStringBlock (
                                  hold the string.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 GetStringWorker (\r
   IN HII_DATABASE_PRIVATE_DATA        *Private,\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
@@ -605,7 +623,7 @@ GetStringWorker (
   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
@@ -618,12 +636,20 @@ GetStringWorker (
              &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
@@ -649,7 +675,7 @@ GetStringWorker (
   }\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
@@ -672,10 +698,159 @@ GetStringWorker (
   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
 \r
+  This is a internal function.\r
+\r
   @param  Private                HII database driver private structure.\r
   @param  StringPackage          HII string package instance.\r
   @param  StringId               The string's id, which is unique within\r
@@ -693,7 +868,6 @@ GetStringWorker (
                                  task.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 SetStringWorker (\r
   IN  HII_DATABASE_PRIVATE_DATA       *Private,\r
@@ -718,8 +892,10 @@ SetStringWorker (
   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
@@ -732,10 +908,25 @@ SetStringWorker (
              &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
@@ -750,11 +941,11 @@ SetStringWorker (
       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
@@ -765,7 +956,7 @@ SetStringWorker (
     // 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
@@ -776,7 +967,7 @@ SetStringWorker (
       // 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
@@ -793,7 +984,7 @@ SetStringWorker (
   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
@@ -807,7 +998,7 @@ SetStringWorker (
     }\r
     *BlockPtr++ = 0;\r
 \r
-    \r
+\r
     TmpSize = OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - AsciiStrSize ((CHAR8 *) StringTextPtr);\r
     CopyMem (\r
       BlockPtr,\r
@@ -815,7 +1006,7 @@ SetStringWorker (
       TmpSize\r
       );\r
 \r
-    SafeFreePool (StringPackage->StringBlock);\r
+    FreePool (StringPackage->StringBlock);\r
     StringPackage->StringBlock = Block;\r
     StringPackage->StringPkgHdr->Header.Length += (UINT32) (BlockSize - OldBlockSize);\r
     break;\r
@@ -848,7 +1039,7 @@ SetStringWorker (
       OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - StringSize\r
       );\r
 \r
-    SafeFreePool (StringPackage->StringBlock);\r
+    FreePool (StringPackage->StringBlock);\r
     StringPackage->StringBlock = Block;\r
     StringPackage->StringPkgHdr->Header.Length += (UINT32) (BlockSize - OldBlockSize);\r
     break;\r
@@ -885,7 +1076,7 @@ SetStringWorker (
   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
@@ -899,7 +1090,7 @@ SetStringWorker (
 \r
   CopyMem (BlockPtr, StringPackage->StringBlock, OldBlockSize);\r
 \r
-  SafeFreePool (StringPackage->StringBlock);\r
+  FreePool (StringPackage->StringBlock);\r
   StringPackage->StringBlock = Block;\r
   StringPackage->StringPkgHdr->Header.Length += Ext2.Length;\r
 \r
@@ -911,6 +1102,9 @@ SetStringWorker (
 /**\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
@@ -953,7 +1147,6 @@ HiiNewString (
 {\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
@@ -969,6 +1162,12 @@ HiiNewString (
   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
@@ -1005,37 +1204,116 @@ HiiNewString (
     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
@@ -1044,29 +1322,31 @@ HiiNewString (
     HeaderSize = (UINT32) (AsciiStrSize ((CHAR8 *) Language) - 1 + sizeof (EFI_HII_STRING_PACKAGE_HDR));\r
     StringPackage->StringPkgHdr = AllocateZeroPool (HeaderSize);\r
     if (StringPackage->StringPkgHdr == NULL) {\r
-      SafeFreePool (StringPackage);\r
-      return EFI_OUT_OF_RESOURCES;\r
+      FreePool (StringPackage);\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
-      SafeFreePool (StringPackage->StringPkgHdr);\r
-      SafeFreePool (StringPackage);\r
-      return EFI_OUT_OF_RESOURCES;\r
+      FreePool (StringPackage->StringPkgHdr);\r
+      FreePool (StringPackage);\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
     }\r
 \r
     //\r
@@ -1077,7 +1357,10 @@ HiiNewString (
     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
@@ -1089,24 +1372,7 @@ HiiNewString (
     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
@@ -1115,13 +1381,13 @@ HiiNewString (
     //\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
@@ -1140,7 +1406,7 @@ HiiNewString (
     // Append a EFI_HII_SIBT_END block to the end.\r
     //\r
     *BlockPtr = EFI_HII_SIBT_END;\r
-    SafeFreePool (StringPackage->StringBlock);\r
+    FreePool (StringPackage->StringBlock);\r
     StringPackage->StringBlock = StringBlock;\r
     StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize;\r
     PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize;\r
@@ -1160,7 +1426,8 @@ HiiNewString (
       //\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
@@ -1173,7 +1440,7 @@ HiiNewString (
       *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
@@ -1181,7 +1448,7 @@ HiiNewString (
       // Append a EFI_HII_SIBT_END block to the end.\r
       //\r
       *BlockPtr = EFI_HII_SIBT_END;\r
-      SafeFreePool (StringPackage->StringBlock);\r
+      FreePool (StringPackage->StringBlock);\r
       StringPackage->StringBlock = StringBlock;\r
       StringPackage->StringPkgHdr->Header.Length += Ucs2FontBlockSize;\r
       PackageListNode->PackageListHdr.PackageLength += Ucs2FontBlockSize;\r
@@ -1196,7 +1463,8 @@ HiiNewString (
                                 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
@@ -1216,7 +1484,7 @@ HiiNewString (
       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
@@ -1226,14 +1494,14 @@ HiiNewString (
         &((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
@@ -1241,20 +1509,69 @@ HiiNewString (
       // Append a EFI_HII_SIBT_END block to the end.\r
       //\r
       *BlockPtr = EFI_HII_SIBT_END;\r
-      SafeFreePool (StringPackage->StringBlock);\r
+      FreePool (StringPackage->StringBlock);\r
       StringPackage->StringBlock = StringBlock;\r
       StringPackage->StringPkgHdr->Header.Length += FontBlockSize + Ucs2FontBlockSize;\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
-  return EFI_SUCCESS;\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
+  // The contents of HiiDataBase may updated,need to check.\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
+  EfiReleaseLock (&mHiiDatabaseLock);\r
+\r
+  return Status;\r
 }\r
 \r
 \r
@@ -1285,7 +1602,8 @@ HiiNewString (
   @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
@@ -1341,7 +1659,7 @@ HiiGetString (
          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
@@ -1351,16 +1669,16 @@ HiiGetString (
       //\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
@@ -1418,6 +1736,8 @@ HiiSetString (
     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
@@ -1434,7 +1754,7 @@ HiiSetString (
          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
@@ -1444,14 +1764,24 @@ HiiSetString (
                    (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
@@ -1463,13 +1793,15 @@ HiiSetString (
 \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
@@ -1493,7 +1825,10 @@ HiiGetLanguages (
   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
@@ -1524,8 +1859,8 @@ HiiGetLanguages (
       ) {\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
+    if (ResultSize <= *LanguagesSize) {\r
+      AsciiStrCpyS (Languages, *LanguagesSize / sizeof (CHAR8), StringPackage->StringPkgHdr->Language);\r
       Languages += AsciiStrSize (StringPackage->StringPkgHdr->Language);\r
       *(Languages - 1) = L';';\r
     }\r
@@ -1551,26 +1886,30 @@ HiiGetLanguages (
 \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  SecondaryLanguageSize  On entry, points to the size of the buffer pointed\r
-                                 to  by SecondLanguages, in bytes. On return,\r
-                                 points to the length of SecondLanguages in bytes.\r
+  @param  SecondaryLanguagesSize On entry, points to the size of the buffer pointed\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 SecondLanguages or\r
-                                 SecondLanguagesSize was NULL.\r
-  @retval EFI_BUFFER_TOO_SMALL   The buffer specified by SecondLanguagesSize is\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
@@ -1578,9 +1917,9 @@ EFIAPI
 HiiGetSecondaryLanguages (\r
   IN CONST EFI_HII_STRING_PROTOCOL   *This,\r
   IN EFI_HII_HANDLE                  PackageList,\r
-  IN CONST CHAR8                     *FirstLanguage,\r
-  IN OUT CHAR8                       *SecondLanguages,\r
-  IN OUT UINTN                       *SecondLanguagesSize\r
+  IN CONST CHAR8                     *PrimaryLanguage,\r
+  IN OUT CHAR8                       *SecondaryLanguages,\r
+  IN OUT UINTN                       *SecondaryLanguagesSize\r
   )\r
 {\r
   LIST_ENTRY                          *Link;\r
@@ -1592,10 +1931,10 @@ HiiGetSecondaryLanguages (
   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 (SecondLanguages == NULL || SecondLanguagesSize == NULL) {\r
+  if (SecondaryLanguages == NULL && *SecondaryLanguagesSize != 0) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   if (!IsHiiHandleValid (PackageList)) {\r
@@ -1604,7 +1943,7 @@ HiiGetSecondaryLanguages (
 \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
@@ -1615,7 +1954,7 @@ HiiGetSecondaryLanguages (
     if (PackageListNode == NULL) {\r
       return EFI_NOT_FOUND;\r
     }\r
-      \r
+\r
     Languages  = NULL;\r
     ResultSize = 0;\r
     for (Link1 = PackageListNode->StringPkgHdr.ForwardLink;\r
@@ -1623,7 +1962,7 @@ HiiGetSecondaryLanguages (
          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
@@ -1637,10 +1976,10 @@ HiiGetSecondaryLanguages (
       Languages++;\r
 \r
       ResultSize = AsciiStrSize (Languages);\r
-      if (ResultSize <= *SecondLanguagesSize) {\r
-        AsciiStrCpy (SecondLanguages, Languages);\r
+      if (ResultSize <= *SecondaryLanguagesSize) {\r
+        AsciiStrCpyS (SecondaryLanguages, *SecondaryLanguagesSize / sizeof (CHAR8), Languages);\r
       } else {\r
-        *SecondLanguagesSize = ResultSize;\r
+        *SecondaryLanguagesSize = ResultSize;\r
         return EFI_BUFFER_TOO_SMALL;\r
       }\r
 \r
@@ -1651,3 +1990,89 @@ HiiGetSecondaryLanguages (
   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