2 Implement protocol interface related to package registrations.
4 Copyright (c) 2006 - 2008, Intel Corporation
5 All rights reserved. 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
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.
16 #include "HiiDatabase.h"
17 #include "HiiHandle.h"
20 BOOLEAN mInFrameworkHiiNewPack
= FALSE
;
21 BOOLEAN mInFrameworkHiiRemovePack
= FALSE
;
22 BOOLEAN mInFrameworkUpdatePakcage
= FALSE
;
23 UINT64 mGuidCount
= 0;
27 Get the number of package IFR and STRING packages in the package list passed in.
29 @param Packages Package List.
30 @param IfrPackageCount Number of IFR Packages.
31 @param StringPackageCount Number of String Packages.
33 @retval EFI_INVALID_PARAMETER If the Package List has package with type of
34 EFI_HII_PACKAGE_KEYBOARD_LAYOUT, EFI_HII_PACKAGE_FONTS, EFI_HII_PACKAGE_IMAGES.
35 @reval EFI_SUCCESS Successfully get the number of IFR and STRING package.
41 IN CONST EFI_HII_PACKAGES
*Packages
,
42 UINTN
*IfrPackageCount
,
43 UINTN
*StringPackageCount
47 TIANO_AUTOGEN_PACKAGES_HEADER
**TianoAutogenPackageHdrArray
;
49 ASSERT (Packages
!= NULL
);
50 ASSERT (IfrPackageCount
!= NULL
);
51 ASSERT (StringPackageCount
!= NULL
);
54 *StringPackageCount
= 0;
56 TianoAutogenPackageHdrArray
= (TIANO_AUTOGEN_PACKAGES_HEADER
**) (((UINT8
*) &Packages
->GuidId
) + sizeof (Packages
->GuidId
));
58 for (Index
= 0; Index
< Packages
->NumberOfPackages
; Index
++) {
60 // The current UEFI HII build tool generate a binary in the format defined by
61 // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in
62 // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount
63 // may not be the exact number of valid package number in the binary generated
66 switch (TianoAutogenPackageHdrArray
[Index
]->PackageHeader
.Type
) {
67 case EFI_HII_PACKAGE_FORMS
:
68 *IfrPackageCount
+= 1;
70 case EFI_HII_PACKAGE_STRINGS
:
71 *StringPackageCount
+= 1;
74 case EFI_HII_PACKAGE_SIMPLE_FONTS
:
78 // The following fonts are invalid for a module that using Framework to UEFI thunk layer.
80 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT
:
81 case EFI_HII_PACKAGE_FONTS
:
82 case EFI_HII_PACKAGE_IMAGES
:
85 return EFI_INVALID_PARAMETER
;
94 Insert the String Package into the Package Lists which has the TAG GUID matching
95 the PackageListGuid of the String Package.
97 The Package List must have only IFR Package and no String Package.
100 @param Private The HII THUNK driver context data.
101 @param StringPackageThunkContext The HII THUNK context data.
102 @param StringPackageListHeader The String Package List Header.
106 UpdatePackListWithOnlyIfrPack (
107 IN HII_THUNK_PRIVATE_DATA
*Private
,
108 IN HII_THUNK_CONTEXT
*StringPackageThunkContext
,
109 IN CONST EFI_HII_PACKAGE_LIST_HEADER
*StringPackageListHeader
114 HII_THUNK_CONTEXT
*ThunkContext
;
116 Link
= GetFirstNode (&Private
->ThunkContextListHead
);
117 while (!IsNull (&Private
->ThunkContextListHead
, Link
)) {
119 ThunkContext
= HII_THUNK_CONTEXT_FROM_LINK (Link
);
121 if (StringPackageThunkContext
!= ThunkContext
) {
123 // Skip the String Package Thunk Entry itself.
126 if (CompareGuid (&StringPackageListHeader
->PackageListGuid
, &ThunkContext
->TagGuid
)) {
128 ASSERT (ThunkContext
->StringPackageCount
== 0 && ThunkContext
->IfrPackageCount
== 1);
130 ThunkContext
->StringPackageCount
= GetPackageCountByType (StringPackageListHeader
, EFI_HII_PACKAGE_STRINGS
);
132 Status
= mHiiDatabase
->UpdatePackageList (
134 ThunkContext
->UefiHiiHandle
,
135 StringPackageListHeader
137 ASSERT_EFI_ERROR (Status
);
142 Link
= GetNextNode (&Private
->ThunkContextListHead
, Link
);
149 Prepare a UEFI Package List from a Framework HII package list registered
150 from a Framework HII NewPack () function.
152 If either Packages or PackageListGuid is NULL, then ASSERT.
154 @param Packages The Framework HII Package List.
155 @param PackageListGuid The Package List GUID.
158 @return The UEFI Package List.
160 EFI_HII_PACKAGE_LIST_HEADER
*
161 PrepareUefiPackageListFromFrameworkHiiPackages (
162 IN CONST EFI_HII_PACKAGES
*Packages
,
163 IN CONST EFI_GUID
*PackageListGuid
166 UINTN NumberOfPackages
;
167 EFI_HII_PACKAGE_LIST_HEADER
*PackageListHeader
;
168 UINT8
*PackageListData
;
169 UINT32 PackageListLength
;
170 UINT32 PackageLength
;
171 EFI_HII_PACKAGE_HEADER PackageHeader
;
173 TIANO_AUTOGEN_PACKAGES_HEADER
**TianoAutogenPackageHdrArray
;
175 ASSERT (Packages
!= NULL
);
176 ASSERT (PackageListGuid
!= NULL
);
178 TianoAutogenPackageHdrArray
= (TIANO_AUTOGEN_PACKAGES_HEADER
**) ((UINT8
*) &Packages
->GuidId
+ sizeof (Packages
->GuidId
));
179 NumberOfPackages
= Packages
->NumberOfPackages
;
181 PackageListLength
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
183 for (Index
= 0; Index
< NumberOfPackages
; Index
++) {
184 CopyMem (&PackageLength
, &TianoAutogenPackageHdrArray
[Index
]->BinaryLength
, sizeof (UINT32
));
186 //TIANO_AUTOGEN_PACKAGES_HEADER.BinaryLength include the BinaryLength itself.
188 PackageListLength
+= (PackageLength
- sizeof(UINT32
));
192 // Include the lenght of EFI_HII_PACKAGE_END
194 PackageListLength
+= sizeof (EFI_HII_PACKAGE_HEADER
);
195 PackageListHeader
= AllocateZeroPool (PackageListLength
);
196 ASSERT (PackageListHeader
!= NULL
);
198 CopyMem (&PackageListHeader
->PackageListGuid
, PackageListGuid
, sizeof (EFI_GUID
));
199 PackageListHeader
->PackageLength
= PackageListLength
;
201 PackageListData
= ((UINT8
*) PackageListHeader
) + sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
203 for (Index
= 0; Index
< NumberOfPackages
; Index
++) {
204 CopyMem (&PackageLength
, &(TianoAutogenPackageHdrArray
[Index
]->BinaryLength
), sizeof (UINT32
));
205 PackageLength
-= sizeof (UINT32
);
206 CopyMem (PackageListData
, &(TianoAutogenPackageHdrArray
[Index
]->PackageHeader
), PackageLength
);
207 PackageListData
+= PackageLength
;
211 // Append EFI_HII_PACKAGE_END
213 PackageHeader
.Type
= EFI_HII_PACKAGE_END
;
214 PackageHeader
.Length
= sizeof (EFI_HII_PACKAGE_HEADER
);
215 CopyMem (PackageListData
, &PackageHeader
, PackageHeader
.Length
);
217 return PackageListHeader
;
222 Generate a Random GUID.
224 @param Guid On output, a Random GUID will be filled.
232 EFI_GUID GuidBase
= { 0x14f95e01, 0xd562, 0x432e, { 0x84, 0x4a, 0x95, 0xa4, 0x39, 0x5, 0x10, 0x7e }};
234 CopyGuid (Guid
, &GuidBase
);
237 *((UINT64
*) Guid
) = *((UINT64
*) Guid
) + mGuidCount
;
241 Given a Package List with only a IFR package, find the Package List that only has a String Package based on
242 the TAG GUID. Then export the String Package from the Package List and insert it
243 to the given IFR package.
245 This is to handle the case of Framework HII interface which allow String Package
246 and IFR package to be registered using two different NewPack () calls.
248 @param Private The HII THUNK driver context data.
249 @param IfrThunkContext Package List with only a IFR package.
251 @retval EFI_SUCCESS If the String Package is found and inserted to the
252 Package List with only a IFR package.
253 @retval EFI_NOT_FOUND No String Package matching the TAG GUID is found.
256 FindStringPackAndUpdatePackListWithOnlyIfrPack (
257 IN HII_THUNK_PRIVATE_DATA
*Private
,
258 IN HII_THUNK_CONTEXT
*IfrThunkContext
263 EFI_HII_PACKAGE_LIST_HEADER
*StringPackageListHeader
;
265 HII_THUNK_CONTEXT
*ThunkContext
;
268 Link
= GetFirstNode (&Private
->ThunkContextListHead
);
270 while (!IsNull (&Private
->ThunkContextListHead
, Link
)) {
272 ThunkContext
= HII_THUNK_CONTEXT_FROM_LINK (Link
);
274 if (ThunkContext
!= IfrThunkContext
) {
275 if (CompareGuid (&IfrThunkContext
->TagGuid
, &ThunkContext
->TagGuid
) && (ThunkContext
->IfrPackageCount
== 0)) {
276 Status
= HiiLibExportPackageLists (ThunkContext
->UefiHiiHandle
, &StringPackageListHeader
, &Size
);
277 ASSERT_EFI_ERROR (Status
);
279 IfrThunkContext
->StringPackageCount
= GetPackageCountByType (StringPackageListHeader
, EFI_HII_PACKAGE_STRINGS
);
281 // Add Function to only get only String Packages from the Package List
283 Status
= mHiiDatabase
->UpdatePackageList (
285 IfrThunkContext
->UefiHiiHandle
,
286 StringPackageListHeader
288 ASSERT_EFI_ERROR (Status
);
290 FreePool (StringPackageListHeader
);
296 Link
= GetNextNode (&Private
->ThunkContextListHead
, Link
);
300 return EFI_NOT_FOUND
;
306 Register the Package List passed from the Framework HII NewPack () interface.
307 The FRAMEWORK_EFI_HII_HANDLE will be returned.
309 @param This The EFI_HII_PROTOCOL context data. Only used
310 to call HiiRemovePack.
311 @param Private The HII THUNK driver context data.
312 @param Package Package List.
313 @param Handle On output, a FRAMEWORK_EFI_HII_HANDLE number is
316 @retval EFI_SUCCESS The Package List is registered successfull in
318 @retval EFI_UNSUPPORTED The number of IFR package in the package list
320 @retval EFI_OUT_OF_RESOURCE Not enough resouce.
324 UefiRegisterPackageList (
325 IN EFI_HII_PROTOCOL
*This
,
326 IN HII_THUNK_PRIVATE_DATA
*Private
,
327 IN EFI_HII_PACKAGES
*Packages
,
328 OUT FRAMEWORK_EFI_HII_HANDLE
*Handle
332 UINTN StringPackageCount
;
333 UINTN IfrPackageCount
;
334 EFI_HII_PACKAGE_LIST_HEADER
*PackageListHeader
;
335 HII_THUNK_CONTEXT
*ThunkContext
;
336 HII_THUNK_CONTEXT
*ThunkContextToRemove
;
338 EFI_HII_PACKAGE_HEADER
*IfrPackage
;
340 PackageListHeader
= NULL
;
342 Status
= GetPackageCount (Packages
, &IfrPackageCount
, &StringPackageCount
);
343 ASSERT_EFI_ERROR (Status
);
345 if (IfrPackageCount
> 1) {
347 // HII Thunk only handle package with 0 or 1 IFR package.
350 return EFI_UNSUPPORTED
;
353 ThunkContext
= CreateThunkContext (Private
, StringPackageCount
, IfrPackageCount
);
354 if (ThunkContext
== NULL
) {
355 return EFI_OUT_OF_RESOURCES
;
357 ThunkContext
->ByFrameworkHiiNewPack
= TRUE
;
359 if (Packages
->GuidId
== NULL
) {
361 // UEFI HII Database require Package List GUID must be unique.
363 // If Packages->GuidId is NULL, the caller of FramworkHii->NewPack is registering
364 // packages with at least 1 StringPack and 1 IfrPack. Therefore, Packages->GuidId is
365 // not used as the name of the package list. Formset GUID is used as the Package List
368 ASSERT (StringPackageCount
>=1 && IfrPackageCount
== 1);
369 IfrPackage
= GetIfrPackage (Packages
);
370 GetFormSetGuid (IfrPackage
, &ThunkContext
->TagGuid
);
372 ThunkContextToRemove
= TagGuidToIfrPackThunkContext (Private
, Packages
->GuidId
);
374 if (IfrPackageCount
> 0 &&
375 StringPackageCount
> 0 &&
376 (ThunkContextToRemove
!= NULL
)) {
377 DEBUG((EFI_D_WARN
, "Framework code registers HII package list with the same GUID more than once.\n"));
378 DEBUG((EFI_D_WARN
, "This package list should be already registered. Just return successfully.\n"));
379 HiiRemovePack (This
, ThunkContextToRemove
->FwHiiHandle
);
381 CopyGuid (&ThunkContext
->TagGuid
, Packages
->GuidId
);
385 // UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so
386 // that Setup Utility can load the Buffer Storage using this protocol. An UEFI VFR can only
387 // produce IFR package generated with Buffer Storage type and EFI Variable Storage.
388 // The default EFI_HII_CONFIG_ACCESS_PROTOCOL is used to Get/Set the Buffer Storage.
390 if (IfrPackageCount
!= 0) {
391 InstallDefaultConfigAccessProtocol (Packages
, ThunkContext
);
393 PackageListHeader
= PrepareUefiPackageListFromFrameworkHiiPackages (Packages
, &ThunkContext
->TagGuid
);
394 Status
= mHiiDatabase
->NewPackageList (
397 ThunkContext
->UefiHiiDriverHandle
,
398 &ThunkContext
->UefiHiiHandle
400 if (Status
== EFI_INVALID_PARAMETER
) {
401 FreePool (PackageListHeader
);
404 // UEFI HII database does not allow two package list with the same GUID.
405 // In Framework HII implementation, Packages->GuidId is used as an identifier to associate
406 // a PackageList with only IFR to a Package list the with String package.
408 GenerateRandomGuid (&GuidId
);
410 PackageListHeader
= PrepareUefiPackageListFromFrameworkHiiPackages (Packages
, &GuidId
);
411 Status
= mHiiDatabase
->NewPackageList (
414 ThunkContext
->UefiHiiDriverHandle
,
415 &ThunkContext
->UefiHiiHandle
420 // BUGBUG: Remove when development is done
422 ASSERT_EFI_ERROR (Status
);
423 if (EFI_ERROR (Status
)) {
427 if (IfrPackageCount
== 0) {
428 if (StringPackageCount
!= 0) {
430 // Look for a Package List with only IFR Package with the same TAG GUID name.
431 // If found one, add the String Packages to the found Package List.
432 // This is needed because Framework HII Module may not register the String Package
433 // and IFR Package in one NewPack () call.
435 UpdatePackListWithOnlyIfrPack (
442 if (StringPackageCount
== 0) {
444 // Look for the String Package with the same TAG GUID name and add
445 // the found String Package to this Package List.
446 // This is needed because Framework HII Module may not register the String Package
447 // and IFR Package in one NewPack () call.
449 Status
= FindStringPackAndUpdatePackListWithOnlyIfrPack (
454 if (EFI_ERROR (Status
)) {
460 // Parse the Formset. Must be called after FindStringPackAndUpdatePackListWithOnlyIfrPack is called so
461 // that String Package is ready.
463 ThunkContext
->FormSet
= ParseFormSet (ThunkContext
->UefiHiiHandle
);
464 ASSERT (ThunkContext
->FormSet
!= NULL
);
469 if (EFI_ERROR (Status
)) {
470 DestroyThunkContext (ThunkContext
);
472 InsertTailList (&Private
->ThunkContextListHead
, &ThunkContext
->Link
);
473 *Handle
= ThunkContext
->FwHiiHandle
;
476 if (PackageListHeader
!= NULL
) {
477 FreePool (PackageListHeader
);
486 Registers the various packages that are passed in a Package List.
488 @param This Pointer of Frameowk HII protocol instance.
489 @param Packages Pointer of HII packages.
490 @param Handle Handle value to be returned.
492 @retval EFI_SUCCESS Pacakges has added to HII database successfully.
493 @retval EFI_INVALID_PARAMETER If Handle or Packages is NULL.
499 IN EFI_HII_PROTOCOL
*This
,
500 IN EFI_HII_PACKAGES
*Packages
,
501 OUT FRAMEWORK_EFI_HII_HANDLE
*Handle
505 HII_THUNK_PRIVATE_DATA
*Private
;
508 if (Handle
== NULL
) {
509 return EFI_INVALID_PARAMETER
;
512 if (Packages
== NULL
) {
513 return EFI_INVALID_PARAMETER
;
516 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
519 // We use a simple Global variable to inform NewOrAddPackNotify()
520 // that the package list registered here is already registered
521 // in the HII Thunk Layer. So NewOrAddPackNotify () does not need to
522 // call registered the Package List again.
524 mInFrameworkHiiNewPack
= TRUE
;
526 Private
= HII_THUNK_PRIVATE_DATA_FROM_THIS(This
);
528 Status
= UefiRegisterPackageList (
535 mInFrameworkHiiNewPack
= FALSE
;
537 gBS
->RestoreTPL (OldTpl
);
544 Remove a package from the HII database.
546 @param This Pointer of Frameowk HII protocol instance.
547 @param Handle Handle value to be removed.
549 @retval EFI_SUCCESS Pacakges has added to HII database successfully.
550 @retval EFI_INVALID_PARAMETER If Handle or Packages is NULL.
556 IN EFI_HII_PROTOCOL
*This
,
557 IN FRAMEWORK_EFI_HII_HANDLE Handle
561 HII_THUNK_PRIVATE_DATA
*Private
;
562 HII_THUNK_CONTEXT
*ThunkContext
;
565 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
567 mInFrameworkHiiRemovePack
= TRUE
;
569 Private
= HII_THUNK_PRIVATE_DATA_FROM_THIS(This
);
571 ThunkContext
= FwHiiHandleToThunkContext (Private
, Handle
);
573 if (ThunkContext
!= NULL
) {
574 Status
= mHiiDatabase
->RemovePackageList (
576 ThunkContext
->UefiHiiHandle
578 ASSERT_EFI_ERROR (Status
);
580 if (ThunkContext
->IfrPackageCount
!= 0) {
581 UninstallDefaultConfigAccessProtocol (ThunkContext
);
584 DestroyThunkContext (ThunkContext
);
586 Status
= EFI_NOT_FOUND
;
589 mInFrameworkHiiRemovePack
= FALSE
;
590 gBS
->RestoreTPL (OldTpl
);
596 This notification function will be called when a Package List is registered
597 using UEFI HII interface. The Package List registered need to be recorded in
598 Framework Thunk module as Thunk Module may need to look for String Package in
599 the package registered.
601 If the Package List registered is not either Sting Package or IFR package,
602 then ASSERT. If the NotifyType is not ADD_PACK or NEW_PACK, then ASSERT.
603 Both cases means UEFI HII Database itself is buggy.
605 @param PackageType The Package Type.
606 @param PackageGuid The Package GUID.
607 @param Package The Package Header.
608 @param Handle The HII Handle of this Package List.
609 @param NotifyType The reason of the notification.
611 @retval EFI_SUCCESS The notification function is successful.
617 IN UINT8 PackageType
,
618 IN CONST EFI_GUID
*PackageGuid
,
619 IN CONST EFI_HII_PACKAGE_HEADER
*Package
,
620 IN EFI_HII_HANDLE Handle
,
621 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
625 HII_THUNK_PRIVATE_DATA
*Private
;
626 HII_THUNK_CONTEXT
*ThunkContext
;
628 ASSERT (PackageType
== EFI_HII_PACKAGE_STRINGS
|| PackageType
== EFI_HII_PACKAGE_FORMS
);
629 ASSERT (NotifyType
== EFI_HII_DATABASE_NOTIFY_ADD_PACK
|| NotifyType
== EFI_HII_DATABASE_NOTIFY_NEW_PACK
);
631 Status
= EFI_SUCCESS
;
632 Private
= mHiiThunkPrivateData
;
634 if (mInFrameworkHiiNewPack
|| mInFrameworkUpdatePakcage
) {
639 // We will create a ThunkContext to log the package list only if the
640 // package is not registered with by Framework HII Thunk module yet.
642 ThunkContext
= UefiHiiHandleToThunkContext (Private
, Handle
);
643 if (ThunkContext
== NULL
) {
644 ThunkContext
= CreateThunkContextForUefiHiiHandle (Handle
);
645 ASSERT (ThunkContext
!= NULL
);
647 InsertTailList (&Private
->ThunkContextListHead
, &ThunkContext
->Link
);
650 if (PackageType
== EFI_HII_PACKAGE_FORMS
) {
651 if (ThunkContext
->FormSet
!= NULL
) {
652 DestroyFormSet (ThunkContext
->FormSet
);
656 // Reparse the FormSet.
658 ThunkContext
->FormSet
= ParseFormSet (ThunkContext
->UefiHiiHandle
);
659 ASSERT (ThunkContext
->FormSet
!= NULL
);
666 This notification function will be called when a Package List is removed
667 using UEFI HII interface. The Package List removed need to be removed from
668 Framework Thunk module too.
670 If the Package List registered is not Sting Package,
671 then ASSERT. If the NotifyType is not REMOVE_PACK, then ASSERT.
672 Both cases means UEFI HII Database itself is buggy.
674 @param PackageType The Package Type.
675 @param PackageGuid The Package GUID.
676 @param Package The Package Header.
677 @param Handle The HII Handle of this Package List.
678 @param NotifyType The reason of the notification.
680 @retval EFI_SUCCESS The notification function is successful.
686 IN UINT8 PackageType
,
687 IN CONST EFI_GUID
*PackageGuid
,
688 IN CONST EFI_HII_PACKAGE_HEADER
*Package
,
689 IN EFI_HII_HANDLE Handle
,
690 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
694 HII_THUNK_PRIVATE_DATA
*Private
;
695 HII_THUNK_CONTEXT
*ThunkContext
;
696 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
699 Status
= EFI_SUCCESS
;
701 ASSERT (PackageType
== EFI_HII_PACKAGE_STRINGS
);
702 ASSERT (NotifyType
== EFI_HII_DATABASE_NOTIFY_REMOVE_PACK
);
704 if (mInFrameworkHiiRemovePack
|| mInFrameworkUpdatePakcage
) {
708 Private
= mHiiThunkPrivateData
;
710 ThunkContext
= UefiHiiHandleToThunkContext (Private
, Handle
);
713 // BugBug: Change to ASSERT if HII Database fix the bug and to also invoke
714 // NEW_PACK_NOTIFY for package (String Package) created internally.
716 if (ThunkContext
!= NULL
) {
717 if (!ThunkContext
->ByFrameworkHiiNewPack
) {
718 Status
= HiiLibExportPackageLists (Handle
, &HiiPackageList
, &BufferSize
);
719 ASSERT_EFI_ERROR (Status
);
721 if (GetPackageCountByType (HiiPackageList
, EFI_HII_PACKAGE_STRINGS
) == 1) {
723 // If the string package will be removed is the last string package
724 // in the package list, we will remove the HII Thunk entry from the
727 DestroyThunkContextForUefiHiiHandle (Private
, Handle
);
730 FreePool (HiiPackageList
);