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}};
22 CONST CHAR16 FrameworkReservedVarstoreName
[] = FRAMEWORK_RESERVED_VARSTORE_NAME
;
26 Find the corressponding UEFI HII Handle from a Framework HII Handle given.
28 @param Private The HII Thunk Module Private context.
29 @param FwHiiHandle The Framemwork HII Handle.
31 @return NULL If Framework HII Handle is invalid.
32 @return The corresponding UEFI HII Handle.
35 FwHiiHandleToUefiHiiHandle (
36 IN CONST HII_THUNK_PRIVATE_DATA
*Private
,
37 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
40 HII_THUNK_CONTEXT
*ThunkContext
;
42 ASSERT (FwHiiHandle
!= (FRAMEWORK_EFI_HII_HANDLE
) 0);
43 ASSERT (Private
!= NULL
);
45 ThunkContext
= FwHiiHandleToThunkContext (Private
, FwHiiHandle
);
47 if (ThunkContext
!= NULL
) {
48 return ThunkContext
->UefiHiiHandle
;
51 return (EFI_HII_HANDLE
) NULL
;
56 Find the corressponding HII Thunk Context from a Framework HII Handle given.
58 @param Private The HII Thunk Module Private context.
59 @param FwHiiHandle The Framemwork HII Handle.
61 @return NULL If Framework HII Handle is invalid.
62 @return The corresponding HII Thunk Context.
65 FwHiiHandleToThunkContext (
66 IN CONST HII_THUNK_PRIVATE_DATA
*Private
,
67 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
71 HII_THUNK_CONTEXT
*ThunkContext
;
74 Link
= GetFirstNode (&Private
->ThunkContextListHead
);
76 while (!IsNull (&Private
->ThunkContextListHead
, Link
)) {
77 ThunkContext
= HII_THUNK_CONTEXT_FROM_LINK (Link
);
79 if (FwHiiHandle
== ThunkContext
->FwHiiHandle
) {
83 Link
= GetNextNode (&Private
->ThunkContextListHead
, Link
);
90 Find the corressponding HII Thunk Context from a UEFI HII Handle given.
92 @param Private The HII Thunk Module Private context.
93 @param UEFIHiiHandle The UEFI HII Handle.
95 @return NULL If UEFI HII Handle is invalid.
96 @return The corresponding HII Thunk Context.
99 UefiHiiHandleToThunkContext (
100 IN CONST HII_THUNK_PRIVATE_DATA
*Private
,
101 IN EFI_HII_HANDLE UefiHiiHandle
105 HII_THUNK_CONTEXT
*ThunkContext
;
107 Link
= GetFirstNode (&Private
->ThunkContextListHead
);
109 while (!IsNull (&Private
->ThunkContextListHead
, Link
)) {
110 ThunkContext
= HII_THUNK_CONTEXT_FROM_LINK (Link
);
112 if (UefiHiiHandle
== ThunkContext
->UefiHiiHandle
) {
115 Link
= GetNextNode (&Private
->ThunkContextListHead
, Link
);
122 Find the corressponding HII Thunk Context from a Tag GUID.
124 @param Private The HII Thunk Module Private context.
125 @param Guid The Tag GUID.
127 @return NULL No HII Thunk Context matched the Tag GUID.
128 @return The corresponding HII Thunk Context.
131 TagGuidToIfrPackThunkContext (
132 IN CONST HII_THUNK_PRIVATE_DATA
*Private
,
133 IN CONST EFI_GUID
*Guid
137 HII_THUNK_CONTEXT
*ThunkContext
;
139 Link
= GetFirstNode (&Private
->ThunkContextListHead
);
141 while (!IsNull (&Private
->ThunkContextListHead
, Link
)) {
142 ThunkContext
= HII_THUNK_CONTEXT_FROM_LINK (Link
);
144 if (CompareGuid (Guid
, &ThunkContext
->TagGuid
) && (ThunkContext
->IfrPackageCount
!= 0)) {
148 Link
= GetNextNode (&Private
->ThunkContextListHead
, Link
);
156 Clean up the HII Thunk Context for a UEFI HII Handle.
158 @param Private The HII Thunk Module Private context.
159 @param UEFIHiiHandle The UEFI HII Handle.
163 DestroyThunkContextForUefiHiiHandle (
164 IN HII_THUNK_PRIVATE_DATA
*Private
,
165 IN EFI_HII_HANDLE UefiHiiHandle
168 HII_THUNK_CONTEXT
*ThunkContext
;
170 ThunkContext
= UefiHiiHandleToThunkContext (Private
, UefiHiiHandle
);
171 ASSERT (ThunkContext
!= NULL
);
173 DestroyThunkContext (ThunkContext
);
178 This function create a HII_THUNK_CONTEXT for a package list registered
179 by a module calling EFI_HII_DATABASE_PROTOCOL.NewPackageList. It records
180 the PackageListGuid in EFI_HII_PACKAGE_LIST_HEADER in the TagGuid in
181 HII_THUNK_CONTEXT created. This TagGuid will be used as a key to s
185 CreateThunkContextForUefiHiiHandle (
186 IN EFI_HII_HANDLE UefiHiiHandle
190 EFI_GUID PackageGuid
;
191 HII_THUNK_CONTEXT
*ThunkContext
;
193 ThunkContext
= AllocateZeroPool (sizeof (*ThunkContext
));
194 ASSERT (ThunkContext
!= NULL
);
196 ThunkContext
->Signature
= HII_THUNK_CONTEXT_SIGNATURE
;
198 Status
= AllocateHiiHandle (&ThunkContext
->FwHiiHandle
);
199 if (EFI_ERROR (Status
)) {
203 ThunkContext
->UefiHiiHandle
= UefiHiiHandle
;
205 Status
= HiiLibExtractGuidFromHiiHandle (UefiHiiHandle
, &PackageGuid
);
206 ASSERT_EFI_ERROR (Status
);
208 CopyGuid(&ThunkContext
->TagGuid
, &PackageGuid
);
215 Get the number of HII Package for a Package type.
217 @param PackageListHeader The Package List.
218 @param PackageType The Package Type.
220 @return The number of Package for given type.
223 GetPackageCountByType (
224 IN CONST EFI_HII_PACKAGE_LIST_HEADER
*PackageListHeader
,
229 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
231 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) ((UINT8
*) PackageListHeader
+ sizeof (EFI_HII_PACKAGE_LIST_HEADER
));
234 while (PackageHeader
->Type
!= EFI_HII_PACKAGE_END
) {
235 if (PackageHeader
->Type
== PackageType
) {
238 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) ((UINT8
*) PackageHeader
+ PackageHeader
->Length
);
246 Get the Form Package from a Framework Package List.
248 @param Packages Framework Package List.
250 @return The Form Package Header found.
252 EFI_HII_PACKAGE_HEADER
*
254 IN CONST EFI_HII_PACKAGES
*Packages
258 TIANO_AUTOGEN_PACKAGES_HEADER
**TianoAutogenPackageHdrArray
;
260 ASSERT (Packages
!= NULL
);
262 TianoAutogenPackageHdrArray
= (TIANO_AUTOGEN_PACKAGES_HEADER
**) (((UINT8
*) &Packages
->GuidId
) + sizeof (Packages
->GuidId
));
264 for (Index
= 0; Index
< Packages
->NumberOfPackages
; Index
++) {
266 // The current UEFI HII build tool generate a binary in the format defined by
267 // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in
268 // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount
269 // may not be the exact number of valid package number in the binary generated
270 // by HII Build tool.
272 switch (TianoAutogenPackageHdrArray
[Index
]->FrameworkPackageHeader
.Type
) {
274 return &TianoAutogenPackageHdrArray
[Index
]->PackageHeader
;
293 ASSERT if no FormSet Opcode is found.
295 @param Packages Form Framework Package.
296 @param FormSetGuid Return the FormSet Guid.
301 IN EFI_HII_PACKAGE_HEADER
*Package
,
302 OUT EFI_GUID
*FormSetGuid
306 EFI_IFR_OP_HEADER
*OpCode
;
307 EFI_IFR_FORM_SET
*FormSet
;
309 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
310 while (Offset
< Package
->Length
) {
311 OpCode
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ Offset
);
313 switch (OpCode
->OpCode
) {
314 case EFI_IFR_FORM_SET_OP
:
315 FormSet
= (EFI_IFR_FORM_SET
*) OpCode
;
316 CopyGuid (FormSetGuid
, (EFI_GUID
*)(VOID
*)&FormSet
->Guid
);
323 Offset
+= OpCode
->Length
;
327 // A proper IFR must have a formset opcode.
334 Creat a Thunk Context.
336 ASSERT if no FormSet Opcode is found.
338 @param Private The HII Thunk Private Context.
339 @param StringPackageCount The String package count.
340 @param FormSetGuid The IFR Package count.
342 @return A newly created Thunk Context.
343 @retval NULL No resource to create a new Thunk Context.
347 IN HII_THUNK_PRIVATE_DATA
*Private
,
348 IN UINTN StringPackageCount
,
349 IN UINTN IfrPackageCount
353 HII_THUNK_CONTEXT
*ThunkContext
;
355 ThunkContext
= AllocateZeroPool (sizeof (HII_THUNK_CONTEXT
));
356 ASSERT (ThunkContext
!= NULL
);
358 ThunkContext
->Signature
= HII_THUNK_CONTEXT_SIGNATURE
;
359 ThunkContext
->IfrPackageCount
= IfrPackageCount
;
360 ThunkContext
->StringPackageCount
= StringPackageCount
;
361 Status
= AllocateHiiHandle (&ThunkContext
->FwHiiHandle
);
362 if (EFI_ERROR (Status
)) {
371 Destroy the Thunk Context and free up all resource.
373 @param ThunkContext The HII Thunk Private Context to be freed.
377 DestroyThunkContext (
378 IN HII_THUNK_CONTEXT
*ThunkContext
381 ASSERT (ThunkContext
!= NULL
);
383 FreeHiiHandle (ThunkContext
->FwHiiHandle
);
385 RemoveEntryList (&ThunkContext
->Link
);
387 if (ThunkContext
->FormSet
!= NULL
) {
388 DestroyFormSet (ThunkContext
->FormSet
);
391 FreePool (ThunkContext
);
395 Get the FormSet's Default Varstore ID based on the rule (Descending Priority):
397 1) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01) is found, Var Store ID is used.
398 2) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID is not found, First Var Store ID is used
399 as the default Var Store ID.
401 @param FormSet The Form Set. The Default Varstore ID is updated if found.
405 GetFormsetDefaultVarstoreId (
406 IN OUT FORM_BROWSER_FORMSET
* FormSet
409 LIST_ENTRY
*StorageList
;
410 FORMSET_STORAGE
*Storage
;
411 FORMSET_STORAGE
*DefaultStorage
;
414 // VarStoreId 0 is invalid in UEFI IFR.
416 DefaultStorage
= NULL
;
417 FormSet
->DefaultVarStoreId
= 0;
418 StorageList
= GetFirstNode (&FormSet
->StorageListHead
);
420 while (!IsNull (&FormSet
->StorageListHead
, StorageList
)) {
421 Storage
= FORMSET_STORAGE_FROM_LINK (StorageList
);
423 DEBUG ((EFI_D_INFO
, "FormSet %g: Found Varstore ID %x Name %s Size 0x%x\n", &FormSet
->Guid
, Storage
->VarStoreId
, Storage
->Name
, Storage
->Size
));
425 if (Storage
->VarStoreId
== FRAMEWORK_RESERVED_VARSTORE_ID
) {
427 // 1) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01) is found, Var Store ID is used.
429 FormSet
->DefaultVarStoreId
= FRAMEWORK_RESERVED_VARSTORE_ID
;
430 DefaultStorage
= Storage
;
434 StorageList
= GetNextNode (&FormSet
->StorageListHead
, StorageList
);
437 if (FormSet
->DefaultVarStoreId
!= FRAMEWORK_RESERVED_VARSTORE_ID
) {
440 // 2) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID is not found, First Var Store ID is used
441 // as the default Var Store ID.
443 StorageList
= GetFirstNode (&FormSet
->StorageListHead
);
444 if (!IsNull (&FormSet
->StorageListHead
, StorageList
)) {
445 Storage
= FORMSET_STORAGE_FROM_LINK (StorageList
);
446 FormSet
->DefaultVarStoreId
= Storage
->VarStoreId
;
447 DefaultStorage
= Storage
;
453 if (FormSet
->DefaultVarStoreId
== 0) {
454 DEBUG ((EFI_D_INFO
, "FormSet %g: No Varstore Found\n", &FormSet
->Guid
));
456 // The name of default VARSTORE with a Explicit declaration statement will be updated to L"Setup" to make sure
457 // the Framework HII Setup module will run correctly. Framework HII Setup module always assumed that default
458 // VARSTORE to have L"Setup" as name, Formset GUID as GUID.
460 DEBUG ((EFI_D_INFO
, "FormSet %g: Default Varstore ID (0x%x) N(%s) G(%g)\n", &FormSet
->Guid
, FormSet
->DefaultVarStoreId
, DefaultStorage
->Name
, &DefaultStorage
->Guid
));
462 if (StrCmp (DefaultStorage
->Name
, FrameworkReservedVarstoreName
) != 0) {
463 DEBUG ((EFI_D_INFO
, " : Name is updated from %s to %s.\n", DefaultStorage
->Name
, FrameworkReservedVarstoreName
));
464 FormSet
->OriginalDefaultVarStoreName
= DefaultStorage
->Name
;
465 DefaultStorage
->Name
= AllocateCopyPool (StrSize (FrameworkReservedVarstoreName
), FrameworkReservedVarstoreName
);
474 Fetch the Ifr binary data of a FormSet.
476 @param Handle PackageList Handle
477 @param FormSetGuid GUID of a formset. If not specified (NULL or zero
478 GUID), take the first FormSet found in package
480 @param BinaryLength The length of the FormSet IFR binary.
481 @param BinaryData The buffer designed to receive the FormSet.
483 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
484 BufferLength was updated.
485 @retval EFI_INVALID_PARAMETER The handle is unknown.
486 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
487 be found with the requested FormId.
492 IN EFI_HII_HANDLE Handle
,
493 IN OUT EFI_GUID
*FormSetGuid
,
494 OUT UINTN
*BinaryLength
,
495 OUT UINT8
**BinaryData
499 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
505 BOOLEAN ReturnDefault
;
506 UINT32 PackageListLength
;
507 EFI_HII_PACKAGE_HEADER PackageHeader
;
511 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));;
514 // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list
516 if (FormSetGuid
== NULL
|| CompareGuid (FormSetGuid
, &gZeroGuid
)) {
517 ReturnDefault
= TRUE
;
519 ReturnDefault
= FALSE
;
523 // Get HII PackageList
526 HiiPackageList
= NULL
;
527 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
528 if (Status
== EFI_BUFFER_TOO_SMALL
) {
529 HiiPackageList
= AllocatePool (BufferSize
);
530 ASSERT (HiiPackageList
!= NULL
);
532 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
534 if (EFI_ERROR (Status
)) {
539 // Get Form package from this HII package List
541 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
543 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
545 while (Offset
< PackageListLength
) {
546 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
547 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
549 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
551 // Search FormSet in this Form Package
553 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
554 while (Offset2
< PackageHeader
.Length
) {
555 OpCodeData
= Package
+ Offset2
;
557 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
559 // Check whether return default FormSet
566 // FormSet GUID is specified, check it
568 if (CompareGuid (FormSetGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
573 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
576 if (Offset2
< PackageHeader
.Length
) {
578 // Target formset found
584 Offset
+= PackageHeader
.Length
;
587 if (Offset
>= PackageListLength
) {
589 // Form package not found in this Package List
591 gBS
->FreePool (HiiPackageList
);
592 return EFI_NOT_FOUND
;
595 if (ReturnDefault
&& FormSetGuid
!= NULL
) {
597 // Return the default FormSet GUID
599 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
603 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
604 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
605 // of the Form Package.
607 *BinaryLength
= PackageHeader
.Length
- Offset2
;
608 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
610 gBS
->FreePool (HiiPackageList
);
612 if (*BinaryData
== NULL
) {
613 return EFI_OUT_OF_RESOURCES
;
620 Initialize the internal data structure of a FormSet.
622 @param Handle PackageList Handle
623 @param FormSetGuid GUID of a formset. If not specified (NULL or zero
624 GUID), take the first FormSet found in package
626 @param FormSet FormSet data structure.
628 @retval EFI_SUCCESS The function completed successfully.
629 @retval EFI_NOT_FOUND The specified FormSet could not be found.
634 IN EFI_HII_HANDLE Handle
,
635 IN OUT EFI_GUID
*FormSetGuid
,
636 OUT FORM_BROWSER_FORMSET
*FormSet
641 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
642 if (EFI_ERROR (Status
)) {
646 FormSet
->HiiHandle
= Handle
;
647 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
650 // Parse the IFR binary OpCodes
652 Status
= ParseOpCodes (FormSet
);
653 if (EFI_ERROR (Status
)) {
657 GetFormsetDefaultVarstoreId (FormSet
);
662 Parse the Form Package and build a FORM_BROWSER_FORMSET structure.
664 @param UefiHiiHandle PackageList Handle
666 @return A pointer to FORM_BROWSER_FORMSET.
669 FORM_BROWSER_FORMSET
*
671 IN EFI_HII_HANDLE UefiHiiHandle
674 FORM_BROWSER_FORMSET
*FormSet
;
675 EFI_GUID FormSetGuid
;
678 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
679 ASSERT (FormSet
!= NULL
);
681 CopyGuid (&FormSetGuid
, &gZeroGuid
);
682 Status
= InitializeFormSet (UefiHiiHandle
, &FormSetGuid
, FormSet
);
683 ASSERT_EFI_ERROR (Status
);