]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Package.c
1) StrGather (Build.exe) in compatible mode add a Framework Package Header to replace...
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiToUefiHiiThunk / Package.c
index d84eadeb93971926dbdc40ed13454534468c56d8..0aa4773abe2b85af727b911eeb5d4873a80613f4 100644 (file)
@@ -17,16 +17,31 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "HiiHandle.h"\r
 \r
 \r
-STATIC BOOLEAN mInFrameworkHiiNewPack = FALSE;\r
-STATIC BOOLEAN mInFrameworkHiiRemovePack = FALSE;\r
+BOOLEAN mInFrameworkHiiNewPack = FALSE;\r
+BOOLEAN mInFrameworkHiiRemovePack = FALSE;\r
 BOOLEAN mInFrameworkUpdatePakcage = FALSE;\r
+UINT64  mGuidCount = 0;\r
 \r
 \r
+/**\r
+  Get the number of package IFR and STRING packages in the package list passed in.\r
+\r
+  @param Packages             Package List.\r
+  @param IfrPackageCount      Number of IFR Packages.\r
+  @param StringPackageCount   Number of String Packages.\r
+\r
+  @retval EFI_INVALID_PARAMETER If the Package List has package with type of \r
+                                EFI_HII_PACKAGE_KEYBOARD_LAYOUT, EFI_HII_PACKAGE_FONTS, EFI_HII_PACKAGE_IMAGES.\r
+  @reval  EFI_SUCCESS           Successfully get the number of IFR and STRING package.\r
+                                 \r
+\r
+**/\r
 EFI_STATUS\r
 GetPackageCount (\r
   IN CONST EFI_HII_PACKAGES               *Packages,\r
-  UINTN                                   *IfrPackageCount,\r
-  UINTN                                   *StringPackageCount\r
+  OUT UINTN                               *IfrPackageCount,\r
+  OUT UINTN                               *StringPackageCount,\r
+  OUT UINTN                               *FontPackageCount\r
   )\r
 {\r
   UINTN                         Index;\r
@@ -35,9 +50,11 @@ GetPackageCount (
   ASSERT (Packages != NULL);\r
   ASSERT (IfrPackageCount != NULL);\r
   ASSERT (StringPackageCount != NULL);\r
+  ASSERT (FontPackageCount != NULL);\r
 \r
   *IfrPackageCount = 0;\r
   *StringPackageCount = 0;\r
+  *FontPackageCount = 0;\r
 \r
   TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId));\r
   \r
@@ -49,23 +66,21 @@ GetPackageCount (
     // 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_FORM:\r
+    switch (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type) {\r
+      case EFI_HII_IFR:\r
         *IfrPackageCount += 1;\r
         break;\r
-      case EFI_HII_PACKAGE_STRINGS:\r
+      case EFI_HII_STRING:\r
         *StringPackageCount += 1;\r
         break;\r
 \r
-      case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
+      case EFI_HII_FONT:\r
+        *FontPackageCount += 1;\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 EFI_INVALID_PARAMETER;\r
@@ -76,6 +91,18 @@ GetPackageCount (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Insert the String Package into the Package Lists which has the TAG GUID matching\r
+  the PackageListGuid of the String Package. \r
+\r
+  The Package List must have only IFR Package and no String Package. \r
+  Otherwise, ASSERT.\r
+\r
+  @param Private                      The HII THUNK driver context data.\r
+  @param StringPackageThunkContext    The HII THUNK context data.\r
+  @param StringPackageListHeader      The String Package List Header.\r
+  \r
+**/\r
 VOID\r
 UpdatePackListWithOnlyIfrPack (\r
   IN       HII_THUNK_PRIVATE_DATA      *Private,\r
@@ -118,7 +145,111 @@ UpdatePackListWithOnlyIfrPack (
   \r
 }\r
 \r
+/**\r
+  Caculate the size of UEFI Simple Font Package that is needed to \r
+  convert all the font a Framework Font Paackage.\r
+\r
+  ONLY Narrow Font is supported. Wide Font is discarded. \r
+\r
+  If the Package Header is not of EFI_HII_FONT type, then ASSERT.\r
+\r
+  @param   The Package header of the Framework Font Package.\r
+  \r
+  @return  The size of the UEFI Simple Font Package.\r
+  \r
+**/\r
+UINTN\r
+GetUefiSimpleFontPackSize (\r
+  IN CONST EFI_HII_PACK_HEADER * PackHeader\r
+  )\r
+{\r
+  UINTN             Size;\r
+  EFI_HII_FONT_PACK *FwFontPack;\r
+\r
+  FwFontPack = (EFI_HII_FONT_PACK *) PackHeader;\r
+\r
+  ASSERT (FwFontPack->Header.Type == EFI_HII_FONT);\r
+  \r
+  Size = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR) \r
+    + (FwFontPack->NumberOfNarrowGlyphs * sizeof (EFI_NARROW_GLYPH));\r
+\r
+   return Size;\r
+}\r
+\r
+\r
+/**\r
+  Convert Font Package in Framework format to a newly allocated UEFI\r
+  Simple Font Package.\r
+\r
+  ONLY Narrow Font is supported. Wide Font is discarded. \r
+\r
+  If memory allocation fails, then ASSERT.\r
+\r
+  @param FwFontPack        Framework Font Package.\r
+\r
+  @reture UEFI Simple Font Package.\r
+**/\r
+EFI_HII_SIMPLE_FONT_PACKAGE_HDR *\r
+FrameworkFontPackToUefiSimpliedFont (\r
+  IN CONST EFI_HII_PACK_HEADER * PackHeader\r
+  )\r
+{\r
+  EFI_HII_SIMPLE_FONT_PACKAGE_HDR       *FontPack;\r
+  UINTN                                 Size;\r
+  EFI_NARROW_GLYPH                      *FwNarrowGlyph;\r
+  EFI_NARROW_GLYPH                      *NarrowGlyph;\r
+  UINTN                                 Idx;\r
+  EFI_HII_FONT_PACK                     *FwFontPack;\r
+\r
+  Size = GetUefiSimpleFontPackSize (PackHeader);\r
+\r
+  FwFontPack = (EFI_HII_FONT_PACK *) PackHeader;\r
+\r
+  FontPack      = AllocateZeroPool (Size);\r
+  ASSERT (FontPack != NULL);\r
+\r
+  //\r
+  // Prepare the Header information.\r
+  //\r
+  FontPack->Header.Length = (UINT32) Size;\r
+  FontPack->Header.Type = EFI_HII_PACKAGE_SIMPLE_FONTS;\r
+\r
+  FontPack->NumberOfNarrowGlyphs = FwFontPack->NumberOfNarrowGlyphs;\r
+  \r
+  //\r
+  // ONLY Narrow Font is supported. Wide Font is discarded. \r
+  //\r
+  FontPack->NumberOfWideGlyphs = 0;\r
\r
+  //\r
+  // Copy Narrow Glyph\r
+  //\r
+  NarrowGlyph   = (EFI_NARROW_GLYPH *) (FontPack + 1);\r
+  FwNarrowGlyph = (EFI_NARROW_GLYPH *) (FwFontPack + 1);\r
+  CopyMem (NarrowGlyph, FwNarrowGlyph, sizeof (EFI_NARROW_GLYPH) * FwFontPack->NumberOfNarrowGlyphs);\r
+  for (Idx = 0; Idx < FwFontPack->NumberOfNarrowGlyphs; Idx++) {\r
+    //\r
+    // Clear the GLYPH_NON_BREAKING (EFI_GLYPH_WIDE is used here as they are all 0x02)\r
+    // attribute which is not defined in UEFI EFI_NARROW_GLYPH\r
+    //\r
+    NarrowGlyph[Idx].Attributes = (UINT8) (NarrowGlyph[Idx].Attributes & ~(EFI_GLYPH_WIDE));\r
+  }\r
+\r
+  return FontPack;\r
+}\r
+\r
+/**\r
+  Prepare a UEFI Package List from a Framework HII package list registered\r
+  from a Framework HII NewPack () function.\r
+\r
+  If either Packages or PackageListGuid is NULL, then ASSERT.\r
+  \r
+  @param Packages                     The Framework HII Package List.\r
+  @param PackageListGuid              The Package List GUID.\r
 \r
+\r
+  @return The UEFI Package List.  \r
+**/\r
 EFI_HII_PACKAGE_LIST_HEADER *\r
 PrepareUefiPackageListFromFrameworkHiiPackages (\r
   IN CONST EFI_HII_PACKAGES            *Packages,\r
@@ -132,7 +263,9 @@ PrepareUefiPackageListFromFrameworkHiiPackages (
   UINT32                      PackageLength;\r
   EFI_HII_PACKAGE_HEADER      PackageHeader;\r
   UINTN                       Index;\r
-  TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;\r
+  TIANO_AUTOGEN_PACKAGES_HEADER   **TianoAutogenPackageHdrArray;\r
+  EFI_HII_SIMPLE_FONT_PACKAGE_HDR *FontPack;\r
+  \r
 \r
   ASSERT (Packages != NULL);\r
   ASSERT (PackageListGuid != NULL);\r
@@ -143,11 +276,29 @@ PrepareUefiPackageListFromFrameworkHiiPackages (
   PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
 \r
   for (Index = 0; Index < NumberOfPackages; Index++) {\r
-    CopyMem (&PackageLength, &TianoAutogenPackageHdrArray[Index]->BinaryLength, sizeof (UINT32));\r
-    //\r
-    //TIANO_AUTOGEN_PACKAGES_HEADER.BinaryLength include the BinaryLength itself.\r
-    //\r
-    PackageListLength += (PackageLength - sizeof(UINT32)); \r
+    if (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type == EFI_HII_FONT) {\r
+      //\r
+      // There is no tool to generate Font package in Framework HII's implementation.\r
+      // Therefore, Font Package be a C structure defined in Framework HII code. \r
+      // Therefore, Font Package will be in Framework HII format defined by EFI_HII_FONT_PACK.\r
+      // We need to create a UEFI Simple Font Package and copy over all data. Hence, EFI_HII_FONT\r
+      // is handled differently than EFI_HII_IFR and EFI_HII_STRING.\r
+      //\r
+      PackageListLength = (UINT32) (PackageListLength + GetUefiSimpleFontPackSize (&TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader));\r
+      \r
+    } else {\r
+      //\r
+      // For EFI_HII_IFR and EFI_HII_STRING, EDK II's VFR Compiler and Build.exe will generate a binary in a format\r
+      // defined by TIANO_AUTOGEN_PACKAGES_HEADER. A Framework HII's EFI_HII_PACK_HEADER is inserted before\r
+      // the UEFI package data.\r
+      //\r
+      CopyMem (&PackageLength, &TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Length, sizeof (UINT32));\r
+      //\r
+      // EFI_HII_PACK_HEADER.FrameworkPackageHeader.Length include the sizeof FrameworkPackageHeader itself.\r
+      //\r
+      PackageListLength += (PackageLength - sizeof(EFI_HII_PACK_HEADER));\r
+      \r
+    }\r
   }\r
 \r
   //\r
@@ -162,10 +313,22 @@ PrepareUefiPackageListFromFrameworkHiiPackages (
 \r
   PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
 \r
+  //\r
+  // Build the UEFI Package List.\r
+  //\r
   for (Index = 0; Index < NumberOfPackages; Index++) {\r
-    CopyMem (&PackageLength, &(TianoAutogenPackageHdrArray[Index]->BinaryLength), sizeof (UINT32));\r
-    PackageLength  -= sizeof (UINT32);\r
-    CopyMem (PackageListData, &(TianoAutogenPackageHdrArray[Index]->PackageHeader), PackageLength);\r
+    if (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type == EFI_HII_FONT) {\r
+      PackageLength = (UINT32) GetUefiSimpleFontPackSize (&TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader);\r
+      FontPack = FrameworkFontPackToUefiSimpliedFont (&TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader);\r
+      CopyMem (PackageListData, FontPack, PackageLength);\r
+      FreePool (FontPack);\r
+      \r
+    } else {\r
+      CopyMem (&PackageLength, &(TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Length), sizeof (UINT32));\r
+      PackageLength  -= sizeof (EFI_HII_PACK_HEADER);\r
+      CopyMem (PackageListData, &(TianoAutogenPackageHdrArray[Index]->PackageHeader), PackageLength);\r
+      \r
+    }\r
     PackageListData += PackageLength;\r
   }\r
 \r
@@ -179,20 +342,41 @@ PrepareUefiPackageListFromFrameworkHiiPackages (
   return PackageListHeader;  \r
 }\r
 \r
+\r
+/**\r
+  Generate a Random GUID.\r
+  \r
+  @param Guid On output, a Random GUID will be filled.\r
+\r
+**/\r
 VOID\r
 GenerateRandomGuid (\r
   OUT           EFI_GUID * Guid\r
   )\r
 {\r
   EFI_GUID        GuidBase = { 0x14f95e01, 0xd562, 0x432e, { 0x84, 0x4a, 0x95, 0xa4, 0x39, 0x5, 0x10, 0x7e }};\r
-  static  UINT64  Count = 0;\r
 \r
   CopyGuid (Guid, &GuidBase);\r
 \r
-  Count++;  \r
-  *((UINT64 *) Guid) = *((UINT64 *) Guid) + Count;\r
+  mGuidCount++;  \r
+  *((UINT64 *) Guid) = *((UINT64 *) Guid) + mGuidCount;\r
 }\r
 \r
+/**\r
+  Given a Package List with only a IFR package, find the Package List that only has a String Package based on\r
+  the TAG GUID. Then export the String Package from the Package List and insert it\r
+  to the given IFR package.\r
+\r
+  This is to handle the case of Framework HII interface which allow String Package\r
+  and IFR package to be registered using two different NewPack () calls.\r
+\r
+  @param Private                      The HII THUNK driver context data.\r
+  @param IfrThunkContext              Package List with only a IFR package.\r
+\r
+  @retval EFI_SUCCESS                 If the String Package is found and inserted to the\r
+                                      Package List with only a IFR package.\r
+  @retval EFI_NOT_FOUND               No String Package matching the TAG GUID is found.\r
+**/\r
 EFI_STATUS\r
 FindStringPackAndUpdatePackListWithOnlyIfrPack (\r
   IN HII_THUNK_PRIVATE_DATA          *Private,\r
@@ -243,11 +427,26 @@ FindStringPackAndUpdatePackListWithOnlyIfrPack (
 }\r
 \r
 \r
-//\r
-// \r
-//\r
+/**\r
+  Register the Package List passed from the Framework HII NewPack () interface.\r
+  The FRAMEWORK_EFI_HII_HANDLE will be returned.\r
+\r
+  @param This                         The EFI_HII_PROTOCOL context data. Only used\r
+                                      to call HiiRemovePack.\r
+  @param Private                      The HII THUNK driver context data.\r
+  @param Package                      Package List.\r
+  @param Handle                       On output, a FRAMEWORK_EFI_HII_HANDLE number is\r
+                                      returned.\r
+\r
+  @retval EFI_SUCCESS                 The Package List is registered successfull in \r
+                                      the database.\r
+  @retval EFI_UNSUPPORTED             The number of IFR package in the package list\r
+                                      is greater than 1.\r
+  @retval EFI_OUT_OF_RESOURCE         Not enough resouce.\r
+  \r
+**/\r
 EFI_STATUS\r
-UefiRegisterPackageList(\r
+UefiRegisterPackageList (\r
   IN  EFI_HII_PROTOCOL               *This,\r
   IN  HII_THUNK_PRIVATE_DATA      *Private,\r
   IN  EFI_HII_PACKAGES            *Packages,\r
@@ -257,6 +456,7 @@ UefiRegisterPackageList(
   EFI_STATUS                  Status;\r
   UINTN                       StringPackageCount;\r
   UINTN                       IfrPackageCount;\r
+  UINTN                       FontPackageCount;\r
   EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
   HII_THUNK_CONTEXT           *ThunkContext;\r
   HII_THUNK_CONTEXT           *ThunkContextToRemove;\r
@@ -265,7 +465,7 @@ UefiRegisterPackageList(
 \r
   PackageListHeader = NULL;\r
 \r
-  Status = GetPackageCount (Packages, &IfrPackageCount, &StringPackageCount);\r
+  Status = GetPackageCount (Packages, &IfrPackageCount, &StringPackageCount, &FontPackageCount);\r
   ASSERT_EFI_ERROR (Status);\r
   \r
   if (IfrPackageCount > 1) {\r
@@ -288,46 +488,67 @@ UefiRegisterPackageList(
     //\r
     // If Packages->GuidId is NULL, the caller of FramworkHii->NewPack is registering\r
     // packages with at least 1 StringPack and 1 IfrPack. Therefore, Packages->GuidId is\r
-    // not used as the name of the package list.  A GUID is generated as a Package List\r
-    // GUID.\r
+    // not used as the name of the package list.  Formset GUID is used as the Package List\r
+    // GUID instead.\r
     //\r
-    ASSERT (StringPackageCount >=1 && IfrPackageCount == 1);\r
-    IfrPackage = GetIfrPackage (Packages);\r
-    GetFormSetGuid (IfrPackage, &ThunkContext->TagGuid);\r
+    ASSERT ((StringPackageCount >=1 && IfrPackageCount == 1) || (FontPackageCount > 0));\r
+    if (IfrPackageCount > 0) {\r
+      IfrPackage = GetIfrPackage (Packages);\r
+      GetFormSetGuid (IfrPackage, &ThunkContext->TagGuid);\r
+    } else {\r
+      ASSERT (FontPackageCount > 0);\r
+      GenerateRandomGuid (&ThunkContext->TagGuid);\r
+    }\r
+    \r
   } else {\r
     ThunkContextToRemove = TagGuidToIfrPackThunkContext (Private, Packages->GuidId);\r
     \r
     if (IfrPackageCount > 0 && \r
         StringPackageCount > 0 && \r
-        (ThunkContextToRemove!= NULL)) {\r
+        (ThunkContextToRemove != NULL)) {\r
         DEBUG((EFI_D_WARN, "Framework code registers HII package list with the same GUID more than once.\n"));\r
-        DEBUG((EFI_D_WARN, "This package list should be already registered. Just return successfully.\n"));\r
+        DEBUG((EFI_D_WARN, "Remove the previously registered package list and register the new one.\n"));\r
         HiiRemovePack (This, ThunkContextToRemove->FwHiiHandle);\r
     }\r
     CopyGuid (&ThunkContext->TagGuid, Packages->GuidId);\r
+    \r
   }\r
 \r
-  //\r
-  // UEFI HII database does not allow two package list with the same GUID.\r
-  // In Framework HII implementation, Packages->GuidId is used as an identifier to associate \r
-  // a PackageList with only IFR to a Package list the with String package.\r
-  //\r
-  GenerateRandomGuid (&GuidId);\r
-\r
   //\r
   // UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so\r
-  // that Setup Utility can load the Buffer Storage using this protocol.\r
+  // that Setup Utility can load the Buffer Storage using this protocol. An UEFI VFR can only\r
+  // produce IFR package generated with Buffer Storage type and EFI Variable Storage.\r
+  // The default EFI_HII_CONFIG_ACCESS_PROTOCOL is used to Get/Set the Buffer Storage.\r
   //\r
   if (IfrPackageCount != 0) {\r
     InstallDefaultConfigAccessProtocol (Packages, ThunkContext);\r
   }\r
-  PackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, &GuidId);\r
+  \r
+  PackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, &ThunkContext->TagGuid);\r
   Status = mHiiDatabase->NewPackageList (\r
               mHiiDatabase,\r
               PackageListHeader,  \r
               ThunkContext->UefiHiiDriverHandle,\r
               &ThunkContext->UefiHiiHandle\r
               );\r
+  if (Status == EFI_INVALID_PARAMETER) {\r
+    FreePool (PackageListHeader);\r
+    \r
+    //\r
+    // UEFI HII database does not allow two package list with the same GUID.\r
+    // In Framework HII implementation, Packages->GuidId is used as an identifier to associate \r
+    // a PackageList with only IFR to a Package list the with String package.\r
+    //\r
+    GenerateRandomGuid (&GuidId);\r
+\r
+    PackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, &GuidId);\r
+    Status = mHiiDatabase->NewPackageList (\r
+                mHiiDatabase,\r
+                PackageListHeader,  \r
+                ThunkContext->UefiHiiDriverHandle,\r
+                &ThunkContext->UefiHiiHandle\r
+                );\r
+  }\r
 \r
   //\r
   // BUGBUG: Remove when development is done\r
@@ -340,8 +561,10 @@ UefiRegisterPackageList(
   if (IfrPackageCount == 0) {\r
     if (StringPackageCount != 0) {\r
       //\r
-      // Look for a Package List with only IFR Package with the same GUID name.\r
-      // If found one, add the String Packages to it.\r
+      // Look for a Package List with only IFR Package with the same TAG GUID name.\r
+      // If found one, add the String Packages to the found Package List.\r
+      // This is needed because Framework HII Module may not register the String Package\r
+      // and IFR Package in one NewPack () call.\r
       //\r
       UpdatePackListWithOnlyIfrPack (\r
           Private,\r
@@ -350,11 +573,12 @@ UefiRegisterPackageList(
       );\r
     }\r
   } else {\r
-    CreateQuestionIdMap (ThunkContext);\r
-    \r
     if (StringPackageCount == 0) {\r
       //\r
-      // Register the Package List to UEFI HII first.\r
+      // Look for the String Package with the same TAG GUID name and add\r
+      // the found String Package to this Package List.\r
+      // This is needed because Framework HII Module may not register the String Package\r
+      // and IFR Package in one NewPack () call.\r
       //\r
       Status = FindStringPackAndUpdatePackListWithOnlyIfrPack (\r
                   Private,\r
@@ -365,6 +589,14 @@ UefiRegisterPackageList(
         goto Done;\r
       }\r
     }\r
+    \r
+    //\r
+    // Parse the Formset. Must be called after FindStringPackAndUpdatePackListWithOnlyIfrPack is called so\r
+    // that String Package is ready.\r
+    //\r
+    ThunkContext->FormSet = ParseFormSet (ThunkContext->UefiHiiHandle);\r
+    ASSERT (ThunkContext->FormSet != NULL);\r
+        \r
   }\r
 \r
 Done:\r
@@ -375,12 +607,26 @@ Done:
     *Handle = ThunkContext->FwHiiHandle;\r
   }\r
 \r
-  SafeFreePool (PackageListHeader);\r
+       if (PackageListHeader != NULL) {\r
+    FreePool (PackageListHeader);\r
+  }\r
   \r
   return Status;\r
 }\r
 \r
 \r
+/**\r
+\r
+  Registers the various packages that are passed in a Package List.\r
+\r
+  @param This      Pointer of Frameowk HII protocol instance.\r
+  @param Packages  Pointer of HII packages.\r
+  @param Handle    Handle value to be returned.\r
+\r
+  @retval EFI_SUCCESS           Pacakges has added to HII database successfully.\r
+  @retval EFI_INVALID_PARAMETER If Handle or Packages is NULL.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 HiiNewPack (\r
@@ -388,24 +634,6 @@ HiiNewPack (
   IN  EFI_HII_PACKAGES               *Packages,\r
   OUT FRAMEWORK_EFI_HII_HANDLE       *Handle\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Extracts the various packs from a package list.\r
-\r
-Arguments:\r
-\r
-  This      - Pointer of HII protocol.\r
-  Packages  - Pointer of HII packages.\r
-  Handle    - Handle value to be returned.\r
-\r
-Returns:\r
-\r
-  EFI_SUCCESS           - Pacakges has added to HII database successfully.\r
-  EFI_INVALID_PARAMETER - Invalid parameter.\r
-\r
---*/\r
 {\r
   EFI_STATUS                 Status;\r
   HII_THUNK_PRIVATE_DATA *Private;\r
@@ -422,10 +650,10 @@ Returns:
   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
   \r
   //\r
-  // We use a simple Global variable to inform NewPackNotify\r
+  // We use a simple Global variable to inform NewOrAddPackNotify()\r
   // that the package list registered here is already registered\r
-  // in the HII Thunk Layer. So NewPackNotify does not need to\r
-  // call RegisterUefiHiiHandle () to registered it.\r
+  // in the HII Thunk Layer. So NewOrAddPackNotify () does not need to\r
+  // call registered the Package List again.\r
   //\r
   mInFrameworkHiiNewPack = TRUE;\r
 \r
@@ -445,26 +673,27 @@ Returns:
   return Status;\r
 }\r
 \r
+/**\r
+\r
+  Remove a package from the HII database.\r
+\r
+  @param This      Pointer of Frameowk HII protocol instance.\r
+  @param Handle    Handle value to be removed.\r
+\r
+  @retval EFI_SUCCESS           Pacakges has added to HII database successfully.\r
+  @retval EFI_INVALID_PARAMETER If Handle or Packages is NULL.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 HiiRemovePack (\r
-  IN EFI_HII_PROTOCOL    *This,\r
+  IN EFI_HII_PROTOCOL               *This,\r
   IN FRAMEWORK_EFI_HII_HANDLE       Handle\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-  Removes the various packs from a Handle\r
-\r
-Arguments:\r
-\r
-Returns:\r
-\r
---*/\r
 {\r
   EFI_STATUS                 Status;\r
-  HII_THUNK_PRIVATE_DATA *Private;\r
-  HII_THUNK_CONTEXT *ThunkContext;\r
+  HII_THUNK_PRIVATE_DATA     *Private;\r
+  HII_THUNK_CONTEXT          *ThunkContext;\r
   EFI_TPL                    OldTpl;\r
 \r
   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
@@ -497,6 +726,25 @@ Returns:
   return Status;\r
 }\r
 \r
+/**\r
+  This notification function will be called when a Package List is registered\r
+  using UEFI HII interface. The Package List registered need to be recorded in\r
+  Framework Thunk module as Thunk Module may need to look for String Package in\r
+  the package registered.\r
+\r
+  If the Package List registered is not either Sting Package or IFR package, \r
+  then ASSERT. If the NotifyType is not ADD_PACK or NEW_PACK, then ASSERT.\r
+  Both cases means UEFI HII Database itself is buggy. \r
+\r
+  @param PackageType The Package Type.\r
+  @param PackageGuid The Package GUID.\r
+  @param Package     The Package Header.\r
+  @param Handle      The HII Handle of this Package List.\r
+  @param NotifyType  The reason of the notification. \r
+\r
+  @retval EFI_SUCCESS The notification function is successful.\r
+  \r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 NewOrAddPackNotify (\r
@@ -511,7 +759,7 @@ NewOrAddPackNotify (
   HII_THUNK_PRIVATE_DATA  *Private;\r
   HII_THUNK_CONTEXT       *ThunkContext;\r
 \r
-  ASSERT (PackageType == EFI_HII_PACKAGE_STRINGS || PackageType == EFI_HII_PACKAGE_FORM);\r
+  ASSERT (PackageType == EFI_HII_PACKAGE_STRINGS || PackageType == EFI_HII_PACKAGE_FORMS);\r
   ASSERT (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK || NotifyType == EFI_HII_DATABASE_NOTIFY_NEW_PACK);\r
 \r
   Status  = EFI_SUCCESS;\r
@@ -522,8 +770,8 @@ NewOrAddPackNotify (
   }\r
 \r
   //\r
-  // We only create a ThunkContext if the Uefi Hii Handle is only already registered\r
-  // by the HII Thunk Layer.\r
+  // We will create a ThunkContext to log the package list only if the\r
+  // package is not registered with by Framework HII Thunk module yet.\r
   //\r
   ThunkContext = UefiHiiHandleToThunkContext (Private, Handle);\r
   if (ThunkContext == NULL) {\r
@@ -533,18 +781,39 @@ NewOrAddPackNotify (
     InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link);\r
   } \r
 \r
-  if (PackageType == EFI_HII_PACKAGE_FORM) {\r
-    GetAttributesOfFirstFormSet (ThunkContext);\r
+  if (PackageType == EFI_HII_PACKAGE_FORMS) {\r
+    if (ThunkContext->FormSet != NULL) {\r
+      DestroyFormSet (ThunkContext->FormSet);\r
+    }\r
+\r
+    //\r
+    // Reparse the FormSet.\r
+    //\r
+    ThunkContext->FormSet = ParseFormSet (ThunkContext->UefiHiiHandle);\r
+    ASSERT (ThunkContext->FormSet != NULL);\r
   }\r
 \r
   return Status;  \r
 }\r
 \r
-//\r
-// Framework HII module may cache a GUID as the name of the package list.\r
-// Then search for the Framework HII handle database for the handle matching\r
-// this GUID\r
+/**\r
+  This notification function will be called when a Package List is removed\r
+  using UEFI HII interface. The Package List removed need to be removed from\r
+  Framework Thunk module too.\r
 \r
+  If the Package List registered is not Sting Package, \r
+  then ASSERT. If the NotifyType is not REMOVE_PACK, then ASSERT.\r
+  Both cases means UEFI HII Database itself is buggy. \r
+\r
+  @param PackageType The Package Type.\r
+  @param PackageGuid The Package GUID.\r
+  @param Package     The Package Header.\r
+  @param Handle      The HII Handle of this Package List.\r
+  @param NotifyType  The reason of the notification. \r
+\r
+  @retval EFI_SUCCESS The notification function is successful.\r
+  \r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 RemovePackNotify (\r