3 This file contains the keyboard processing code to the HII database.
5 Copyright (c) 2006 - 2008, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "HiiDatabase.h"
18 #include "HiiHandle.h"
19 #include <Library/DebugLib.h>
21 CONST EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
24 Find the corressponding UEFI HII Handle from a Framework HII Handle given.
26 @param Private The HII Thunk Module Private context.
27 @param FwHiiHandle The Framemwork HII Handle.
29 @return NULL If Framework HII Handle is invalid.
30 @return The corresponding UEFI HII Handle.
33 FwHiiHandleToUefiHiiHandle (
34 IN CONST HII_THUNK_PRIVATE_DATA
*Private
,
35 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
38 HII_THUNK_CONTEXT
*ThunkContext
;
40 ASSERT (FwHiiHandle
!= (FRAMEWORK_EFI_HII_HANDLE
) 0);
41 ASSERT (Private
!= NULL
);
43 ThunkContext
= FwHiiHandleToThunkContext (Private
, FwHiiHandle
);
45 if (ThunkContext
!= NULL
) {
46 return ThunkContext
->UefiHiiHandle
;
49 return (EFI_HII_HANDLE
) NULL
;
54 Find the corressponding HII Thunk Context from a Framework HII Handle given.
56 @param Private The HII Thunk Module Private context.
57 @param FwHiiHandle The Framemwork HII Handle.
59 @return NULL If Framework HII Handle is invalid.
60 @return The corresponding HII Thunk Context.
63 FwHiiHandleToThunkContext (
64 IN CONST HII_THUNK_PRIVATE_DATA
*Private
,
65 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
69 HII_THUNK_CONTEXT
*ThunkContext
;
72 Link
= GetFirstNode (&Private
->ThunkContextListHead
);
74 while (!IsNull (&Private
->ThunkContextListHead
, Link
)) {
75 ThunkContext
= HII_THUNK_CONTEXT_FROM_LINK (Link
);
77 if (FwHiiHandle
== ThunkContext
->FwHiiHandle
) {
81 Link
= GetNextNode (&Private
->ThunkContextListHead
, Link
);
88 Find the corressponding HII Thunk Context from a UEFI HII Handle given.
90 @param Private The HII Thunk Module Private context.
91 @param UEFIHiiHandle The UEFI HII Handle.
93 @return NULL If UEFI HII Handle is invalid.
94 @return The corresponding HII Thunk Context.
97 UefiHiiHandleToThunkContext (
98 IN CONST HII_THUNK_PRIVATE_DATA
*Private
,
99 IN EFI_HII_HANDLE UefiHiiHandle
103 HII_THUNK_CONTEXT
*ThunkContext
;
105 Link
= GetFirstNode (&Private
->ThunkContextListHead
);
107 while (!IsNull (&Private
->ThunkContextListHead
, Link
)) {
108 ThunkContext
= HII_THUNK_CONTEXT_FROM_LINK (Link
);
110 if (UefiHiiHandle
== ThunkContext
->UefiHiiHandle
) {
113 Link
= GetNextNode (&Private
->ThunkContextListHead
, Link
);
120 Find the corressponding HII Thunk Context from a Tag GUID.
122 @param Private The HII Thunk Module Private context.
123 @param Guid The Tag GUID.
125 @return NULL No HII Thunk Context matched the Tag GUID.
126 @return The corresponding HII Thunk Context.
129 TagGuidToIfrPackThunkContext (
130 IN CONST HII_THUNK_PRIVATE_DATA
*Private
,
131 IN CONST EFI_GUID
*Guid
135 HII_THUNK_CONTEXT
*ThunkContext
;
137 Link
= GetFirstNode (&Private
->ThunkContextListHead
);
139 while (!IsNull (&Private
->ThunkContextListHead
, Link
)) {
140 ThunkContext
= HII_THUNK_CONTEXT_FROM_LINK (Link
);
142 if (CompareGuid (Guid
, &ThunkContext
->TagGuid
) && (ThunkContext
->IfrPackageCount
!= 0)) {
146 Link
= GetNextNode (&Private
->ThunkContextListHead
, Link
);
154 Clean up the HII Thunk Context for a UEFI HII Handle.
156 @param Private The HII Thunk Module Private context.
157 @param UEFIHiiHandle The UEFI HII Handle.
161 DestroyThunkContextForUefiHiiHandle (
162 IN HII_THUNK_PRIVATE_DATA
*Private
,
163 IN EFI_HII_HANDLE UefiHiiHandle
166 HII_THUNK_CONTEXT
*ThunkContext
;
168 ThunkContext
= UefiHiiHandleToThunkContext (Private
, UefiHiiHandle
);
169 ASSERT (ThunkContext
!= NULL
);
171 DestroyThunkContext (ThunkContext
);
176 This function create a HII_THUNK_CONTEXT for a package list registered
177 by a module calling EFI_HII_DATABASE_PROTOCOL.NewPackageList. It records
178 the PackageListGuid in EFI_HII_PACKAGE_LIST_HEADER in the TagGuid in
179 HII_THUNK_CONTEXT created. This TagGuid will be used as a key to s
183 CreateThunkContextForUefiHiiHandle (
184 IN EFI_HII_HANDLE UefiHiiHandle
188 EFI_GUID PackageGuid
;
189 HII_THUNK_CONTEXT
*ThunkContext
;
191 ThunkContext
= AllocateZeroPool (sizeof (*ThunkContext
));
192 ASSERT (ThunkContext
!= NULL
);
194 ThunkContext
->Signature
= HII_THUNK_CONTEXT_SIGNATURE
;
196 Status
= AllocateHiiHandle (&ThunkContext
->FwHiiHandle
);
197 if (EFI_ERROR (Status
)) {
201 ThunkContext
->UefiHiiHandle
= UefiHiiHandle
;
203 Status
= HiiLibExtractGuidFromHiiHandle (UefiHiiHandle
, &PackageGuid
);
204 ASSERT_EFI_ERROR (Status
);
206 CopyGuid(&ThunkContext
->TagGuid
, &PackageGuid
);
213 Get the number of HII Package for a Package type.
215 @param PackageListHeader The Package List.
216 @param PackageType The Package Type.
218 @return The number of Package for given type.
221 GetPackageCountByType (
222 IN CONST EFI_HII_PACKAGE_LIST_HEADER
*PackageListHeader
,
227 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
229 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) ((UINT8
*) PackageListHeader
+ sizeof (EFI_HII_PACKAGE_LIST_HEADER
));
232 while (PackageHeader
->Type
!= EFI_HII_PACKAGE_END
) {
233 if (PackageHeader
->Type
== PackageType
) {
236 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) ((UINT8
*) PackageHeader
+ PackageHeader
->Length
);
244 Get the Form Package from a Framework Package List.
246 @param Packages Framework Package List.
248 @return The Form Package Header found.
250 EFI_HII_PACKAGE_HEADER
*
252 IN CONST EFI_HII_PACKAGES
*Packages
256 TIANO_AUTOGEN_PACKAGES_HEADER
**TianoAutogenPackageHdrArray
;
258 ASSERT (Packages
!= NULL
);
260 TianoAutogenPackageHdrArray
= (TIANO_AUTOGEN_PACKAGES_HEADER
**) (((UINT8
*) &Packages
->GuidId
) + sizeof (Packages
->GuidId
));
262 for (Index
= 0; Index
< Packages
->NumberOfPackages
; Index
++) {
264 // The current UEFI HII build tool generate a binary in the format defined by
265 // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in
266 // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount
267 // may not be the exact number of valid package number in the binary generated
268 // by HII Build tool.
270 switch (TianoAutogenPackageHdrArray
[Index
]->PackageHeader
.Type
) {
271 case EFI_HII_PACKAGE_FORMS
:
272 return &TianoAutogenPackageHdrArray
[Index
]->PackageHeader
;
274 case EFI_HII_PACKAGE_STRINGS
:
275 case EFI_HII_PACKAGE_SIMPLE_FONTS
:
279 // The following fonts are invalid for a module that using Framework to UEFI thunk layer.
281 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT
:
282 case EFI_HII_PACKAGE_FONTS
:
283 case EFI_HII_PACKAGE_IMAGES
:
297 ASSERT if no FormSet Opcode is found.
299 @param Packages Form Framework Package.
300 @param FormSetGuid Return the FormSet Guid.
305 IN EFI_HII_PACKAGE_HEADER
*Package
,
306 OUT EFI_GUID
*FormSetGuid
310 EFI_IFR_OP_HEADER
*OpCode
;
311 EFI_IFR_FORM_SET
*FormSet
;
313 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
314 while (Offset
< Package
->Length
) {
315 OpCode
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ Offset
);
317 switch (OpCode
->OpCode
) {
318 case EFI_IFR_FORM_SET_OP
:
319 FormSet
= (EFI_IFR_FORM_SET
*) OpCode
;
320 CopyGuid (FormSetGuid
, (EFI_GUID
*)(VOID
*)&FormSet
->Guid
);
327 Offset
+= OpCode
->Length
;
331 // A proper IFR must have a formset opcode.
338 Creat a Thunk Context.
340 ASSERT if no FormSet Opcode is found.
342 @param Private The HII Thunk Private Context.
343 @param StringPackageCount The String package count.
344 @param FormSetGuid The IFR Package count.
346 @return A newly created Thunk Context.
347 @retval NULL No resource to create a new Thunk Context.
351 IN HII_THUNK_PRIVATE_DATA
*Private
,
352 IN UINTN StringPackageCount
,
353 IN UINTN IfrPackageCount
357 HII_THUNK_CONTEXT
*ThunkContext
;
359 ThunkContext
= AllocateZeroPool (sizeof (HII_THUNK_CONTEXT
));
360 ASSERT (ThunkContext
!= NULL
);
362 ThunkContext
->Signature
= HII_THUNK_CONTEXT_SIGNATURE
;
363 ThunkContext
->IfrPackageCount
= IfrPackageCount
;
364 ThunkContext
->StringPackageCount
= StringPackageCount
;
365 Status
= AllocateHiiHandle (&ThunkContext
->FwHiiHandle
);
366 if (EFI_ERROR (Status
)) {
375 Destroy the Thunk Context and free up all resource.
377 @param ThunkContext The HII Thunk Private Context to be freed.
381 DestroyThunkContext (
382 IN HII_THUNK_CONTEXT
*ThunkContext
385 ASSERT (ThunkContext
!= NULL
);
387 FreeHiiHandle (ThunkContext
->FwHiiHandle
);
389 RemoveEntryList (&ThunkContext
->Link
);
391 if (ThunkContext
->FormSet
!= NULL
) {
392 DestroyFormSet (ThunkContext
->FormSet
);
395 FreePool (ThunkContext
);
399 Get the FormSet's Default Varstore ID based on the rule (Descending Priority):
401 1) Var Store ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01).
402 2) First Var Store ID.
404 @param FormSet The Form Set.
408 GetFormsetDefaultVarstoreId (
409 IN OUT FORM_BROWSER_FORMSET
* FormSet
412 LIST_ENTRY
*StorageList
;
413 FORMSET_STORAGE
*Storage
;
416 // VarStoreId 0 is invalid in UEFI IFR.
418 FormSet
->DefaultVarStoreId
= 0;
419 StorageList
= GetFirstNode (&FormSet
->StorageListHead
);
421 while (!IsNull (&FormSet
->StorageListHead
, StorageList
)) {
422 Storage
= FORMSET_STORAGE_FROM_LINK (StorageList
);
424 DEBUG ((EFI_D_INFO
, "FormSet %g: Found Varstore ID %x\n", &FormSet
->Guid
, Storage
->VarStoreId
));
426 if (Storage
->VarStoreId
== FRAMEWORK_RESERVED_VARSTORE_ID
) {
427 FormSet
->DefaultVarStoreId
= FRAMEWORK_RESERVED_VARSTORE_ID
;
431 StorageList
= GetNextNode (&FormSet
->StorageListHead
, StorageList
);
434 if (FormSet
->DefaultVarStoreId
!= FRAMEWORK_RESERVED_VARSTORE_ID
) {
435 StorageList
= GetFirstNode (&FormSet
->StorageListHead
);
436 if (!IsNull (&FormSet
->StorageListHead
, StorageList
)) {
437 Storage
= FORMSET_STORAGE_FROM_LINK (StorageList
);
438 FormSet
->DefaultVarStoreId
= Storage
->VarStoreId
;
444 if (FormSet
->DefaultVarStoreId
== 0) {
445 DEBUG ((EFI_D_INFO
, "FormSet %g: No Varstore Found\n", &FormSet
->Guid
));
447 DEBUG ((EFI_D_INFO
, "FormSet %g: Default Varstore ID is %x\n", &FormSet
->Guid
, FormSet
->DefaultVarStoreId
));
455 Fetch the Ifr binary data of a FormSet.
457 @param Handle PackageList Handle
458 @param FormSetGuid GUID of a formset. If not specified (NULL or zero
459 GUID), take the first FormSet found in package
461 @param BinaryLength The length of the FormSet IFR binary.
462 @param BinaryData The buffer designed to receive the FormSet.
464 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
465 BufferLength was updated.
466 @retval EFI_INVALID_PARAMETER The handle is unknown.
467 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
468 be found with the requested FormId.
473 IN EFI_HII_HANDLE Handle
,
474 IN OUT EFI_GUID
*FormSetGuid
,
475 OUT UINTN
*BinaryLength
,
476 OUT UINT8
**BinaryData
480 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
486 BOOLEAN ReturnDefault
;
487 UINT32 PackageListLength
;
488 EFI_HII_PACKAGE_HEADER PackageHeader
;
492 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));;
495 // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list
497 if (FormSetGuid
== NULL
|| CompareGuid (FormSetGuid
, &gZeroGuid
)) {
498 ReturnDefault
= TRUE
;
500 ReturnDefault
= FALSE
;
504 // Get HII PackageList
507 HiiPackageList
= NULL
;
508 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
509 if (Status
== EFI_BUFFER_TOO_SMALL
) {
510 HiiPackageList
= AllocatePool (BufferSize
);
511 ASSERT (HiiPackageList
!= NULL
);
513 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
515 if (EFI_ERROR (Status
)) {
520 // Get Form package from this HII package List
522 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
524 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
526 while (Offset
< PackageListLength
) {
527 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
528 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
530 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
532 // Search FormSet in this Form Package
534 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
535 while (Offset2
< PackageHeader
.Length
) {
536 OpCodeData
= Package
+ Offset2
;
538 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
540 // Check whether return default FormSet
547 // FormSet GUID is specified, check it
549 if (CompareGuid (FormSetGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
554 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
557 if (Offset2
< PackageHeader
.Length
) {
559 // Target formset found
565 Offset
+= PackageHeader
.Length
;
568 if (Offset
>= PackageListLength
) {
570 // Form package not found in this Package List
572 gBS
->FreePool (HiiPackageList
);
573 return EFI_NOT_FOUND
;
576 if (ReturnDefault
&& FormSetGuid
!= NULL
) {
578 // Return the default FormSet GUID
580 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
584 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
585 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
586 // of the Form Package.
588 *BinaryLength
= PackageHeader
.Length
- Offset2
;
589 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
591 gBS
->FreePool (HiiPackageList
);
593 if (*BinaryData
== NULL
) {
594 return EFI_OUT_OF_RESOURCES
;
601 Initialize the internal data structure of a FormSet.
603 @param Handle PackageList Handle
604 @param FormSetGuid GUID of a formset. If not specified (NULL or zero
605 GUID), take the first FormSet found in package
607 @param FormSet FormSet data structure.
609 @retval EFI_SUCCESS The function completed successfully.
610 @retval EFI_NOT_FOUND The specified FormSet could not be found.
615 IN EFI_HII_HANDLE Handle
,
616 IN OUT EFI_GUID
*FormSetGuid
,
617 OUT FORM_BROWSER_FORMSET
*FormSet
622 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
623 if (EFI_ERROR (Status
)) {
627 FormSet
->HiiHandle
= Handle
;
628 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
631 // Parse the IFR binary OpCodes
633 Status
= ParseOpCodes (FormSet
);
634 if (EFI_ERROR (Status
)) {
638 GetFormsetDefaultVarstoreId (FormSet
);
643 Parse the Form Package and build a FORM_BROWSER_FORMSET structure.
645 @param UefiHiiHandle PackageList Handle
647 @return A pointer to FORM_BROWSER_FORMSET.
650 FORM_BROWSER_FORMSET
*
652 IN EFI_HII_HANDLE UefiHiiHandle
655 FORM_BROWSER_FORMSET
*FormSet
;
656 EFI_GUID FormSetGuid
;
659 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
660 ASSERT (FormSet
!= NULL
);
662 CopyGuid (&FormSetGuid
, &gZeroGuid
);
663 Status
= InitializeFormSet (UefiHiiHandle
, &FormSetGuid
, FormSet
);
664 ASSERT_EFI_ERROR (Status
);