]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Utility.c
clean up for IPF ICC tool chain.
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiToUefiHiiThunk / Utility.c
index 9e41487778f2304022e5e354ea0f6f0ba611640c..48a133da63c6e083438418fa952af198083398fe 100644 (file)
@@ -16,34 +16,19 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "HiiDatabase.h"\r
 #include "HiiHandle.h"\r
+#include <Library/DebugLib.h>\r
 \r
-EFI_GUID  gFrameworkHiiCompatbilityGuid = EFI_IFR_FRAMEWORK_GUID;\r
-EFI_GUID  gTianoHiiIfrGuid              = EFI_IFR_TIANO_GUID;\r
+CONST EFI_GUID  gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
 \r
+/**\r
+  Find the corressponding UEFI HII Handle from a Framework HII Handle given.\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
-\r
-  StartOfNextPackage = (UINT8 *) FormPackage + FormPackage->Header.Length;\r
-  OpCodeData = (EFI_IFR_OP_HEADER *) (FormPackage + 1);\r
-\r
-  while ((UINT8 *) OpCodeData < StartOfNextPackage) {\r
-    if (OpCodeData->OpCode == EFI_IFR_FORM_SET_OP) {\r
-      return AllocateCopyPool (sizeof(EFI_GUID), &(((EFI_IFR_FORM_SET *) OpCodeData)->Guid));\r
-    }\r
-    OpCodeData = (EFI_IFR_OP_HEADER *) ((UINT8 *) OpCodeData + OpCodeData->Length);\r
-  }\r
-\r
-  ASSERT (FALSE);\r
-\r
-  return NULL;\r
-}\r
+  @param Private      The HII Thunk Module Private context.\r
+  @param FwHiiHandle  The Framemwork HII Handle.\r
 \r
+  @return NULL        If Framework HII Handle is invalid.\r
+  @return The corresponding UEFI HII Handle.\r
+**/\r
 EFI_HII_HANDLE\r
 FwHiiHandleToUefiHiiHandle (\r
   IN CONST HII_THUNK_PRIVATE_DATA      *Private,\r
@@ -65,6 +50,15 @@ FwHiiHandleToUefiHiiHandle (
 }\r
 \r
 \r
+/**\r
+  Find the corressponding HII Thunk Context from a Framework HII Handle given.\r
+\r
+  @param Private      The HII Thunk Module Private context.\r
+  @param FwHiiHandle  The Framemwork HII Handle.\r
+\r
+  @return NULL        If Framework HII Handle is invalid.\r
+  @return The corresponding HII Thunk Context.\r
+**/\r
 HII_THUNK_CONTEXT *\r
 FwHiiHandleToThunkContext (\r
   IN CONST HII_THUNK_PRIVATE_DATA      *Private,\r
@@ -90,6 +84,15 @@ FwHiiHandleToThunkContext (
   return NULL;\r
 }\r
 \r
+/**\r
+  Find the corressponding HII Thunk Context from a UEFI HII Handle given.\r
+\r
+  @param Private      The HII Thunk Module Private context.\r
+  @param UEFIHiiHandle  The UEFI HII Handle.\r
+\r
+  @return NULL        If UEFI HII Handle is invalid.\r
+  @return The corresponding HII Thunk Context.\r
+**/\r
 HII_THUNK_CONTEXT *\r
 UefiHiiHandleToThunkContext (\r
   IN CONST HII_THUNK_PRIVATE_DATA     *Private,\r
@@ -113,8 +116,17 @@ UefiHiiHandleToThunkContext (
   return NULL;\r
 }\r
 \r
-EFI_HII_HANDLE *\r
-TagGuidToUefiHiiHandle (\r
+/**\r
+  Find the corressponding HII Thunk Context from a Tag GUID.\r
+\r
+  @param Private      The HII Thunk Module Private context.\r
+  @param Guid         The Tag GUID.\r
+\r
+  @return NULL        No HII Thunk Context matched the Tag GUID.\r
+  @return The corresponding HII Thunk Context.\r
+**/\r
+HII_THUNK_CONTEXT *\r
+TagGuidToIfrPackThunkContext (\r
   IN CONST HII_THUNK_PRIVATE_DATA *Private,\r
   IN CONST EFI_GUID                   *Guid\r
   )\r
@@ -128,7 +140,7 @@ TagGuidToUefiHiiHandle (
     ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);\r
 \r
     if (CompareGuid (Guid, &ThunkContext->TagGuid) && (ThunkContext->IfrPackageCount != 0)) {\r
-      return ThunkContext->UefiHiiHandle;\r
+      return ThunkContext;\r
     }\r
 \r
     Link = GetNextNode (&Private->ThunkContextListHead, Link);\r
@@ -138,7 +150,13 @@ TagGuidToUefiHiiHandle (
   \r
 }\r
 \r
+/**\r
+  Clean up the HII Thunk Context for a UEFI HII Handle.\r
+\r
+  @param Private      The HII Thunk Module Private context.\r
+  @param UEFIHiiHandle  The UEFI HII Handle.\r
 \r
+**/\r
 VOID\r
 DestroyThunkContextForUefiHiiHandle (\r
   IN HII_THUNK_PRIVATE_DATA     *Private,\r
@@ -187,13 +205,18 @@ CreateThunkContextForUefiHiiHandle (
   \r
   CopyGuid(&ThunkContext->TagGuid, &PackageGuid);\r
 \r
-  InitializeListHead (&ThunkContext->QuestionIdMapListHead);\r
-  InitializeListHead (&ThunkContext->OneOfOptionMapListHead);\r
-  \r
   return ThunkContext;\r
 }\r
 \r
 \r
+/**\r
+  Get the number of HII Package for a Package type.\r
+\r
+  @param PackageListHeader      The Package List.\r
+  @param PackageType            The Package Type.\r
+\r
+  @return The number of Package for given type.\r
+**/\r
 UINTN\r
 GetPackageCountByType (\r
   IN CONST EFI_HII_PACKAGE_LIST_HEADER     *PackageListHeader,\r
@@ -217,212 +240,112 @@ GetPackageCountByType (
   return Count;\r
 }\r
 \r
-LIST_ENTRY *\r
-GetOneOfOptionMapEntryListHead (\r
-  IN CONST HII_THUNK_CONTEXT  *ThunkContext,\r
-  IN       UINT16             QuestionId\r
+/**\r
+  Get the Form Package from a Framework Package List.\r
+\r
+  @param Packages               Framework Package List.\r
+\r
+  @return The Form Package Header found.\r
+**/\r
+EFI_HII_PACKAGE_HEADER *\r
+GetIfrPackage (\r
+  IN CONST EFI_HII_PACKAGES               *Packages\r
   )\r
 {\r
-  LIST_ENTRY            *Link;\r
-  ONE_OF_OPTION_MAP     *Map;\r
+  UINTN                         Index;\r
+  TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;\r
 \r
-  Link = GetFirstNode (&ThunkContext->OneOfOptionMapListHead);\r
+  ASSERT (Packages != NULL);\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
+  TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId));\r
+  \r
+  for (Index = 0; Index < Packages->NumberOfPackages; Index++) {\r
+    //\r
+    // The current UEFI HII build tool generate a binary in the format defined by \r
+    // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in\r
+    // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount\r
+    // may not be the exact number of valid package number in the binary generated \r
+    // by HII Build tool.\r
+    //\r
+    switch (TianoAutogenPackageHdrArray[Index]->PackageHeader.Type) {\r
+      case EFI_HII_PACKAGE_FORMS:\r
+        return &TianoAutogenPackageHdrArray[Index]->PackageHeader;\r
+        break;\r
+      case EFI_HII_PACKAGE_STRINGS:\r
+      case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
+        break;\r
+\r
+      //\r
+      // The following fonts are invalid for a module that using Framework to UEFI thunk layer.\r
+      //\r
+      case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:\r
+      case EFI_HII_PACKAGE_FONTS:\r
+      case EFI_HII_PACKAGE_IMAGES:\r
+      default:\r
+        ASSERT (FALSE);\r
+        return NULL;\r
+        break;\r
     }\r
-    Link = GetNextNode (&ThunkContext->OneOfOptionMapListHead, Link);\r
   }\r
-  \r
+\r
   return NULL;\r
 }\r
 \r
+/**\r
+  Get FormSet GUID.\r
+\r
+  ASSERT if no FormSet Opcode is found.\r
 \r
-EFI_STATUS\r
-CreateQuestionIdMap (\r
-  IN    OUT HII_THUNK_CONTEXT  *ThunkContext\r
+  @param Packages             Form Framework Package.\r
+  @param FormSetGuid          Return the FormSet Guid.\r
+\r
+**/\r
+VOID\r
+GetFormSetGuid (\r
+  IN  EFI_HII_PACKAGE_HEADER  *Package,\r
+  OUT EFI_GUID                *FormSetGuid\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_OP_HEADER             *OpCode;\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
+  Offset = sizeof (EFI_HII_PACKAGE_HEADER);\r
+  while (Offset < Package->Length) {\r
+    OpCode = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + Offset);\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
+    switch (OpCode->OpCode) {\r
+    case EFI_IFR_FORM_SET_OP:\r
+      FormSet = (EFI_IFR_FORM_SET *) OpCode;\r
+      CopyGuid (FormSetGuid, (EFI_GUID *)(VOID *)&FormSet->Guid);\r
+      return;\r
+      \r
+      default:\r
+        break;\r
+      \r
+    }\r
+    Offset += OpCode->Length;\r
+  }\r
 \r
   //\r
-  // Skip the package list header.\r
+  // A proper IFR must have a formset opcode.\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
+  ASSERT (FALSE);\r
 \r
-  FreePool (List);\r
-  return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Creat a Thunk Context.\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
+  ASSERT if no FormSet Opcode is found.\r
 \r
+  @param Private             The HII Thunk Private Context.\r
+  @param StringPackageCount  The String package count.\r
+  @param FormSetGuid         The IFR Package count.\r
 \r
+  @return  A newly created Thunk Context.\r
+  @retval  NULL  No resource to create a new Thunk Context.\r
+**/\r
 HII_THUNK_CONTEXT *\r
 CreateThunkContext (\r
   IN  HII_THUNK_PRIVATE_DATA      *Private,\r
@@ -444,14 +367,16 @@ CreateThunkContext (
     return NULL;\r
   }\r
 \r
-  InitializeListHead (&ThunkContext->QuestionIdMapListHead);\r
-  InitializeListHead (&ThunkContext->OneOfOptionMapListHead);\r
-\r
-\r
   return ThunkContext;\r
      \r
 }\r
 \r
+/**\r
+  Destroy the Thunk Context and free up all resource.\r
+\r
+  @param ThunkContext        The HII Thunk Private Context to be freed.\r
+\r
+**/\r
 VOID\r
 DestroyThunkContext (\r
   IN HII_THUNK_CONTEXT          *ThunkContext\r
@@ -461,76 +386,283 @@ DestroyThunkContext (
 \r
   FreeHiiHandle (ThunkContext->FwHiiHandle);\r
 \r
-  DestroyQuestionIdMap (&ThunkContext->QuestionIdMapListHead);\r
-\r
-  DestoryOneOfOptionMap (&ThunkContext->OneOfOptionMapListHead);\r
-\r
   RemoveEntryList (&ThunkContext->Link);\r
 \r
+  if (ThunkContext->FormSet != NULL) {\r
+    DestroyFormSet (ThunkContext->FormSet);\r
+  }\r
+\r
   FreePool (ThunkContext);\r
 }\r
 \r
+/**\r
+  Get the FormSet's Default Varstore ID based on the rule (Descending Priority):\r
+\r
+  1) Var Store ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01).\r
+  2) First Var Store ID.\r
 \r
+  @param FormSet The Form Set.\r
+  \r
+**/\r
 VOID\r
-DestroyQuestionIdMap (\r
-  IN LIST_ENTRY     *QuestionIdMapListHead\r
+GetFormsetDefaultVarstoreId (\r
+  IN OUT FORM_BROWSER_FORMSET  * FormSet\r
   )\r
 {\r
-  QUESTION_ID_MAP           *IdMap;\r
-  QUESTION_ID_MAP_ENTRY     *IdMapEntry;\r
-  LIST_ENTRY                *Link;\r
-  LIST_ENTRY                *Link2;\r
+  LIST_ENTRY             *StorageList;\r
+  FORMSET_STORAGE        *Storage;\r
 \r
-  while (!IsListEmpty (QuestionIdMapListHead)) {\r
-    Link = GetFirstNode (QuestionIdMapListHead);\r
-    \r
-    IdMap = QUESTION_ID_MAP_FROM_LINK (Link);\r
+  //\r
+  // VarStoreId 0 is invalid in UEFI IFR.\r
+  //\r
+  FormSet->DefaultVarStoreId = 0;\r
+  StorageList = GetFirstNode (&FormSet->StorageListHead);\r
 \r
-    while (!IsListEmpty (&IdMap->MapEntryListHead)) {\r
-      Link2 = GetFirstNode (&IdMap->MapEntryListHead);\r
-      \r
-      IdMapEntry = QUESTION_ID_MAP_ENTRY_FROM_LINK (Link);\r
+  while (!IsNull (&FormSet->StorageListHead, StorageList)) {\r
+    Storage = FORMSET_STORAGE_FROM_LINK (StorageList);\r
 \r
-      RemoveEntryList (Link2);\r
+    DEBUG ((EFI_D_INFO, "FormSet %g: Found Varstore ID %x\n", &FormSet->Guid, Storage->VarStoreId));\r
 \r
-      FreePool (IdMapEntry);\r
+    if (Storage->VarStoreId == FRAMEWORK_RESERVED_VARSTORE_ID) {\r
+      FormSet->DefaultVarStoreId = FRAMEWORK_RESERVED_VARSTORE_ID;\r
+      break;\r
     }\r
 \r
-    RemoveEntryList (Link);\r
-    FreePool (IdMap);\r
+    StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);\r
   }\r
+\r
+  if (FormSet->DefaultVarStoreId != FRAMEWORK_RESERVED_VARSTORE_ID) {\r
+    StorageList = GetFirstNode (&FormSet->StorageListHead);\r
+    if (!IsNull (&FormSet->StorageListHead, StorageList)) {\r
+      Storage = FORMSET_STORAGE_FROM_LINK (StorageList);\r
+      FormSet->DefaultVarStoreId = Storage->VarStoreId;\r
+    }\r
+    \r
+  }\r
+\r
+  DEBUG_CODE_BEGIN ();\r
+  if (FormSet->DefaultVarStoreId == 0) {\r
+    DEBUG ((EFI_D_INFO, "FormSet %g: No Varstore Found\n", &FormSet->Guid));\r
+  } else {\r
+    DEBUG ((EFI_D_INFO, "FormSet %g: Default Varstore ID is %x\n", &FormSet->Guid, FormSet->DefaultVarStoreId));\r
+  }\r
+  DEBUG_CODE_END ();\r
+  \r
+  return;\r
 }\r
 \r
-VOID\r
-DestoryOneOfOptionMap (\r
-  IN LIST_ENTRY     *OneOfOptionMapListHead\r
+/**\r
+  Fetch the Ifr binary data of a FormSet.\r
+\r
+  @param  Handle                 PackageList Handle\r
+  @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero\r
+                                 GUID), take the first FormSet found in package\r
+                                 list.\r
+  @param  BinaryLength           The length of the FormSet IFR binary.\r
+  @param  BinaryData             The buffer designed to receive the FormSet.\r
+\r
+  @retval EFI_SUCCESS            Buffer filled with the requested FormSet.\r
+                                 BufferLength was updated.\r
+  @retval EFI_INVALID_PARAMETER  The handle is unknown.\r
+  @retval EFI_NOT_FOUND          A form or FormSet on the requested handle cannot\r
+                                 be found with the requested FormId.\r
+\r
+**/\r
+EFI_STATUS\r
+GetIfrBinaryData (\r
+  IN  EFI_HII_HANDLE   Handle,\r
+  IN OUT EFI_GUID      *FormSetGuid,\r
+  OUT UINTN            *BinaryLength,\r
+  OUT UINT8            **BinaryData\r
   )\r
 {\r
-  ONE_OF_OPTION_MAP         *Map;\r
-  ONE_OF_OPTION_MAP_ENTRY   *MapEntry;\r
-  LIST_ENTRY                *Link;\r
-  LIST_ENTRY                *Link2;\r
+  EFI_STATUS                   Status;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+  UINTN                        BufferSize;\r
+  UINT8                        *Package;\r
+  UINT8                        *OpCodeData;\r
+  UINT32                       Offset;\r
+  UINT32                       Offset2;\r
+  BOOLEAN                      ReturnDefault;\r
+  UINT32                       PackageListLength;\r
+  EFI_HII_PACKAGE_HEADER       PackageHeader;\r
+\r
+  OpCodeData = NULL;\r
+  Package = NULL;\r
+  ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;\r
 \r
-  while (!IsListEmpty (OneOfOptionMapListHead)) {\r
-    Link = GetFirstNode (OneOfOptionMapListHead);\r
-    \r
-    Map = ONE_OF_OPTION_MAP_FROM_LINK (Link);\r
+  //\r
+  // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list\r
+  //\r
+  if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {\r
+    ReturnDefault = TRUE;\r
+  } else {\r
+    ReturnDefault = FALSE;\r
+  }\r
 \r
-    while (!IsListEmpty (&Map->OneOfOptionMapEntryListHead)) {\r
-      Link2 = GetFirstNode (&Map->OneOfOptionMapEntryListHead);\r
-      \r
-      MapEntry = ONE_OF_OPTION_MAP_ENTRY_FROM_LINK (Link);\r
+  //\r
+  // Get HII PackageList\r
+  //\r
+  BufferSize = 0;\r
+  HiiPackageList = NULL;\r
+  Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HiiPackageList = AllocatePool (BufferSize);\r
+    ASSERT (HiiPackageList != NULL);\r
+\r
+    Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get Form package from this HII package List\r
+  //\r
+  Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+  Offset2 = 0;\r
+  CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
+\r
+  while (Offset < PackageListLength) {\r
+    Package = ((UINT8 *) HiiPackageList) + Offset;\r
+    CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+    if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
+      //\r
+      // Search FormSet in this Form Package\r
+      //\r
+      Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
+      while (Offset2 < PackageHeader.Length) {\r
+        OpCodeData = Package + Offset2;\r
+\r
+        if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
+          //\r
+          // Check whether return default FormSet\r
+          //\r
+          if (ReturnDefault) {\r
+            break;\r
+          }\r
+\r
+          //\r
+          // FormSet GUID is specified, check it\r
+          //\r
+          if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
+            break;\r
+          }\r
+        }\r
 \r
-      RemoveEntryList (Link2);\r
+        Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+      }\r
 \r
-      FreePool (MapEntry);\r
+      if (Offset2 < PackageHeader.Length) {\r
+        //\r
+        // Target formset found\r
+        //\r
+        break;\r
+      }\r
     }\r
 \r
-    RemoveEntryList (Link);\r
-    FreePool (Map);\r
+    Offset += PackageHeader.Length;\r
+  }\r
+\r
+  if (Offset >= PackageListLength) {\r
+    //\r
+    // Form package not found in this Package List\r
+    //\r
+    gBS->FreePool (HiiPackageList);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (ReturnDefault && FormSetGuid != NULL) {\r
+    //\r
+    // Return the default FormSet GUID\r
+    //\r
+    CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
+  }\r
+\r
+  //\r
+  // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
+  // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
+  // of the Form Package.\r
+  //\r
+  *BinaryLength = PackageHeader.Length - Offset2;\r
+  *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
+\r
+  gBS->FreePool (HiiPackageList);\r
+\r
+  if (*BinaryData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Initialize the internal data structure of a FormSet.\r
+\r
+  @param  Handle                 PackageList Handle\r
+  @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero\r
+                                 GUID), take the first FormSet found in package\r
+                                 list.\r
+  @param  FormSet                FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_NOT_FOUND          The specified FormSet could not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeFormSet (\r
+  IN  EFI_HII_HANDLE                   Handle,\r
+  IN OUT EFI_GUID                      *FormSetGuid,\r
+  OUT FORM_BROWSER_FORMSET             *FormSet\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+\r
+  Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  FormSet->HiiHandle = Handle;\r
+  CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
+\r
+  //\r
+  // Parse the IFR binary OpCodes\r
+  //\r
+  Status = ParseOpCodes (FormSet);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
   }\r
+\r
+  GetFormsetDefaultVarstoreId (FormSet);\r
+  return Status;\r
 }\r
 \r
+/**\r
+  Parse the Form Package and build a FORM_BROWSER_FORMSET structure.\r
+\r
+  @param  UefiHiiHandle          PackageList Handle\r
+\r
+  @return A pointer to FORM_BROWSER_FORMSET.\r
+\r
+**/\r
+FORM_BROWSER_FORMSET *\r
+ParseFormSet (\r
+  IN EFI_HII_HANDLE   UefiHiiHandle\r
+  )\r
+{\r
+  FORM_BROWSER_FORMSET  *FormSet;\r
+  EFI_GUID              FormSetGuid;\r
+  EFI_STATUS            Status;\r
+  \r
+  FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));    \r
+  ASSERT (FormSet != NULL);\r
 \r
+  CopyGuid (&FormSetGuid, &gZeroGuid);\r
+  Status = InitializeFormSet (UefiHiiHandle, &FormSetGuid, FormSet);\r
+  ASSERT_EFI_ERROR (Status);\r
 \r
+  return FormSet;\r
+}\r
 \r