Home | History | Annotate | Download | only in FrameworkHiiOnUefiHiiThunk
      1 /** @file
      2   Implement protocol interface related to package registrations.
      3 
      4 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 
     16 #include "HiiDatabase.h"
     17 #include "HiiHandle.h"
     18 
     19 
     20 BOOLEAN mInFrameworkHiiNewPack = FALSE;
     21 BOOLEAN mInFrameworkHiiRemovePack = FALSE;
     22 BOOLEAN mInFrameworkUpdatePakcage = FALSE;
     23 UINT64  mGuidCount = 0;
     24 
     25 EFI_GUID mGuidBase = { 0x14f95e01, 0xd562, 0x432e, { 0x84, 0x4a, 0x95, 0xa4, 0x39, 0x5, 0x10, 0x7e }};
     26 
     27 
     28 
     29 /**
     30   Get the number of Form, STRING and Font packages in the package list passed in.
     31 
     32   @param Packages             Package List.
     33   @param IfrPackageCount      Number of IFR Packages.
     34   @param StringPackageCount   Number of String Packages.
     35   @param FontPackageCount     Number of Font Packages.
     36 
     37   @retval EFI_INVALID_PARAMETER If the Package List has package with type of
     38                                 EFI_HII_PACKAGE_KEYBOARD_LAYOUT, EFI_HII_PACKAGE_FONTS, EFI_HII_PACKAGE_IMAGES.
     39   @retval EFI_SUCCESS           Successfully get the number of IFR and STRING package.
     40 
     41 
     42 **/
     43 EFI_STATUS
     44 GetPackageCount (
     45   IN CONST EFI_HII_PACKAGES               *Packages,
     46   OUT UINTN                               *IfrPackageCount,
     47   OUT UINTN                               *StringPackageCount,
     48   OUT UINTN                               *FontPackageCount
     49   )
     50 {
     51   UINTN                         Index;
     52   TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;
     53 
     54   ASSERT (Packages != NULL);
     55   ASSERT (IfrPackageCount != NULL);
     56   ASSERT (StringPackageCount != NULL);
     57   ASSERT (FontPackageCount != NULL);
     58 
     59   *IfrPackageCount = 0;
     60   *StringPackageCount = 0;
     61   *FontPackageCount = 0;
     62 
     63   TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId));
     64 
     65   for (Index = 0; Index < Packages->NumberOfPackages; Index++) {
     66     //
     67     // The current UEFI HII build tool generate a binary in the format defined by
     68     // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in
     69     // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount
     70     // may not be the exact number of valid package number in the binary generated
     71     // by HII Build tool.
     72     //
     73     switch (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type) {
     74       case EFI_HII_IFR:
     75         *IfrPackageCount += 1;
     76         break;
     77       case EFI_HII_STRING:
     78         *StringPackageCount += 1;
     79         break;
     80 
     81       case EFI_HII_FONT:
     82         *FontPackageCount += 1;
     83         break;
     84 
     85       //
     86       // The following fonts are invalid for a module that using Framework to UEFI thunk layer.
     87       //
     88       default:
     89         ASSERT (FALSE);
     90         return EFI_INVALID_PARAMETER;
     91         break;
     92     }
     93   }
     94 
     95   return EFI_SUCCESS;
     96 }
     97 
     98 /**
     99   Insert the String Package into the Package Lists which has the TAG GUID matching
    100   the PackageListGuid of the String Package.
    101 
    102   The Package List must have only IFR Package and no String Package.
    103   Otherwise, ASSERT.
    104 
    105   @param Private                      The HII THUNK driver context data.
    106   @param StringPackageThunkContext    The HII THUNK context data.
    107   @param StringPackageListHeader      The String Package List Header.
    108 
    109 **/
    110 VOID
    111 UpdatePackListWithOnlyIfrPack (
    112   IN       HII_THUNK_PRIVATE_DATA      *Private,
    113   IN       HII_THUNK_CONTEXT            *StringPackageThunkContext,
    114   IN CONST EFI_HII_PACKAGE_LIST_HEADER *StringPackageListHeader
    115   )
    116 {
    117   EFI_STATUS                 Status;
    118   LIST_ENTRY                 *Link;
    119   HII_THUNK_CONTEXT          *ThunkContext;
    120 
    121   Link = GetFirstNode (&Private->ThunkContextListHead);
    122   while (!IsNull (&Private->ThunkContextListHead, Link)) {
    123 
    124     ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
    125 
    126     if (StringPackageThunkContext != ThunkContext) {
    127       //
    128       // Skip the String Package Thunk Entry itself.
    129       //
    130 
    131       if (CompareGuid (&StringPackageListHeader->PackageListGuid, &ThunkContext->TagGuid)) {
    132 
    133         ASSERT (ThunkContext->StringPackageCount == 0 && ThunkContext->IfrPackageCount == 1);
    134 
    135         ThunkContext->StringPackageCount = GetPackageCountByType (StringPackageListHeader, EFI_HII_PACKAGE_STRINGS);
    136 
    137         Status = mHiiDatabase->UpdatePackageList (
    138                                               mHiiDatabase,
    139                                               ThunkContext->UefiHiiHandle,
    140                                               StringPackageListHeader
    141                                               );
    142         ASSERT_EFI_ERROR (Status);
    143 
    144         ThunkContext->SharingStringPack = TRUE;
    145         StringPackageThunkContext->SharingStringPack = TRUE;
    146 
    147       }
    148     }
    149 
    150     Link = GetNextNode (&Private->ThunkContextListHead, Link);
    151   }
    152 
    153 }
    154 
    155 /**
    156   Caculate the size of UEFI Simple Font Package that is needed to
    157   convert all the font a Framework Font Paackage.
    158 
    159   ONLY Narrow Font is supported. Wide Font is discarded.
    160 
    161   If the Package Header is not of EFI_HII_FONT type, then ASSERT.
    162 
    163   @param   PackHeader Pointer to Framework Font Package.
    164 
    165   @return  The size of the UEFI Simple Font Package.
    166 
    167 **/
    168 UINTN
    169 GetUefiSimpleFontPackSize (
    170   IN CONST EFI_HII_PACK_HEADER * PackHeader
    171   )
    172 {
    173   UINTN             Size;
    174   EFI_HII_FONT_PACK *FwFontPack;
    175 
    176   FwFontPack = (EFI_HII_FONT_PACK *) PackHeader;
    177 
    178   ASSERT (FwFontPack->Header.Type == EFI_HII_FONT);
    179 
    180   Size = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR)
    181     + (FwFontPack->NumberOfNarrowGlyphs * sizeof (EFI_NARROW_GLYPH));
    182 
    183    return Size;
    184 }
    185 
    186 
    187 /**
    188   Convert Font Package in Framework format to a newly allocated UEFI
    189   Simple Font Package.
    190 
    191   ONLY Narrow Font is supported. Wide Font is discarded.
    192 
    193   If memory allocation fails, then ASSERT.
    194 
    195   @param PackHeader        Pointer to Framework Font Package header.
    196 
    197   @return UEFI Simple Font Package.
    198 **/
    199 EFI_HII_SIMPLE_FONT_PACKAGE_HDR *
    200 FrameworkFontPackToUefiSimpliedFont (
    201   IN CONST EFI_HII_PACK_HEADER * PackHeader
    202   )
    203 {
    204   EFI_HII_SIMPLE_FONT_PACKAGE_HDR       *FontPack;
    205   UINTN                                 Size;
    206   EFI_NARROW_GLYPH                      *FwNarrowGlyph;
    207   EFI_NARROW_GLYPH                      *NarrowGlyph;
    208   UINTN                                 Idx;
    209   EFI_HII_FONT_PACK                     *FwFontPack;
    210 
    211   Size = GetUefiSimpleFontPackSize (PackHeader);
    212 
    213   FwFontPack = (EFI_HII_FONT_PACK *) PackHeader;
    214 
    215   FontPack      = AllocateZeroPool (Size);
    216   ASSERT (FontPack != NULL);
    217 
    218   //
    219   // Prepare the Header information.
    220   //
    221   FontPack->Header.Length = (UINT32) Size;
    222   FontPack->Header.Type = EFI_HII_PACKAGE_SIMPLE_FONTS;
    223 
    224   FontPack->NumberOfNarrowGlyphs = FwFontPack->NumberOfNarrowGlyphs;
    225 
    226   //
    227   // ONLY Narrow Font is supported. Wide Font is discarded.
    228   //
    229   FontPack->NumberOfWideGlyphs = 0;
    230 
    231   //
    232   // Copy Narrow Glyph
    233   //
    234   NarrowGlyph   = (EFI_NARROW_GLYPH *) (FontPack + 1);
    235   FwNarrowGlyph = (EFI_NARROW_GLYPH *) (FwFontPack + 1);
    236   CopyMem (NarrowGlyph, FwNarrowGlyph, sizeof (EFI_NARROW_GLYPH) * FwFontPack->NumberOfNarrowGlyphs);
    237   for (Idx = 0; Idx < FwFontPack->NumberOfNarrowGlyphs; Idx++) {
    238     //
    239     // Clear the GLYPH_NON_BREAKING (EFI_GLYPH_WIDE is used here as they are all 0x02)
    240     // attribute which is not defined in UEFI EFI_NARROW_GLYPH
    241     //
    242     NarrowGlyph[Idx].Attributes = (UINT8) (NarrowGlyph[Idx].Attributes & ~(EFI_GLYPH_WIDE));
    243   }
    244 
    245   return FontPack;
    246 }
    247 
    248 /**
    249   Prepare a UEFI Package List from a Framework HII package list registered
    250   from a Framework HII NewPack () function.
    251 
    252   If either Packages or PackageListGuid is NULL, then ASSERT.
    253 
    254   @param Packages                     The Framework HII Package List.
    255   @param PackageListGuid              The Package List GUID.
    256 
    257 
    258   @return The UEFI Package List.
    259 **/
    260 EFI_HII_PACKAGE_LIST_HEADER *
    261 PrepareUefiPackageListFromFrameworkHiiPackages (
    262   IN CONST EFI_HII_PACKAGES            *Packages,
    263   IN CONST EFI_GUID                    *PackageListGuid
    264   )
    265 {
    266   UINTN                       NumberOfPackages;
    267   EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
    268   UINT8                       *PackageListData;
    269   UINT32                      PackageListLength;
    270   UINT32                      PackageLength;
    271   EFI_HII_PACKAGE_HEADER      PackageHeader;
    272   UINTN                       Index;
    273   TIANO_AUTOGEN_PACKAGES_HEADER   **TianoAutogenPackageHdrArray;
    274   EFI_HII_SIMPLE_FONT_PACKAGE_HDR *FontPack;
    275 
    276 
    277   ASSERT (Packages != NULL);
    278   ASSERT (PackageListGuid != NULL);
    279 
    280   TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) ((UINT8 *) &Packages->GuidId + sizeof (Packages->GuidId));
    281   NumberOfPackages = Packages->NumberOfPackages;
    282 
    283   PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
    284 
    285   for (Index = 0; Index < NumberOfPackages; Index++) {
    286     if (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type == EFI_HII_FONT) {
    287       //
    288       // There is no tool to generate Font package in Framework HII's implementation.
    289       // Therefore, Font Package be a C structure defined in Framework HII code.
    290       // Therefore, Font Package will be in Framework HII format defined by EFI_HII_FONT_PACK.
    291       // We need to create a UEFI Simple Font Package and copy over all data. Hence, EFI_HII_FONT
    292       // is handled differently than EFI_HII_IFR and EFI_HII_STRING.
    293       //
    294       PackageListLength = (UINT32) (PackageListLength + GetUefiSimpleFontPackSize (&TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader));
    295 
    296     } else {
    297       //
    298       // For EFI_HII_IFR and EFI_HII_STRING, EDK II's VFR Compiler and Build.exe will generate a binary in a format
    299       // defined by TIANO_AUTOGEN_PACKAGES_HEADER. A Framework HII's EFI_HII_PACK_HEADER is inserted before
    300       // the UEFI package data.
    301       //
    302       CopyMem (&PackageLength, &TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Length, sizeof (UINT32));
    303       //
    304       // EFI_HII_PACK_HEADER.FrameworkPackageHeader.Length include the sizeof FrameworkPackageHeader itself.
    305       //
    306       PackageListLength += (PackageLength - sizeof(EFI_HII_PACK_HEADER));
    307 
    308     }
    309   }
    310 
    311   //
    312   // Include the lenght of EFI_HII_PACKAGE_END
    313   //
    314   PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER);
    315   PackageListHeader = AllocateZeroPool (PackageListLength);
    316   ASSERT (PackageListHeader != NULL);
    317 
    318   CopyMem (&PackageListHeader->PackageListGuid, PackageListGuid, sizeof (EFI_GUID));
    319   PackageListHeader->PackageLength = PackageListLength;
    320 
    321   PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);
    322 
    323   //
    324   // Build the UEFI Package List.
    325   //
    326   for (Index = 0; Index < NumberOfPackages; Index++) {
    327     if (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type == EFI_HII_FONT) {
    328       PackageLength = (UINT32) GetUefiSimpleFontPackSize (&TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader);
    329       FontPack = FrameworkFontPackToUefiSimpliedFont (&TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader);
    330       CopyMem (PackageListData, FontPack, PackageLength);
    331       FreePool (FontPack);
    332 
    333     } else {
    334       CopyMem (&PackageLength, &(TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Length), sizeof (UINT32));
    335       PackageLength  -= sizeof (EFI_HII_PACK_HEADER);
    336       CopyMem (PackageListData, &(TianoAutogenPackageHdrArray[Index]->PackageHeader), PackageLength);
    337 
    338     }
    339     PackageListData += PackageLength;
    340   }
    341 
    342   //
    343   // Append EFI_HII_PACKAGE_END
    344   //
    345   PackageHeader.Type = EFI_HII_PACKAGE_END;
    346   PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER);
    347   CopyMem (PackageListData, &PackageHeader, PackageHeader.Length);
    348 
    349   return PackageListHeader;
    350 }
    351 
    352 
    353 /**
    354   Generate a Random GUID.
    355 
    356   @param Guid On output, a Random GUID will be filled.
    357 
    358 **/
    359 VOID
    360 GenerateRandomGuid (
    361   OUT           EFI_GUID * Guid
    362   )
    363 {
    364   CopyGuid (Guid, &mGuidBase);
    365 
    366   mGuidCount++;
    367   *((UINT64 *) Guid) = *((UINT64 *) Guid) + mGuidCount;
    368 }
    369 
    370 /**
    371   Given a Package List with only a IFR package, find the Package List that only has a String Package based on
    372   the TAG GUID. Then export the String Package from the Package List and insert it
    373   to the given IFR package.
    374 
    375   This is to handle the case of Framework HII interface which allow String Package
    376   and IFR package to be registered using two different NewPack () calls.
    377 
    378   @param Private                      The HII THUNK driver context data.
    379   @param IfrThunkContext              Package List with only a IFR package.
    380 
    381   @retval EFI_SUCCESS                 If the String Package is found and inserted to the
    382                                       Package List with only a IFR package.
    383   @retval EFI_NOT_FOUND               No String Package matching the TAG GUID is found.
    384 **/
    385 EFI_STATUS
    386 FindStringPackAndUpdatePackListWithOnlyIfrPack (
    387   IN HII_THUNK_PRIVATE_DATA          *Private,
    388   IN HII_THUNK_CONTEXT                *IfrThunkContext
    389   )
    390 {
    391   EFI_STATUS                      Status;
    392   LIST_ENTRY                      *Link;
    393   EFI_HII_PACKAGE_LIST_HEADER     *StringPackageListHeader;
    394   UINTN                           Size;
    395   HII_THUNK_CONTEXT               *ThunkContext;
    396 
    397   Link = GetFirstNode (&Private->ThunkContextListHead);
    398 
    399   while (!IsNull (&Private->ThunkContextListHead, Link)) {
    400 
    401     ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
    402 
    403     if (ThunkContext != IfrThunkContext) {
    404       if (CompareGuid (&IfrThunkContext->TagGuid, &ThunkContext->TagGuid) && (ThunkContext->IfrPackageCount == 0)) {
    405         StringPackageListHeader = NULL;
    406         Status = ExportPackageLists (ThunkContext->UefiHiiHandle, &StringPackageListHeader, &Size);
    407         ASSERT_EFI_ERROR (Status);
    408         if (StringPackageListHeader == NULL) {
    409           return EFI_NOT_FOUND;
    410         }
    411 
    412         IfrThunkContext->StringPackageCount = GetPackageCountByType (StringPackageListHeader, EFI_HII_PACKAGE_STRINGS);
    413         //
    414         // Add Function to only get only String Packages from the Package List
    415         //
    416         Status = mHiiDatabase->UpdatePackageList (
    417                                   mHiiDatabase,
    418                                   IfrThunkContext->UefiHiiHandle,
    419                                   StringPackageListHeader
    420                                   );
    421         ASSERT_EFI_ERROR (Status);
    422 
    423         FreePool (StringPackageListHeader);
    424 
    425         IfrThunkContext->SharingStringPack = TRUE;
    426         ThunkContext->SharingStringPack = TRUE;
    427 
    428         return EFI_SUCCESS;
    429 
    430       }
    431     }
    432 
    433     Link = GetNextNode (&Private->ThunkContextListHead, Link);
    434   }
    435 
    436   //
    437   // A Form Package must have a String Package to function.
    438   // If ASSERT here, check the sequence of call to Hii->NewPack.
    439   // String Pack must be registered before Ifr Package is registered.
    440   //
    441   ASSERT (FALSE);
    442   return EFI_NOT_FOUND;
    443 
    444 }
    445 
    446 
    447 /**
    448   Register the Package List passed from the Framework HII NewPack () interface.
    449   The FRAMEWORK_EFI_HII_HANDLE will be returned.
    450 
    451   @param This                         The EFI_HII_PROTOCOL context data. Only used
    452                                       to call HiiRemovePack.
    453   @param Private                      The HII THUNK driver context data.
    454   @param Packages                     Package List.
    455   @param Handle                       On output, a FRAMEWORK_EFI_HII_HANDLE number is
    456                                       returned.
    457 
    458   @retval EFI_SUCCESS                 The Package List is registered successfully in
    459                                       the database.
    460   @retval EFI_UNSUPPORTED             The number of IFR package in the package list
    461                                       is greater than 1.
    462   @retval EFI_OUT_OF_RESOURCE         Not enough resouce.
    463 
    464 **/
    465 EFI_STATUS
    466 UefiRegisterPackageList (
    467   IN  EFI_HII_PROTOCOL            *This,
    468   IN  HII_THUNK_PRIVATE_DATA      *Private,
    469   IN  EFI_HII_PACKAGES            *Packages,
    470   OUT FRAMEWORK_EFI_HII_HANDLE    *Handle
    471   )
    472 {
    473   EFI_STATUS                  Status;
    474   UINTN                       StringPackageCount;
    475   UINTN                       IfrPackageCount;
    476   UINTN                       FontPackageCount;
    477   EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
    478   HII_THUNK_CONTEXT           *ThunkContext;
    479   HII_THUNK_CONTEXT           *ThunkContextToRemove;
    480   EFI_GUID                    GuidId;
    481   EFI_HII_PACKAGE_HEADER      *IfrPackage;
    482 
    483   PackageListHeader = NULL;
    484 
    485   Status = GetPackageCount (Packages, &IfrPackageCount, &StringPackageCount, &FontPackageCount);
    486   ASSERT_EFI_ERROR (Status);
    487 
    488   if (IfrPackageCount > 1) {
    489     //
    490     // HII Thunk only handle package with 0 or 1 IFR package.
    491     //
    492     ASSERT (FALSE);
    493     return EFI_UNSUPPORTED;
    494   }
    495 
    496   ThunkContext = CreateThunkContext (Private, StringPackageCount, IfrPackageCount);
    497   if (ThunkContext == NULL) {
    498     return EFI_OUT_OF_RESOURCES;
    499   }
    500   ThunkContext->ByFrameworkHiiNewPack = TRUE;
    501 
    502   if (Packages->GuidId == NULL) {
    503     //
    504     // UEFI HII Database require Package List GUID must be unique.
    505     //
    506     // If Packages->GuidId is NULL, the caller of FramworkHii->NewPack is registering
    507     // packages with at least 1 StringPack and 1 IfrPack. Therefore, Packages->GuidId is
    508     // not used as the name of the package list.  Formset GUID is used as the Package List
    509     // GUID instead.
    510     //
    511     ASSERT ((StringPackageCount >=1 && IfrPackageCount == 1) || (FontPackageCount > 0));
    512     if (IfrPackageCount > 0) {
    513       IfrPackage = GetIfrPackage (Packages);
    514       if (IfrPackage == NULL) {
    515         Status = EFI_NOT_FOUND;
    516         goto Done;
    517       }
    518       GetFormSetGuid (IfrPackage, &ThunkContext->TagGuid);
    519     } else {
    520       ASSERT (FontPackageCount > 0);
    521       GenerateRandomGuid (&ThunkContext->TagGuid);
    522     }
    523 
    524   } else {
    525     ThunkContextToRemove = TagGuidToIfrPackThunkContext (Private, Packages->GuidId);
    526 
    527     if (IfrPackageCount > 0 &&
    528         StringPackageCount > 0 &&
    529         (ThunkContextToRemove != NULL)) {
    530         DEBUG((EFI_D_WARN, "Framework code registers HII package list with the same GUID more than once.\n"));
    531         DEBUG((EFI_D_WARN, "Remove the previously registered package list and register the new one.\n"));
    532         HiiRemovePack (This, ThunkContextToRemove->FwHiiHandle);
    533     }
    534     CopyGuid (&ThunkContext->TagGuid, Packages->GuidId);
    535 
    536   }
    537 
    538   //
    539   // UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so
    540   // that Setup Utility can load the Buffer Storage using this protocol. An UEFI VFR can only
    541   // produce IFR package generated with Buffer Storage type and EFI Variable Storage.
    542   // The default EFI_HII_CONFIG_ACCESS_PROTOCOL is used to Get/Set the Buffer Storage.
    543   //
    544   if (IfrPackageCount != 0) {
    545     InstallDefaultConfigAccessProtocol (Packages, ThunkContext);
    546   }
    547 
    548   PackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, &ThunkContext->TagGuid);
    549   Status = mHiiDatabase->NewPackageList (
    550               mHiiDatabase,
    551               PackageListHeader,
    552               ThunkContext->UefiHiiDriverHandle,
    553               &ThunkContext->UefiHiiHandle
    554               );
    555   if (Status == EFI_INVALID_PARAMETER) {
    556     FreePool (PackageListHeader);
    557 
    558     //
    559     // UEFI HII database does not allow two package list with the same GUID.
    560     // In Framework HII implementation, Packages->GuidId is used as an identifier to associate
    561     // a PackageList with only IFR to a Package list the with String package.
    562     //
    563     GenerateRandomGuid (&GuidId);
    564 
    565     PackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, &GuidId);
    566     Status = mHiiDatabase->NewPackageList (
    567                 mHiiDatabase,
    568                 PackageListHeader,
    569                 ThunkContext->UefiHiiDriverHandle,
    570                 &ThunkContext->UefiHiiHandle
    571                 );
    572   }
    573 
    574   //
    575   // BUGBUG: Remove when development is done
    576   //
    577   ASSERT_EFI_ERROR (Status);
    578   if (EFI_ERROR (Status)) {
    579     goto Done;
    580   }
    581 
    582   if (IfrPackageCount == 0) {
    583     if (StringPackageCount != 0) {
    584       //
    585       // Look for a Package List with only IFR Package with the same TAG GUID name.
    586       // If found one, add the String Packages to the found Package List.
    587       // This is needed because Framework HII Module may not register the String Package
    588       // and IFR Package in one NewPack () call.
    589       //
    590       UpdatePackListWithOnlyIfrPack (
    591           Private,
    592           ThunkContext,
    593           PackageListHeader
    594       );
    595     }
    596   } else {
    597     if (StringPackageCount == 0) {
    598       //
    599       // Look for the String Package with the same TAG GUID name and add
    600       // the found String Package to this Package List.
    601       // This is needed because Framework HII Module may not register the String Package
    602       // and IFR Package in one NewPack () call.
    603       //
    604       Status = FindStringPackAndUpdatePackListWithOnlyIfrPack (
    605                   Private,
    606                   ThunkContext
    607                   );
    608 
    609       if (EFI_ERROR (Status)) {
    610         goto Done;
    611       }
    612     }
    613 
    614     //
    615     // Parse the Formset. Must be called after FindStringPackAndUpdatePackListWithOnlyIfrPack is called so
    616     // that String Package is ready.
    617     //
    618     ThunkContext->FormSet = ParseFormSet (ThunkContext->UefiHiiHandle);
    619     ASSERT (ThunkContext->FormSet != NULL);
    620 
    621   }
    622 
    623 Done:
    624   if (EFI_ERROR (Status)) {
    625     DestroyThunkContext (ThunkContext);
    626   } else {
    627     InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link);
    628     *Handle = ThunkContext->FwHiiHandle;
    629   }
    630 
    631 	if (PackageListHeader != NULL) {
    632     FreePool (PackageListHeader);
    633   }
    634 
    635   return Status;
    636 }
    637 
    638 
    639 /**
    640 
    641   Registers the various packages that are passed in a Package List.
    642 
    643   @param This      Pointer of Frameowk HII protocol instance.
    644   @param Packages  Pointer of HII packages.
    645   @param Handle    Handle value to be returned.
    646 
    647   @retval EFI_SUCCESS           Packages has added to HII database successfully.
    648   @retval EFI_INVALID_PARAMETER If Handle or Packages is NULL.
    649 
    650 **/
    651 EFI_STATUS
    652 EFIAPI
    653 HiiNewPack (
    654   IN  EFI_HII_PROTOCOL               *This,
    655   IN  EFI_HII_PACKAGES               *Packages,
    656   OUT FRAMEWORK_EFI_HII_HANDLE       *Handle
    657   )
    658 {
    659   EFI_STATUS                 Status;
    660   HII_THUNK_PRIVATE_DATA *Private;
    661   EFI_TPL                    OldTpl;
    662 
    663   if (Handle == NULL) {
    664     return EFI_INVALID_PARAMETER;
    665   }
    666 
    667   if (Packages == NULL) {
    668     return EFI_INVALID_PARAMETER;
    669   }
    670 
    671   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
    672 
    673   //
    674   // We use a simple Global variable to inform NewOrAddPackNotify()
    675   // that the package list registered here is already registered
    676   // in the HII Thunk Layer. So NewOrAddPackNotify () does not need to
    677   // call registered the Package List again.
    678   //
    679   mInFrameworkHiiNewPack = TRUE;
    680 
    681   Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
    682 
    683   Status = UefiRegisterPackageList (
    684               This,
    685               Private,
    686               Packages,
    687               Handle
    688             );
    689 
    690   mInFrameworkHiiNewPack = FALSE;
    691 
    692   gBS->RestoreTPL (OldTpl);
    693 
    694   return Status;
    695 }
    696 
    697 /**
    698 
    699   Remove a package from the HII database.
    700 
    701   @param This      Pointer of Frameowk HII protocol instance.
    702   @param Handle    Handle value to be removed.
    703 
    704   @retval EFI_SUCCESS           Packages has added to HII database successfully.
    705   @retval EFI_INVALID_PARAMETER If Handle or Packages is NULL.
    706 
    707 **/
    708 EFI_STATUS
    709 EFIAPI
    710 HiiRemovePack (
    711   IN EFI_HII_PROTOCOL               *This,
    712   IN FRAMEWORK_EFI_HII_HANDLE       Handle
    713   )
    714 {
    715   EFI_STATUS                 Status;
    716   HII_THUNK_PRIVATE_DATA     *Private;
    717   HII_THUNK_CONTEXT          *ThunkContext;
    718   EFI_TPL                    OldTpl;
    719 
    720   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
    721 
    722   mInFrameworkHiiRemovePack = TRUE;
    723 
    724   Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
    725 
    726   ThunkContext = FwHiiHandleToThunkContext (Private, Handle);
    727 
    728   if (ThunkContext != NULL) {
    729     Status = mHiiDatabase->RemovePackageList (
    730                                           mHiiDatabase,
    731                                           ThunkContext->UefiHiiHandle
    732                                           );
    733     ASSERT_EFI_ERROR (Status);
    734 
    735     if (ThunkContext->IfrPackageCount != 0) {
    736       UninstallDefaultConfigAccessProtocol (ThunkContext);
    737     }
    738 
    739     DestroyThunkContext (ThunkContext);
    740   }else {
    741     Status = EFI_NOT_FOUND;
    742   }
    743 
    744   mInFrameworkHiiRemovePack = FALSE;
    745   gBS->RestoreTPL (OldTpl);
    746 
    747   return Status;
    748 }
    749 
    750 /**
    751   This notification function will be called when a Package List is registered
    752   using UEFI HII interface. The Package List registered need to be recorded in
    753   Framework Thunk module as Thunk Module may need to look for String Package in
    754   the package registered.
    755 
    756   If the Package List registered is not either Sting Package or IFR package,
    757   then ASSERT. If the NotifyType is not ADD_PACK or NEW_PACK, then ASSERT.
    758   Both cases means UEFI HII Database itself is buggy.
    759 
    760   @param PackageType The Package Type.
    761   @param PackageGuid The Package GUID.
    762   @param Package     The Package Header.
    763   @param Handle      The HII Handle of this Package List.
    764   @param NotifyType  The reason of the notification.
    765 
    766   @retval EFI_SUCCESS The notification function is successful.
    767 
    768 **/
    769 EFI_STATUS
    770 EFIAPI
    771 NewOrAddPackNotify (
    772   IN UINT8                              PackageType,
    773   IN CONST EFI_GUID                     *PackageGuid,
    774   IN CONST EFI_HII_PACKAGE_HEADER       *Package,
    775   IN EFI_HII_HANDLE                     Handle,
    776   IN EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType
    777   )
    778 {
    779   EFI_STATUS              Status;
    780   HII_THUNK_PRIVATE_DATA  *Private;
    781   HII_THUNK_CONTEXT       *ThunkContext;
    782 
    783   ASSERT (PackageType == EFI_HII_PACKAGE_STRINGS || PackageType == EFI_HII_PACKAGE_FORMS);
    784   ASSERT (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK || NotifyType == EFI_HII_DATABASE_NOTIFY_NEW_PACK);
    785 
    786   Status  = EFI_SUCCESS;
    787   Private = mHiiThunkPrivateData;
    788 
    789   if (mInFrameworkHiiNewPack || mInFrameworkUpdatePakcage) {
    790     return EFI_SUCCESS;
    791   }
    792 
    793   //
    794   // We will create a ThunkContext to log the package list only if the
    795   // package is not registered with by Framework HII Thunk module yet.
    796   //
    797   ThunkContext = UefiHiiHandleToThunkContext (Private, Handle);
    798   if (ThunkContext == NULL) {
    799     ThunkContext = CreateThunkContextForUefiHiiHandle (Handle);
    800     ASSERT (ThunkContext != NULL);
    801 
    802     InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link);
    803   }
    804 
    805   if (PackageType == EFI_HII_PACKAGE_FORMS) {
    806     if (ThunkContext->FormSet != NULL) {
    807       DestroyFormSet (ThunkContext->FormSet);
    808     }
    809 
    810     //
    811     // Reparse the FormSet.
    812     //
    813     ThunkContext->FormSet = ParseFormSet (ThunkContext->UefiHiiHandle);
    814   }
    815 
    816   return Status;
    817 }
    818 
    819 /**
    820   This notification function will be called when a Package List is removed
    821   using UEFI HII interface. The Package List removed need to be removed from
    822   Framework Thunk module too.
    823 
    824   If the Package List registered is not Sting Package,
    825   then ASSERT. If the NotifyType is not REMOVE_PACK, then ASSERT.
    826   Both cases means UEFI HII Database itself is buggy.
    827 
    828   @param PackageType The Package Type.
    829   @param PackageGuid The Package GUID.
    830   @param Package     The Package Header.
    831   @param Handle      The HII Handle of this Package List.
    832   @param NotifyType  The reason of the notification.
    833 
    834   @retval EFI_SUCCESS The notification function is successful.
    835 
    836 **/
    837 EFI_STATUS
    838 EFIAPI
    839 RemovePackNotify (
    840   IN UINT8                              PackageType,
    841   IN CONST EFI_GUID                     *PackageGuid,
    842   IN CONST EFI_HII_PACKAGE_HEADER       *Package,
    843   IN EFI_HII_HANDLE                     Handle,
    844   IN EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType
    845   )
    846 {
    847   EFI_STATUS                  Status;
    848   HII_THUNK_PRIVATE_DATA      *Private;
    849   HII_THUNK_CONTEXT           *ThunkContext;
    850   EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
    851   UINTN                        BufferSize;
    852 
    853   Status = EFI_SUCCESS;
    854 
    855   ASSERT (PackageType == EFI_HII_PACKAGE_STRINGS);
    856   ASSERT (NotifyType == EFI_HII_DATABASE_NOTIFY_REMOVE_PACK);
    857 
    858   if (mInFrameworkHiiRemovePack || mInFrameworkUpdatePakcage) {
    859     return EFI_SUCCESS;
    860   }
    861 
    862   Private = mHiiThunkPrivateData;
    863 
    864   ThunkContext = UefiHiiHandleToThunkContext (Private, Handle);
    865 
    866   //
    867   // BugBug: Change to ASSERT if HII Database fix the bug and to also invoke
    868   // NEW_PACK_NOTIFY for package (String Package) created internally.
    869   //
    870   if (ThunkContext != NULL) {
    871     if (!ThunkContext->ByFrameworkHiiNewPack) {
    872       HiiPackageList = NULL;
    873       Status = ExportPackageLists (Handle, &HiiPackageList, &BufferSize);
    874       ASSERT_EFI_ERROR (Status);
    875       if (HiiPackageList == NULL) {
    876         return EFI_NOT_FOUND;
    877       }
    878 
    879       if (GetPackageCountByType (HiiPackageList, EFI_HII_PACKAGE_STRINGS) == 1) {
    880         //
    881         // If the string package will be removed is the last string package
    882         // in the package list, we will remove the HII Thunk entry from the
    883         // database.
    884         //
    885         DestroyThunkContextForUefiHiiHandle (Private, Handle);
    886       }
    887 
    888       FreePool (HiiPackageList);
    889     }
    890   }
    891 
    892 
    893   return Status;
    894 }
    895 
    896 
    897 
    898