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_FORM
:
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 HII_THUNK_PRIVATE_DATA
*Private
,
252 IN EFI_HII_PACKAGES
*Packages
,
253 OUT FRAMEWORK_EFI_HII_HANDLE
*Handle
257 UINTN StringPackageCount
;
258 UINTN IfrPackageCount
;
259 EFI_HII_PACKAGE_LIST_HEADER
*PackageListHeader
;
260 HII_THUNK_CONTEXT
*ThunkContext
;
263 PackageListHeader
= NULL
;
265 Status
= GetPackageCount (Packages
, &IfrPackageCount
, &StringPackageCount
);
266 ASSERT_EFI_ERROR (Status
);
268 if (IfrPackageCount
> 1) {
270 // HII Thunk only handle package with 0 or 1 IFR package.
273 return EFI_UNSUPPORTED
;
276 ThunkContext
= CreateThunkContext (Private
, StringPackageCount
, IfrPackageCount
);
277 if (ThunkContext
== NULL
) {
278 return EFI_OUT_OF_RESOURCES
;
280 ThunkContext
->ByFrameworkHiiNewPack
= TRUE
;
282 if (Packages
->GuidId
== NULL
) {
284 // UEFI HII Database require Package List GUID must be unique.
286 // If Packages->GuidId is NULL, the caller of FramworkHii->NewPack is registering
287 // packages with at least 1 StringPack and 1 IfrPack. Therefore, Packages->GuidId is
288 // not used as the name of the package list. A GUID is generated as a Package List
291 ASSERT (StringPackageCount
>=1 && IfrPackageCount
== 1);
292 GenerateRandomGuid (&GuidId
);
294 CopyGuid (&GuidId
, Packages
->GuidId
);
298 // Record the Package List GUID, it is used as a name for the package list by Framework HII.
300 CopyGuid (&ThunkContext
->TagGuid
, &GuidId
);
302 if ((StringPackageCount
== 0) && (IfrPackageCount
!= 0)) {
304 // UEFI HII database does not allow two package list with the same GUID.
305 // In Framework HII implementation, Packages->GuidId is used as an identifier to associate
306 // a PackageList with only IFR to a Package list the with String package.
308 GenerateRandomGuid (&GuidId
);
312 // UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so
313 // that Setup Utility can load the Buffer Storage using this protocol.
315 if (IfrPackageCount
!= 0) {
316 InstallDefaultConfigAccessProtocol (Packages
, ThunkContext
);
318 PackageListHeader
= PrepareUefiPackageListFromFrameworkHiiPackages (Packages
, &GuidId
);
319 Status
= mHiiDatabase
->NewPackageList (
322 ThunkContext
->UefiHiiDriverHandle
,
323 &ThunkContext
->UefiHiiHandle
327 // BUGBUG: Remove when development is done
329 ASSERT_EFI_ERROR (Status
);
330 if (EFI_ERROR (Status
)) {
334 if (IfrPackageCount
== 0) {
335 if (StringPackageCount
!= 0) {
337 // Look for a Package List with only IFR Package with the same GUID name.
338 // If found one, add the String Packages to it.
340 UpdatePackListWithOnlyIfrPack (
347 CreateQuestionIdMap (ThunkContext
);
349 if (StringPackageCount
== 0) {
351 // Register the Package List to UEFI HII first.
353 Status
= FindStringPackAndUpdatePackListWithOnlyIfrPack (
358 if (EFI_ERROR (Status
)) {
365 if (EFI_ERROR (Status
)) {
366 DestroyThunkContext (ThunkContext
);
368 InsertTailList (&Private
->ThunkContextListHead
, &ThunkContext
->Link
);
369 *Handle
= ThunkContext
->FwHiiHandle
;
372 SafeFreePool (PackageListHeader
);
381 IN EFI_HII_PROTOCOL
*This
,
382 IN EFI_HII_PACKAGES
*Packages
,
383 OUT FRAMEWORK_EFI_HII_HANDLE
*Handle
389 Extracts the various packs from a package list.
393 This - Pointer of HII protocol.
394 Packages - Pointer of HII packages.
395 Handle - Handle value to be returned.
399 EFI_SUCCESS - Pacakges has added to HII database successfully.
400 EFI_INVALID_PARAMETER - Invalid parameter.
405 HII_THUNK_PRIVATE_DATA
*Private
;
408 if (Handle
== NULL
) {
409 return EFI_INVALID_PARAMETER
;
412 if (Packages
== NULL
) {
413 return EFI_INVALID_PARAMETER
;
416 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
419 // We use a simple Global variable to inform NewPackNotify
420 // that the package list registered here is already registered
421 // in the HII Thunk Layer. So NewPackNotify does not need to
422 // call RegisterUefiHiiHandle () to registered it.
424 mInFrameworkHiiNewPack
= TRUE
;
426 Private
= HII_THUNK_PRIVATE_DATA_FROM_THIS(This
);
428 Status
= UefiRegisterPackageList (
434 mInFrameworkHiiNewPack
= FALSE
;
436 gBS
->RestoreTPL (OldTpl
);
444 IN EFI_HII_PROTOCOL
*This
,
445 IN FRAMEWORK_EFI_HII_HANDLE Handle
450 Removes the various packs from a Handle
459 HII_THUNK_PRIVATE_DATA
*Private
;
460 HII_THUNK_CONTEXT
*ThunkContext
;
463 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
465 mInFrameworkHiiRemovePack
= TRUE
;
467 Private
= HII_THUNK_PRIVATE_DATA_FROM_THIS(This
);
469 ThunkContext
= FwHiiHandleToThunkContext (Private
, Handle
);
471 if (ThunkContext
!= NULL
) {
472 Status
= mHiiDatabase
->RemovePackageList (
474 ThunkContext
->UefiHiiHandle
476 ASSERT_EFI_ERROR (Status
);
478 if (ThunkContext
->IfrPackageCount
!= 0) {
479 UninstallDefaultConfigAccessProtocol (ThunkContext
);
482 RemoveEntryList (&ThunkContext
->Link
);
483 DestroyThunkContext (ThunkContext
);
485 Status
= EFI_NOT_FOUND
;
488 mInFrameworkHiiRemovePack
= FALSE
;
489 gBS
->RestoreTPL (OldTpl
);
497 IN UINT8 PackageType
,
498 IN CONST EFI_GUID
*PackageGuid
,
499 IN CONST EFI_HII_PACKAGE_HEADER
*Package
,
500 IN EFI_HII_HANDLE Handle
,
501 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
505 HII_THUNK_PRIVATE_DATA
*Private
;
506 HII_THUNK_CONTEXT
*ThunkContext
;
508 ASSERT (PackageType
== EFI_HII_PACKAGE_STRINGS
|| PackageType
== EFI_HII_PACKAGE_FORM
);
509 ASSERT (NotifyType
== EFI_HII_DATABASE_NOTIFY_ADD_PACK
|| NotifyType
== EFI_HII_DATABASE_NOTIFY_NEW_PACK
);
511 Status
= EFI_SUCCESS
;
512 Private
= mHiiThunkPrivateData
;
514 if (mInFrameworkHiiNewPack
|| mInFrameworkUpdatePakcage
) {
519 // We only create a ThunkContext if the Uefi Hii Handle is only already registered
520 // by the HII Thunk Layer.
522 ThunkContext
= UefiHiiHandleToThunkContext (Private
, Handle
);
523 if (ThunkContext
== NULL
) {
524 ThunkContext
= CreateThunkContextForUefiHiiHandle (Handle
);
525 ASSERT (ThunkContext
!= NULL
);
527 InsertTailList (&Private
->ThunkContextListHead
, &ThunkContext
->Link
);
530 if (PackageType
== EFI_HII_PACKAGE_FORM
) {
531 GetAttributesOfFirstFormSet (ThunkContext
);
538 // Framework HII module may cache a GUID as the name of the package list.
539 // Then search for the Framework HII handle database for the handle matching
545 IN UINT8 PackageType
,
546 IN CONST EFI_GUID
*PackageGuid
,
547 IN CONST EFI_HII_PACKAGE_HEADER
*Package
,
548 IN EFI_HII_HANDLE Handle
,
549 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
553 HII_THUNK_PRIVATE_DATA
*Private
;
554 HII_THUNK_CONTEXT
*ThunkContext
;
555 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
558 Status
= EFI_SUCCESS
;
560 ASSERT (PackageType
== EFI_HII_PACKAGE_STRINGS
);
561 ASSERT (NotifyType
== EFI_HII_DATABASE_NOTIFY_REMOVE_PACK
);
563 if (mInFrameworkHiiRemovePack
|| mInFrameworkUpdatePakcage
) {
567 Private
= mHiiThunkPrivateData
;
569 ThunkContext
= UefiHiiHandleToThunkContext (Private
, Handle
);
571 if (!ThunkContext
->ByFrameworkHiiNewPack
) {
572 Status
= HiiLibExportPackageLists (Handle
, &HiiPackageList
, &BufferSize
);
573 ASSERT_EFI_ERROR (Status
);
575 if (GetPackageCountByType (HiiPackageList
, EFI_HII_PACKAGE_STRINGS
) == 1) {
577 // If the string package will be removed is the last string package
578 // in the package list, we will remove the HII Thunk entry from the
581 DestroyThunkContextForUefiHiiHandle (Private
, Handle
);
584 FreePool (HiiPackageList
);