]> 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 bda7d5ac06afb1099faec19ca2d84f4f952da73d..505e063d49c39dbda15a86ca578b7fd9b16be48d 100644 (file)
@@ -2,14 +2,9 @@
 Implementation for EFI_HII_STRING_PROTOCOL.\r
 \r
 \r
-Copyright (c) 2007 - 2010, 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
@@ -105,7 +100,7 @@ ReferFontInfoLocally (
   @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
@@ -149,7 +144,7 @@ ConvertToUnicodeText (
   @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
@@ -198,7 +193,7 @@ GetUnicodeStringTextOrSize (
   @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
@@ -235,7 +230,7 @@ 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. If LastStringId is \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
@@ -248,6 +243,7 @@ GetStringFontInfo (
   @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
@@ -265,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
@@ -293,6 +290,7 @@ 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
@@ -333,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
@@ -352,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
@@ -404,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
@@ -420,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
@@ -459,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
@@ -473,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
@@ -488,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
@@ -516,7 +518,7 @@ 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
         FreePool (FontInfo);\r
@@ -529,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
@@ -540,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
@@ -553,14 +564,16 @@ FindStringBlock (
       }\r
     }\r
     BlockHdr  = StringPackage->StringBlock + BlockSize;\r
-\r
+    if (StartStringId != NULL) {\r
+        *StartStringId  = CurrentStringId;\r
+    }\r
   }\r
-  \r
+\r
   //\r
   // Get last string ID\r
   //\r
-  if (StringId == (EFI_STRING_ID) (-1)) {\r
-    *LastStringId = CurrentStringId - 1;\r
+  if (StringId == (EFI_STRING_ID) (-1) && LastStringId != NULL) {\r
+    *LastStringId = (EFI_STRING_ID) (CurrentStringId - 1);\r
     return EFI_SUCCESS;\r
   }\r
 \r
@@ -599,7 +612,7 @@ GetStringWorker (
   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
@@ -610,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
@@ -623,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
@@ -654,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
@@ -677,6 +698,153 @@ 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
@@ -724,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
@@ -738,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
@@ -756,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
@@ -771,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
@@ -782,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
@@ -799,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
@@ -813,7 +998,7 @@ SetStringWorker (
     }\r
     *BlockPtr++ = 0;\r
 \r
-    \r
+\r
     TmpSize = OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - AsciiStrSize ((CHAR8 *) StringTextPtr);\r
     CopyMem (\r
       BlockPtr,\r
@@ -891,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
@@ -916,9 +1101,9 @@ SetStringWorker (
 \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
+  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
@@ -1019,6 +1204,8 @@ HiiNewString (
     return EFI_NOT_FOUND;\r
   }\r
 \r
+  EfiAcquireLock (&mHiiDatabaseLock);\r
+\r
   Status = EFI_SUCCESS;\r
   NewStringPackageCreated = FALSE;\r
   NewStringId   = 0;\r
@@ -1041,7 +1228,8 @@ HiiNewString (
                NULL,\r
                NULL,\r
                NULL,\r
-               &NextStringId\r
+               &NextStringId,\r
+               NULL\r
                );\r
     if (EFI_ERROR (Status)) {\r
       goto Done;\r
@@ -1103,7 +1291,7 @@ HiiNewString (
     //\r
     // Set new StringId\r
     //\r
-    *StringId = NewStringId + 1;\r
+    *StringId = (EFI_STRING_ID) (NewStringId + 1);\r
   }\r
 \r
   if (MatchStringPackage != NULL) {\r
@@ -1143,13 +1331,13 @@ HiiNewString (
     StringPackage->StringPkgHdr->StringInfoOffset = HeaderSize;\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
+    Ucs2BlockSize = (UINT32) (StrSize ((CHAR16 *) LanguageName) +\r
                               (*StringId - 1) * sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16));\r
 \r
     BlockSize     = Ucs2BlockSize + sizeof (EFI_HII_SIBT_END_BLOCK);\r
@@ -1252,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
@@ -1296,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
@@ -1313,7 +1501,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
@@ -1327,7 +1515,7 @@ HiiNewString (
       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
@@ -1368,6 +1556,20 @@ Done:
     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
@@ -1400,7 +1602,8 @@ Done:
   @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
@@ -1466,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
@@ -1533,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
@@ -1559,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
@@ -1578,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
@@ -1608,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
@@ -1640,7 +1860,7 @@ HiiGetLanguages (
     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
@@ -1666,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  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
@@ -1693,7 +1917,7 @@ EFIAPI
 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
@@ -1707,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 (SecondaryLanguages == NULL || SecondaryLanguagesSize == NULL) {\r
+  if (SecondaryLanguages == NULL && *SecondaryLanguagesSize != 0) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   if (!IsHiiHandleValid (PackageList)) {\r
@@ -1719,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
@@ -1730,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
@@ -1738,7 +1962,7 @@ HiiGetSecondaryLanguages (
          Link1 = Link1->ForwardLink\r
         ) {\r
     StringPackage = CR (Link1, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
-    if (HiiCompareLanguage (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
@@ -1753,7 +1977,7 @@ HiiGetSecondaryLanguages (
 \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
@@ -1766,11 +1990,36 @@ 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\r
-  @param  Language2              Name of language 2\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
@@ -1782,25 +2031,48 @@ HiiCompareLanguage (
   IN  CHAR8  *Language2\r
   )\r
 {\r
+  UINTN  Index;\r
+  UINTN  StrLen;\r
+  CHAR8  *Lan1;\r
+  CHAR8  *Lan2;\r
+\r
   //\r
-  // Porting Guide:\r
-  // This library interface is simply obsolete.\r
-  // Include the source code to user code.\r
+  // Convert to lower to compare.\r
   //\r
-  UINTN Index;\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
-  for (Index = 0; (Language1[Index] != 0) && (Language2[Index] != 0); Index++) {\r
-    if (Language1[Index] != Language2[Index]) {\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
-  if (((Language1[Index] == 0) && (Language2[Index] == 0))   || \r
-         ((Language1[Index] == 0) && (Language2[Index] != ';')) ||\r
-         ((Language1[Index] == ';') && (Language2[Index] != 0)) ||\r
-         ((Language1[Index] == ';') && (Language2[Index] != ';'))) {\r
-    return TRUE;\r
-  }\r
+  FreePool (Lan1);\r
+  FreePool (Lan2);\r
 \r
-  return FALSE;\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