]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Utility.c
Bug fixes for FrameworkHiiToUefiHiiThunk;
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiToUefiHiiThunk / Utility.c
index 03da20eb0dbf8d8301472f18270dcf919a84492f..58019d5b9516b9bb4d58404248e7a53f9ca5188b 100644 (file)
@@ -16,13 +16,17 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "HiiDatabase.h"\r
 \r
+EFI_GUID  gFrameworkHiiCompatbilityGuid = EFI_IFR_FRAMEWORK_GUID;\r
+EFI_GUID  gTianoHiiIfrGuid              = EFI_IFR_TIANO_GUID;\r
+\r
+\r
 EFI_GUID *\r
 GetGuidOfFirstFormset (\r
   CONST EFI_HII_FORM_PACKAGE * FormPackage\r
 ) \r
 {\r
-  UINT8             *StartOfNextPackage;\r
-  EFI_IFR_OP_HEADER *OpCodeData;\r
+  UINT8                   *StartOfNextPackage;\r
+  EFI_IFR_OP_HEADER       *OpCodeData;\r
 \r
   StartOfNextPackage = (UINT8 *) FormPackage + FormPackage->Header.Length;\r
   OpCodeData = (EFI_IFR_OP_HEADER *) (FormPackage + 1);\r
@@ -40,138 +44,430 @@ GetGuidOfFirstFormset (
 }\r
 \r
 EFI_HII_HANDLE\r
-FrameworkHiiHandleToUefiHiiHandle (\r
-  IN CONST EFI_HII_THUNK_PRIVATE_DATA *Private,\r
-  IN FRAMEWORK_EFI_HII_HANDLE          FrameworkHiiHandle\r
+FwHiiHandleToUefiHiiHandle (\r
+  IN CONST HII_THUNK_PRIVATE_DATA      *Private,\r
+  IN FRAMEWORK_EFI_HII_HANDLE          FwHiiHandle\r
   )\r
 {\r
-  HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY  *HandleMapEntry;\r
+  HII_THUNK_CONTEXT            *ThunkContext;\r
 \r
-  ASSERT (FrameworkHiiHandle != (FRAMEWORK_EFI_HII_HANDLE) 0);\r
+  ASSERT (FwHiiHandle != (FRAMEWORK_EFI_HII_HANDLE) 0);\r
   ASSERT (Private != NULL);\r
 \r
-  HandleMapEntry = FrameworkHiiHandleToMapDatabaseEntry (Private, FrameworkHiiHandle);\r
+  ThunkContext = FwHiiHandleToThunkContext (Private, FwHiiHandle);\r
 \r
-  if (HandleMapEntry != NULL) {\r
-    return HandleMapEntry->UefiHiiHandle;\r
+  if (ThunkContext != NULL) {\r
+    return ThunkContext->UefiHiiHandle;\r
   }\r
   \r
   return (EFI_HII_HANDLE) NULL;\r
 }\r
 \r
 \r
-HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *\r
-FrameworkHiiHandleToMapDatabaseEntry (\r
-  IN CONST EFI_HII_THUNK_PRIVATE_DATA *Private,\r
-  IN FRAMEWORK_EFI_HII_HANDLE          FrameworkHiiHandle\r
+HII_THUNK_CONTEXT *\r
+FwHiiHandleToThunkContext (\r
+  IN CONST HII_THUNK_PRIVATE_DATA      *Private,\r
+  IN FRAMEWORK_EFI_HII_HANDLE          FwHiiHandle\r
   )\r
 {\r
-  LIST_ENTRY                 *ListEntry;\r
-  HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMapEntry;\r
+  LIST_ENTRY                 *Link;\r
+  HII_THUNK_CONTEXT           *ThunkContext;\r
+\r
 \r
-  for (ListEntry = Private->HiiThunkHandleMappingDBListHead.ForwardLink;\r
-       ListEntry != &Private->HiiThunkHandleMappingDBListHead;\r
-       ListEntry = ListEntry->ForwardLink\r
-       ) {\r
-    HandleMapEntry = HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY_FROM_LISTENTRY (ListEntry);\r
+  Link = GetFirstNode (&Private->ThunkContextListHead);\r
 \r
-    if (FrameworkHiiHandle == HandleMapEntry->FrameworkHiiHandle) {\r
-      return HandleMapEntry;\r
+  while (!IsNull (&Private->ThunkContextListHead, Link)) {\r
+    ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);\r
+\r
+    if (FwHiiHandle == ThunkContext->FwHiiHandle) {\r
+      return ThunkContext;\r
     }\r
+\r
+    Link = GetNextNode (&Private->ThunkContextListHead, Link);\r
   }\r
 \r
-  return (HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *) NULL;\r
+  return NULL;\r
 }\r
 \r
-HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *\r
-UefiHiiHandleToMapDatabaseEntry (\r
-  IN CONST EFI_HII_THUNK_PRIVATE_DATA *Private,\r
+HII_THUNK_CONTEXT *\r
+UefiHiiHandleToThunkContext (\r
+  IN CONST HII_THUNK_PRIVATE_DATA     *Private,\r
   IN EFI_HII_HANDLE                   UefiHiiHandle\r
   )\r
 {\r
-  LIST_ENTRY                 *ListEntry;\r
-  HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMapEntry;\r
+  LIST_ENTRY                 *Link;\r
+  HII_THUNK_CONTEXT           *ThunkContext;\r
 \r
-  for (ListEntry = Private->HiiThunkHandleMappingDBListHead.ForwardLink;\r
-       ListEntry != &Private->HiiThunkHandleMappingDBListHead;\r
-       ListEntry = ListEntry->ForwardLink\r
-       ) {\r
-    HandleMapEntry = HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY_FROM_LISTENTRY (ListEntry);\r
+  Link = GetFirstNode (&Private->ThunkContextListHead);\r
 \r
-    if (UefiHiiHandle == HandleMapEntry->UefiHiiHandle) {\r
-      return HandleMapEntry;\r
+  while (!IsNull (&Private->ThunkContextListHead, Link)) {\r
+    ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);\r
+\r
+    if (UefiHiiHandle == ThunkContext->UefiHiiHandle) {\r
+      return ThunkContext;\r
     }\r
+    Link = GetNextNode (&Private->ThunkContextListHead, Link);\r
   }\r
 \r
-  return (HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *) NULL;\r
+  return NULL;\r
 }\r
 \r
 EFI_HII_HANDLE *\r
-TagGuidToUefiIfrHiiHandle (\r
-  IN CONST EFI_HII_THUNK_PRIVATE_DATA *Private,\r
+TagGuidToUefiHiiHandle (\r
+  IN CONST HII_THUNK_PRIVATE_DATA *Private,\r
   IN CONST EFI_GUID                   *Guid\r
   )\r
 {\r
-  LIST_ENTRY                 *ListEntry;\r
-  HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMapEntry;\r
+  LIST_ENTRY                 *Link;\r
+  HII_THUNK_CONTEXT           *ThunkContext;\r
+\r
+  Link = GetFirstNode (&Private->ThunkContextListHead);\r
 \r
-  for (ListEntry = Private->HiiThunkHandleMappingDBListHead.ForwardLink;\r
-       ListEntry != &Private->HiiThunkHandleMappingDBListHead;\r
-       ListEntry = ListEntry->ForwardLink\r
-       ) {\r
-    HandleMapEntry = HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY_FROM_LISTENTRY (ListEntry);\r
+  while (!IsNull (&Private->ThunkContextListHead, Link)) {\r
+    ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);\r
 \r
-    if (CompareGuid (Guid, &HandleMapEntry->TagGuid) && HandleMapEntry->DoesPackageListImportStringPackages) {\r
-      return HandleMapEntry->UefiHiiHandle;\r
+    if (CompareGuid (Guid, &ThunkContext->TagGuid) && (ThunkContext->IfrPackageCount != 0)) {\r
+      return ThunkContext->UefiHiiHandle;\r
     }\r
+\r
+    Link = GetNextNode (&Private->ThunkContextListHead, Link);\r
   }\r
 \r
-  return (EFI_HII_HANDLE *) NULL;\r
+  return NULL;\r
   \r
 }\r
 \r
 BOOLEAN\r
 IsFrameworkHiiDatabaseHandleDepleted (\r
-  IN CONST EFI_HII_THUNK_PRIVATE_DATA *Private\r
+  IN CONST HII_THUNK_PRIVATE_DATA *Private\r
   )\r
 {\r
   return (BOOLEAN) (Private->StaticHiiHandle == (UINTN) Private->StaticPureUefiHiiHandle);\r
 }\r
 \r
 EFI_STATUS\r
-\r
-AssignHiiHandle (\r
-  IN OUT EFI_HII_THUNK_PRIVATE_DATA *Private,\r
+AssignFrameworkHiiHandle (\r
+  IN OUT HII_THUNK_PRIVATE_DATA     *Private,\r
+  IN     BOOLEAN                    FromFwHiiNewPack,\r
   OUT    FRAMEWORK_EFI_HII_HANDLE   *Handle\r
   )\r
 {\r
   ASSERT (Handle != NULL);\r
 \r
-  *Handle = Private->StaticHiiHandle;\r
-  Private->StaticHiiHandle += 1;\r
+  if (FromFwHiiNewPack) {\r
+\r
+    *Handle = Private->StaticHiiHandle;\r
+    Private->StaticHiiHandle += 1;\r
+\r
+    if (IsFrameworkHiiDatabaseHandleDepleted (Private)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+  } else {\r
+\r
+    *Handle = Private->StaticPureUefiHiiHandle;\r
+    Private->StaticPureUefiHiiHandle -= 1;\r
+    \r
+    if (IsFrameworkHiiDatabaseHandleDepleted (Private)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
 \r
-  if (IsFrameworkHiiDatabaseHandleDepleted (Private)) {\r
-    return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
 EFI_STATUS\r
-AssignPureUefiHiiHandle (\r
-  IN OUT EFI_HII_THUNK_PRIVATE_DATA *Private,\r
-    OUT    FRAMEWORK_EFI_HII_HANDLE   *Handle\r
+DestroyThunkContextForUefiHiiHandle (\r
+  IN HII_THUNK_PRIVATE_DATA     *Private,\r
+  IN EFI_HII_HANDLE             UefiHiiHandle\r
+ )\r
+{\r
+  HII_THUNK_CONTEXT     *ThunkContext;\r
+\r
+  ThunkContext = UefiHiiHandleToThunkContext (Private, UefiHiiHandle);\r
+  ASSERT (ThunkContext != NULL);\r
+\r
+  ASSERT (IsListEmpty (&ThunkContext->OneOfOptionMapListHead));\r
+  ASSERT (IsListEmpty (&ThunkContext->QuestionIdMapListHead));\r
+  \r
+  RemoveEntryList (&ThunkContext->Link);\r
+\r
+  FreePool (ThunkContext);\r
+    \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function create a HII_THUNK_CONTEXT for a package list registered\r
+  by a module calling EFI_HII_DATABASE_PROTOCOL.NewPackageList. It records\r
+  the PackageListGuid in EFI_HII_PACKAGE_LIST_HEADER in the TagGuid in \r
+  HII_THUNK_CONTEXT created. This TagGuid will be used as a key to s\r
+\r
+**/\r
+HII_THUNK_CONTEXT *\r
+CreateThunkContextForUefiHiiHandle (\r
+  IN  HII_THUNK_PRIVATE_DATA     *Private,\r
+  IN  EFI_HII_HANDLE             UefiHiiHandle\r
+ )\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_GUID              PackageGuid;\r
+  HII_THUNK_CONTEXT      *ThunkContext;\r
+\r
+  ThunkContext = AllocateZeroPool (sizeof (*ThunkContext));\r
+  ASSERT (ThunkContext != NULL);\r
+  \r
+  ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE;\r
+\r
+  Status = AssignFrameworkHiiHandle (Private, FALSE, &ThunkContext->FwHiiHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+  \r
+  ThunkContext->UefiHiiHandle = UefiHiiHandle;\r
+  \r
+  Status = HiiLibExtractGuidFromHiiHandle (UefiHiiHandle, &PackageGuid);\r
+  ASSERT_EFI_ERROR (Status);\r
+  \r
+  CopyGuid(&ThunkContext->TagGuid, &PackageGuid);\r
+\r
+  InitializeListHead (&ThunkContext->QuestionIdMapListHead);\r
+  InitializeListHead (&ThunkContext->OneOfOptionMapListHead);\r
+  \r
+  InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link);\r
+\r
+  return ThunkContext;\r
+}\r
+\r
+\r
+UINTN\r
+GetPackageCountByType (\r
+  IN CONST EFI_HII_PACKAGE_LIST_HEADER     *PackageListHeader,\r
+  IN       UINT8                           PackageType\r
   )\r
 {\r
-  ASSERT (Handle != NULL);\r
+  UINTN                     Count;\r
+  EFI_HII_PACKAGE_HEADER    *PackageHeader;\r
+\r
+  PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageListHeader + sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
+  Count = 0;\r
+  \r
+  while (PackageHeader->Type != EFI_HII_PACKAGE_END) {\r
+    if (PackageHeader->Type == PackageType ) {\r
+      Count++;\r
+    }\r
+    PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHeader + PackageHeader->Length);\r
+  }\r
+  \r
+  \r
+  return Count;\r
+}\r
+\r
+LIST_ENTRY *\r
+GetOneOfOptionMapEntryListHead (\r
+  IN CONST HII_THUNK_CONTEXT  *ThunkContext,\r
+  IN       UINT16             QuestionId\r
+  )\r
+{\r
+  LIST_ENTRY            *Link;\r
+  ONE_OF_OPTION_MAP     *Map;\r
+\r
+  Link = GetFirstNode (&ThunkContext->OneOfOptionMapListHead);\r
+\r
+  while (!IsNull (&ThunkContext->OneOfOptionMapListHead, Link)) {\r
+    Map = ONE_OF_OPTION_MAP_FROM_LINK (Link);\r
+    if (QuestionId == Map->QuestionId) {\r
+      return &Map->OneOfOptionMapEntryListHead;\r
+    }\r
+    Link = GetNextNode (&ThunkContext->OneOfOptionMapListHead, Link);\r
+  }\r
+  \r
+  return NULL;\r
+}\r
 \r
-  *Handle = Private->StaticPureUefiHiiHandle;\r
-  Private->StaticPureUefiHiiHandle -= 1;\r
 \r
-  if (IsFrameworkHiiDatabaseHandleDepleted (Private)) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+EFI_STATUS\r
+CreateQuestionIdMap (\r
+  IN    OUT HII_THUNK_CONTEXT  *ThunkContext\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_HII_PACKAGE_LIST_HEADER   *List;\r
+  EFI_HII_PACKAGE_HEADER        *Package;\r
+  UINTN                         Size;\r
+  EFI_IFR_OP_HEADER             *OpCode;\r
+  UINTN                         Offset;\r
+  QUESTION_ID_MAP               *IdMap;\r
+  EFI_IFR_VARSTORE              *VarStore;\r
+  EFI_IFR_FORM_SET              *FormSet;\r
+  EFI_IFR_QUESTION_HEADER       *Question;\r
+  LIST_ENTRY                    *QuestionIdMapEntryListHead;\r
+  LIST_ENTRY                    *OneOfOptinMapEntryListHead;\r
+  QUESTION_ID_MAP_ENTRY         *IdMapEntry;\r
+  EFI_IFR_GUID_OPTIONKEY        *OptionMap;\r
+  ONE_OF_OPTION_MAP             *OneOfOptionMap;\r
+  ONE_OF_OPTION_MAP_ENTRY       *OneOfOptionMapEntry;\r
+  EFI_IFR_GUID_CLASS            *Class;\r
+  \r
+\r
+  Status = HiiLibExportPackageLists (ThunkContext->UefiHiiHandle, &List, &Size);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
   }\r
 \r
+  //\r
+  // Get all VarStoreId and build the the QuestionId map.\r
+  // EFI_IFR_QUESTION_HEADER.VarStoreInfo.VarOffset -> Framework Question ID\r
+  // EFI_IFR_QUESTION_HEADER.QuestionId             -> UEFI Question ID\r
+  //\r
+\r
+  //\r
+  // Skip the package list header.\r
+  //\r
+  Package = (EFI_HII_PACKAGE_HEADER *) (List + 1);\r
+\r
+  while (Package->Type != EFI_HII_PACKAGE_END) {\r
+\r
+    if (Package->Type == EFI_HII_PACKAGE_FORM) {\r
+\r
+      //\r
+      // Skip the package header\r
+      //\r
+      Offset = sizeof (EFI_HII_PACKAGE_HEADER);\r
+      while (Offset < Package->Length) {\r
+        OpCode = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + Offset);\r
+\r
+        switch (OpCode->OpCode) {\r
+        case EFI_IFR_FORM_SET_OP:\r
+          FormSet = (EFI_IFR_FORM_SET *) OpCode;\r
+          ThunkContext->FormSetTitle = FormSet->FormSetTitle;\r
+          ThunkContext->FormSetHelp  = FormSet->Help;\r
+          break;\r
+          \r
+        case EFI_IFR_VARSTORE_OP:\r
+          //\r
+          // IFR built from Framework VFR only has UEFI Buffer Type Storage\r
+          //\r
+          VarStore = (EFI_IFR_VARSTORE *) OpCode;\r
+          IdMap = AllocateZeroPool (sizeof (QUESTION_ID_MAP));\r
+          ASSERT (IdMap != NULL);\r
+          \r
+          IdMap->Signature  = QUESTION_ID_MAP_SIGNATURE;\r
+          IdMap->VarStoreId = VarStore->VarStoreId;\r
+          IdMap->VarSize    = VarStore->Size;\r
+          InitializeListHead (&IdMap->MapEntryListHead);\r
+          InsertTailList (&ThunkContext->QuestionIdMapListHead, &IdMap->Link);\r
+          break;\r
+\r
+        case EFI_IFR_NUMERIC_OP:\r
+        case EFI_IFR_CHECKBOX_OP:\r
+        case EFI_IFR_ONE_OF_OP:\r
+        case EFI_IFR_ORDERED_LIST_OP:\r
+        case EFI_IFR_STRING_OP:\r
+        //case EFI_IFR_PASSWORD_OP:\r
+          Question = (EFI_IFR_QUESTION_HEADER *)(OpCode + 1);\r
+          QuestionIdMapEntryListHead = GetMapEntryListHead (ThunkContext, Question->VarStoreId);\r
+\r
+          if (QuestionIdMapEntryListHead != NULL) {\r
+            //\r
+            // If the Question is using Buffer (EFI_IFR_VARSTORE_OP) type VarStore.\r
+            //\r
+            IdMapEntry = AllocateZeroPool (sizeof (QUESTION_ID_MAP_ENTRY));\r
+            ASSERT (IdMapEntry != NULL);\r
+\r
+            IdMapEntry->FwQId = Question->VarStoreInfo.VarOffset;\r
+            IdMapEntry->UefiQid = Question->QuestionId;\r
+            IdMapEntry->Signature = QUESTION_ID_MAP_ENTRY_SIGNATURE;\r
+\r
+            InsertTailList (QuestionIdMapEntryListHead, &IdMapEntry->Link);\r
+          }\r
+\r
+          break;\r
+       \r
+        case EFI_IFR_GUID_OP:\r
+          OptionMap = (EFI_IFR_GUID_OPTIONKEY *) OpCode;\r
+          if (CompareGuid (&OptionMap->Guid, &gFrameworkHiiCompatbilityGuid)) {\r
+            if (OptionMap->ExtendOpCode == EFI_IFR_EXTEND_OP_OPTIONKEY) {\r
+              OneOfOptinMapEntryListHead = GetOneOfOptionMapEntryListHead (ThunkContext, OptionMap->QuestionId);\r
+              if (OneOfOptinMapEntryListHead == NULL) {\r
+                OneOfOptionMap = AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP));\r
+                ASSERT (OneOfOptionMap != NULL);\r
+\r
+                OneOfOptionMap->Signature = ONE_OF_OPTION_MAP_SIGNATURE;\r
+                OneOfOptionMap->QuestionId = OptionMap->QuestionId;\r
+                OneOfOptionMap->ValueType = EFI_IFR_TYPE_NUM_SIZE_8;\r
+                InitializeListHead (&OneOfOptionMap->OneOfOptionMapEntryListHead);\r
+                OneOfOptinMapEntryListHead = &OneOfOptionMap->OneOfOptionMapEntryListHead;\r
+                InsertTailList (&ThunkContext->OneOfOptionMapListHead, &OneOfOptionMap->Link);\r
+              }\r
+              OneOfOptionMapEntry = AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP_ENTRY));\r
+              ASSERT (OneOfOptionMapEntry != NULL);\r
+\r
+              OneOfOptionMapEntry->Signature = ONE_OF_OPTION_MAP_ENTRY_SIGNATURE;\r
+              OneOfOptionMapEntry->FwKey = OptionMap->KeyValue;\r
+              CopyMem (&OneOfOptionMapEntry->Value, &OptionMap->OptionValue, sizeof (EFI_IFR_TYPE_VALUE));\r
+              \r
+              InsertTailList (OneOfOptinMapEntryListHead, &OneOfOptionMapEntry->Link);\r
+            }\r
+          }else if (CompareGuid (&OptionMap->Guid, &gTianoHiiIfrGuid)) {\r
+            Class = (EFI_IFR_GUID_CLASS *) OpCode;\r
+\r
+            switch (Class->ExtendOpCode) {\r
+              case EFI_IFR_EXTEND_OP_CLASS:\r
+                ThunkContext->FormSetClass = Class->Class;\r
+                break;\r
+              case EFI_IFR_EXTEND_OP_SUBCLASS:\r
+                ThunkContext->FormSetSubClass = ((EFI_IFR_GUID_SUBCLASS *) Class)->SubClass;\r
+                break;\r
+\r
+              default:\r
+                break;\r
+            }\r
+          }\r
+          break;\r
+          \r
+        default:\r
+          break;\r
+        \r
+        }\r
+\r
+        Offset += OpCode->Length;\r
+      }\r
+      //\r
+      // Only Form Package is in a Package List.\r
+      //\r
+      break;\r
+    }\r
+\r
+    Package = (EFI_HII_PACKAGE_HEADER *) (UINT8 *) Package + Package->Length;\r
+  }\r
+\r
+  FreePool (List);\r
   return EFI_SUCCESS;\r
 }\r
 \r
+\r
+LIST_ENTRY *\r
+GetMapEntryListHead (\r
+  IN CONST HII_THUNK_CONTEXT  *ThunkContext,\r
+  IN       UINT16             VarStoreId\r
+  )\r
+{\r
+  LIST_ENTRY            *Link;\r
+  QUESTION_ID_MAP       *Map;\r
+\r
+  Link = GetFirstNode (&ThunkContext->QuestionIdMapListHead);\r
+\r
+  while (!IsNull (&ThunkContext->QuestionIdMapListHead, Link)) {\r
+    Map = QUESTION_ID_MAP_FROM_LINK (Link);\r
+    if (VarStoreId == Map->VarStoreId) {\r
+      return &Map->MapEntryListHead;\r
+    }\r
+    Link = GetNextNode (&ThunkContext->QuestionIdMapListHead, Link);\r
+  }\r
+  return NULL;\r
+}\r
+\r
+\r