+CVfrStringDB::CVfrStringDB ()\r
+{\r
+ mStringFileName = NULL;\r
+}\r
+\r
+CVfrStringDB::~CVfrStringDB ()\r
+{\r
+ if (mStringFileName != NULL) {\r
+ delete mStringFileName;\r
+ }\r
+ mStringFileName = NULL;\r
+}\r
+\r
+\r
+VOID \r
+CVfrStringDB::SetStringFileName(IN CHAR8 *StringFileName)\r
+{\r
+ UINT32 FileLen = 0;\r
+\r
+ if (StringFileName == NULL) {\r
+ return;\r
+ }\r
+\r
+ FileLen = strlen (StringFileName) + 1;\r
+ mStringFileName = new CHAR8[FileLen];\r
+ if (mStringFileName == NULL) {\r
+ return;\r
+ }\r
+\r
+ strcpy (mStringFileName, StringFileName);\r
+ mStringFileName[FileLen - 1] = '\0';\r
+}\r
+\r
+\r
+/**\r
+ Returns TRUE or FALSE whether SupportedLanguages contains the best matching language \r
+ from a set of supported languages.\r
+\r
+ @param[in] SupportedLanguages A pointer to a Null-terminated ASCII string that\r
+ contains a set of language codes.\r
+ @param[in] Language A variable that contains pointers to Null-terminated\r
+ ASCII strings that contain one language codes.\r
+\r
+ @retval FALSE The best matching language could not be found in SupportedLanguages.\r
+ @retval TRUE The best matching language could be found in SupportedLanguages.\r
+\r
+**/\r
+BOOLEAN\r
+CVfrStringDB::GetBestLanguage (\r
+ IN CONST CHAR8 *SupportedLanguages,\r
+ IN CHAR8 *Language\r
+ )\r
+{\r
+ UINTN CompareLength;\r
+ UINTN LanguageLength;\r
+ CONST CHAR8 *Supported;\r
+\r
+ if (SupportedLanguages == NULL || Language == NULL){\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Determine the length of the first RFC 4646 language code in Language\r
+ //\r
+ for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++);\r
+\r
+ //\r
+ // Trim back the length of Language used until it is empty\r
+ //\r
+ while (LanguageLength > 0) {\r
+ //\r
+ // Loop through all language codes in SupportedLanguages\r
+ //\r
+ for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) {\r
+ //\r
+ // Skip ';' characters in Supported\r
+ //\r
+ for (; *Supported != '\0' && *Supported == ';'; Supported++);\r
+ //\r
+ // Determine the length of the next language code in Supported\r
+ //\r
+ for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++);\r
+ //\r
+ // If Language is longer than the Supported, then skip to the next language\r
+ //\r
+ if (LanguageLength > CompareLength) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // See if the first LanguageLength characters in Supported match Language\r
+ //\r
+ if (strncmp (Supported, Language, LanguageLength) == 0) {\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Trim Language from the right to the next '-' character \r
+ //\r
+ for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--);\r
+ }\r
+\r
+ //\r
+ // No matches were found \r
+ //\r
+ return FALSE;\r
+}\r
+\r
+\r
+CHAR8 *\r
+CVfrStringDB::GetVarStoreNameFormStringId (\r
+ IN EFI_STRING_ID StringId\r
+ )\r
+{\r
+ FILE *pInFile = NULL;\r
+ UINT32 NameOffset;\r
+ UINT32 Length;\r
+ UINT8 *StringPtr;\r
+ CHAR8 *StringName;\r
+ CHAR16 *UnicodeString;\r
+ CHAR8 *VarStoreName = NULL;\r
+ CHAR8 *DestTmp;\r
+ UINT8 *Current;\r
+ EFI_STATUS Status;\r
+ CHAR8 LineBuf[EFI_IFR_MAX_LENGTH];\r
+ UINT8 BlockType;\r
+ EFI_HII_STRING_PACKAGE_HDR *PkgHeader;\r
+ \r
+ if (mStringFileName == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ if ((pInFile = fopen (LongFilePath (mStringFileName), "rb")) == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Get file length.\r
+ //\r
+ fseek (pInFile, 0, SEEK_END);\r
+ Length = ftell (pInFile);\r
+ fseek (pInFile, 0, SEEK_SET);\r
+\r
+ //\r
+ // Get file data.\r
+ //\r
+ StringPtr = new UINT8[Length];\r
+ if (StringPtr == NULL) {\r
+ fclose (pInFile);\r
+ return NULL;\r
+ }\r
+ fread ((char *)StringPtr, sizeof (UINT8), Length, pInFile);\r
+ fclose (pInFile);\r
+\r
+ PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) StringPtr;\r
+ //\r
+ // Check the String package.\r
+ //\r
+ if (PkgHeader->Header.Type != EFI_HII_PACKAGE_STRINGS) {\r
+ delete[] StringPtr;\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Search the language, get best language base on RFC 4647 matching algorithm.\r
+ //\r
+ Current = StringPtr;\r
+ while (!GetBestLanguage ("en", PkgHeader->Language)) {\r
+ Current += PkgHeader->Header.Length;\r
+ PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) Current;\r
+ //\r
+ // If can't find string package base on language, just return the first string package.\r
+ //\r
+ if (Current - StringPtr >= Length) {\r
+ Current = StringPtr;\r
+ PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) StringPtr;\r
+ break;\r
+ }\r
+ }\r
+\r
+ Current += PkgHeader->HdrSize;\r
+ //\r
+ // Find the string block according the stringId.\r
+ //\r
+ Status = FindStringBlock(Current, StringId, &NameOffset, &BlockType);\r
+ if (Status != EFI_SUCCESS) {\r
+ delete[] StringPtr;\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Get varstore name according the string type.\r
+ //\r
+ switch (BlockType) {\r
+ case EFI_HII_SIBT_STRING_SCSU:\r
+ case EFI_HII_SIBT_STRING_SCSU_FONT:\r
+ case EFI_HII_SIBT_STRINGS_SCSU:\r
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
+ StringName = (CHAR8*)(Current + NameOffset);\r
+ VarStoreName = new CHAR8[strlen(StringName) + 1];\r
+ strcpy (VarStoreName, StringName);\r
+ break;\r
+ case EFI_HII_SIBT_STRING_UCS2:\r
+ case EFI_HII_SIBT_STRING_UCS2_FONT:\r
+ case EFI_HII_SIBT_STRINGS_UCS2:\r
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
+ UnicodeString = (CHAR16*)(Current + NameOffset);\r
+ Length = GetUnicodeStringTextSize ((UINT8*)UnicodeString) ;\r
+ DestTmp = new CHAR8[Length / 2 + 1];\r
+ VarStoreName = DestTmp;\r
+ while (*UnicodeString != '\0') {\r
+ *(DestTmp++) = (CHAR8) *(UnicodeString++);\r
+ }\r
+ *DestTmp = '\0';\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+\r
+ delete[] StringPtr;\r
+\r
+ return VarStoreName;\r
+}\r
+\r
+EFI_STATUS\r
+CVfrStringDB::FindStringBlock (\r
+ IN UINT8 *StringData,\r
+ IN EFI_STRING_ID StringId,\r
+ OUT UINT32 *StringTextOffset,\r
+ OUT UINT8 *BlockType\r
+ )\r
+{\r
+ UINT8 *BlockHdr;\r
+ EFI_STRING_ID CurrentStringId;\r
+ UINT32 BlockSize;\r
+ UINT32 Index;\r
+ UINT8 *StringTextPtr;\r
+ UINT32 Offset;\r
+ UINT16 StringCount;\r
+ UINT16 SkipCount;\r
+ UINT8 Length8;\r
+ EFI_HII_SIBT_EXT2_BLOCK Ext2;\r
+ UINT32 Length32;\r
+ UINT32 StringSize;\r
+\r
+ CurrentStringId = 1;\r
+\r
+ //\r
+ // Parse the string blocks to get the string text and font.\r
+ //\r
+ BlockHdr = StringData;\r
+ BlockSize = 0;\r
+ Offset = 0;\r
+ while (*BlockHdr != EFI_HII_SIBT_END) {\r
+ switch (*BlockHdr) {\r
+ case EFI_HII_SIBT_STRING_SCSU:\r
+ Offset = sizeof (EFI_HII_STRING_BLOCK);\r
+ StringTextPtr = BlockHdr + Offset;\r
+ BlockSize += Offset + strlen ((CHAR8 *) StringTextPtr) + 1;\r
+ CurrentStringId++;\r
+ break;\r
+\r
+ case EFI_HII_SIBT_STRING_SCSU_FONT:\r
+ Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);\r
+ StringTextPtr = BlockHdr + Offset;\r
+ BlockSize += Offset + strlen ((CHAR8 *) StringTextPtr) + 1;\r
+ CurrentStringId++;\r
+ break;\r
+\r
+ case EFI_HII_SIBT_STRINGS_SCSU:\r
+ memcpy (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
+ StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8);\r
+ BlockSize += StringTextPtr - BlockHdr;\r
+\r
+ for (Index = 0; Index < StringCount; Index++) {\r
+ BlockSize += strlen ((CHAR8 *) StringTextPtr) + 1;\r
+ if (CurrentStringId == StringId) {\r
+ *BlockType = *BlockHdr;\r
+ *StringTextOffset = StringTextPtr - StringData;\r
+ return EFI_SUCCESS;\r
+ }\r
+ StringTextPtr = StringTextPtr + strlen ((CHAR8 *) StringTextPtr) + 1;\r
+ CurrentStringId++;\r
+ }\r
+ break;\r
+\r
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
+ memcpy (\r
+ &StringCount,\r
+ 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
+ BlockSize += StringTextPtr - BlockHdr;\r
+\r
+ for (Index = 0; Index < StringCount; Index++) {\r
+ BlockSize += strlen ((CHAR8 *) StringTextPtr) + 1;\r
+ if (CurrentStringId == StringId) {\r
+ *BlockType = *BlockHdr;\r
+ *StringTextOffset = StringTextPtr - StringData;\r
+ return EFI_SUCCESS;\r
+ }\r
+ StringTextPtr = StringTextPtr + strlen ((CHAR8 *) StringTextPtr) + 1;\r
+ CurrentStringId++;\r
+ }\r
+ break;\r
+\r
+ case EFI_HII_SIBT_STRING_UCS2:\r
+ Offset = sizeof (EFI_HII_STRING_BLOCK);\r
+ StringTextPtr = BlockHdr + Offset;\r
+ //\r
+ // Use StringSize to store the size of the specified string, including the NULL\r
+ // terminator.\r
+ //\r
+ StringSize = GetUnicodeStringTextSize (StringTextPtr);\r
+ BlockSize += Offset + StringSize;\r
+ CurrentStringId++;\r
+ break;\r
+\r
+ case EFI_HII_SIBT_STRING_UCS2_FONT:\r
+ Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);\r
+ StringTextPtr = BlockHdr + Offset;\r
+ //\r
+ // Use StrSize to store the size of the specified string, including the NULL\r
+ // terminator.\r
+ //\r
+ StringSize = GetUnicodeStringTextSize (StringTextPtr);\r
+ BlockSize += Offset + StringSize;\r
+ CurrentStringId++;\r
+ break;\r
+\r
+ case EFI_HII_SIBT_STRINGS_UCS2:\r
+ Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);\r
+ StringTextPtr = BlockHdr + Offset;\r
+ BlockSize += Offset;\r
+ memcpy (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
+ for (Index = 0; Index < StringCount; Index++) {\r
+ StringSize = GetUnicodeStringTextSize (StringTextPtr);\r
+ BlockSize += StringSize;\r
+ if (CurrentStringId == StringId) {\r
+ *BlockType = *BlockHdr;\r
+ *StringTextOffset = StringTextPtr - StringData;\r
+ return EFI_SUCCESS;\r
+ }\r
+ StringTextPtr = StringTextPtr + StringSize;\r
+ CurrentStringId++;\r
+ }\r
+ break;\r
+\r
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
+ Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);\r
+ StringTextPtr = BlockHdr + Offset;\r
+ BlockSize += Offset;\r
+ memcpy (\r
+ &StringCount,\r
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),\r
+ sizeof (UINT16)\r
+ );\r
+ for (Index = 0; Index < StringCount; Index++) {\r
+ StringSize = GetUnicodeStringTextSize (StringTextPtr);\r
+ BlockSize += StringSize;\r
+ if (CurrentStringId == StringId) {\r
+ *BlockType = *BlockHdr;\r
+ *StringTextOffset = StringTextPtr - StringData;\r
+ return EFI_SUCCESS;\r
+ }\r
+ StringTextPtr = StringTextPtr + StringSize;\r
+ CurrentStringId++;\r
+ }\r
+ break;\r
+\r
+ case EFI_HII_SIBT_DUPLICATE:\r
+ if (CurrentStringId == StringId) {\r
+ //\r
+ // Incoming StringId is an id of a duplicate string block.\r
+ // Update the StringId to be the previous string block.\r
+ // Go back to the header of string block to search.\r
+ //\r
+ memcpy (\r
+ &StringId,\r
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK),\r
+ sizeof (EFI_STRING_ID)\r
+ );\r
+ CurrentStringId = 1;\r
+ BlockSize = 0;\r
+ } else {\r
+ BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);\r
+ CurrentStringId++;\r
+ }\r
+ break;\r
+\r
+ case EFI_HII_SIBT_SKIP1:\r
+ SkipCount = (UINT16) (*(BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));\r
+ CurrentStringId = (UINT16) (CurrentStringId + SkipCount);\r
+ BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);\r
+ break;\r
+\r
+ case EFI_HII_SIBT_SKIP2:\r
+ memcpy (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
+ CurrentStringId = (UINT16) (CurrentStringId + SkipCount);\r
+ BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);\r
+ break;\r
+\r
+ case EFI_HII_SIBT_EXT1:\r
+ memcpy (\r
+ &Length8,\r
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),\r
+ sizeof (UINT8)\r
+ );\r
+ BlockSize += Length8;\r
+ break;\r
+\r
+ case EFI_HII_SIBT_EXT2:\r
+ memcpy (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));\r
+ BlockSize += Ext2.Length;\r
+ break;\r
+\r
+ case EFI_HII_SIBT_EXT4:\r
+ memcpy (\r
+ &Length32,\r
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),\r
+ sizeof (UINT32)\r
+ );\r
+\r
+ BlockSize += Length32;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ if (StringId > 0 && StringId != (EFI_STRING_ID)(-1)) {\r
+ *StringTextOffset = BlockHdr - StringData + Offset;\r
+ *BlockType = *BlockHdr;\r
+\r
+ if (StringId == CurrentStringId - 1) {\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
+ return EFI_NOT_FOUND;\r
+ }\r
+ }\r
+ BlockHdr = StringData + BlockSize;\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+UINT32\r
+CVfrStringDB::GetUnicodeStringTextSize (\r
+ IN UINT8 *StringSrc\r
+ )\r
+{\r
+ UINT32 StringSize;\r
+ CHAR16 *StringPtr;\r
+\r
+ StringSize = sizeof (CHAR16);\r
+ StringPtr = (UINT16*)StringSrc;\r
+ while (*StringPtr++ != L'\0') {\r
+ StringSize += sizeof (CHAR16);\r
+ }\r
+\r
+ return StringSize;\r
+}\r
+\r