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 TagGuidToUefiHiiHandle (
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 (CompareMem (Guid
, &ThunkContext
->TagGuid
, sizeof (EFI_GUID
) == 0) && (ThunkContext
->IfrPackageCount
!= 0)) {
108 return ThunkContext
->UefiHiiHandle
;
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
);
220 GetAttributesOfFirstFormSet (
221 IN OUT HII_THUNK_CONTEXT
*ThunkContext
225 EFI_HII_PACKAGE_LIST_HEADER
*List
;
226 EFI_HII_PACKAGE_HEADER
*Package
;
228 EFI_IFR_OP_HEADER
*OpCode
;
230 EFI_IFR_GUID_CLASS
*Class
;
231 EFI_IFR_FORM_SET
*FormSet
;
232 EFI_IFR_GUID_SUBCLASS
*SubClass
;
234 Status
= HiiLibExportPackageLists (ThunkContext
->UefiHiiHandle
, &List
, &Size
);
235 ASSERT_EFI_ERROR (Status
);
238 // There must be at least one EFI_HII_PACKAGE_FORM in the package list.
240 ASSERT (GetPackageCountByType (List
, EFI_HII_PACKAGE_FORM
) >= 1);
243 // Skip the package list header.
245 Package
= (EFI_HII_PACKAGE_HEADER
*) (List
+ 1);
247 while (Package
->Type
!= EFI_HII_PACKAGE_END
) {
249 if (Package
->Type
== EFI_HII_PACKAGE_FORM
) {
252 // Skip the package header
254 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
255 while (Offset
< Package
->Length
) {
256 OpCode
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ Offset
);
258 switch (OpCode
->OpCode
) {
259 case EFI_IFR_FORM_SET_OP
:
260 FormSet
= (EFI_IFR_FORM_SET
*) OpCode
;
261 ThunkContext
->FormSetTitle
= FormSet
->FormSetTitle
;
262 ThunkContext
->FormSetHelp
= FormSet
->Help
;
266 case EFI_IFR_GUID_OP
:
267 Class
= (EFI_IFR_GUID_CLASS
*) OpCode
;
268 if (CompareMem (&Class
->Guid
, &gTianoHiiIfrGuid
, sizeof (EFI_GUID
)) == 0) {
269 Class
= (EFI_IFR_GUID_CLASS
*) OpCode
;
271 switch (Class
->ExtendOpCode
) {
272 case EFI_IFR_EXTEND_OP_CLASS
:
273 ThunkContext
->FormSetClass
= Class
->Class
;
275 case EFI_IFR_EXTEND_OP_SUBCLASS
:
276 SubClass
= (EFI_IFR_GUID_SUBCLASS
*) OpCode
;
277 ThunkContext
->FormSetSubClass
= SubClass
->SubClass
;
291 Offset
+= OpCode
->Length
;
294 // The attributes of first FormSet is ready now.
302 Package
= (EFI_HII_PACKAGE_HEADER
*) (UINT8
*) Package
+ Package
->Length
;
309 CreateQuestionIdMap (
310 IN OUT HII_THUNK_CONTEXT
*ThunkContext
314 EFI_HII_PACKAGE_LIST_HEADER
*List
;
315 EFI_HII_PACKAGE_HEADER
*Package
;
317 EFI_IFR_OP_HEADER
*OpCode
;
319 QUESTION_ID_MAP
*IdMap
;
320 EFI_IFR_VARSTORE
*VarStore
;
321 EFI_IFR_FORM_SET
*FormSet
;
322 EFI_IFR_QUESTION_HEADER
*Question
;
323 LIST_ENTRY
*QuestionIdMapEntryListHead
;
324 LIST_ENTRY
*OneOfOptinMapEntryListHead
;
325 QUESTION_ID_MAP_ENTRY
*IdMapEntry
;
326 EFI_IFR_GUID_OPTIONKEY
*OptionMap
;
327 ONE_OF_OPTION_MAP
*OneOfOptionMap
;
328 ONE_OF_OPTION_MAP_ENTRY
*OneOfOptionMapEntry
;
329 EFI_IFR_GUID_CLASS
*Class
;
330 EFI_IFR_GUID_SUBCLASS
*SubClass
;
332 EFI_IFR_ONE_OF
*OneOfOpcode
;
335 // Set to a invalid value.
337 OneOfType
= (UINT8
) -1;
340 Status
= HiiLibExportPackageLists (ThunkContext
->UefiHiiHandle
, &List
, &Size
);
341 if (EFI_ERROR (Status
)) {
346 // Get all VarStoreId and build the the QuestionId map.
347 // EFI_IFR_QUESTION_HEADER.VarStoreInfo.VarOffset -> Framework Question ID
348 // EFI_IFR_QUESTION_HEADER.QuestionId -> UEFI Question ID
352 // Skip the package list header.
354 Package
= (EFI_HII_PACKAGE_HEADER
*) (List
+ 1);
356 while (Package
->Type
!= EFI_HII_PACKAGE_END
) {
358 if (Package
->Type
== EFI_HII_PACKAGE_FORM
) {
361 // Skip the package header
363 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
364 while (Offset
< Package
->Length
) {
365 OpCode
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ Offset
);
367 switch (OpCode
->OpCode
) {
368 case EFI_IFR_FORM_SET_OP
:
369 FormSet
= (EFI_IFR_FORM_SET
*) OpCode
;
370 ThunkContext
->FormSetTitle
= FormSet
->FormSetTitle
;
371 ThunkContext
->FormSetHelp
= FormSet
->Help
;
374 case EFI_IFR_VARSTORE_OP
:
376 // IFR built from Framework VFR only has UEFI Buffer Type Storage
378 VarStore
= (EFI_IFR_VARSTORE
*) OpCode
;
379 IdMap
= AllocateZeroPool (sizeof (QUESTION_ID_MAP
));
380 ASSERT (IdMap
!= NULL
);
382 IdMap
->Signature
= QUESTION_ID_MAP_SIGNATURE
;
383 IdMap
->VarStoreId
= VarStore
->VarStoreId
;
384 IdMap
->VarSize
= VarStore
->Size
;
385 InitializeListHead (&IdMap
->MapEntryListHead
);
386 InsertTailList (&ThunkContext
->QuestionIdMapListHead
, &IdMap
->Link
);
389 case EFI_IFR_NUMERIC_OP
:
390 case EFI_IFR_CHECKBOX_OP
:
391 case EFI_IFR_ONE_OF_OP
:
392 case EFI_IFR_ORDERED_LIST_OP
:
393 case EFI_IFR_STRING_OP
:
394 //case EFI_IFR_PASSWORD_OP:
395 Question
= (EFI_IFR_QUESTION_HEADER
*)(OpCode
+ 1);
396 QuestionIdMapEntryListHead
= GetMapEntryListHead (ThunkContext
, Question
->VarStoreId
);
398 if (QuestionIdMapEntryListHead
!= NULL
) {
400 // If the Question is using Buffer (EFI_IFR_VARSTORE_OP) type VarStore.
402 IdMapEntry
= AllocateZeroPool (sizeof (QUESTION_ID_MAP_ENTRY
));
403 ASSERT (IdMapEntry
!= NULL
);
405 IdMapEntry
->FwQId
= Question
->VarStoreInfo
.VarOffset
;
406 IdMapEntry
->UefiQid
= Question
->QuestionId
;
407 IdMapEntry
->Signature
= QUESTION_ID_MAP_ENTRY_SIGNATURE
;
409 InsertTailList (QuestionIdMapEntryListHead
, &IdMapEntry
->Link
);
412 if (OpCode
->OpCode
== EFI_IFR_ONE_OF_OP
) {
413 OneOfOpcode
= (EFI_IFR_ONE_OF
*) OpCode
;
414 OneOfType
= OneOfOpcode
->Flags
& EFI_IFR_NUMERIC_SIZE
;
419 case EFI_IFR_GUID_OP
:
420 OptionMap
= (EFI_IFR_GUID_OPTIONKEY
*) OpCode
;
421 if (CompareMem (&OptionMap
->Guid
, &gFrameworkHiiCompatbilityGuid
, sizeof (EFI_GUID
)) == 0) {
422 if (OptionMap
->ExtendOpCode
== EFI_IFR_EXTEND_OP_OPTIONKEY
) {
423 OneOfOptinMapEntryListHead
= GetOneOfOptionMapEntryListHead (ThunkContext
, OptionMap
->QuestionId
);
424 if (OneOfOptinMapEntryListHead
== NULL
) {
425 OneOfOptionMap
= AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP
));
426 ASSERT (OneOfOptionMap
!= NULL
);
428 OneOfOptionMap
->Signature
= ONE_OF_OPTION_MAP_SIGNATURE
;
429 OneOfOptionMap
->QuestionId
= OptionMap
->QuestionId
;
432 // Make sure OneOfType is initialized.
434 ASSERT (OneOfType
!= (UINT8
) -1);
435 OneOfOptionMap
->ValueType
= OneOfType
;
436 InitializeListHead (&OneOfOptionMap
->OneOfOptionMapEntryListHead
);
437 OneOfOptinMapEntryListHead
= &OneOfOptionMap
->OneOfOptionMapEntryListHead
;
438 InsertTailList (&ThunkContext
->OneOfOptionMapListHead
, &OneOfOptionMap
->Link
);
440 OneOfOptionMapEntry
= AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP_ENTRY
));
441 ASSERT (OneOfOptionMapEntry
!= NULL
);
443 OneOfOptionMapEntry
->Signature
= ONE_OF_OPTION_MAP_ENTRY_SIGNATURE
;
444 OneOfOptionMapEntry
->FwKey
= OptionMap
->KeyValue
;
445 CopyMem (&OneOfOptionMapEntry
->Value
, &OptionMap
->OptionValue
, sizeof (EFI_IFR_TYPE_VALUE
));
447 InsertTailList (OneOfOptinMapEntryListHead
, &OneOfOptionMapEntry
->Link
);
449 } else if (CompareMem (&OptionMap
->Guid
, &gTianoHiiIfrGuid
, sizeof (EFI_GUID
)) == 0) {
450 Class
= (EFI_IFR_GUID_CLASS
*) OpCode
;
452 switch (Class
->ExtendOpCode
) {
453 case EFI_IFR_EXTEND_OP_CLASS
:
454 ThunkContext
->FormSetClass
= Class
->Class
;
456 case EFI_IFR_EXTEND_OP_SUBCLASS
:
457 SubClass
= (EFI_IFR_GUID_SUBCLASS
*) OpCode
;
458 ThunkContext
->FormSetSubClass
= SubClass
->SubClass
;
472 Offset
+= OpCode
->Length
;
475 // Only Form Package is in a Package List.
480 Package
= (EFI_HII_PACKAGE_HEADER
*) (UINT8
*) Package
+ Package
->Length
;
489 GetMapEntryListHead (
490 IN CONST HII_THUNK_CONTEXT
*ThunkContext
,
495 QUESTION_ID_MAP
*Map
;
497 Link
= GetFirstNode (&ThunkContext
->QuestionIdMapListHead
);
499 while (!IsNull (&ThunkContext
->QuestionIdMapListHead
, Link
)) {
500 Map
= QUESTION_ID_MAP_FROM_LINK (Link
);
501 if (VarStoreId
== Map
->VarStoreId
) {
502 return &Map
->MapEntryListHead
;
504 Link
= GetNextNode (&ThunkContext
->QuestionIdMapListHead
, Link
);
512 IN HII_THUNK_PRIVATE_DATA
*Private
,
513 IN UINTN StringPackageCount
,
514 IN UINTN IfrPackageCount
518 HII_THUNK_CONTEXT
*ThunkContext
;
520 ThunkContext
= AllocateZeroPool (sizeof (HII_THUNK_CONTEXT
));
521 ASSERT (ThunkContext
!= NULL
);
523 ThunkContext
->Signature
= HII_THUNK_CONTEXT_SIGNATURE
;
524 ThunkContext
->IfrPackageCount
= IfrPackageCount
;
525 ThunkContext
->StringPackageCount
= StringPackageCount
;
526 Status
= AllocateHiiHandle (&ThunkContext
->FwHiiHandle
);
527 if (EFI_ERROR (Status
)) {
531 InitializeListHead (&ThunkContext
->QuestionIdMapListHead
);
532 InitializeListHead (&ThunkContext
->OneOfOptionMapListHead
);
540 DestroyThunkContext (
541 IN HII_THUNK_CONTEXT
*ThunkContext
544 ASSERT (ThunkContext
!= NULL
);
546 FreeHiiHandle (ThunkContext
->FwHiiHandle
);
548 DestroyQuestionIdMap (&ThunkContext
->QuestionIdMapListHead
);
550 DestoryOneOfOptionMap (&ThunkContext
->OneOfOptionMapListHead
);
552 RemoveEntryList (&ThunkContext
->Link
);
554 FreePool (ThunkContext
);
559 DestroyQuestionIdMap (
560 IN LIST_ENTRY
*QuestionIdMapListHead
563 QUESTION_ID_MAP
*IdMap
;
564 QUESTION_ID_MAP_ENTRY
*IdMapEntry
;
568 while (!IsListEmpty (QuestionIdMapListHead
)) {
569 Link
= GetFirstNode (QuestionIdMapListHead
);
571 IdMap
= QUESTION_ID_MAP_FROM_LINK (Link
);
573 while (!IsListEmpty (&IdMap
->MapEntryListHead
)) {
574 Link2
= GetFirstNode (&IdMap
->MapEntryListHead
);
576 IdMapEntry
= QUESTION_ID_MAP_ENTRY_FROM_LINK (Link2
);
578 RemoveEntryList (Link2
);
580 FreePool (IdMapEntry
);
583 RemoveEntryList (Link
);
589 DestoryOneOfOptionMap (
590 IN LIST_ENTRY
*OneOfOptionMapListHead
593 ONE_OF_OPTION_MAP
*Map
;
594 ONE_OF_OPTION_MAP_ENTRY
*MapEntry
;
598 while (!IsListEmpty (OneOfOptionMapListHead
)) {
599 Link
= GetFirstNode (OneOfOptionMapListHead
);
601 Map
= ONE_OF_OPTION_MAP_FROM_LINK (Link
);
603 while (!IsListEmpty (&Map
->OneOfOptionMapEntryListHead
)) {
604 Link2
= GetFirstNode (&Map
->OneOfOptionMapEntryListHead
);
606 MapEntry
= ONE_OF_OPTION_MAP_ENTRY_FROM_LINK (Link2
);
608 RemoveEntryList (Link2
);
613 RemoveEntryList (Link
);