]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp
Sync BaseTools Branch (version r2271) to EDKII main trunk.
[mirror_edk2.git] / BaseTools / Source / C / VfrCompile / VfrUtilityLib.cpp
index b839a0ab0e6a7d8ed98f97b22f5a4275429e3337..c3a729eabfb8d3a9c13b6f901d3fc9319318f2c2 100644 (file)
@@ -468,6 +468,7 @@ static struct {
   {"EFI_HII_DATE",  EFI_IFR_TYPE_DATE,        sizeof (EFI_HII_DATE), sizeof (UINT16)},\r
   {"EFI_STRING_ID", EFI_IFR_TYPE_STRING,      sizeof (EFI_STRING_ID),sizeof (EFI_STRING_ID)},\r
   {"EFI_HII_TIME",  EFI_IFR_TYPE_TIME,        sizeof (EFI_HII_TIME), sizeof (UINT8)},\r
+  {"EFI_HII_REF",   EFI_IFR_TYPE_REF,         sizeof (EFI_HII_REF),  sizeof (EFI_GUID)},\r
   {NULL,            EFI_IFR_TYPE_OTHER,       0,                     0}\r
 };\r
 \r
@@ -635,7 +636,7 @@ CVfrVarDataTypeDB::ExtractFieldNameAndArrary (
 \r
 EFI_VFR_RETURN_CODE\r
 CVfrVarDataTypeDB::GetTypeField (\r
-  IN  CHAR8          *FName,\r
+  IN  CONST CHAR8   *FName,\r
   IN  SVfrDataType  *Type,\r
   OUT SVfrDataField *&Field\r
   )\r
@@ -647,6 +648,20 @@ CVfrVarDataTypeDB::GetTypeField (
   }\r
 \r
   for (pField = Type->mMembers; pField != NULL; pField = pField->mNext) {\r
+    //\r
+    // For type EFI_IFR_TYPE_TIME, because field name is not correctly wrote,\r
+    // add code to adjust it.\r
+    //\r
+    if (Type->mType == EFI_IFR_TYPE_TIME) {\r
+      if (strcmp (FName, "Hour") == 0) {\r
+        FName = "Hours";\r
+      } else if (strcmp (FName, "Minute") == 0) {\r
+        FName = "Minuts";\r
+      } else if (strcmp (FName, "Second") == 0) {\r
+        FName = "Seconds";\r
+      }\r
+    }\r
+\r
     if (strcmp (pField->mFieldName, FName) == 0) {\r
       Field = pField;\r
       return VFR_RETURN_SUCCESS;\r
@@ -789,6 +804,37 @@ CVfrVarDataTypeDB::InternalTypesListInit (
         pSecondsField->mArrayNum = 0;\r
 \r
         New->mMembers            = pHoursField;\r
+      } else if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_REF") == 0) {\r
+        SVfrDataField *pQuestionIdField   = new SVfrDataField;\r
+        SVfrDataField *pFormIdField       = new SVfrDataField;\r
+        SVfrDataField *pFormSetGuidField  = new SVfrDataField;\r
+        SVfrDataField *pDevicePathField   = new SVfrDataField;\r
+\r
+        strcpy (pQuestionIdField->mFieldName, "QuestionId");\r
+        GetDataType ((CHAR8 *)"UINT16", &pQuestionIdField->mFieldType);\r
+        pQuestionIdField->mOffset     = 0;\r
+        pQuestionIdField->mNext       = pFormIdField;\r
+        pQuestionIdField->mArrayNum   = 0;\r
+\r
+        strcpy (pFormIdField->mFieldName, "FormId");\r
+        GetDataType ((CHAR8 *)"UINT16", &pFormIdField->mFieldType);\r
+        pFormIdField->mOffset   = 2;\r
+        pFormIdField->mNext     = pFormSetGuidField;\r
+        pFormIdField->mArrayNum = 0;\r
+\r
+        strcpy (pFormSetGuidField->mFieldName, "FormSetGuid");\r
+        GetDataType ((CHAR8 *)"EFI_GUID", &pFormSetGuidField->mFieldType);\r
+        pFormSetGuidField->mOffset   = 4;\r
+        pFormSetGuidField->mNext     = pDevicePathField;\r
+        pFormSetGuidField->mArrayNum = 0;\r
+\r
+        strcpy (pDevicePathField->mFieldName, "DevicePath");\r
+        GetDataType ((CHAR8 *)"EFI_STRING_ID", &pDevicePathField->mFieldType);\r
+        pDevicePathField->mOffset   = 20;\r
+        pDevicePathField->mNext     = NULL;\r
+        pDevicePathField->mArrayNum = 0;\r
+\r
+        New->mMembers            = pQuestionIdField;\r
       } else {\r
         New->mMembers            = NULL;\r
       }\r
@@ -2770,6 +2816,100 @@ Err:
   }\r
 }\r
 \r
+VOID \r
+CVfrQuestionDB::RegisterRefQuestion (\r
+  IN     CHAR8           *Name,\r
+  IN     CHAR8           *BaseVarId,\r
+  IN OUT EFI_QUESTION_ID &QuestionId\r
+  )\r
+{\r
+  SVfrQuestionNode     *pNode[4] = {NULL, };\r
+  UINT32               Len;\r
+  CHAR8                *VarIdStr[4] = {NULL, };\r
+  CHAR8                 Index;\r
+\r
+  if (BaseVarId == NULL) {\r
+    return;\r
+  }\r
+\r
+  Len = strlen (BaseVarId);\r
+\r
+  VarIdStr[0] = new CHAR8[Len + strlen (".QuestionId") + 1];\r
+  if (VarIdStr[0] != NULL) {\r
+    strcpy (VarIdStr[0], BaseVarId);\r
+    strcat (VarIdStr[0], ".QuestionId");\r
+  }\r
+  VarIdStr[1] = new CHAR8[Len + strlen (".FormId") + 1];\r
+  if (VarIdStr[1] != NULL) {\r
+    strcpy (VarIdStr[1], BaseVarId);\r
+    strcat (VarIdStr[1], ".FormId");\r
+  }\r
+  VarIdStr[2] = new CHAR8[Len + strlen (".FormSetGuid") + 1];\r
+  if (VarIdStr[2] != NULL) {\r
+    strcpy (VarIdStr[2], BaseVarId);\r
+    strcat (VarIdStr[2], ".FormSetGuid");\r
+  }\r
+  VarIdStr[3] = new CHAR8[Len + strlen (".DevicePath") + 1];\r
+  if (VarIdStr[3] != NULL) {\r
+    strcpy (VarIdStr[3], BaseVarId);\r
+    strcat (VarIdStr[3], ".DevicePath");\r
+  }\r
+\r
+  if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0])) == NULL) {\r
+    goto Err;\r
+  }\r
+  if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1])) == NULL) {\r
+    goto Err;\r
+  }\r
+  if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2])) == NULL) {\r
+    goto Err;\r
+  }\r
+  if ((pNode[3] = new SVfrQuestionNode (Name, VarIdStr[3])) == NULL) {\r
+    goto Err;\r
+  }\r
+\r
+  if (QuestionId == EFI_QUESTION_ID_INVALID) {\r
+    QuestionId = GetFreeQuestionId ();\r
+  } else {\r
+    if (ChekQuestionIdFree (QuestionId) == FALSE) {\r
+      goto Err;\r
+    }\r
+    MarkQuestionIdUsed (QuestionId);\r
+  }\r
+\r
+  pNode[0]->mQuestionId = QuestionId;\r
+  pNode[1]->mQuestionId = QuestionId;\r
+  pNode[2]->mQuestionId = QuestionId;\r
+  pNode[3]->mQuestionId = QuestionId;  \r
+  pNode[0]->mQtype      = QUESTION_REF;\r
+  pNode[1]->mQtype      = QUESTION_REF;\r
+  pNode[2]->mQtype      = QUESTION_REF;\r
+  pNode[3]->mQtype      = QUESTION_REF;  \r
+  pNode[0]->mNext       = pNode[1];\r
+  pNode[1]->mNext       = pNode[2];\r
+  pNode[2]->mNext       = pNode[3];\r
+  pNode[3]->mNext       = mQuestionList;  \r
+  mQuestionList         = pNode[0];\r
+\r
+  gCFormPkg.DoPendingAssign (VarIdStr[0], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));\r
+  gCFormPkg.DoPendingAssign (VarIdStr[1], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));\r
+  gCFormPkg.DoPendingAssign (VarIdStr[2], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));\r
+  gCFormPkg.DoPendingAssign (VarIdStr[3], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));\r
+\r
+  return;\r
+\r
+  Err:\r
+  for (Index = 0; Index < 4; Index++) {\r
+    if (pNode[Index] != NULL) {\r
+      delete pNode[Index];\r
+    }\r
+\r
+    if (VarIdStr[Index] != NULL) {\r
+      delete VarIdStr[Index];\r
+    }\r
+  }\r
+}\r
+\r
 EFI_VFR_RETURN_CODE\r
 CVfrQuestionDB::UpdateQuestionId (\r
   IN EFI_QUESTION_ID   QId,\r
@@ -2894,6 +3034,402 @@ CVfrQuestionDB::FindQuestion (
   return VFR_RETURN_UNDEFINED;\r
 }\r
 \r
+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
+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 == '\0' ) {\r
+    return NULL;\r
+  }\r
+\r
+  if ((pInFile = fopen (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, only search the "en-US".\r
+  //\r
+  Current = StringPtr;\r
+  while (strcmp (PkgHeader->Language, "en-US") != 0) {\r
+    Current += PkgHeader->Header.Length;\r
+    PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) Current;\r
+    //\r
+    // If can't find "en-US" string package, just return the first string package.\r
+    //\r
+    if (Current - StringPtr >= Length) {\r
+      Current = 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
 BOOLEAN  VfrCompatibleMode = FALSE;\r
 \r
 CVfrVarDataTypeDB gCVfrVarDataTypeDB;\r