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
]->FrameworkPackageHeader
.Type
) {
272 return &TianoAutogenPackageHdrArray
[Index
]->PackageHeader
;
291 ASSERT if no FormSet Opcode is found.
293 @param Packages Form Framework Package.
294 @param FormSetGuid Return the FormSet Guid.
299 IN EFI_HII_PACKAGE_HEADER
*Package
,
300 OUT EFI_GUID
*FormSetGuid
304 EFI_IFR_OP_HEADER
*OpCode
;
305 EFI_IFR_FORM_SET
*FormSet
;
307 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
308 while (Offset
< Package
->Length
) {
309 OpCode
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ Offset
);
311 switch (OpCode
->OpCode
) {
312 case EFI_IFR_FORM_SET_OP
:
313 FormSet
= (EFI_IFR_FORM_SET
*) OpCode
;
314 CopyGuid (FormSetGuid
, (EFI_GUID
*)(VOID
*)&FormSet
->Guid
);
321 Offset
+= OpCode
->Length
;
325 // A proper IFR must have a formset opcode.
332 Creat a Thunk Context.
334 ASSERT if no FormSet Opcode is found.
336 @param Private The HII Thunk Private Context.
337 @param StringPackageCount The String package count.
338 @param FormSetGuid The IFR Package count.
340 @return A newly created Thunk Context.
341 @retval NULL No resource to create a new Thunk Context.
345 IN HII_THUNK_PRIVATE_DATA
*Private
,
346 IN UINTN StringPackageCount
,
347 IN UINTN IfrPackageCount
351 HII_THUNK_CONTEXT
*ThunkContext
;
353 ThunkContext
= AllocateZeroPool (sizeof (HII_THUNK_CONTEXT
));
354 ASSERT (ThunkContext
!= NULL
);
356 ThunkContext
->Signature
= HII_THUNK_CONTEXT_SIGNATURE
;
357 ThunkContext
->IfrPackageCount
= IfrPackageCount
;
358 ThunkContext
->StringPackageCount
= StringPackageCount
;
359 Status
= AllocateHiiHandle (&ThunkContext
->FwHiiHandle
);
360 if (EFI_ERROR (Status
)) {
369 Destroy the Thunk Context and free up all resource.
371 @param ThunkContext The HII Thunk Private Context to be freed.
375 DestroyThunkContext (
376 IN HII_THUNK_CONTEXT
*ThunkContext
379 ASSERT (ThunkContext
!= NULL
);
381 FreeHiiHandle (ThunkContext
->FwHiiHandle
);
383 RemoveEntryList (&ThunkContext
->Link
);
385 if (ThunkContext
->FormSet
!= NULL
) {
386 DestroyFormSet (ThunkContext
->FormSet
);
389 FreePool (ThunkContext
);
393 Get the FormSet's Default Varstore ID based on the rule (Descending Priority):
395 1) Var Store ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01).
396 2) First Var Store ID.
398 @param FormSet The Form Set.
402 GetFormsetDefaultVarstoreId (
403 IN OUT FORM_BROWSER_FORMSET
* FormSet
406 LIST_ENTRY
*StorageList
;
407 FORMSET_STORAGE
*Storage
;
410 // VarStoreId 0 is invalid in UEFI IFR.
412 FormSet
->DefaultVarStoreId
= 0;
413 StorageList
= GetFirstNode (&FormSet
->StorageListHead
);
415 while (!IsNull (&FormSet
->StorageListHead
, StorageList
)) {
416 Storage
= FORMSET_STORAGE_FROM_LINK (StorageList
);
418 DEBUG ((EFI_D_INFO
, "FormSet %g: Found Varstore ID %x\n", &FormSet
->Guid
, Storage
->VarStoreId
));
420 if (Storage
->VarStoreId
== FRAMEWORK_RESERVED_VARSTORE_ID
) {
421 FormSet
->DefaultVarStoreId
= FRAMEWORK_RESERVED_VARSTORE_ID
;
425 StorageList
= GetNextNode (&FormSet
->StorageListHead
, StorageList
);
428 if (FormSet
->DefaultVarStoreId
!= FRAMEWORK_RESERVED_VARSTORE_ID
) {
429 StorageList
= GetFirstNode (&FormSet
->StorageListHead
);
430 if (!IsNull (&FormSet
->StorageListHead
, StorageList
)) {
431 Storage
= FORMSET_STORAGE_FROM_LINK (StorageList
);
432 FormSet
->DefaultVarStoreId
= Storage
->VarStoreId
;
438 if (FormSet
->DefaultVarStoreId
== 0) {
439 DEBUG ((EFI_D_INFO
, "FormSet %g: No Varstore Found\n", &FormSet
->Guid
));
441 DEBUG ((EFI_D_INFO
, "FormSet %g: Default Varstore ID is %x\n", &FormSet
->Guid
, FormSet
->DefaultVarStoreId
));
449 Fetch the Ifr binary data of a FormSet.
451 @param Handle PackageList Handle
452 @param FormSetGuid GUID of a formset. If not specified (NULL or zero
453 GUID), take the first FormSet found in package
455 @param BinaryLength The length of the FormSet IFR binary.
456 @param BinaryData The buffer designed to receive the FormSet.
458 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
459 BufferLength was updated.
460 @retval EFI_INVALID_PARAMETER The handle is unknown.
461 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
462 be found with the requested FormId.
467 IN EFI_HII_HANDLE Handle
,
468 IN OUT EFI_GUID
*FormSetGuid
,
469 OUT UINTN
*BinaryLength
,
470 OUT UINT8
**BinaryData
474 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
480 BOOLEAN ReturnDefault
;
481 UINT32 PackageListLength
;
482 EFI_HII_PACKAGE_HEADER PackageHeader
;
486 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));;
489 // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list
491 if (FormSetGuid
== NULL
|| CompareGuid (FormSetGuid
, &gZeroGuid
)) {
492 ReturnDefault
= TRUE
;
494 ReturnDefault
= FALSE
;
498 // Get HII PackageList
501 HiiPackageList
= NULL
;
502 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
503 if (Status
== EFI_BUFFER_TOO_SMALL
) {
504 HiiPackageList
= AllocatePool (BufferSize
);
505 ASSERT (HiiPackageList
!= NULL
);
507 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
509 if (EFI_ERROR (Status
)) {
514 // Get Form package from this HII package List
516 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
518 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
520 while (Offset
< PackageListLength
) {
521 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
522 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
524 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
526 // Search FormSet in this Form Package
528 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
529 while (Offset2
< PackageHeader
.Length
) {
530 OpCodeData
= Package
+ Offset2
;
532 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
534 // Check whether return default FormSet
541 // FormSet GUID is specified, check it
543 if (CompareGuid (FormSetGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
548 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
551 if (Offset2
< PackageHeader
.Length
) {
553 // Target formset found
559 Offset
+= PackageHeader
.Length
;
562 if (Offset
>= PackageListLength
) {
564 // Form package not found in this Package List
566 gBS
->FreePool (HiiPackageList
);
567 return EFI_NOT_FOUND
;
570 if (ReturnDefault
&& FormSetGuid
!= NULL
) {
572 // Return the default FormSet GUID
574 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
578 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
579 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
580 // of the Form Package.
582 *BinaryLength
= PackageHeader
.Length
- Offset2
;
583 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
585 gBS
->FreePool (HiiPackageList
);
587 if (*BinaryData
== NULL
) {
588 return EFI_OUT_OF_RESOURCES
;
595 Initialize the internal data structure of a FormSet.
597 @param Handle PackageList Handle
598 @param FormSetGuid GUID of a formset. If not specified (NULL or zero
599 GUID), take the first FormSet found in package
601 @param FormSet FormSet data structure.
603 @retval EFI_SUCCESS The function completed successfully.
604 @retval EFI_NOT_FOUND The specified FormSet could not be found.
609 IN EFI_HII_HANDLE Handle
,
610 IN OUT EFI_GUID
*FormSetGuid
,
611 OUT FORM_BROWSER_FORMSET
*FormSet
616 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
617 if (EFI_ERROR (Status
)) {
621 FormSet
->HiiHandle
= Handle
;
622 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
625 // Parse the IFR binary OpCodes
627 Status
= ParseOpCodes (FormSet
);
628 if (EFI_ERROR (Status
)) {
632 GetFormsetDefaultVarstoreId (FormSet
);
637 Parse the Form Package and build a FORM_BROWSER_FORMSET structure.
639 @param UefiHiiHandle PackageList Handle
641 @return A pointer to FORM_BROWSER_FORMSET.
644 FORM_BROWSER_FORMSET
*
646 IN EFI_HII_HANDLE UefiHiiHandle
649 FORM_BROWSER_FORMSET
*FormSet
;
650 EFI_GUID FormSetGuid
;
653 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
654 ASSERT (FormSet
!= NULL
);
656 CopyGuid (&FormSetGuid
, &gZeroGuid
);
657 Status
= InitializeFormSet (UefiHiiHandle
, &FormSetGuid
, FormSet
);
658 ASSERT_EFI_ERROR (Status
);