Home | History | Annotate | Download | only in FrameworkHiiOnUefiHiiThunk
      1 /** @file
      2 
      3   This file contains the keyboard processing code to the HII database.
      4 
      5 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 
     17 #include "HiiDatabase.h"
     18 #include "HiiHandle.h"
     19 #include <Library/DebugLib.h>
     20 #include <Guid/ZeroGuid.h>
     21 
     22 CONST CHAR16 FrameworkReservedVarstoreName[] = FRAMEWORK_RESERVED_VARSTORE_NAME;
     23 
     24 /**
     25 
     26   This function returns a list of the package handles of the
     27   specified type that are currently active in the HII database. The
     28   pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package
     29   handles to be listed.
     30 
     31   If HandleBufferLength is NULL, then ASSERT.
     32   If HandleBuffer is NULL, the ASSERT.
     33   If PackageType is EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is
     34   NULL, then ASSERT.
     35   If PackageType is not EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is not
     36   NULL, then ASSERT.
     37 
     38 
     39   @param PackageType          Specifies the package type of the packages
     40                               to list or EFI_HII_PACKAGE_TYPE_ALL for
     41                               all packages to be listed.
     42 
     43   @param PackageGuid          If PackageType is
     44                               EFI_HII_PACKAGE_TYPE_GUID, then this is
     45                               the pointer to the GUID which must match
     46                               the Guid field of
     47                               EFI_HII_PACKAGE_GUID_HEADER. Otherwise, it
     48                               must be NULL.
     49 
     50   @param HandleBufferLength   On output, the length of the handle buffer
     51                               that is required for the handles found.
     52 
     53   @param HandleBuffer         On output, an array of EFI_HII_HANDLE  instances returned.
     54                               The caller is responcible to free this pointer allocated.
     55 
     56   @retval EFI_SUCCESS           The matching handles are outputed successfully.
     57                                 HandleBufferLength is updated with the actual length.
     58   @retval EFI_OUT_OF_RESOURCES  Not enough resource to complete the operation.
     59   @retval EFI_NOT_FOUND         No matching handle could not be found in database.
     60 **/
     61 EFI_STATUS
     62 EFIAPI
     63 ListPackageLists (
     64   IN        UINT8                     PackageType,
     65   IN CONST  EFI_GUID                  *PackageGuid,
     66   IN OUT    UINTN                     *HandleBufferLength,
     67   OUT       EFI_HII_HANDLE            **HandleBuffer
     68   )
     69 {
     70   EFI_STATUS          Status;
     71 
     72   ASSERT (HandleBufferLength != NULL);
     73   ASSERT (HandleBuffer != NULL);
     74 
     75   *HandleBufferLength = 0;
     76   *HandleBuffer       = NULL;
     77 
     78   if (PackageType == EFI_HII_PACKAGE_TYPE_GUID) {
     79     ASSERT (PackageGuid != NULL);
     80   } else {
     81     ASSERT (PackageGuid == NULL);
     82   }
     83 
     84   Status = mHiiDatabase->ListPackageLists (
     85                            mHiiDatabase,
     86                            PackageType,
     87                            PackageGuid,
     88                            HandleBufferLength,
     89                            *HandleBuffer
     90                            );
     91   if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
     92     //
     93     // No packages is registered to UEFI HII Database, just return.
     94     //
     95     //
     96     return Status;
     97   }
     98 
     99   *HandleBuffer = AllocateZeroPool (*HandleBufferLength);
    100 
    101   if (*HandleBuffer == NULL) {
    102     return EFI_OUT_OF_RESOURCES;
    103   }
    104 
    105   return mHiiDatabase->ListPackageLists (
    106                          mHiiDatabase,
    107                          PackageType,
    108                          PackageGuid,
    109                          HandleBufferLength,
    110                          *HandleBuffer
    111                          );
    112 
    113 }
    114 
    115 /**
    116   Exports the contents of one or all package lists in the HII database into a buffer.
    117 
    118   If Handle is not NULL and not a valid EFI_HII_HANDLE registered in the database,
    119   then ASSERT.
    120   If PackageListHeader is NULL, then ASSERT.
    121   If PackageListSize is NULL, then ASSERT.
    122 
    123   @param  Handle                 The HII Handle.
    124   @param  PackageListHeader      A pointer to a buffer that will contain the results of
    125                                  the export function.
    126   @param  PackageListSize        On output, the length of the buffer that is required for the exported data.
    127 
    128   @retval EFI_SUCCESS            Package exported.
    129 
    130   @retval EFI_OUT_OF_RESOURCES   Not enought memory to complete the operations.
    131 
    132 **/
    133 EFI_STATUS
    134 EFIAPI
    135 ExportPackageLists (
    136   IN EFI_HII_HANDLE                    Handle,
    137   OUT EFI_HII_PACKAGE_LIST_HEADER      **PackageListHeader,
    138   OUT UINTN                            *PackageListSize
    139   )
    140 {
    141   EFI_STATUS                       Status;
    142   UINTN                            Size;
    143   EFI_HII_PACKAGE_LIST_HEADER      *PackageListHdr;
    144 
    145   ASSERT (PackageListSize != NULL);
    146   ASSERT (PackageListHeader != NULL);
    147 
    148   Size = 0;
    149   PackageListHdr = NULL;
    150   Status = mHiiDatabase->ExportPackageLists (
    151                            mHiiDatabase,
    152                            Handle,
    153                            &Size,
    154                            PackageListHdr
    155                            );
    156   ASSERT_EFI_ERROR (Status != EFI_BUFFER_TOO_SMALL);
    157 
    158   if (Status == EFI_BUFFER_TOO_SMALL) {
    159     PackageListHdr = AllocateZeroPool (Size);
    160 
    161     if (PackageListHeader == NULL) {
    162       return EFI_OUT_OF_RESOURCES;
    163     } else {
    164       Status = mHiiDatabase->ExportPackageLists (
    165                                mHiiDatabase,
    166                                Handle,
    167                                &Size,
    168                                PackageListHdr
    169                                );
    170     }
    171   }
    172 
    173   if (!EFI_ERROR (Status)) {
    174     *PackageListHeader = PackageListHdr;
    175     *PackageListSize   = Size;
    176   } else {
    177     FreePool (PackageListHdr);
    178   }
    179 
    180   return Status;
    181 }
    182 
    183 /**
    184   Extract Hii package list GUID for given HII handle.
    185 
    186   If HiiHandle could not be found in the HII database, then ASSERT.
    187   If Guid is NULL, then ASSERT.
    188 
    189   @param  Handle              Hii handle
    190   @param  Guid                Package list GUID
    191 
    192   @retval EFI_SUCCESS            Successfully extract GUID from Hii database.
    193 
    194 **/
    195 EFI_STATUS
    196 EFIAPI
    197 ExtractGuidFromHiiHandle (
    198   IN      EFI_HII_HANDLE      Handle,
    199   OUT     EFI_GUID            *Guid
    200   )
    201 {
    202   EFI_STATUS                   Status;
    203   UINTN                        BufferSize;
    204   EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
    205 
    206   ASSERT (Guid != NULL);
    207   ASSERT (Handle != NULL);
    208 
    209   //
    210   // Get HII PackageList
    211   //
    212   BufferSize = 0;
    213   HiiPackageList = NULL;
    214 
    215   Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
    216   ASSERT (Status != EFI_NOT_FOUND);
    217 
    218   if (Status == EFI_BUFFER_TOO_SMALL) {
    219     HiiPackageList = AllocatePool (BufferSize);
    220     ASSERT (HiiPackageList != NULL);
    221 
    222     Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
    223   }
    224   if (EFI_ERROR (Status)) {
    225     FreePool (HiiPackageList);
    226     return Status;
    227   }
    228 
    229   //
    230   // Extract GUID
    231   //
    232   CopyGuid (Guid, &HiiPackageList->PackageListGuid);
    233 
    234   FreePool (HiiPackageList);
    235 
    236   return EFI_SUCCESS;
    237 }
    238 
    239 /**
    240   Find the corressponding UEFI HII Handle from a Framework HII Handle given.
    241 
    242   @param Private      The HII Thunk Module Private context.
    243   @param FwHiiHandle  The Framemwork HII Handle.
    244 
    245   @return NULL        If Framework HII Handle is invalid.
    246   @return The corresponding UEFI HII Handle.
    247 **/
    248 EFI_HII_HANDLE
    249 FwHiiHandleToUefiHiiHandle (
    250   IN CONST HII_THUNK_PRIVATE_DATA      *Private,
    251   IN FRAMEWORK_EFI_HII_HANDLE          FwHiiHandle
    252   )
    253 {
    254   HII_THUNK_CONTEXT            *ThunkContext;
    255 
    256   ASSERT (FwHiiHandle != (FRAMEWORK_EFI_HII_HANDLE) 0);
    257   ASSERT (Private != NULL);
    258 
    259   ThunkContext = FwHiiHandleToThunkContext (Private, FwHiiHandle);
    260 
    261   if (ThunkContext != NULL) {
    262     return ThunkContext->UefiHiiHandle;
    263   }
    264 
    265   return (EFI_HII_HANDLE) NULL;
    266 }
    267 
    268 
    269 /**
    270   Find the corressponding HII Thunk Context from a Framework HII Handle given.
    271 
    272   @param Private      The HII Thunk Module Private context.
    273   @param FwHiiHandle  The Framemwork HII Handle.
    274 
    275   @return NULL        If Framework HII Handle is invalid.
    276   @return The corresponding HII Thunk Context.
    277 **/
    278 HII_THUNK_CONTEXT *
    279 FwHiiHandleToThunkContext (
    280   IN CONST HII_THUNK_PRIVATE_DATA      *Private,
    281   IN FRAMEWORK_EFI_HII_HANDLE          FwHiiHandle
    282   )
    283 {
    284   LIST_ENTRY                 *Link;
    285   HII_THUNK_CONTEXT           *ThunkContext;
    286 
    287 
    288   Link = GetFirstNode (&Private->ThunkContextListHead);
    289 
    290   while (!IsNull (&Private->ThunkContextListHead, Link)) {
    291     ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
    292 
    293     if (FwHiiHandle == ThunkContext->FwHiiHandle) {
    294       return ThunkContext;
    295     }
    296 
    297     Link = GetNextNode (&Private->ThunkContextListHead, Link);
    298   }
    299 
    300   return NULL;
    301 }
    302 
    303 /**
    304   Find the corressponding HII Thunk Context from a UEFI HII Handle given.
    305 
    306   @param Private        The HII Thunk Module Private context.
    307   @param UefiHiiHandle  The UEFI HII Handle.
    308 
    309   @return NULL        If UEFI HII Handle is invalid.
    310   @return The corresponding HII Thunk Context.
    311 **/
    312 HII_THUNK_CONTEXT *
    313 UefiHiiHandleToThunkContext (
    314   IN CONST HII_THUNK_PRIVATE_DATA     *Private,
    315   IN EFI_HII_HANDLE                   UefiHiiHandle
    316   )
    317 {
    318   LIST_ENTRY                 *Link;
    319   HII_THUNK_CONTEXT           *ThunkContext;
    320 
    321   Link = GetFirstNode (&Private->ThunkContextListHead);
    322 
    323   while (!IsNull (&Private->ThunkContextListHead, Link)) {
    324     ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
    325 
    326     if (UefiHiiHandle == ThunkContext->UefiHiiHandle) {
    327       return ThunkContext;
    328     }
    329     Link = GetNextNode (&Private->ThunkContextListHead, Link);
    330   }
    331 
    332   return NULL;
    333 }
    334 
    335 /**
    336   Find the corressponding HII Thunk Context from a Tag GUID.
    337 
    338   @param Private      The HII Thunk Module Private context.
    339   @param Guid         The Tag GUID.
    340 
    341   @return NULL        No HII Thunk Context matched the Tag GUID.
    342   @return The corresponding HII Thunk Context.
    343 **/
    344 HII_THUNK_CONTEXT *
    345 TagGuidToIfrPackThunkContext (
    346   IN CONST HII_THUNK_PRIVATE_DATA *Private,
    347   IN CONST EFI_GUID                   *Guid
    348   )
    349 {
    350   LIST_ENTRY                 *Link;
    351   HII_THUNK_CONTEXT           *ThunkContext;
    352 
    353   Link = GetFirstNode (&Private->ThunkContextListHead);
    354 
    355   while (!IsNull (&Private->ThunkContextListHead, Link)) {
    356     ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
    357 
    358     if (CompareGuid (Guid, &ThunkContext->TagGuid) && (ThunkContext->IfrPackageCount != 0)) {
    359       return ThunkContext;
    360     }
    361 
    362     Link = GetNextNode (&Private->ThunkContextListHead, Link);
    363   }
    364 
    365   return NULL;
    366 
    367 }
    368 
    369 /**
    370   Clean up the HII Thunk Context for a UEFI HII Handle.
    371 
    372   @param Private        The HII Thunk Module Private context.
    373   @param UefiHiiHandle  The UEFI HII Handle.
    374 
    375 **/
    376 VOID
    377 DestroyThunkContextForUefiHiiHandle (
    378   IN HII_THUNK_PRIVATE_DATA     *Private,
    379   IN EFI_HII_HANDLE             UefiHiiHandle
    380   )
    381 {
    382   HII_THUNK_CONTEXT     *ThunkContext;
    383 
    384   ThunkContext = UefiHiiHandleToThunkContext (Private, UefiHiiHandle);
    385   ASSERT (ThunkContext != NULL);
    386 
    387   DestroyThunkContext (ThunkContext);
    388 }
    389 
    390 
    391 /**
    392   This function create a HII_THUNK_CONTEXT for the input UEFI HiiHandle
    393   that is created when a package list registered by a module calling
    394   EFI_HII_DATABASE_PROTOCOL.NewPackageList.
    395   This function records the PackageListGuid of EFI_HII_PACKAGE_LIST_HEADER
    396   into the TagGuid of the created HII_THUNK_CONTEXT.
    397 
    398   @param UefiHiiHandle  The UEFI HII Handle.
    399 
    400   @return the new created Hii thunk context.
    401 
    402 **/
    403 HII_THUNK_CONTEXT *
    404 CreateThunkContextForUefiHiiHandle (
    405   IN  EFI_HII_HANDLE             UefiHiiHandle
    406   )
    407 {
    408   EFI_STATUS            Status;
    409   EFI_GUID              PackageGuid;
    410   HII_THUNK_CONTEXT      *ThunkContext;
    411 
    412   ThunkContext = AllocateZeroPool (sizeof (*ThunkContext));
    413   ASSERT (ThunkContext != NULL);
    414 
    415   ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE;
    416 
    417   Status = AllocateHiiHandle (&ThunkContext->FwHiiHandle);
    418   if (EFI_ERROR (Status)) {
    419     return NULL;
    420   }
    421 
    422   ThunkContext->UefiHiiHandle = UefiHiiHandle;
    423 
    424   Status = ExtractGuidFromHiiHandle (UefiHiiHandle, &PackageGuid);
    425   ASSERT_EFI_ERROR (Status);
    426 
    427   CopyGuid(&ThunkContext->TagGuid, &PackageGuid);
    428 
    429   return ThunkContext;
    430 }
    431 
    432 
    433 /**
    434   Get the number of HII Package for a Package type.
    435 
    436   @param PackageListHeader      The Package List.
    437   @param PackageType            The Package Type.
    438 
    439   @return The number of Package for given type.
    440 **/
    441 UINTN
    442 GetPackageCountByType (
    443   IN CONST EFI_HII_PACKAGE_LIST_HEADER     *PackageListHeader,
    444   IN       UINT8                           PackageType
    445   )
    446 {
    447   UINTN                     Count;
    448   EFI_HII_PACKAGE_HEADER    *PackageHeader;
    449 
    450   PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageListHeader + sizeof (EFI_HII_PACKAGE_LIST_HEADER));
    451   Count = 0;
    452 
    453   while (PackageHeader->Type != EFI_HII_PACKAGE_END) {
    454     if (PackageHeader->Type == PackageType ) {
    455       Count++;
    456     }
    457     PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHeader + PackageHeader->Length);
    458   }
    459 
    460 
    461   return Count;
    462 }
    463 
    464 /**
    465   Get the Form Package from a Framework Package List.
    466 
    467   @param Packages               Framework Package List.
    468 
    469   @return The Form Package Header found.
    470 **/
    471 EFI_HII_PACKAGE_HEADER *
    472 GetIfrPackage (
    473   IN CONST EFI_HII_PACKAGES               *Packages
    474   )
    475 {
    476   UINTN                         Index;
    477   TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;
    478 
    479   ASSERT (Packages != NULL);
    480 
    481   TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId));
    482 
    483   for (Index = 0; Index < Packages->NumberOfPackages; Index++) {
    484     //
    485     // The current UEFI HII build tool generate a binary in the format defined by
    486     // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in
    487     // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount
    488     // may not be the exact number of valid package number in the binary generated
    489     // by HII Build tool.
    490     //
    491     switch (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type) {
    492       case EFI_HII_IFR:
    493         return &TianoAutogenPackageHdrArray[Index]->PackageHeader;
    494         break;
    495       case EFI_HII_STRING:
    496       case EFI_HII_FONT:
    497         break;
    498 
    499       default:
    500         ASSERT (FALSE);
    501         return NULL;
    502         break;
    503     }
    504   }
    505 
    506   return NULL;
    507 }
    508 
    509 /**
    510   Get FormSet GUID.
    511 
    512   ASSERT if no FormSet Opcode is found.
    513 
    514   @param Packages             Form Framework Package.
    515   @param FormSetGuid          Return the FormSet Guid.
    516 
    517 **/
    518 VOID
    519 GetFormSetGuid (
    520   IN  EFI_HII_PACKAGE_HEADER  *Package,
    521   OUT EFI_GUID                *FormSetGuid
    522   )
    523 {
    524   UINTN                         Offset;
    525   EFI_IFR_OP_HEADER             *OpCode;
    526   EFI_IFR_FORM_SET              *FormSet;
    527 
    528   Offset = sizeof (EFI_HII_PACKAGE_HEADER);
    529   while (Offset < Package->Length) {
    530     OpCode = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + Offset);
    531 
    532     switch (OpCode->OpCode) {
    533     case EFI_IFR_FORM_SET_OP:
    534       FormSet = (EFI_IFR_FORM_SET *) OpCode;
    535       CopyGuid (FormSetGuid, (EFI_GUID *)(VOID *)&FormSet->Guid);
    536       return;
    537 
    538       default:
    539         break;
    540 
    541     }
    542     Offset += OpCode->Length;
    543   }
    544 
    545   //
    546   // A proper IFR must have a formset opcode.
    547   //
    548   ASSERT (FALSE);
    549 
    550 }
    551 
    552 /**
    553   Creat a Thunk Context.
    554 
    555   ASSERT if no FormSet Opcode is found.
    556 
    557   @param Private             The HII Thunk Private Context.
    558   @param StringPackageCount  The String package count.
    559   @param IfrPackageCount     The IFR Package count.
    560 
    561   @return  A newly created Thunk Context.
    562   @retval  NULL  No resource to create a new Thunk Context.
    563 **/
    564 HII_THUNK_CONTEXT *
    565 CreateThunkContext (
    566   IN  HII_THUNK_PRIVATE_DATA      *Private,
    567   IN  UINTN                       StringPackageCount,
    568   IN  UINTN                       IfrPackageCount
    569   )
    570 {
    571   EFI_STATUS                   Status;
    572   HII_THUNK_CONTEXT            *ThunkContext;
    573 
    574   ThunkContext = AllocateZeroPool (sizeof (HII_THUNK_CONTEXT));
    575   ASSERT (ThunkContext != NULL);
    576 
    577   ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE;
    578   ThunkContext->IfrPackageCount = IfrPackageCount;
    579   ThunkContext->StringPackageCount = StringPackageCount;
    580   Status = AllocateHiiHandle (&ThunkContext->FwHiiHandle);
    581   if (EFI_ERROR (Status)) {
    582     return NULL;
    583   }
    584 
    585   return ThunkContext;
    586 
    587 }
    588 
    589 /**
    590   Destroy the Thunk Context and free up all resource.
    591 
    592   @param ThunkContext        The HII Thunk Private Context to be freed.
    593 
    594 **/
    595 VOID
    596 DestroyThunkContext (
    597   IN HII_THUNK_CONTEXT          *ThunkContext
    598   )
    599 {
    600   ASSERT (ThunkContext != NULL);
    601 
    602   FreeHiiHandle (ThunkContext->FwHiiHandle);
    603 
    604   RemoveEntryList (&ThunkContext->Link);
    605 
    606   if (ThunkContext->FormSet != NULL) {
    607     DestroyFormSet (ThunkContext->FormSet);
    608   }
    609 
    610   FreePool (ThunkContext);
    611 }
    612 
    613 /**
    614   Get the FormSet's Default Varstore ID based on the rule (Descending Priority):
    615 
    616   1) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01) is found, Var Store ID is used.
    617   2) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID is not found, First Var Store ID is used
    618      as the default Var Store ID.
    619 
    620   @param FormSet The Form Set. The Default Varstore ID is updated if found.
    621 
    622 **/
    623 VOID
    624 GetFormsetDefaultVarstoreId (
    625   IN OUT FORM_BROWSER_FORMSET  * FormSet
    626   )
    627 {
    628   LIST_ENTRY             *StorageList;
    629   FORMSET_STORAGE        *Storage;
    630 
    631   //
    632   // VarStoreId 0 is invalid in UEFI IFR.
    633   //
    634   FormSet->DefaultVarStoreId = 0;
    635   StorageList = GetFirstNode (&FormSet->StorageListHead);
    636 
    637   while (!IsNull (&FormSet->StorageListHead, StorageList)) {
    638     Storage = FORMSET_STORAGE_FROM_LINK (StorageList);
    639 
    640     DEBUG ((EFI_D_INFO, "FormSet %g: Found Varstore ID %x Name %s Size 0x%x\n", &FormSet->Guid, Storage->VarStoreId, Storage->Name, Storage->Size));
    641 
    642     if (Storage->VarStoreId == FRAMEWORK_RESERVED_VARSTORE_ID) {
    643       //
    644       // 1) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01) is found, Var Store ID is used.
    645       //
    646       FormSet->DefaultVarStoreId = FRAMEWORK_RESERVED_VARSTORE_ID;
    647       break;
    648     }
    649 
    650     StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);
    651   }
    652 
    653   if (FormSet->DefaultVarStoreId != FRAMEWORK_RESERVED_VARSTORE_ID) {
    654     //
    655     //
    656     // 2) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID is not found, First Var Store ID is used
    657     //   as the default Var Store ID.
    658     //
    659     StorageList = GetFirstNode (&FormSet->StorageListHead);
    660     if (!IsNull (&FormSet->StorageListHead, StorageList)) {
    661       Storage = FORMSET_STORAGE_FROM_LINK (StorageList);
    662       FormSet->DefaultVarStoreId = Storage->VarStoreId;
    663     }
    664 
    665   }
    666 
    667   if (FormSet->DefaultVarStoreId == 0) {
    668     DEBUG ((EFI_D_INFO, "FormSet %g: No Varstore Found\n", &FormSet->Guid));
    669   }
    670 
    671   return;
    672 }
    673 
    674 /**
    675   Fetch the Ifr binary data of a FormSet.
    676 
    677   @param  Handle                 PackageList Handle
    678   @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero
    679                                  GUID), take the first FormSet found in package
    680                                  list.
    681   @param  BinaryLength           The length of the FormSet IFR binary.
    682   @param  BinaryData             The buffer designed to receive the FormSet.
    683 
    684   @retval EFI_SUCCESS            Buffer filled with the requested FormSet.
    685                                  BufferLength was updated.
    686   @retval EFI_INVALID_PARAMETER  The handle is unknown.
    687   @retval EFI_NOT_FOUND          A form or FormSet on the requested handle cannot
    688                                  be found with the requested FormId.
    689 
    690 **/
    691 EFI_STATUS
    692 GetIfrBinaryData (
    693   IN  EFI_HII_HANDLE   Handle,
    694   IN OUT EFI_GUID      *FormSetGuid,
    695   OUT UINTN            *BinaryLength,
    696   OUT UINT8            **BinaryData
    697   )
    698 {
    699   EFI_STATUS                   Status;
    700   EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
    701   UINTN                        BufferSize;
    702   UINT8                        *Package;
    703   UINT8                        *OpCodeData;
    704   UINT32                       Offset;
    705   UINT32                       Offset2;
    706   BOOLEAN                      ReturnDefault;
    707   UINT32                       PackageListLength;
    708   EFI_HII_PACKAGE_HEADER       PackageHeader;
    709 
    710   OpCodeData = NULL;
    711   Package = NULL;
    712   ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;
    713 
    714   //
    715   // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list
    716   //
    717   if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {
    718     ReturnDefault = TRUE;
    719   } else {
    720     ReturnDefault = FALSE;
    721   }
    722 
    723   //
    724   // Get HII PackageList
    725   //
    726   BufferSize = 0;
    727   HiiPackageList = NULL;
    728   Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
    729   if (Status == EFI_BUFFER_TOO_SMALL) {
    730     HiiPackageList = AllocatePool (BufferSize);
    731     ASSERT (HiiPackageList != NULL);
    732 
    733     Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
    734   }
    735   if (EFI_ERROR (Status) || HiiPackageList == NULL) {
    736     return EFI_NOT_FOUND;
    737   }
    738 
    739   //
    740   // Get Form package from this HII package List
    741   //
    742   Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
    743   Offset2 = 0;
    744   CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
    745 
    746   while (Offset < PackageListLength) {
    747     Package = ((UINT8 *) HiiPackageList) + Offset;
    748     CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
    749 
    750     if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
    751       //
    752       // Search FormSet in this Form Package
    753       //
    754       Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
    755       while (Offset2 < PackageHeader.Length) {
    756         OpCodeData = Package + Offset2;
    757 
    758         if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
    759           //
    760           // Check whether return default FormSet
    761           //
    762           if (ReturnDefault) {
    763             break;
    764           }
    765 
    766           //
    767           // FormSet GUID is specified, check it
    768           //
    769           if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
    770             break;
    771           }
    772         }
    773 
    774         Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
    775       }
    776 
    777       if (Offset2 < PackageHeader.Length) {
    778         //
    779         // Target formset found
    780         //
    781         break;
    782       }
    783     }
    784 
    785     Offset += PackageHeader.Length;
    786   }
    787 
    788   if (Offset >= PackageListLength) {
    789     //
    790     // Form package not found in this Package List
    791     //
    792     gBS->FreePool (HiiPackageList);
    793     return EFI_NOT_FOUND;
    794   }
    795 
    796   if (ReturnDefault && FormSetGuid != NULL) {
    797     //
    798     // Return the default FormSet GUID
    799     //
    800     CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
    801   }
    802 
    803   //
    804   // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
    805   // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
    806   // of the Form Package.
    807   //
    808   *BinaryLength = PackageHeader.Length - Offset2;
    809   *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);
    810 
    811   gBS->FreePool (HiiPackageList);
    812 
    813   if (*BinaryData == NULL) {
    814     return EFI_OUT_OF_RESOURCES;
    815   }
    816 
    817   return EFI_SUCCESS;
    818 }
    819 
    820 /**
    821   Initialize the internal data structure of a FormSet.
    822 
    823   @param  Handle                 PackageList Handle
    824   @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero
    825                                  GUID), take the first FormSet found in package
    826                                  list.
    827   @param  FormSet                FormSet data structure.
    828 
    829   @retval EFI_SUCCESS            The function completed successfully.
    830   @retval EFI_NOT_FOUND          The specified FormSet could not be found.
    831 
    832 **/
    833 EFI_STATUS
    834 InitializeFormSet (
    835   IN  EFI_HII_HANDLE                   Handle,
    836   IN OUT EFI_GUID                      *FormSetGuid,
    837   OUT FORM_BROWSER_FORMSET             *FormSet
    838   )
    839 {
    840   EFI_STATUS                Status;
    841 
    842   Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
    843   if (EFI_ERROR (Status)) {
    844     return Status;
    845   }
    846 
    847   FormSet->HiiHandle = Handle;
    848   CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
    849 
    850   //
    851   // Parse the IFR binary OpCodes
    852   //
    853   Status = ParseOpCodes (FormSet);
    854   if (EFI_ERROR (Status)) {
    855     return Status;
    856   }
    857 
    858   GetFormsetDefaultVarstoreId (FormSet);
    859   return Status;
    860 }
    861 
    862 /**
    863   Parse the Form Package and build a FORM_BROWSER_FORMSET structure.
    864 
    865   @param  UefiHiiHandle          PackageList Handle
    866 
    867   @return A pointer to FORM_BROWSER_FORMSET.
    868 
    869 **/
    870 FORM_BROWSER_FORMSET *
    871 ParseFormSet (
    872   IN EFI_HII_HANDLE   UefiHiiHandle
    873   )
    874 {
    875   FORM_BROWSER_FORMSET  *FormSet;
    876   EFI_GUID              FormSetGuid;
    877   EFI_STATUS            Status;
    878 
    879   FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
    880   ASSERT (FormSet != NULL);
    881 
    882   CopyGuid (&FormSetGuid, &gZeroGuid);
    883   Status = InitializeFormSet (UefiHiiHandle, &FormSetGuid, FormSet);
    884   if (EFI_ERROR (Status)) {
    885     FreePool (FormSet);
    886     return NULL;
    887   }
    888 
    889   return FormSet;
    890 }
    891 
    892