+/**\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 outputed 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