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 (CompareGuid (Guid
, &ThunkContext
->TagGuid
) && (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 (CompareGuid (&Class
->Guid
, &gTianoHiiIfrGuid
)) {
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
;
333 Status
= HiiLibExportPackageLists (ThunkContext
->UefiHiiHandle
, &List
, &Size
);
334 if (EFI_ERROR (Status
)) {
339 // Get all VarStoreId and build the the QuestionId map.
340 // EFI_IFR_QUESTION_HEADER.VarStoreInfo.VarOffset -> Framework Question ID
341 // EFI_IFR_QUESTION_HEADER.QuestionId -> UEFI Question ID
345 // Skip the package list header.
347 Package
= (EFI_HII_PACKAGE_HEADER
*) (List
+ 1);
349 while (Package
->Type
!= EFI_HII_PACKAGE_END
) {
351 if (Package
->Type
== EFI_HII_PACKAGE_FORM
) {
354 // Skip the package header
356 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
357 while (Offset
< Package
->Length
) {
358 OpCode
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ Offset
);
360 switch (OpCode
->OpCode
) {
361 case EFI_IFR_FORM_SET_OP
:
362 FormSet
= (EFI_IFR_FORM_SET
*) OpCode
;
363 ThunkContext
->FormSetTitle
= FormSet
->FormSetTitle
;
364 ThunkContext
->FormSetHelp
= FormSet
->Help
;
367 case EFI_IFR_VARSTORE_OP
:
369 // IFR built from Framework VFR only has UEFI Buffer Type Storage
371 VarStore
= (EFI_IFR_VARSTORE
*) OpCode
;
372 IdMap
= AllocateZeroPool (sizeof (QUESTION_ID_MAP
));
373 ASSERT (IdMap
!= NULL
);
375 IdMap
->Signature
= QUESTION_ID_MAP_SIGNATURE
;
376 IdMap
->VarStoreId
= VarStore
->VarStoreId
;
377 IdMap
->VarSize
= VarStore
->Size
;
378 InitializeListHead (&IdMap
->MapEntryListHead
);
379 InsertTailList (&ThunkContext
->QuestionIdMapListHead
, &IdMap
->Link
);
382 case EFI_IFR_NUMERIC_OP
:
383 case EFI_IFR_CHECKBOX_OP
:
384 case EFI_IFR_ONE_OF_OP
:
385 case EFI_IFR_ORDERED_LIST_OP
:
386 case EFI_IFR_STRING_OP
:
387 //case EFI_IFR_PASSWORD_OP:
388 Question
= (EFI_IFR_QUESTION_HEADER
*)(OpCode
+ 1);
389 QuestionIdMapEntryListHead
= GetMapEntryListHead (ThunkContext
, Question
->VarStoreId
);
391 if (QuestionIdMapEntryListHead
!= NULL
) {
393 // If the Question is using Buffer (EFI_IFR_VARSTORE_OP) type VarStore.
395 IdMapEntry
= AllocateZeroPool (sizeof (QUESTION_ID_MAP_ENTRY
));
396 ASSERT (IdMapEntry
!= NULL
);
398 IdMapEntry
->FwQId
= Question
->VarStoreInfo
.VarOffset
;
399 IdMapEntry
->UefiQid
= Question
->QuestionId
;
400 IdMapEntry
->Signature
= QUESTION_ID_MAP_ENTRY_SIGNATURE
;
402 InsertTailList (QuestionIdMapEntryListHead
, &IdMapEntry
->Link
);
407 case EFI_IFR_GUID_OP
:
408 OptionMap
= (EFI_IFR_GUID_OPTIONKEY
*) OpCode
;
409 if (CompareGuid (&OptionMap
->Guid
, &gFrameworkHiiCompatbilityGuid
)) {
410 if (OptionMap
->ExtendOpCode
== EFI_IFR_EXTEND_OP_OPTIONKEY
) {
411 OneOfOptinMapEntryListHead
= GetOneOfOptionMapEntryListHead (ThunkContext
, OptionMap
->QuestionId
);
412 if (OneOfOptinMapEntryListHead
== NULL
) {
413 OneOfOptionMap
= AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP
));
414 ASSERT (OneOfOptionMap
!= NULL
);
416 OneOfOptionMap
->Signature
= ONE_OF_OPTION_MAP_SIGNATURE
;
417 OneOfOptionMap
->QuestionId
= OptionMap
->QuestionId
;
418 OneOfOptionMap
->ValueType
= EFI_IFR_TYPE_NUM_SIZE_8
;
419 InitializeListHead (&OneOfOptionMap
->OneOfOptionMapEntryListHead
);
420 OneOfOptinMapEntryListHead
= &OneOfOptionMap
->OneOfOptionMapEntryListHead
;
421 InsertTailList (&ThunkContext
->OneOfOptionMapListHead
, &OneOfOptionMap
->Link
);
423 OneOfOptionMapEntry
= AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP_ENTRY
));
424 ASSERT (OneOfOptionMapEntry
!= NULL
);
426 OneOfOptionMapEntry
->Signature
= ONE_OF_OPTION_MAP_ENTRY_SIGNATURE
;
427 OneOfOptionMapEntry
->FwKey
= OptionMap
->KeyValue
;
428 CopyMem (&OneOfOptionMapEntry
->Value
, &OptionMap
->OptionValue
, sizeof (EFI_IFR_TYPE_VALUE
));
430 InsertTailList (OneOfOptinMapEntryListHead
, &OneOfOptionMapEntry
->Link
);
432 }else if (CompareMem (&OptionMap
->Guid
, &gTianoHiiIfrGuid
, sizeof (EFI_GUID
))) {
433 Class
= (EFI_IFR_GUID_CLASS
*) OpCode
;
435 switch (Class
->ExtendOpCode
) {
436 case EFI_IFR_EXTEND_OP_CLASS
:
437 ThunkContext
->FormSetClass
= Class
->Class
;
439 case EFI_IFR_EXTEND_OP_SUBCLASS
:
440 SubClass
= (EFI_IFR_GUID_SUBCLASS
*) OpCode
;
441 ThunkContext
->FormSetSubClass
= SubClass
->SubClass
;
455 Offset
+= OpCode
->Length
;
458 // Only Form Package is in a Package List.
463 Package
= (EFI_HII_PACKAGE_HEADER
*) (UINT8
*) Package
+ Package
->Length
;
472 GetMapEntryListHead (
473 IN CONST HII_THUNK_CONTEXT
*ThunkContext
,
478 QUESTION_ID_MAP
*Map
;
480 Link
= GetFirstNode (&ThunkContext
->QuestionIdMapListHead
);
482 while (!IsNull (&ThunkContext
->QuestionIdMapListHead
, Link
)) {
483 Map
= QUESTION_ID_MAP_FROM_LINK (Link
);
484 if (VarStoreId
== Map
->VarStoreId
) {
485 return &Map
->MapEntryListHead
;
487 Link
= GetNextNode (&ThunkContext
->QuestionIdMapListHead
, Link
);
495 IN HII_THUNK_PRIVATE_DATA
*Private
,
496 IN UINTN StringPackageCount
,
497 IN UINTN IfrPackageCount
501 HII_THUNK_CONTEXT
*ThunkContext
;
503 ThunkContext
= AllocateZeroPool (sizeof (HII_THUNK_CONTEXT
));
504 ASSERT (ThunkContext
!= NULL
);
506 ThunkContext
->Signature
= HII_THUNK_CONTEXT_SIGNATURE
;
507 ThunkContext
->IfrPackageCount
= IfrPackageCount
;
508 ThunkContext
->StringPackageCount
= StringPackageCount
;
509 Status
= AllocateHiiHandle (&ThunkContext
->FwHiiHandle
);
510 if (EFI_ERROR (Status
)) {
514 InitializeListHead (&ThunkContext
->QuestionIdMapListHead
);
515 InitializeListHead (&ThunkContext
->OneOfOptionMapListHead
);
523 DestroyThunkContext (
524 IN HII_THUNK_CONTEXT
*ThunkContext
527 ASSERT (ThunkContext
!= NULL
);
529 FreeHiiHandle (ThunkContext
->FwHiiHandle
);
531 DestroyQuestionIdMap (&ThunkContext
->QuestionIdMapListHead
);
533 DestoryOneOfOptionMap (&ThunkContext
->OneOfOptionMapListHead
);
535 RemoveEntryList (&ThunkContext
->Link
);
537 FreePool (ThunkContext
);
542 DestroyQuestionIdMap (
543 IN LIST_ENTRY
*QuestionIdMapListHead
546 QUESTION_ID_MAP
*IdMap
;
547 QUESTION_ID_MAP_ENTRY
*IdMapEntry
;
551 while (!IsListEmpty (QuestionIdMapListHead
)) {
552 Link
= GetFirstNode (QuestionIdMapListHead
);
554 IdMap
= QUESTION_ID_MAP_FROM_LINK (Link
);
556 while (!IsListEmpty (&IdMap
->MapEntryListHead
)) {
557 Link2
= GetFirstNode (&IdMap
->MapEntryListHead
);
559 IdMapEntry
= QUESTION_ID_MAP_ENTRY_FROM_LINK (Link2
);
561 RemoveEntryList (Link2
);
563 FreePool (IdMapEntry
);
566 RemoveEntryList (Link
);
572 DestoryOneOfOptionMap (
573 IN LIST_ENTRY
*OneOfOptionMapListHead
576 ONE_OF_OPTION_MAP
*Map
;
577 ONE_OF_OPTION_MAP_ENTRY
*MapEntry
;
581 while (!IsListEmpty (OneOfOptionMapListHead
)) {
582 Link
= GetFirstNode (OneOfOptionMapListHead
);
584 Map
= ONE_OF_OPTION_MAP_FROM_LINK (Link
);
586 while (!IsListEmpty (&Map
->OneOfOptionMapEntryListHead
)) {
587 Link2
= GetFirstNode (&Map
->OneOfOptionMapEntryListHead
);
589 MapEntry
= ONE_OF_OPTION_MAP_ENTRY_FROM_LINK (Link2
);
591 RemoveEntryList (Link2
);
596 RemoveEntryList (Link
);