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
GetPackageCount(IN CONST EFI_HII_PACKAGES * Packages,OUT UINTN * IfrPackageCount,OUT UINTN * StringPackageCount,OUT UINTN * FontPackageCount)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
UpdatePackListWithOnlyIfrPack(IN HII_THUNK_PRIVATE_DATA * Private,IN HII_THUNK_CONTEXT * StringPackageThunkContext,IN CONST EFI_HII_PACKAGE_LIST_HEADER * StringPackageListHeader)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
GetUefiSimpleFontPackSize(IN CONST EFI_HII_PACK_HEADER * PackHeader)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 *
FrameworkFontPackToUefiSimpliedFont(IN CONST EFI_HII_PACK_HEADER * PackHeader)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 *
PrepareUefiPackageListFromFrameworkHiiPackages(IN CONST EFI_HII_PACKAGES * Packages,IN CONST EFI_GUID * PackageListGuid)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
GenerateRandomGuid(OUT EFI_GUID * Guid)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
FindStringPackAndUpdatePackListWithOnlyIfrPack(IN HII_THUNK_PRIVATE_DATA * Private,IN HII_THUNK_CONTEXT * IfrThunkContext)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 successfull 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
UefiRegisterPackageList(IN EFI_HII_PROTOCOL * This,IN HII_THUNK_PRIVATE_DATA * Private,IN EFI_HII_PACKAGES * Packages,OUT FRAMEWORK_EFI_HII_HANDLE * Handle)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           Pacakges has added to HII database successfully.
648   @retval EFI_INVALID_PARAMETER If Handle or Packages is NULL.
649 
650 **/
651 EFI_STATUS
652 EFIAPI
HiiNewPack(IN EFI_HII_PROTOCOL * This,IN EFI_HII_PACKAGES * Packages,OUT FRAMEWORK_EFI_HII_HANDLE * Handle)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           Pacakges has added to HII database successfully.
705   @retval EFI_INVALID_PARAMETER If Handle or Packages is NULL.
706 
707 **/
708 EFI_STATUS
709 EFIAPI
HiiRemovePack(IN EFI_HII_PROTOCOL * This,IN FRAMEWORK_EFI_HII_HANDLE Handle)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
NewOrAddPackNotify(IN UINT8 PackageType,IN CONST EFI_GUID * PackageGuid,IN CONST EFI_HII_PACKAGE_HEADER * Package,IN EFI_HII_HANDLE Handle,IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType)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
RemovePackNotify(IN UINT8 PackageType,IN CONST EFI_GUID * PackageGuid,IN CONST EFI_HII_PACKAGE_HEADER * Package,IN EFI_HII_HANDLE Handle,IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType)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