]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp
Sync BaseTools Trunk (version r2518) to EDKII main trunk.
[mirror_edk2.git] / BaseTools / Source / C / VfrCompile / VfrUtilityLib.cpp
index f047b2c471905ed5494c6eefb389f4bb067b6c31..0444677e861e496b175b42d3c68f23da08443a38 100644 (file)
@@ -2,8 +2,8 @@
   \r
   Vfr common library functions.\r
 \r
-Copyright (c) 2004 - 2008, Intel Corporation                                                         \r
-All rights reserved. This program and the accompanying materials                          \r
+Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>\r
+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
@@ -20,11 +20,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 VOID\r
 CVfrBinaryOutput::WriteLine (\r
-  IN FILE   *pFile,\r
-  IN UINT32 LineBytes,\r
-  IN CHAR8  *LineHeader,\r
-  IN CHAR8  *BlkBuf,\r
-  IN UINT32 BlkSize\r
+  IN FILE         *pFile,\r
+  IN UINT32       LineBytes,\r
+  IN CONST CHAR8  *LineHeader,\r
+  IN CHAR8        *BlkBuf,\r
+  IN UINT32       BlkSize\r
   )\r
 {\r
   UINT32    Index;\r
@@ -43,11 +43,11 @@ CVfrBinaryOutput::WriteLine (
 \r
 VOID\r
 CVfrBinaryOutput::WriteEnd (\r
-  IN FILE   *pFile,\r
-  IN UINT32 LineBytes,\r
-  IN CHAR8  *LineHeader,\r
-  IN CHAR8  *BlkBuf,\r
-  IN UINT32 BlkSize\r
+  IN FILE         *pFile,\r
+  IN UINT32       LineBytes,\r
+  IN CONST CHAR8  *LineHeader,\r
+  IN CHAR8        *BlkBuf,\r
+  IN UINT32       BlkSize\r
   )\r
 {\r
   UINT32    Index;\r
@@ -287,7 +287,7 @@ CVfrBufferConfig::Write (
   switch (Mode) {\r
   case 'a' : // add\r
     if (Select (Name, Id) != 0) {\r
-      if ((pItem = new SConfigItem (Name, Id, Type, Offset, Width, Value)) == NULL) {\r
+      if ((pItem = new SConfigItem (Name, Id, Type, Offset, (UINT16) Width, Value)) == NULL) {\r
         return 2;\r
       }\r
       if (mItemListHead == NULL) {\r
@@ -455,7 +455,7 @@ CVfrBufferConfig::~CVfrBufferConfig (
 CVfrBufferConfig gCVfrBufferConfig;\r
 \r
 static struct {\r
-  CHAR8  *mTypeName;\r
+  CONST CHAR8  *mTypeName;\r
   UINT8  mType;\r
   UINT32 mSize;\r
   UINT32 mAlign;\r
@@ -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
@@ -622,6 +623,9 @@ CVfrVarDataTypeDB::ExtractFieldNameAndArrary (
     if (*VarStr == ']') {\r
       VarStr++;\r
     }\r
+    if (*VarStr == '.') {\r
+      VarStr++;\r
+    }\r
     return VFR_RETURN_SUCCESS;\r
   case ']':\r
     return VFR_RETURN_DATA_STRING_ERROR;\r
@@ -632,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
@@ -644,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
@@ -744,20 +762,20 @@ CVfrVarDataTypeDB::InternalTypesListInit (
         SVfrDataField *pDayField   = new SVfrDataField;\r
 \r
         strcpy (pYearField->mFieldName, "Year");\r
-        GetDataType ("UINT8", &pYearField->mFieldType);\r
+        GetDataType ((CHAR8 *)"UINT16", &pYearField->mFieldType);\r
         pYearField->mOffset      = 0;\r
         pYearField->mNext        = pMonthField;\r
         pYearField->mArrayNum    = 0;\r
 \r
         strcpy (pMonthField->mFieldName, "Month");\r
-        GetDataType ("UINT8", &pMonthField->mFieldType);\r
-        pMonthField->mOffset     = 1;\r
+        GetDataType ((CHAR8 *)"UINT8", &pMonthField->mFieldType);\r
+        pMonthField->mOffset     = 2;\r
         pMonthField->mNext       = pDayField;\r
         pMonthField->mArrayNum   = 0;\r
 \r
         strcpy (pDayField->mFieldName, "Day");\r
-        GetDataType ("UINT8", &pDayField->mFieldType);\r
-        pDayField->mOffset       = 2;\r
+        GetDataType ((CHAR8 *)"UINT8", &pDayField->mFieldType);\r
+        pDayField->mOffset       = 3;\r
         pDayField->mNext         = NULL;\r
         pDayField->mArrayNum     = 0;\r
 \r
@@ -768,24 +786,55 @@ CVfrVarDataTypeDB::InternalTypesListInit (
         SVfrDataField *pSecondsField = new SVfrDataField;\r
 \r
         strcpy (pHoursField->mFieldName, "Hours");\r
-        GetDataType ("UINT8", &pHoursField->mFieldType);\r
+        GetDataType ((CHAR8 *)"UINT8", &pHoursField->mFieldType);\r
         pHoursField->mOffset     = 0;\r
         pHoursField->mNext       = pMinutesField;\r
         pHoursField->mArrayNum   = 0;\r
 \r
         strcpy (pMinutesField->mFieldName, "Minutes");\r
-        GetDataType ("UINT8", &pMinutesField->mFieldType);\r
+        GetDataType ((CHAR8 *)"UINT8", &pMinutesField->mFieldType);\r
         pMinutesField->mOffset   = 1;\r
         pMinutesField->mNext     = pSecondsField;\r
         pMinutesField->mArrayNum = 0;\r
 \r
         strcpy (pSecondsField->mFieldName, "Seconds");\r
-        GetDataType ("UINT8", &pSecondsField->mFieldType);\r
+        GetDataType ((CHAR8 *)"UINT8", &pSecondsField->mFieldType);\r
         pSecondsField->mOffset   = 2;\r
         pSecondsField->mNext     = NULL;\r
         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
@@ -853,7 +902,7 @@ CVfrVarDataTypeDB::Pack (
 \r
   if (Action & VFR_PACK_SHOW) {\r
     sprintf (Msg, "value of pragma pack(show) == %d", mPackAlign);\r
-    gCVfrErrorHandle.PrintMsg (LineNum, "", "Warning", Msg);\r
+    gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Warning", Msg);\r
   }\r
 \r
   if (Action & VFR_PACK_PUSH) {\r
@@ -870,7 +919,7 @@ CVfrVarDataTypeDB::Pack (
     SVfrPackStackNode *pNode = NULL;\r
 \r
     if (mPackStack == NULL) {\r
-      gCVfrErrorHandle.PrintMsg (LineNum, "", "Error", "#pragma pack(pop...) : more pops than pushes");\r
+      gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Error", "#pragma pack(pop...) : more pops than pushes");\r
     }\r
 \r
     for (pNode = mPackStack; pNode != NULL; pNode = pNode->mNext) {\r
@@ -884,7 +933,7 @@ CVfrVarDataTypeDB::Pack (
   if (Action & VFR_PACK_ASSIGN) {\r
     PackAlign = (Number > 1) ? Number + Number % 2 : Number;\r
     if ((PackAlign == 0) || (PackAlign > 16)) {\r
-      gCVfrErrorHandle.PrintMsg (LineNum, "", "Error", "expected pragma parameter to be '1', '2', '4', '8', or '16'");\r
+      gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Error", "expected pragma parameter to be '1', '2', '4', '8', or '16'");\r
     } else {\r
       mPackAlign = PackAlign;\r
     }\r
@@ -1127,7 +1176,7 @@ CVfrVarDataTypeDB::GetDataFieldInfo (
     CHECK_ERROR_RETURN(GetTypeField (FName, pType, pField), VFR_RETURN_SUCCESS);\r
     pType  = pField->mFieldType;\r
     CHECK_ERROR_RETURN(GetFieldOffset (pField, ArrayIdx, Tmp), VFR_RETURN_SUCCESS);\r
-    Offset += Tmp;\r
+    Offset = (UINT16) (Offset + Tmp);\r
     Type   = GetFieldWidth (pField);\r
     Size   = GetFieldSize (pField, ArrayIdx);\r
   }\r
@@ -1386,6 +1435,7 @@ CVfrDataStorage::GetFreeVarStoreId (
   //\r
   // Assign the different ID range for the different type VarStore to support Framework Vfr\r
   //\r
+  Index = 0;\r
   if ((!VfrCompatibleMode) || (VarType == EFI_VFR_VARSTORE_BUFFER)) {\r
     Index = 0;\r
   } else if (VarType == EFI_VFR_VARSTORE_EFI) {\r
@@ -1455,10 +1505,8 @@ CVfrDataStorage::DeclareNameVarStoreBegin (
     return VFR_RETURN_FATAL_ERROR;\r
   }\r
 \r
-  for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) {\r
-    if (strcmp (pNode->mVarStoreName, StoreName) == 0) {\r
-      return VFR_RETURN_REDEFINED;\r
-    }\r
+  if (GetVarStoreId (StoreName, &VarStoreId) == VFR_RETURN_SUCCESS) {\r
+    return VFR_RETURN_REDEFINED;\r
   }\r
 \r
   VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_NAME);\r
@@ -1530,10 +1578,8 @@ CVfrDataStorage::DeclareEfiVarStore (
     return VFR_RETURN_EFIVARSTORE_SIZE_ERROR;\r
   }\r
 \r
-  for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) {\r
-    if (strcmp (pNode->mVarStoreName, StoreName) == 0) {\r
-      return VFR_RETURN_REDEFINED;\r
-    }\r
+  if (GetVarStoreId (StoreName, &VarStoreId) == VFR_RETURN_SUCCESS) {\r
+    return VFR_RETURN_REDEFINED;\r
   }\r
 \r
   VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_EFI);\r
@@ -1559,11 +1605,16 @@ CVfrDataStorage::DeclareBufferVarStore (
 {\r
   SVfrVarStorageNode   *pNew = NULL;\r
   SVfrDataType         *pDataType = NULL;\r
+  EFI_VARSTORE_ID      TempVarStoreId;\r
 \r
   if ((StoreName == NULL) || (Guid == NULL) || (DataTypeDB == NULL)) {\r
     return VFR_RETURN_FATAL_ERROR;\r
   }\r
 \r
+  if (GetVarStoreId (StoreName, &TempVarStoreId) == VFR_RETURN_SUCCESS) {\r
+    return VFR_RETURN_REDEFINED;\r
+  }\r
+\r
   CHECK_ERROR_RETURN(DataTypeDB->GetDataType (TypeName, &pDataType), VFR_RETURN_SUCCESS);\r
 \r
   if (VarStoreId == EFI_VARSTORE_ID_INVALID) {\r
@@ -1589,12 +1640,51 @@ CVfrDataStorage::DeclareBufferVarStore (
   return VFR_RETURN_SUCCESS;\r
 }\r
 \r
+EFI_VFR_RETURN_CODE \r
+CVfrDataStorage::GetVarStoreByDataType (\r
+  IN  CHAR8              *DataTypeName,\r
+  OUT SVfrVarStorageNode **VarNode\r
+  )\r
+{\r
+  SVfrVarStorageNode    *pNode;\r
+  SVfrVarStorageNode    *MatchNode;\r
+  \r
+  //\r
+  // Framework VFR uses Data type name as varstore name, so don't need check again.\r
+  //\r
+  if (VfrCompatibleMode) {\r
+    return VFR_RETURN_UNDEFINED;\r
+  }\r
+\r
+  MatchNode = NULL;\r
+  for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {\r
+    if (strcmp (pNode->mStorageInfo.mDataType->mTypeName, DataTypeName) == 0) {\r
+      if (MatchNode == NULL) {\r
+        MatchNode = pNode;\r
+      } else {\r
+        //\r
+        // More than one varstores referred the same data structures.\r
+        //\r
+        return VFR_RETURN_VARSTORE_DATATYPE_REDEFINED_ERROR;\r
+      }\r
+    }\r
+  }\r
+  \r
+  if (MatchNode == NULL) {\r
+    return VFR_RETURN_UNDEFINED;\r
+  }\r
+\r
+  *VarNode = MatchNode;\r
+  return VFR_RETURN_SUCCESS;\r
+}\r
+\r
 EFI_VFR_RETURN_CODE \r
 CVfrDataStorage::GetVarStoreId (\r
   IN  CHAR8           *StoreName,\r
   OUT EFI_VARSTORE_ID *VarStoreId\r
   )\r
 {\r
+  EFI_VFR_RETURN_CODE   ReturnCode;\r
   SVfrVarStorageNode    *pNode;\r
 \r
   for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {\r
@@ -1622,8 +1712,18 @@ CVfrDataStorage::GetVarStoreId (
   }\r
 \r
   mCurrVarStorageNode = NULL;\r
-  *VarStoreId        = EFI_VARSTORE_ID_INVALID;\r
-  return VFR_RETURN_UNDEFINED;\r
+  *VarStoreId         = EFI_VARSTORE_ID_INVALID;\r
+\r
+  //\r
+  // Assume that Data strucutre name is used as StoreName, and check again. \r
+  //\r
+  ReturnCode = GetVarStoreByDataType (StoreName, &pNode);\r
+  if (pNode != NULL) {\r
+    mCurrVarStorageNode = pNode;\r
+    *VarStoreId = pNode->mVarStoreId;\r
+  }\r
+  \r
+  return ReturnCode;\r
 }\r
 \r
 EFI_VFR_RETURN_CODE\r
@@ -1633,6 +1733,7 @@ CVfrDataStorage::GetBufferVarStoreDataTypeName (
   )\r
 {\r
   SVfrVarStorageNode    *pNode;\r
+  EFI_VFR_RETURN_CODE   ReturnCode;\r
 \r
   if ((StoreName == NULL) || (DataTypeName == NULL)) {\r
     return VFR_RETURN_FATAL_ERROR;\r
@@ -1644,8 +1745,16 @@ CVfrDataStorage::GetBufferVarStoreDataTypeName (
     }\r
   }\r
 \r
+  ReturnCode = VFR_RETURN_UNDEFINED;\r
+  //\r
+  // Assume that Data strucutre name is used as StoreName, and check again. \r
+  //\r
+  if (pNode == NULL) {\r
+    ReturnCode = GetVarStoreByDataType (StoreName, &pNode);\r
+  }\r
+\r
   if (pNode == NULL) {\r
-    return VFR_RETURN_UNDEFINED;\r
+    return ReturnCode;\r
   }\r
 \r
   if (pNode->mStorageInfo.mDataType == NULL) {\r
@@ -1663,6 +1772,7 @@ CVfrDataStorage::GetVarStoreType (
   )\r
 {\r
   SVfrVarStorageNode    *pNode;\r
+  EFI_VFR_RETURN_CODE   ReturnCode;\r
 \r
   if (StoreName == NULL) {\r
     return VFR_RETURN_FATAL_ERROR;\r
@@ -1690,7 +1800,16 @@ CVfrDataStorage::GetVarStoreType (
   }\r
 \r
   VarStoreType = EFI_VFR_VARSTORE_INVALID;\r
-  return VFR_RETURN_UNDEFINED;\r
+\r
+  //\r
+  // Assume that Data strucutre name is used as StoreName, and check again. \r
+  //\r
+  ReturnCode = GetVarStoreByDataType (StoreName, &pNode);\r
+  if (pNode != NULL) {\r
+    VarStoreType = pNode->mVarStoreType;\r
+  }\r
+  \r
+  return ReturnCode;\r
 }\r
 \r
 EFI_VFR_VARSTORE_TYPE\r
@@ -1838,19 +1957,26 @@ CVfrDataStorage::BufferVarStoreRequestElementAdd (
   IN EFI_VARSTORE_INFO &Info\r
   )\r
 {\r
-  CHAR8                 NewReqElt[128] = {'\0',};\r
-  CHAR8                 *OldReqElt = NULL;\r
   SVfrVarStorageNode    *pNode = NULL;\r
   EFI_IFR_TYPE_VALUE    Value = gZeroEfiIfrTypeValue;\r
+  EFI_VFR_RETURN_CODE   ReturnCode;\r
 \r
   for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {\r
-    if (strcmp (pNode->mVarStoreName, StoreName) == NULL) {\r
+    if (strcmp (pNode->mVarStoreName, StoreName) == 0) {\r
       break;\r
     }\r
   }\r
 \r
+  ReturnCode = VFR_RETURN_UNDEFINED;\r
+  //\r
+  // Assume that Data strucutre name is used as StoreName, and check again. \r
+  //\r
   if (pNode == NULL) {\r
-    return VFR_RETURN_UNDEFINED;\r
+    ReturnCode = GetVarStoreByDataType (StoreName, &pNode);\r
+  }\r
+\r
+  if (pNode == NULL) {\r
+    return ReturnCode;\r
   }\r
 \r
   gCVfrBufferConfig.Open ();\r
@@ -2024,85 +2150,6 @@ CVfrDefaultStore::GetDefaultId (
   return VFR_RETURN_UNDEFINED;\r
 }\r
 \r
-STATIC\r
-EFI_VFR_RETURN_CODE\r
-AltCfgItemPrintToBuffer (\r
-  IN CHAR8              *NewAltCfg, \r
-  IN EFI_VARSTORE_INFO  Info, \r
-  IN UINT8              Type,\r
-  IN EFI_IFR_TYPE_VALUE Value\r
-  )\r
-{\r
-  UINT32 Index;\r
-  UINT8  *BufChar = NULL;\r
-  UINT32 Count    = 0;\r
-\r
-  if (NewAltCfg != NULL) {\r
-    Count = sprintf (\r
-              NewAltCfg,\r
-              "&OFFSET=%x&WIDTH=%x&VALUE=",\r
-              Info.mInfo.mVarOffset,\r
-              Info.mVarTotalSize\r
-              );\r
-    NewAltCfg += Count;\r
-\r
-    switch (Type) {\r
-    case EFI_IFR_TYPE_NUM_SIZE_8 :\r
-      Count = sprintf (NewAltCfg, "%x", Value.u8);\r
-      NewAltCfg += Count;\r
-      break;\r
-    case EFI_IFR_TYPE_NUM_SIZE_16 :\r
-      Count = sprintf (NewAltCfg, "%x", Value.u16);\r
-      NewAltCfg += Count;\r
-      break;\r
-    case EFI_IFR_TYPE_NUM_SIZE_32 :\r
-      Count = sprintf (NewAltCfg, "%x", Value.u32);\r
-      NewAltCfg += Count;\r
-      break;\r
-    case EFI_IFR_TYPE_NUM_SIZE_64 :\r
-      Count = sprintf (NewAltCfg, "%x", Value.u64);\r
-      NewAltCfg += Count;\r
-      break;\r
-    case EFI_IFR_TYPE_BOOLEAN :\r
-      Count = sprintf (NewAltCfg, "%x", Value.b);\r
-      NewAltCfg += Count;\r
-      break;\r
-    case EFI_IFR_TYPE_TIME :\r
-#if 1\r
-      Count = sprintf (NewAltCfg, "%x", *((UINT32 *)(&Value.time)));\r
-      NewAltCfg += Count;\r
-#else\r
-      BufChar = (UINT8 *)&Value.time;\r
-      for (Index = 0; Index < sizeof(EFI_HII_TIME); Index++) {\r
-        Count = sprintf (NewAltCfg, "%02x", (UINT8)BufChar[Index]);\r
-        NewAltCfg += Count;\r
-      }\r
-#endif\r
-      break;\r
-    case EFI_IFR_TYPE_DATE :\r
-#if 1\r
-      Count = sprintf (NewAltCfg, "%x", *((UINT32 *)(&Value.date)));\r
-      NewAltCfg += Count;\r
-#else\r
-      BufChar = (UINT8 *)&Value.date;\r
-      for (Index = 0; Index < sizeof(EFI_HII_DATE); Index++) {\r
-        Count = sprintf (NewAltCfg, "%02x", (UINT8)BufChar[Index]);\r
-        NewAltCfg += Count;\r
-      }\r
-#endif\r
-      break;\r
-    case EFI_IFR_TYPE_STRING :\r
-      Count = sprintf (NewAltCfg, "%x", Value.string);\r
-      NewAltCfg += Count;\r
-      break;\r
-    case EFI_IFR_TYPE_OTHER :\r
-      return VFR_RETURN_UNSUPPORTED;\r
-       }\r
-  }\r
-\r
-  return VFR_RETURN_FATAL_ERROR;\r
-}\r
-\r
 EFI_VFR_RETURN_CODE\r
 CVfrDefaultStore::BufferVarStoreAltConfigAdd (\r
   IN EFI_VARSTORE_ID    DefaultId,\r
@@ -2340,6 +2387,7 @@ SVfrQuestionNode::SVfrQuestionNode (
   mQuestionId = EFI_QUESTION_ID_INVALID;\r
   mBitMask    = BitMask;\r
   mNext       = NULL;\r
+  mQtype      = QUESTION_NORMAL;\r
 \r
   if (Name == NULL) {\r
     mName = new CHAR8[strlen ("$DEFAULT") + 1];\r
@@ -2509,6 +2557,9 @@ CVfrQuestionDB::RegisterOldDateQuestion (
   pNode[0]->mQuestionId = QuestionId;\r
   pNode[1]->mQuestionId = QuestionId;\r
   pNode[2]->mQuestionId = QuestionId;\r
+  pNode[0]->mQtype      = QUESTION_DATE;\r
+  pNode[1]->mQtype      = QUESTION_DATE;\r
+  pNode[2]->mQtype      = QUESTION_DATE;\r
   pNode[0]->mNext       = pNode[1];\r
   pNode[1]->mNext       = pNode[2];\r
   pNode[2]->mNext       = mQuestionList;\r
@@ -2585,6 +2636,9 @@ CVfrQuestionDB::RegisterNewDateQuestion (
   pNode[0]->mQuestionId = QuestionId;\r
   pNode[1]->mQuestionId = QuestionId;\r
   pNode[2]->mQuestionId = QuestionId;\r
+  pNode[0]->mQtype      = QUESTION_DATE;\r
+  pNode[1]->mQtype      = QUESTION_DATE;\r
+  pNode[2]->mQtype      = QUESTION_DATE;\r
   pNode[0]->mNext       = pNode[1];\r
   pNode[1]->mNext       = pNode[2];\r
   pNode[2]->mNext       = mQuestionList;\r
@@ -2651,6 +2705,9 @@ CVfrQuestionDB::RegisterOldTimeQuestion (
   pNode[0]->mQuestionId = QuestionId;\r
   pNode[1]->mQuestionId = QuestionId;\r
   pNode[2]->mQuestionId = QuestionId;\r
+  pNode[0]->mQtype      = QUESTION_TIME;\r
+  pNode[1]->mQtype      = QUESTION_TIME;\r
+  pNode[2]->mQtype      = QUESTION_TIME;\r
   pNode[0]->mNext       = pNode[1];\r
   pNode[1]->mNext       = pNode[2];\r
   pNode[2]->mNext       = mQuestionList;\r
@@ -2727,6 +2784,9 @@ CVfrQuestionDB::RegisterNewTimeQuestion (
   pNode[0]->mQuestionId = QuestionId;\r
   pNode[1]->mQuestionId = QuestionId;\r
   pNode[2]->mQuestionId = QuestionId;\r
+  pNode[0]->mQtype      = QUESTION_TIME;\r
+  pNode[1]->mQtype      = QUESTION_TIME;\r
+  pNode[2]->mQtype      = QUESTION_TIME;\r
   pNode[0]->mNext       = pNode[1];\r
   pNode[1]->mNext       = pNode[2];\r
   pNode[2]->mNext       = mQuestionList;\r
@@ -2756,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
@@ -2800,13 +2954,17 @@ CVfrQuestionDB::GetQuestionId (
   IN  CHAR8             *Name,\r
   IN  CHAR8             *VarIdStr,\r
   OUT EFI_QUESTION_ID   &QuestionId,\r
-  OUT UINT32            &BitMask\r
+  OUT UINT32            &BitMask,\r
+  OUT EFI_QUESION_TYPE  *QType\r
   )\r
 {\r
   SVfrQuestionNode *pNode;\r
 \r
   QuestionId = EFI_QUESTION_ID_INVALID;\r
   BitMask    = 0x00000000;\r
+  if (QType != NULL) {\r
+    *QType = QUESTION_NORMAL;\r
+  }\r
 \r
   if ((Name == NULL) && (VarIdStr == NULL)) {\r
     return ;\r
@@ -2827,6 +2985,9 @@ CVfrQuestionDB::GetQuestionId (
 \r
     QuestionId = pNode->mQuestionId;\r
     BitMask    = pNode->mBitMask;\r
+    if (QType != NULL) {\r
+      *QType     = pNode->mQtype;\r
+    }\r
     break;\r
   }\r
 \r
@@ -2873,7 +3034,482 @@ 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
+\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 == '\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, 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
 BOOLEAN  VfrCompatibleMode = FALSE;\r
 \r
 CVfrVarDataTypeDB gCVfrVarDataTypeDB;\r
 \r
+\r