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"
20 EFI_GUID gFrameworkHiiCompatbilityGuid
= EFI_IFR_FRAMEWORK_GUID
;
21 EFI_GUID gTianoHiiIfrGuid
= EFI_IFR_TIANO_GUID
;
25 FwHiiHandleToUefiHiiHandle (
26 IN CONST HII_THUNK_PRIVATE_DATA
*Private
,
27 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
30 HII_THUNK_CONTEXT
*ThunkContext
;
32 ASSERT (FwHiiHandle
!= (FRAMEWORK_EFI_HII_HANDLE
) 0);
33 ASSERT (Private
!= NULL
);
35 ThunkContext
= FwHiiHandleToThunkContext (Private
, FwHiiHandle
);
37 if (ThunkContext
!= NULL
) {
38 return ThunkContext
->UefiHiiHandle
;
41 return (EFI_HII_HANDLE
) NULL
;
46 FwHiiHandleToThunkContext (
47 IN CONST HII_THUNK_PRIVATE_DATA
*Private
,
48 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
52 HII_THUNK_CONTEXT
*ThunkContext
;
55 Link
= GetFirstNode (&Private
->ThunkContextListHead
);
57 while (!IsNull (&Private
->ThunkContextListHead
, Link
)) {
58 ThunkContext
= HII_THUNK_CONTEXT_FROM_LINK (Link
);
60 if (FwHiiHandle
== ThunkContext
->FwHiiHandle
) {
64 Link
= GetNextNode (&Private
->ThunkContextListHead
, Link
);
71 UefiHiiHandleToThunkContext (
72 IN CONST HII_THUNK_PRIVATE_DATA
*Private
,
73 IN EFI_HII_HANDLE UefiHiiHandle
77 HII_THUNK_CONTEXT
*ThunkContext
;
79 Link
= GetFirstNode (&Private
->ThunkContextListHead
);
81 while (!IsNull (&Private
->ThunkContextListHead
, Link
)) {
82 ThunkContext
= HII_THUNK_CONTEXT_FROM_LINK (Link
);
84 if (UefiHiiHandle
== ThunkContext
->UefiHiiHandle
) {
87 Link
= GetNextNode (&Private
->ThunkContextListHead
, Link
);
94 TagGuidToIfrPackThunkContext (
95 IN CONST HII_THUNK_PRIVATE_DATA
*Private
,
96 IN CONST EFI_GUID
*Guid
100 HII_THUNK_CONTEXT
*ThunkContext
;
102 Link
= GetFirstNode (&Private
->ThunkContextListHead
);
104 while (!IsNull (&Private
->ThunkContextListHead
, Link
)) {
105 ThunkContext
= HII_THUNK_CONTEXT_FROM_LINK (Link
);
107 if (CompareGuid (Guid
, &ThunkContext
->TagGuid
) && (ThunkContext
->IfrPackageCount
!= 0)) {
111 Link
= GetNextNode (&Private
->ThunkContextListHead
, Link
);
120 DestroyThunkContextForUefiHiiHandle (
121 IN HII_THUNK_PRIVATE_DATA
*Private
,
122 IN EFI_HII_HANDLE UefiHiiHandle
125 HII_THUNK_CONTEXT
*ThunkContext
;
127 ThunkContext
= UefiHiiHandleToThunkContext (Private
, UefiHiiHandle
);
128 ASSERT (ThunkContext
!= NULL
);
130 DestroyThunkContext (ThunkContext
);
135 This function create a HII_THUNK_CONTEXT for a package list registered
136 by a module calling EFI_HII_DATABASE_PROTOCOL.NewPackageList. It records
137 the PackageListGuid in EFI_HII_PACKAGE_LIST_HEADER in the TagGuid in
138 HII_THUNK_CONTEXT created. This TagGuid will be used as a key to s
142 CreateThunkContextForUefiHiiHandle (
143 IN EFI_HII_HANDLE UefiHiiHandle
147 EFI_GUID PackageGuid
;
148 HII_THUNK_CONTEXT
*ThunkContext
;
150 ThunkContext
= AllocateZeroPool (sizeof (*ThunkContext
));
151 ASSERT (ThunkContext
!= NULL
);
153 ThunkContext
->Signature
= HII_THUNK_CONTEXT_SIGNATURE
;
155 Status
= AllocateHiiHandle (&ThunkContext
->FwHiiHandle
);
156 if (EFI_ERROR (Status
)) {
160 ThunkContext
->UefiHiiHandle
= UefiHiiHandle
;
162 Status
= HiiLibExtractGuidFromHiiHandle (UefiHiiHandle
, &PackageGuid
);
163 ASSERT_EFI_ERROR (Status
);
165 CopyGuid(&ThunkContext
->TagGuid
, &PackageGuid
);
167 InitializeListHead (&ThunkContext
->QuestionIdMapListHead
);
168 InitializeListHead (&ThunkContext
->OneOfOptionMapListHead
);
175 GetPackageCountByType (
176 IN CONST EFI_HII_PACKAGE_LIST_HEADER
*PackageListHeader
,
181 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
183 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) ((UINT8
*) PackageListHeader
+ sizeof (EFI_HII_PACKAGE_LIST_HEADER
));
186 while (PackageHeader
->Type
!= EFI_HII_PACKAGE_END
) {
187 if (PackageHeader
->Type
== PackageType
) {
190 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) ((UINT8
*) PackageHeader
+ PackageHeader
->Length
);
198 GetOneOfOptionMapEntryListHead (
199 IN CONST HII_THUNK_CONTEXT
*ThunkContext
,
204 ONE_OF_OPTION_MAP
*Map
;
206 Link
= GetFirstNode (&ThunkContext
->OneOfOptionMapListHead
);
208 while (!IsNull (&ThunkContext
->OneOfOptionMapListHead
, Link
)) {
209 Map
= ONE_OF_OPTION_MAP_FROM_LINK (Link
);
210 if (QuestionId
== Map
->QuestionId
) {
211 return &Map
->OneOfOptionMapEntryListHead
;
213 Link
= GetNextNode (&ThunkContext
->OneOfOptionMapListHead
, Link
);
219 EFI_HII_PACKAGE_HEADER
*
221 IN CONST EFI_HII_PACKAGES
*Packages
225 TIANO_AUTOGEN_PACKAGES_HEADER
**TianoAutogenPackageHdrArray
;
227 ASSERT (Packages
!= NULL
);
229 TianoAutogenPackageHdrArray
= (TIANO_AUTOGEN_PACKAGES_HEADER
**) (((UINT8
*) &Packages
->GuidId
) + sizeof (Packages
->GuidId
));
231 for (Index
= 0; Index
< Packages
->NumberOfPackages
; Index
++) {
233 // The current UEFI HII build tool generate a binary in the format defined by
234 // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in
235 // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount
236 // may not be the exact number of valid package number in the binary generated
237 // by HII Build tool.
239 switch (TianoAutogenPackageHdrArray
[Index
]->PackageHeader
.Type
) {
240 case EFI_HII_PACKAGE_FORM
:
241 return &TianoAutogenPackageHdrArray
[Index
]->PackageHeader
;
243 case EFI_HII_PACKAGE_STRINGS
:
244 case EFI_HII_PACKAGE_SIMPLE_FONTS
:
248 // The following fonts are invalid for a module that using Framework to UEFI thunk layer.
250 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT
:
251 case EFI_HII_PACKAGE_FONTS
:
252 case EFI_HII_PACKAGE_IMAGES
:
265 IN EFI_HII_PACKAGE_HEADER
*Package
,
266 OUT EFI_GUID
*FormSetGuid
270 EFI_IFR_OP_HEADER
*OpCode
;
271 EFI_IFR_FORM_SET
*FormSet
;
273 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
274 while (Offset
< Package
->Length
) {
275 OpCode
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ Offset
);
277 switch (OpCode
->OpCode
) {
278 case EFI_IFR_FORM_SET_OP
:
279 FormSet
= (EFI_IFR_FORM_SET
*) OpCode
;
280 CopyMem (FormSetGuid
, &FormSet
->Guid
, sizeof (EFI_GUID
));
287 Offset
+= OpCode
->Length
;
291 // A proper IFR must have a formset opcode.
299 GetAttributesOfFirstFormSet (
300 IN OUT HII_THUNK_CONTEXT
*ThunkContext
304 EFI_HII_PACKAGE_LIST_HEADER
*List
;
305 EFI_HII_PACKAGE_HEADER
*Package
;
307 EFI_IFR_OP_HEADER
*OpCode
;
309 EFI_IFR_GUID_CLASS
*Class
;
310 EFI_IFR_FORM_SET
*FormSet
;
311 EFI_IFR_GUID_SUBCLASS
*SubClass
;
313 Status
= HiiLibExportPackageLists (ThunkContext
->UefiHiiHandle
, &List
, &Size
);
314 ASSERT_EFI_ERROR (Status
);
317 // There must be at least one EFI_HII_PACKAGE_FORM in the package list.
319 ASSERT (GetPackageCountByType (List
, EFI_HII_PACKAGE_FORM
) >= 1);
322 // Skip the package list header.
324 Package
= (EFI_HII_PACKAGE_HEADER
*) (List
+ 1);
326 while (Package
->Type
!= EFI_HII_PACKAGE_END
) {
328 if (Package
->Type
== EFI_HII_PACKAGE_FORM
) {
331 // Skip the package header
333 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
334 while (Offset
< Package
->Length
) {
335 OpCode
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ Offset
);
337 switch (OpCode
->OpCode
) {
338 case EFI_IFR_FORM_SET_OP
:
339 FormSet
= (EFI_IFR_FORM_SET
*) OpCode
;
340 ThunkContext
->FormSetTitle
= FormSet
->FormSetTitle
;
341 ThunkContext
->FormSetHelp
= FormSet
->Help
;
345 case EFI_IFR_GUID_OP
:
346 Class
= (EFI_IFR_GUID_CLASS
*) OpCode
;
347 if (CompareMem (&Class
->Guid
, &gTianoHiiIfrGuid
, sizeof (EFI_GUID
)) == 0) {
348 Class
= (EFI_IFR_GUID_CLASS
*) OpCode
;
350 switch (Class
->ExtendOpCode
) {
351 case EFI_IFR_EXTEND_OP_CLASS
:
352 ThunkContext
->FormSetClass
= Class
->Class
;
354 case EFI_IFR_EXTEND_OP_SUBCLASS
:
355 SubClass
= (EFI_IFR_GUID_SUBCLASS
*) OpCode
;
356 ThunkContext
->FormSetSubClass
= SubClass
->SubClass
;
370 Offset
+= OpCode
->Length
;
373 // The attributes of first FormSet is ready now.
381 Package
= (EFI_HII_PACKAGE_HEADER
*) ((UINT8
*) Package
+ Package
->Length
);
388 CreateQuestionIdMap (
389 IN OUT HII_THUNK_CONTEXT
*ThunkContext
393 EFI_HII_PACKAGE_LIST_HEADER
*List
;
394 EFI_HII_PACKAGE_HEADER
*Package
;
396 EFI_IFR_OP_HEADER
*OpCode
;
398 QUESTION_ID_MAP
*IdMap
;
399 EFI_IFR_VARSTORE
*VarStore
;
400 EFI_IFR_FORM_SET
*FormSet
;
401 EFI_IFR_QUESTION_HEADER
*Question
;
402 LIST_ENTRY
*QuestionIdMapEntryListHead
;
403 LIST_ENTRY
*OneOfOptinMapEntryListHead
;
404 QUESTION_ID_MAP_ENTRY
*IdMapEntry
;
405 EFI_IFR_GUID_OPTIONKEY
*OptionMap
;
406 ONE_OF_OPTION_MAP
*OneOfOptionMap
;
407 ONE_OF_OPTION_MAP_ENTRY
*OneOfOptionMapEntry
;
408 EFI_IFR_GUID_CLASS
*Class
;
409 EFI_IFR_GUID_SUBCLASS
*SubClass
;
411 EFI_IFR_ONE_OF
*OneOfOpcode
;
414 // Set to a invalid value.
416 OneOfType
= (UINT8
) -1;
419 Status
= HiiLibExportPackageLists (ThunkContext
->UefiHiiHandle
, &List
, &Size
);
420 if (EFI_ERROR (Status
)) {
425 // Get all VarStoreId and build the the QuestionId map.
426 // EFI_IFR_QUESTION_HEADER.VarStoreInfo.VarOffset -> Framework Question ID
427 // EFI_IFR_QUESTION_HEADER.QuestionId -> UEFI Question ID
431 // Skip the package list header.
433 Package
= (EFI_HII_PACKAGE_HEADER
*) (List
+ 1);
435 while (Package
->Type
!= EFI_HII_PACKAGE_END
) {
437 if (Package
->Type
== EFI_HII_PACKAGE_FORM
) {
440 // Skip the package header
442 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
443 while (Offset
< Package
->Length
) {
444 OpCode
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ Offset
);
446 switch (OpCode
->OpCode
) {
447 case EFI_IFR_FORM_SET_OP
:
448 FormSet
= (EFI_IFR_FORM_SET
*) OpCode
;
449 ThunkContext
->FormSetTitle
= FormSet
->FormSetTitle
;
450 ThunkContext
->FormSetHelp
= FormSet
->Help
;
453 case EFI_IFR_VARSTORE_OP
:
455 // IFR built from Framework VFR only has UEFI Buffer Type Storage
457 VarStore
= (EFI_IFR_VARSTORE
*) OpCode
;
458 IdMap
= AllocateZeroPool (sizeof (QUESTION_ID_MAP
));
459 ASSERT (IdMap
!= NULL
);
461 IdMap
->Signature
= QUESTION_ID_MAP_SIGNATURE
;
462 IdMap
->VarStoreId
= VarStore
->VarStoreId
;
463 IdMap
->VarSize
= VarStore
->Size
;
464 InitializeListHead (&IdMap
->MapEntryListHead
);
465 InsertTailList (&ThunkContext
->QuestionIdMapListHead
, &IdMap
->Link
);
468 case EFI_IFR_NUMERIC_OP
:
469 case EFI_IFR_CHECKBOX_OP
:
470 case EFI_IFR_ONE_OF_OP
:
471 case EFI_IFR_ORDERED_LIST_OP
:
472 case EFI_IFR_STRING_OP
:
473 //case EFI_IFR_PASSWORD_OP:
474 Question
= (EFI_IFR_QUESTION_HEADER
*)(OpCode
+ 1);
475 QuestionIdMapEntryListHead
= GetMapEntryListHead (ThunkContext
, Question
->VarStoreId
);
477 if (QuestionIdMapEntryListHead
!= NULL
) {
479 // If the Question is using Buffer (EFI_IFR_VARSTORE_OP) type VarStore.
481 IdMapEntry
= AllocateZeroPool (sizeof (QUESTION_ID_MAP_ENTRY
));
482 ASSERT (IdMapEntry
!= NULL
);
484 IdMapEntry
->FwQId
= Question
->VarStoreInfo
.VarOffset
;
485 IdMapEntry
->UefiQid
= Question
->QuestionId
;
486 IdMapEntry
->Signature
= QUESTION_ID_MAP_ENTRY_SIGNATURE
;
488 InsertTailList (QuestionIdMapEntryListHead
, &IdMapEntry
->Link
);
491 if (OpCode
->OpCode
== EFI_IFR_ONE_OF_OP
) {
492 OneOfOpcode
= (EFI_IFR_ONE_OF
*) OpCode
;
493 OneOfType
= OneOfOpcode
->Flags
& EFI_IFR_NUMERIC_SIZE
;
498 case EFI_IFR_GUID_OP
:
499 OptionMap
= (EFI_IFR_GUID_OPTIONKEY
*) OpCode
;
500 if (CompareMem (&OptionMap
->Guid
, &gFrameworkHiiCompatbilityGuid
, sizeof (EFI_GUID
)) == 0) {
501 if (OptionMap
->ExtendOpCode
== EFI_IFR_EXTEND_OP_OPTIONKEY
) {
502 OneOfOptinMapEntryListHead
= GetOneOfOptionMapEntryListHead (ThunkContext
, OptionMap
->QuestionId
);
503 if (OneOfOptinMapEntryListHead
== NULL
) {
504 OneOfOptionMap
= AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP
));
505 ASSERT (OneOfOptionMap
!= NULL
);
507 OneOfOptionMap
->Signature
= ONE_OF_OPTION_MAP_SIGNATURE
;
508 OneOfOptionMap
->QuestionId
= OptionMap
->QuestionId
;
511 // Make sure OneOfType is initialized.
513 ASSERT (OneOfType
!= (UINT8
) -1);
514 OneOfOptionMap
->ValueType
= OneOfType
;
515 InitializeListHead (&OneOfOptionMap
->OneOfOptionMapEntryListHead
);
516 OneOfOptinMapEntryListHead
= &OneOfOptionMap
->OneOfOptionMapEntryListHead
;
517 InsertTailList (&ThunkContext
->OneOfOptionMapListHead
, &OneOfOptionMap
->Link
);
519 OneOfOptionMapEntry
= AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP_ENTRY
));
520 ASSERT (OneOfOptionMapEntry
!= NULL
);
522 OneOfOptionMapEntry
->Signature
= ONE_OF_OPTION_MAP_ENTRY_SIGNATURE
;
523 OneOfOptionMapEntry
->FwKey
= OptionMap
->KeyValue
;
524 CopyMem (&OneOfOptionMapEntry
->Value
, &OptionMap
->OptionValue
, sizeof (EFI_IFR_TYPE_VALUE
));
526 InsertTailList (OneOfOptinMapEntryListHead
, &OneOfOptionMapEntry
->Link
);
528 } else if (CompareMem (&OptionMap
->Guid
, &gTianoHiiIfrGuid
, sizeof (EFI_GUID
)) == 0) {
529 Class
= (EFI_IFR_GUID_CLASS
*) OpCode
;
531 switch (Class
->ExtendOpCode
) {
532 case EFI_IFR_EXTEND_OP_CLASS
:
533 ThunkContext
->FormSetClass
= Class
->Class
;
535 case EFI_IFR_EXTEND_OP_SUBCLASS
:
536 SubClass
= (EFI_IFR_GUID_SUBCLASS
*) OpCode
;
537 ThunkContext
->FormSetSubClass
= SubClass
->SubClass
;
551 Offset
+= OpCode
->Length
;
554 // Only Form Package is in a Package List.
559 Package
= (EFI_HII_PACKAGE_HEADER
*) (UINT8
*) Package
+ Package
->Length
;
568 GetMapEntryListHead (
569 IN CONST HII_THUNK_CONTEXT
*ThunkContext
,
574 QUESTION_ID_MAP
*Map
;
576 Link
= GetFirstNode (&ThunkContext
->QuestionIdMapListHead
);
578 while (!IsNull (&ThunkContext
->QuestionIdMapListHead
, Link
)) {
579 Map
= QUESTION_ID_MAP_FROM_LINK (Link
);
580 if (VarStoreId
== Map
->VarStoreId
) {
581 return &Map
->MapEntryListHead
;
583 Link
= GetNextNode (&ThunkContext
->QuestionIdMapListHead
, Link
);
591 IN HII_THUNK_PRIVATE_DATA
*Private
,
592 IN UINTN StringPackageCount
,
593 IN UINTN IfrPackageCount
597 HII_THUNK_CONTEXT
*ThunkContext
;
599 ThunkContext
= AllocateZeroPool (sizeof (HII_THUNK_CONTEXT
));
600 ASSERT (ThunkContext
!= NULL
);
602 ThunkContext
->Signature
= HII_THUNK_CONTEXT_SIGNATURE
;
603 ThunkContext
->IfrPackageCount
= IfrPackageCount
;
604 ThunkContext
->StringPackageCount
= StringPackageCount
;
605 Status
= AllocateHiiHandle (&ThunkContext
->FwHiiHandle
);
606 if (EFI_ERROR (Status
)) {
610 InitializeListHead (&ThunkContext
->QuestionIdMapListHead
);
611 InitializeListHead (&ThunkContext
->OneOfOptionMapListHead
);
619 DestroyThunkContext (
620 IN HII_THUNK_CONTEXT
*ThunkContext
623 ASSERT (ThunkContext
!= NULL
);
625 FreeHiiHandle (ThunkContext
->FwHiiHandle
);
627 DestroyQuestionIdMap (&ThunkContext
->QuestionIdMapListHead
);
629 DestoryOneOfOptionMap (&ThunkContext
->OneOfOptionMapListHead
);
631 RemoveEntryList (&ThunkContext
->Link
);
633 FreePool (ThunkContext
);
638 DestroyQuestionIdMap (
639 IN LIST_ENTRY
*QuestionIdMapListHead
642 QUESTION_ID_MAP
*IdMap
;
643 QUESTION_ID_MAP_ENTRY
*IdMapEntry
;
647 while (!IsListEmpty (QuestionIdMapListHead
)) {
648 Link
= GetFirstNode (QuestionIdMapListHead
);
650 IdMap
= QUESTION_ID_MAP_FROM_LINK (Link
);
652 while (!IsListEmpty (&IdMap
->MapEntryListHead
)) {
653 Link2
= GetFirstNode (&IdMap
->MapEntryListHead
);
655 IdMapEntry
= QUESTION_ID_MAP_ENTRY_FROM_LINK (Link2
);
657 RemoveEntryList (Link2
);
659 FreePool (IdMapEntry
);
662 RemoveEntryList (Link
);
668 DestoryOneOfOptionMap (
669 IN LIST_ENTRY
*OneOfOptionMapListHead
672 ONE_OF_OPTION_MAP
*Map
;
673 ONE_OF_OPTION_MAP_ENTRY
*MapEntry
;
677 while (!IsListEmpty (OneOfOptionMapListHead
)) {
678 Link
= GetFirstNode (OneOfOptionMapListHead
);
680 Map
= ONE_OF_OPTION_MAP_FROM_LINK (Link
);
682 while (!IsListEmpty (&Map
->OneOfOptionMapEntryListHead
)) {
683 Link2
= GetFirstNode (&Map
->OneOfOptionMapEntryListHead
);
685 MapEntry
= ONE_OF_OPTION_MAP_ENTRY_FROM_LINK (Link2
);
687 RemoveEntryList (Link2
);
692 RemoveEntryList (Link
);