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"
19 EFI_GUID gFrameworkHiiCompatbilityGuid
= EFI_IFR_FRAMEWORK_GUID
;
20 EFI_GUID gTianoHiiIfrGuid
= EFI_IFR_TIANO_GUID
;
24 GetGuidOfFirstFormset (
25 CONST EFI_HII_FORM_PACKAGE
* FormPackage
28 UINT8
*StartOfNextPackage
;
29 EFI_IFR_OP_HEADER
*OpCodeData
;
31 StartOfNextPackage
= (UINT8
*) FormPackage
+ FormPackage
->Header
.Length
;
32 OpCodeData
= (EFI_IFR_OP_HEADER
*) (FormPackage
+ 1);
34 while ((UINT8
*) OpCodeData
< StartOfNextPackage
) {
35 if (OpCodeData
->OpCode
== EFI_IFR_FORM_SET_OP
) {
36 return AllocateCopyPool (sizeof(EFI_GUID
), &(((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
));
38 OpCodeData
= (EFI_IFR_OP_HEADER
*) ((UINT8
*) OpCodeData
+ OpCodeData
->Length
);
47 FwHiiHandleToUefiHiiHandle (
48 IN CONST HII_THUNK_PRIVATE_DATA
*Private
,
49 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
52 HII_THUNK_CONTEXT
*ThunkContext
;
54 ASSERT (FwHiiHandle
!= (FRAMEWORK_EFI_HII_HANDLE
) 0);
55 ASSERT (Private
!= NULL
);
57 ThunkContext
= FwHiiHandleToThunkContext (Private
, FwHiiHandle
);
59 if (ThunkContext
!= NULL
) {
60 return ThunkContext
->UefiHiiHandle
;
63 return (EFI_HII_HANDLE
) NULL
;
68 FwHiiHandleToThunkContext (
69 IN CONST HII_THUNK_PRIVATE_DATA
*Private
,
70 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
74 HII_THUNK_CONTEXT
*ThunkContext
;
77 Link
= GetFirstNode (&Private
->ThunkContextListHead
);
79 while (!IsNull (&Private
->ThunkContextListHead
, Link
)) {
80 ThunkContext
= HII_THUNK_CONTEXT_FROM_LINK (Link
);
82 if (FwHiiHandle
== ThunkContext
->FwHiiHandle
) {
86 Link
= GetNextNode (&Private
->ThunkContextListHead
, Link
);
93 UefiHiiHandleToThunkContext (
94 IN CONST HII_THUNK_PRIVATE_DATA
*Private
,
95 IN EFI_HII_HANDLE UefiHiiHandle
99 HII_THUNK_CONTEXT
*ThunkContext
;
101 Link
= GetFirstNode (&Private
->ThunkContextListHead
);
103 while (!IsNull (&Private
->ThunkContextListHead
, Link
)) {
104 ThunkContext
= HII_THUNK_CONTEXT_FROM_LINK (Link
);
106 if (UefiHiiHandle
== ThunkContext
->UefiHiiHandle
) {
109 Link
= GetNextNode (&Private
->ThunkContextListHead
, Link
);
116 TagGuidToUefiHiiHandle (
117 IN CONST HII_THUNK_PRIVATE_DATA
*Private
,
118 IN CONST EFI_GUID
*Guid
122 HII_THUNK_CONTEXT
*ThunkContext
;
124 Link
= GetFirstNode (&Private
->ThunkContextListHead
);
126 while (!IsNull (&Private
->ThunkContextListHead
, Link
)) {
127 ThunkContext
= HII_THUNK_CONTEXT_FROM_LINK (Link
);
129 if (CompareGuid (Guid
, &ThunkContext
->TagGuid
) && (ThunkContext
->IfrPackageCount
!= 0)) {
130 return ThunkContext
->UefiHiiHandle
;
133 Link
= GetNextNode (&Private
->ThunkContextListHead
, Link
);
141 IsFrameworkHiiDatabaseHandleDepleted (
142 IN CONST HII_THUNK_PRIVATE_DATA
*Private
145 return (BOOLEAN
) (Private
->StaticHiiHandle
== (UINTN
) Private
->StaticPureUefiHiiHandle
);
149 AssignFrameworkHiiHandle (
150 IN OUT HII_THUNK_PRIVATE_DATA
*Private
,
151 IN BOOLEAN FromFwHiiNewPack
,
152 OUT FRAMEWORK_EFI_HII_HANDLE
*Handle
155 ASSERT (Handle
!= NULL
);
157 if (FromFwHiiNewPack
) {
159 *Handle
= Private
->StaticHiiHandle
;
160 Private
->StaticHiiHandle
+= 1;
162 if (IsFrameworkHiiDatabaseHandleDepleted (Private
)) {
163 return EFI_OUT_OF_RESOURCES
;
168 *Handle
= Private
->StaticPureUefiHiiHandle
;
169 Private
->StaticPureUefiHiiHandle
-= 1;
171 if (IsFrameworkHiiDatabaseHandleDepleted (Private
)) {
172 return EFI_OUT_OF_RESOURCES
;
181 DestroyThunkContextForUefiHiiHandle (
182 IN HII_THUNK_PRIVATE_DATA
*Private
,
183 IN EFI_HII_HANDLE UefiHiiHandle
186 HII_THUNK_CONTEXT
*ThunkContext
;
188 ThunkContext
= UefiHiiHandleToThunkContext (Private
, UefiHiiHandle
);
189 ASSERT (ThunkContext
!= NULL
);
191 ASSERT (IsListEmpty (&ThunkContext
->OneOfOptionMapListHead
));
192 ASSERT (IsListEmpty (&ThunkContext
->QuestionIdMapListHead
));
194 RemoveEntryList (&ThunkContext
->Link
);
196 FreePool (ThunkContext
);
203 This function create a HII_THUNK_CONTEXT for a package list registered
204 by a module calling EFI_HII_DATABASE_PROTOCOL.NewPackageList. It records
205 the PackageListGuid in EFI_HII_PACKAGE_LIST_HEADER in the TagGuid in
206 HII_THUNK_CONTEXT created. This TagGuid will be used as a key to s
210 CreateThunkContextForUefiHiiHandle (
211 IN HII_THUNK_PRIVATE_DATA
*Private
,
212 IN EFI_HII_HANDLE UefiHiiHandle
216 EFI_GUID PackageGuid
;
217 HII_THUNK_CONTEXT
*ThunkContext
;
219 ThunkContext
= AllocateZeroPool (sizeof (*ThunkContext
));
220 ASSERT (ThunkContext
!= NULL
);
222 ThunkContext
->Signature
= HII_THUNK_CONTEXT_SIGNATURE
;
224 Status
= AssignFrameworkHiiHandle (Private
, FALSE
, &ThunkContext
->FwHiiHandle
);
225 if (EFI_ERROR (Status
)) {
229 ThunkContext
->UefiHiiHandle
= UefiHiiHandle
;
231 Status
= HiiLibExtractGuidFromHiiHandle (UefiHiiHandle
, &PackageGuid
);
232 ASSERT_EFI_ERROR (Status
);
234 CopyGuid(&ThunkContext
->TagGuid
, &PackageGuid
);
236 InitializeListHead (&ThunkContext
->QuestionIdMapListHead
);
237 InitializeListHead (&ThunkContext
->OneOfOptionMapListHead
);
239 InsertTailList (&Private
->ThunkContextListHead
, &ThunkContext
->Link
);
246 GetPackageCountByType (
247 IN CONST EFI_HII_PACKAGE_LIST_HEADER
*PackageListHeader
,
252 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
254 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) ((UINT8
*) PackageListHeader
+ sizeof (EFI_HII_PACKAGE_LIST_HEADER
));
257 while (PackageHeader
->Type
!= EFI_HII_PACKAGE_END
) {
258 if (PackageHeader
->Type
== PackageType
) {
261 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) ((UINT8
*) PackageHeader
+ PackageHeader
->Length
);
269 GetOneOfOptionMapEntryListHead (
270 IN CONST HII_THUNK_CONTEXT
*ThunkContext
,
275 ONE_OF_OPTION_MAP
*Map
;
277 Link
= GetFirstNode (&ThunkContext
->OneOfOptionMapListHead
);
279 while (!IsNull (&ThunkContext
->OneOfOptionMapListHead
, Link
)) {
280 Map
= ONE_OF_OPTION_MAP_FROM_LINK (Link
);
281 if (QuestionId
== Map
->QuestionId
) {
282 return &Map
->OneOfOptionMapEntryListHead
;
284 Link
= GetNextNode (&ThunkContext
->OneOfOptionMapListHead
, Link
);
292 CreateQuestionIdMap (
293 IN OUT HII_THUNK_CONTEXT
*ThunkContext
297 EFI_HII_PACKAGE_LIST_HEADER
*List
;
298 EFI_HII_PACKAGE_HEADER
*Package
;
300 EFI_IFR_OP_HEADER
*OpCode
;
302 QUESTION_ID_MAP
*IdMap
;
303 EFI_IFR_VARSTORE
*VarStore
;
304 EFI_IFR_FORM_SET
*FormSet
;
305 EFI_IFR_QUESTION_HEADER
*Question
;
306 LIST_ENTRY
*QuestionIdMapEntryListHead
;
307 LIST_ENTRY
*OneOfOptinMapEntryListHead
;
308 QUESTION_ID_MAP_ENTRY
*IdMapEntry
;
309 EFI_IFR_GUID_OPTIONKEY
*OptionMap
;
310 ONE_OF_OPTION_MAP
*OneOfOptionMap
;
311 ONE_OF_OPTION_MAP_ENTRY
*OneOfOptionMapEntry
;
312 EFI_IFR_GUID_CLASS
*Class
;
315 Status
= HiiLibExportPackageLists (ThunkContext
->UefiHiiHandle
, &List
, &Size
);
316 if (EFI_ERROR (Status
)) {
321 // Get all VarStoreId and build the the QuestionId map.
322 // EFI_IFR_QUESTION_HEADER.VarStoreInfo.VarOffset -> Framework Question ID
323 // EFI_IFR_QUESTION_HEADER.QuestionId -> UEFI Question ID
327 // Skip the package list header.
329 Package
= (EFI_HII_PACKAGE_HEADER
*) (List
+ 1);
331 while (Package
->Type
!= EFI_HII_PACKAGE_END
) {
333 if (Package
->Type
== EFI_HII_PACKAGE_FORM
) {
336 // Skip the package header
338 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
339 while (Offset
< Package
->Length
) {
340 OpCode
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ Offset
);
342 switch (OpCode
->OpCode
) {
343 case EFI_IFR_FORM_SET_OP
:
344 FormSet
= (EFI_IFR_FORM_SET
*) OpCode
;
345 ThunkContext
->FormSetTitle
= FormSet
->FormSetTitle
;
346 ThunkContext
->FormSetHelp
= FormSet
->Help
;
349 case EFI_IFR_VARSTORE_OP
:
351 // IFR built from Framework VFR only has UEFI Buffer Type Storage
353 VarStore
= (EFI_IFR_VARSTORE
*) OpCode
;
354 IdMap
= AllocateZeroPool (sizeof (QUESTION_ID_MAP
));
355 ASSERT (IdMap
!= NULL
);
357 IdMap
->Signature
= QUESTION_ID_MAP_SIGNATURE
;
358 IdMap
->VarStoreId
= VarStore
->VarStoreId
;
359 IdMap
->VarSize
= VarStore
->Size
;
360 InitializeListHead (&IdMap
->MapEntryListHead
);
361 InsertTailList (&ThunkContext
->QuestionIdMapListHead
, &IdMap
->Link
);
364 case EFI_IFR_NUMERIC_OP
:
365 case EFI_IFR_CHECKBOX_OP
:
366 case EFI_IFR_ONE_OF_OP
:
367 case EFI_IFR_ORDERED_LIST_OP
:
368 case EFI_IFR_STRING_OP
:
369 //case EFI_IFR_PASSWORD_OP:
370 Question
= (EFI_IFR_QUESTION_HEADER
*)(OpCode
+ 1);
371 QuestionIdMapEntryListHead
= GetMapEntryListHead (ThunkContext
, Question
->VarStoreId
);
373 if (QuestionIdMapEntryListHead
!= NULL
) {
375 // If the Question is using Buffer (EFI_IFR_VARSTORE_OP) type VarStore.
377 IdMapEntry
= AllocateZeroPool (sizeof (QUESTION_ID_MAP_ENTRY
));
378 ASSERT (IdMapEntry
!= NULL
);
380 IdMapEntry
->FwQId
= Question
->VarStoreInfo
.VarOffset
;
381 IdMapEntry
->UefiQid
= Question
->QuestionId
;
382 IdMapEntry
->Signature
= QUESTION_ID_MAP_ENTRY_SIGNATURE
;
384 InsertTailList (QuestionIdMapEntryListHead
, &IdMapEntry
->Link
);
389 case EFI_IFR_GUID_OP
:
390 OptionMap
= (EFI_IFR_GUID_OPTIONKEY
*) OpCode
;
391 if (CompareGuid (&OptionMap
->Guid
, &gFrameworkHiiCompatbilityGuid
)) {
392 if (OptionMap
->ExtendOpCode
== EFI_IFR_EXTEND_OP_OPTIONKEY
) {
393 OneOfOptinMapEntryListHead
= GetOneOfOptionMapEntryListHead (ThunkContext
, OptionMap
->QuestionId
);
394 if (OneOfOptinMapEntryListHead
== NULL
) {
395 OneOfOptionMap
= AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP
));
396 ASSERT (OneOfOptionMap
!= NULL
);
398 OneOfOptionMap
->Signature
= ONE_OF_OPTION_MAP_SIGNATURE
;
399 OneOfOptionMap
->QuestionId
= OptionMap
->QuestionId
;
400 OneOfOptionMap
->ValueType
= EFI_IFR_TYPE_NUM_SIZE_8
;
401 InitializeListHead (&OneOfOptionMap
->OneOfOptionMapEntryListHead
);
402 OneOfOptinMapEntryListHead
= &OneOfOptionMap
->OneOfOptionMapEntryListHead
;
403 InsertTailList (&ThunkContext
->OneOfOptionMapListHead
, &OneOfOptionMap
->Link
);
405 OneOfOptionMapEntry
= AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP_ENTRY
));
406 ASSERT (OneOfOptionMapEntry
!= NULL
);
408 OneOfOptionMapEntry
->Signature
= ONE_OF_OPTION_MAP_ENTRY_SIGNATURE
;
409 OneOfOptionMapEntry
->FwKey
= OptionMap
->KeyValue
;
410 CopyMem (&OneOfOptionMapEntry
->Value
, &OptionMap
->OptionValue
, sizeof (EFI_IFR_TYPE_VALUE
));
412 InsertTailList (OneOfOptinMapEntryListHead
, &OneOfOptionMapEntry
->Link
);
414 }else if (CompareGuid (&OptionMap
->Guid
, &gTianoHiiIfrGuid
)) {
415 Class
= (EFI_IFR_GUID_CLASS
*) OpCode
;
417 switch (Class
->ExtendOpCode
) {
418 case EFI_IFR_EXTEND_OP_CLASS
:
419 ThunkContext
->FormSetClass
= Class
->Class
;
421 case EFI_IFR_EXTEND_OP_SUBCLASS
:
422 ThunkContext
->FormSetSubClass
= ((EFI_IFR_GUID_SUBCLASS
*) Class
)->SubClass
;
436 Offset
+= OpCode
->Length
;
439 // Only Form Package is in a Package List.
444 Package
= (EFI_HII_PACKAGE_HEADER
*) (UINT8
*) Package
+ Package
->Length
;
453 GetMapEntryListHead (
454 IN CONST HII_THUNK_CONTEXT
*ThunkContext
,
459 QUESTION_ID_MAP
*Map
;
461 Link
= GetFirstNode (&ThunkContext
->QuestionIdMapListHead
);
463 while (!IsNull (&ThunkContext
->QuestionIdMapListHead
, Link
)) {
464 Map
= QUESTION_ID_MAP_FROM_LINK (Link
);
465 if (VarStoreId
== Map
->VarStoreId
) {
466 return &Map
->MapEntryListHead
;
468 Link
= GetNextNode (&ThunkContext
->QuestionIdMapListHead
, Link
);