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 STATIC BOOLEAN mInFrameworkHiiNewPack
= FALSE
;
21 STATIC BOOLEAN mInFrameworkHiiRemovePack
= FALSE
;
22 BOOLEAN mInFrameworkUpdatePakcage
= FALSE
;
27 IN CONST EFI_HII_PACKAGES
*Packages
,
28 UINTN
*IfrPackageCount
,
29 UINTN
*StringPackageCount
33 TIANO_AUTOGEN_PACKAGES_HEADER
**TianoAutogenPackageHdrArray
;
35 ASSERT (Packages
!= NULL
);
36 ASSERT (IfrPackageCount
!= NULL
);
37 ASSERT (StringPackageCount
!= NULL
);
40 *StringPackageCount
= 0;
42 TianoAutogenPackageHdrArray
= (TIANO_AUTOGEN_PACKAGES_HEADER
**) (((UINT8
*) &Packages
->GuidId
) + sizeof (Packages
->GuidId
));
44 for (Index
= 0; Index
< Packages
->NumberOfPackages
; Index
++) {
46 // The current UEFI HII build tool generate a binary in the format defined by
47 // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in
48 // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount
49 // may not be the exact number of valid package number in the binary generated
52 switch (TianoAutogenPackageHdrArray
[Index
]->PackageHeader
.Type
) {
53 case EFI_HII_PACKAGE_FORMS
:
54 *IfrPackageCount
+= 1;
56 case EFI_HII_PACKAGE_STRINGS
:
57 *StringPackageCount
+= 1;
60 case EFI_HII_PACKAGE_SIMPLE_FONTS
:
64 // The following fonts are invalid for a module that using Framework to UEFI thunk layer.
66 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT
:
67 case EFI_HII_PACKAGE_FONTS
:
68 case EFI_HII_PACKAGE_IMAGES
:
71 return EFI_INVALID_PARAMETER
;
80 UpdatePackListWithOnlyIfrPack (
81 IN HII_THUNK_PRIVATE_DATA
*Private
,
82 IN HII_THUNK_CONTEXT
*StringPackageThunkContext
,
83 IN CONST EFI_HII_PACKAGE_LIST_HEADER
*StringPackageListHeader
88 HII_THUNK_CONTEXT
*ThunkContext
;
90 Link
= GetFirstNode (&Private
->ThunkContextListHead
);
91 while (!IsNull (&Private
->ThunkContextListHead
, Link
)) {
93 ThunkContext
= HII_THUNK_CONTEXT_FROM_LINK (Link
);
95 if (StringPackageThunkContext
!= ThunkContext
) {
97 // Skip the String Package Thunk Entry itself.
100 if (CompareGuid (&StringPackageListHeader
->PackageListGuid
, &ThunkContext
->TagGuid
)) {
102 ASSERT (ThunkContext
->StringPackageCount
== 0 && ThunkContext
->IfrPackageCount
== 1);
104 ThunkContext
->StringPackageCount
= GetPackageCountByType (StringPackageListHeader
, EFI_HII_PACKAGE_STRINGS
);
106 Status
= mHiiDatabase
->UpdatePackageList (
108 ThunkContext
->UefiHiiHandle
,
109 StringPackageListHeader
111 ASSERT_EFI_ERROR (Status
);
116 Link
= GetNextNode (&Private
->ThunkContextListHead
, Link
);
122 EFI_HII_PACKAGE_LIST_HEADER
*
123 PrepareUefiPackageListFromFrameworkHiiPackages (
124 IN CONST EFI_HII_PACKAGES
*Packages
,
125 IN CONST EFI_GUID
*PackageListGuid
128 UINTN NumberOfPackages
;
129 EFI_HII_PACKAGE_LIST_HEADER
*PackageListHeader
;
130 UINT8
*PackageListData
;
131 UINT32 PackageListLength
;
132 UINT32 PackageLength
;
133 EFI_HII_PACKAGE_HEADER PackageHeader
;
135 TIANO_AUTOGEN_PACKAGES_HEADER
**TianoAutogenPackageHdrArray
;
137 ASSERT (Packages
!= NULL
);
138 ASSERT (PackageListGuid
!= NULL
);
140 TianoAutogenPackageHdrArray
= (TIANO_AUTOGEN_PACKAGES_HEADER
**) ((UINT8
*) &Packages
->GuidId
+ sizeof (Packages
->GuidId
));
141 NumberOfPackages
= Packages
->NumberOfPackages
;
143 PackageListLength
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
145 for (Index
= 0; Index
< NumberOfPackages
; Index
++) {
146 CopyMem (&PackageLength
, &TianoAutogenPackageHdrArray
[Index
]->BinaryLength
, sizeof (UINT32
));
148 //TIANO_AUTOGEN_PACKAGES_HEADER.BinaryLength include the BinaryLength itself.
150 PackageListLength
+= (PackageLength
- sizeof(UINT32
));
154 // Include the lenght of EFI_HII_PACKAGE_END
156 PackageListLength
+= sizeof (EFI_HII_PACKAGE_HEADER
);
157 PackageListHeader
= AllocateZeroPool (PackageListLength
);
158 ASSERT (PackageListHeader
!= NULL
);
160 CopyMem (&PackageListHeader
->PackageListGuid
, PackageListGuid
, sizeof (EFI_GUID
));
161 PackageListHeader
->PackageLength
= PackageListLength
;
163 PackageListData
= ((UINT8
*) PackageListHeader
) + sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
165 for (Index
= 0; Index
< NumberOfPackages
; Index
++) {
166 CopyMem (&PackageLength
, &(TianoAutogenPackageHdrArray
[Index
]->BinaryLength
), sizeof (UINT32
));
167 PackageLength
-= sizeof (UINT32
);
168 CopyMem (PackageListData
, &(TianoAutogenPackageHdrArray
[Index
]->PackageHeader
), PackageLength
);
169 PackageListData
+= PackageLength
;
173 // Append EFI_HII_PACKAGE_END
175 PackageHeader
.Type
= EFI_HII_PACKAGE_END
;
176 PackageHeader
.Length
= sizeof (EFI_HII_PACKAGE_HEADER
);
177 CopyMem (PackageListData
, &PackageHeader
, PackageHeader
.Length
);
179 return PackageListHeader
;
187 EFI_GUID GuidBase
= { 0x14f95e01, 0xd562, 0x432e, { 0x84, 0x4a, 0x95, 0xa4, 0x39, 0x5, 0x10, 0x7e }};
188 static UINT64 Count
= 0;
190 CopyGuid (Guid
, &GuidBase
);
193 *((UINT64
*) Guid
) = *((UINT64
*) Guid
) + Count
;
197 FindStringPackAndUpdatePackListWithOnlyIfrPack (
198 IN HII_THUNK_PRIVATE_DATA
*Private
,
199 IN HII_THUNK_CONTEXT
*IfrThunkContext
204 EFI_HII_PACKAGE_LIST_HEADER
*StringPackageListHeader
;
206 HII_THUNK_CONTEXT
*ThunkContext
;
209 Link
= GetFirstNode (&Private
->ThunkContextListHead
);
211 while (!IsNull (&Private
->ThunkContextListHead
, Link
)) {
213 ThunkContext
= HII_THUNK_CONTEXT_FROM_LINK (Link
);
215 if (ThunkContext
!= IfrThunkContext
) {
216 if (CompareGuid (&IfrThunkContext
->TagGuid
, &ThunkContext
->TagGuid
) && (ThunkContext
->IfrPackageCount
== 0)) {
217 Status
= HiiLibExportPackageLists (ThunkContext
->UefiHiiHandle
, &StringPackageListHeader
, &Size
);
218 ASSERT_EFI_ERROR (Status
);
220 IfrThunkContext
->StringPackageCount
= GetPackageCountByType (StringPackageListHeader
, EFI_HII_PACKAGE_STRINGS
);
222 // Add Function to only get only String Packages from the Package List
224 Status
= mHiiDatabase
->UpdatePackageList (
226 IfrThunkContext
->UefiHiiHandle
,
227 StringPackageListHeader
229 ASSERT_EFI_ERROR (Status
);
231 FreePool (StringPackageListHeader
);
237 Link
= GetNextNode (&Private
->ThunkContextListHead
, Link
);
241 return EFI_NOT_FOUND
;
250 UefiRegisterPackageList(
251 IN EFI_HII_PROTOCOL
*This
,
252 IN HII_THUNK_PRIVATE_DATA
*Private
,
253 IN EFI_HII_PACKAGES
*Packages
,
254 OUT FRAMEWORK_EFI_HII_HANDLE
*Handle
258 UINTN StringPackageCount
;
259 UINTN IfrPackageCount
;
260 EFI_HII_PACKAGE_LIST_HEADER
*PackageListHeader
;
261 HII_THUNK_CONTEXT
*ThunkContext
;
262 HII_THUNK_CONTEXT
*ThunkContextToRemove
;
264 EFI_HII_PACKAGE_HEADER
*IfrPackage
;
266 PackageListHeader
= NULL
;
268 Status
= GetPackageCount (Packages
, &IfrPackageCount
, &StringPackageCount
);
269 ASSERT_EFI_ERROR (Status
);
271 if (IfrPackageCount
> 1) {
273 // HII Thunk only handle package with 0 or 1 IFR package.
276 return EFI_UNSUPPORTED
;
279 ThunkContext
= CreateThunkContext (Private
, StringPackageCount
, IfrPackageCount
);
280 if (ThunkContext
== NULL
) {
281 return EFI_OUT_OF_RESOURCES
;
283 ThunkContext
->ByFrameworkHiiNewPack
= TRUE
;
285 if (Packages
->GuidId
== NULL
) {
287 // UEFI HII Database require Package List GUID must be unique.
289 // If Packages->GuidId is NULL, the caller of FramworkHii->NewPack is registering
290 // packages with at least 1 StringPack and 1 IfrPack. Therefore, Packages->GuidId is
291 // not used as the name of the package list. A GUID is generated as a Package List
294 ASSERT (StringPackageCount
>=1 && IfrPackageCount
== 1);
295 IfrPackage
= GetIfrPackage (Packages
);
296 GetFormSetGuid (IfrPackage
, &ThunkContext
->TagGuid
);
298 ThunkContextToRemove
= TagGuidToIfrPackThunkContext (Private
, Packages
->GuidId
);
300 if (IfrPackageCount
> 0 &&
301 StringPackageCount
> 0 &&
302 (ThunkContextToRemove
!= NULL
)) {
303 DEBUG((EFI_D_WARN
, "Framework code registers HII package list with the same GUID more than once.\n"));
304 DEBUG((EFI_D_WARN
, "This package list should be already registered. Just return successfully.\n"));
305 HiiRemovePack (This
, ThunkContextToRemove
->FwHiiHandle
);
307 CopyGuid (&ThunkContext
->TagGuid
, Packages
->GuidId
);
311 // UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so
312 // that Setup Utility can load the Buffer Storage using this protocol.
314 if (IfrPackageCount
!= 0) {
315 InstallDefaultConfigAccessProtocol (Packages
, ThunkContext
);
317 PackageListHeader
= PrepareUefiPackageListFromFrameworkHiiPackages (Packages
, &ThunkContext
->TagGuid
);
318 Status
= mHiiDatabase
->NewPackageList (
321 ThunkContext
->UefiHiiDriverHandle
,
322 &ThunkContext
->UefiHiiHandle
324 if (Status
== EFI_INVALID_PARAMETER
) {
325 FreePool (PackageListHeader
);
328 // UEFI HII database does not allow two package list with the same GUID.
329 // In Framework HII implementation, Packages->GuidId is used as an identifier to associate
330 // a PackageList with only IFR to a Package list the with String package.
332 GenerateRandomGuid (&GuidId
);
334 PackageListHeader
= PrepareUefiPackageListFromFrameworkHiiPackages (Packages
, &GuidId
);
335 Status
= mHiiDatabase
->NewPackageList (
338 ThunkContext
->UefiHiiDriverHandle
,
339 &ThunkContext
->UefiHiiHandle
344 // BUGBUG: Remove when development is done
346 ASSERT_EFI_ERROR (Status
);
347 if (EFI_ERROR (Status
)) {
351 if (IfrPackageCount
== 0) {
352 if (StringPackageCount
!= 0) {
354 // Look for a Package List with only IFR Package with the same GUID name.
355 // If found one, add the String Packages to it.
357 UpdatePackListWithOnlyIfrPack (
364 CreateQuestionIdMap (ThunkContext
);
366 if (StringPackageCount
== 0) {
368 // Register the Package List to UEFI HII first.
370 Status
= FindStringPackAndUpdatePackListWithOnlyIfrPack (
375 if (EFI_ERROR (Status
)) {
382 if (EFI_ERROR (Status
)) {
383 DestroyThunkContext (ThunkContext
);
385 InsertTailList (&Private
->ThunkContextListHead
, &ThunkContext
->Link
);
386 *Handle
= ThunkContext
->FwHiiHandle
;
389 if (PackageListHeader
!= NULL
) {
390 FreePool (PackageListHeader
);
400 IN EFI_HII_PROTOCOL
*This
,
401 IN EFI_HII_PACKAGES
*Packages
,
402 OUT FRAMEWORK_EFI_HII_HANDLE
*Handle
408 Extracts the various packs from a package list.
412 This - Pointer of HII protocol.
413 Packages - Pointer of HII packages.
414 Handle - Handle value to be returned.
418 EFI_SUCCESS - Pacakges has added to HII database successfully.
419 EFI_INVALID_PARAMETER - Invalid parameter.
424 HII_THUNK_PRIVATE_DATA
*Private
;
427 if (Handle
== NULL
) {
428 return EFI_INVALID_PARAMETER
;
431 if (Packages
== NULL
) {
432 return EFI_INVALID_PARAMETER
;
435 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
438 // We use a simple Global variable to inform NewPackNotify
439 // that the package list registered here is already registered
440 // in the HII Thunk Layer. So NewPackNotify does not need to
441 // call RegisterUefiHiiHandle () to registered it.
443 mInFrameworkHiiNewPack
= TRUE
;
445 Private
= HII_THUNK_PRIVATE_DATA_FROM_THIS(This
);
447 Status
= UefiRegisterPackageList (
454 mInFrameworkHiiNewPack
= FALSE
;
456 gBS
->RestoreTPL (OldTpl
);
464 IN EFI_HII_PROTOCOL
*This
,
465 IN FRAMEWORK_EFI_HII_HANDLE Handle
470 Removes the various packs from a Handle
479 HII_THUNK_PRIVATE_DATA
*Private
;
480 HII_THUNK_CONTEXT
*ThunkContext
;
483 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
485 mInFrameworkHiiRemovePack
= TRUE
;
487 Private
= HII_THUNK_PRIVATE_DATA_FROM_THIS(This
);
489 ThunkContext
= FwHiiHandleToThunkContext (Private
, Handle
);
491 if (ThunkContext
!= NULL
) {
492 Status
= mHiiDatabase
->RemovePackageList (
494 ThunkContext
->UefiHiiHandle
496 ASSERT_EFI_ERROR (Status
);
498 if (ThunkContext
->IfrPackageCount
!= 0) {
499 UninstallDefaultConfigAccessProtocol (ThunkContext
);
502 DestroyThunkContext (ThunkContext
);
504 Status
= EFI_NOT_FOUND
;
507 mInFrameworkHiiRemovePack
= FALSE
;
508 gBS
->RestoreTPL (OldTpl
);
516 IN UINT8 PackageType
,
517 IN CONST EFI_GUID
*PackageGuid
,
518 IN CONST EFI_HII_PACKAGE_HEADER
*Package
,
519 IN EFI_HII_HANDLE Handle
,
520 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
524 HII_THUNK_PRIVATE_DATA
*Private
;
525 HII_THUNK_CONTEXT
*ThunkContext
;
527 ASSERT (PackageType
== EFI_HII_PACKAGE_STRINGS
|| PackageType
== EFI_HII_PACKAGE_FORMS
);
528 ASSERT (NotifyType
== EFI_HII_DATABASE_NOTIFY_ADD_PACK
|| NotifyType
== EFI_HII_DATABASE_NOTIFY_NEW_PACK
);
530 Status
= EFI_SUCCESS
;
531 Private
= mHiiThunkPrivateData
;
533 if (mInFrameworkHiiNewPack
|| mInFrameworkUpdatePakcage
) {
538 // We only create a ThunkContext if the Uefi Hii Handle is only already registered
539 // by the HII Thunk Layer.
541 ThunkContext
= UefiHiiHandleToThunkContext (Private
, Handle
);
542 if (ThunkContext
== NULL
) {
543 ThunkContext
= CreateThunkContextForUefiHiiHandle (Handle
);
544 ASSERT (ThunkContext
!= NULL
);
546 InsertTailList (&Private
->ThunkContextListHead
, &ThunkContext
->Link
);
549 if (PackageType
== EFI_HII_PACKAGE_FORMS
) {
550 GetAttributesOfFirstFormSet (ThunkContext
);
557 // Framework HII module may cache a GUID as the name of the package list.
558 // Then search for the Framework HII handle database for the handle matching
564 IN UINT8 PackageType
,
565 IN CONST EFI_GUID
*PackageGuid
,
566 IN CONST EFI_HII_PACKAGE_HEADER
*Package
,
567 IN EFI_HII_HANDLE Handle
,
568 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
572 HII_THUNK_PRIVATE_DATA
*Private
;
573 HII_THUNK_CONTEXT
*ThunkContext
;
574 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
577 Status
= EFI_SUCCESS
;
579 ASSERT (PackageType
== EFI_HII_PACKAGE_STRINGS
);
580 ASSERT (NotifyType
== EFI_HII_DATABASE_NOTIFY_REMOVE_PACK
);
582 if (mInFrameworkHiiRemovePack
|| mInFrameworkUpdatePakcage
) {
586 Private
= mHiiThunkPrivateData
;
588 ThunkContext
= UefiHiiHandleToThunkContext (Private
, Handle
);
591 // BugBug: Change to ASSERT if HII Database fix the bug and to also invoke
592 // NEW_PACK_NOTIFY for package (String Package) created internally.
594 if (ThunkContext
!= NULL
) {
595 if (!ThunkContext
->ByFrameworkHiiNewPack
) {
596 Status
= HiiLibExportPackageLists (Handle
, &HiiPackageList
, &BufferSize
);
597 ASSERT_EFI_ERROR (Status
);
599 if (GetPackageCountByType (HiiPackageList
, EFI_HII_PACKAGE_STRINGS
) == 1) {
601 // If the string package will be removed is the last string package
602 // in the package list, we will remove the HII Thunk entry from the
605 DestroyThunkContextForUefiHiiHandle (Private
, Handle
);
608 FreePool (HiiPackageList
);