]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Utility.c
e015f832c087d899b371c777f868e2ae1f020d88
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiToUefiHiiThunk / Utility.c
1 /**@file
2
3 This file contains the keyboard processing code to the HII database.
4
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
10
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.
13
14 **/
15
16
17 #include "HiiDatabase.h"
18 #include "HiiHandle.h"
19
20 EFI_GUID gFrameworkHiiCompatbilityGuid = EFI_IFR_FRAMEWORK_GUID;
21 EFI_GUID gTianoHiiIfrGuid = EFI_IFR_TIANO_GUID;
22
23
24 EFI_HII_HANDLE
25 FwHiiHandleToUefiHiiHandle (
26 IN CONST HII_THUNK_PRIVATE_DATA *Private,
27 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
28 )
29 {
30 HII_THUNK_CONTEXT *ThunkContext;
31
32 ASSERT (FwHiiHandle != (FRAMEWORK_EFI_HII_HANDLE) 0);
33 ASSERT (Private != NULL);
34
35 ThunkContext = FwHiiHandleToThunkContext (Private, FwHiiHandle);
36
37 if (ThunkContext != NULL) {
38 return ThunkContext->UefiHiiHandle;
39 }
40
41 return (EFI_HII_HANDLE) NULL;
42 }
43
44
45 HII_THUNK_CONTEXT *
46 FwHiiHandleToThunkContext (
47 IN CONST HII_THUNK_PRIVATE_DATA *Private,
48 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
49 )
50 {
51 LIST_ENTRY *Link;
52 HII_THUNK_CONTEXT *ThunkContext;
53
54
55 Link = GetFirstNode (&Private->ThunkContextListHead);
56
57 while (!IsNull (&Private->ThunkContextListHead, Link)) {
58 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
59
60 if (FwHiiHandle == ThunkContext->FwHiiHandle) {
61 return ThunkContext;
62 }
63
64 Link = GetNextNode (&Private->ThunkContextListHead, Link);
65 }
66
67 return NULL;
68 }
69
70 HII_THUNK_CONTEXT *
71 UefiHiiHandleToThunkContext (
72 IN CONST HII_THUNK_PRIVATE_DATA *Private,
73 IN EFI_HII_HANDLE UefiHiiHandle
74 )
75 {
76 LIST_ENTRY *Link;
77 HII_THUNK_CONTEXT *ThunkContext;
78
79 Link = GetFirstNode (&Private->ThunkContextListHead);
80
81 while (!IsNull (&Private->ThunkContextListHead, Link)) {
82 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
83
84 if (UefiHiiHandle == ThunkContext->UefiHiiHandle) {
85 return ThunkContext;
86 }
87 Link = GetNextNode (&Private->ThunkContextListHead, Link);
88 }
89
90 return NULL;
91 }
92
93 HII_THUNK_CONTEXT *
94 TagGuidToIfrPackThunkContext (
95 IN CONST HII_THUNK_PRIVATE_DATA *Private,
96 IN CONST EFI_GUID *Guid
97 )
98 {
99 LIST_ENTRY *Link;
100 HII_THUNK_CONTEXT *ThunkContext;
101
102 Link = GetFirstNode (&Private->ThunkContextListHead);
103
104 while (!IsNull (&Private->ThunkContextListHead, Link)) {
105 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
106
107 if (CompareGuid (Guid, &ThunkContext->TagGuid) && (ThunkContext->IfrPackageCount != 0)) {
108 return ThunkContext;
109 }
110
111 Link = GetNextNode (&Private->ThunkContextListHead, Link);
112 }
113
114 return NULL;
115
116 }
117
118
119 VOID
120 DestroyThunkContextForUefiHiiHandle (
121 IN HII_THUNK_PRIVATE_DATA *Private,
122 IN EFI_HII_HANDLE UefiHiiHandle
123 )
124 {
125 HII_THUNK_CONTEXT *ThunkContext;
126
127 ThunkContext = UefiHiiHandleToThunkContext (Private, UefiHiiHandle);
128 ASSERT (ThunkContext != NULL);
129
130 DestroyThunkContext (ThunkContext);
131 }
132
133
134 /**
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
139
140 **/
141 HII_THUNK_CONTEXT *
142 CreateThunkContextForUefiHiiHandle (
143 IN EFI_HII_HANDLE UefiHiiHandle
144 )
145 {
146 EFI_STATUS Status;
147 EFI_GUID PackageGuid;
148 HII_THUNK_CONTEXT *ThunkContext;
149
150 ThunkContext = AllocateZeroPool (sizeof (*ThunkContext));
151 ASSERT (ThunkContext != NULL);
152
153 ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE;
154
155 Status = AllocateHiiHandle (&ThunkContext->FwHiiHandle);
156 if (EFI_ERROR (Status)) {
157 return NULL;
158 }
159
160 ThunkContext->UefiHiiHandle = UefiHiiHandle;
161
162 Status = HiiLibExtractGuidFromHiiHandle (UefiHiiHandle, &PackageGuid);
163 ASSERT_EFI_ERROR (Status);
164
165 CopyGuid(&ThunkContext->TagGuid, &PackageGuid);
166
167 InitializeListHead (&ThunkContext->QuestionIdMapListHead);
168 InitializeListHead (&ThunkContext->OneOfOptionMapListHead);
169
170 return ThunkContext;
171 }
172
173
174 UINTN
175 GetPackageCountByType (
176 IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader,
177 IN UINT8 PackageType
178 )
179 {
180 UINTN Count;
181 EFI_HII_PACKAGE_HEADER *PackageHeader;
182
183 PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageListHeader + sizeof (EFI_HII_PACKAGE_LIST_HEADER));
184 Count = 0;
185
186 while (PackageHeader->Type != EFI_HII_PACKAGE_END) {
187 if (PackageHeader->Type == PackageType ) {
188 Count++;
189 }
190 PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHeader + PackageHeader->Length);
191 }
192
193
194 return Count;
195 }
196
197 LIST_ENTRY *
198 GetOneOfOptionMapEntryListHead (
199 IN CONST HII_THUNK_CONTEXT *ThunkContext,
200 IN UINT16 QuestionId
201 )
202 {
203 LIST_ENTRY *Link;
204 ONE_OF_OPTION_MAP *Map;
205
206 Link = GetFirstNode (&ThunkContext->OneOfOptionMapListHead);
207
208 while (!IsNull (&ThunkContext->OneOfOptionMapListHead, Link)) {
209 Map = ONE_OF_OPTION_MAP_FROM_LINK (Link);
210 if (QuestionId == Map->QuestionId) {
211 return &Map->OneOfOptionMapEntryListHead;
212 }
213 Link = GetNextNode (&ThunkContext->OneOfOptionMapListHead, Link);
214 }
215
216 return NULL;
217 }
218
219 VOID
220 GetAttributesOfFirstFormSet (
221 IN OUT HII_THUNK_CONTEXT *ThunkContext
222 )
223 {
224 EFI_STATUS Status;
225 EFI_HII_PACKAGE_LIST_HEADER *List;
226 EFI_HII_PACKAGE_HEADER *Package;
227 UINTN Size;
228 EFI_IFR_OP_HEADER *OpCode;
229 UINTN Offset;
230 EFI_IFR_GUID_CLASS *Class;
231 EFI_IFR_FORM_SET *FormSet;
232 EFI_IFR_GUID_SUBCLASS *SubClass;
233
234 Status = HiiLibExportPackageLists (ThunkContext->UefiHiiHandle, &List, &Size);
235 ASSERT_EFI_ERROR (Status);
236
237 //
238 // There must be at least one EFI_HII_PACKAGE_FORM in the package list.
239 //
240 ASSERT (GetPackageCountByType (List, EFI_HII_PACKAGE_FORM) >= 1);
241
242 //
243 // Skip the package list header.
244 //
245 Package = (EFI_HII_PACKAGE_HEADER *) (List + 1);
246
247 while (Package->Type != EFI_HII_PACKAGE_END) {
248
249 if (Package->Type == EFI_HII_PACKAGE_FORM) {
250
251 //
252 // Skip the package header
253 //
254 Offset = sizeof (EFI_HII_PACKAGE_HEADER);
255 while (Offset < Package->Length) {
256 OpCode = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + Offset);
257
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;
263 break;
264
265
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;
270
271 switch (Class->ExtendOpCode) {
272 case EFI_IFR_EXTEND_OP_CLASS:
273 ThunkContext->FormSetClass = Class->Class;
274 break;
275 case EFI_IFR_EXTEND_OP_SUBCLASS:
276 SubClass = (EFI_IFR_GUID_SUBCLASS *) OpCode;
277 ThunkContext->FormSetSubClass = SubClass->SubClass;
278 break;
279
280 default:
281 break;
282 }
283 }
284 break;
285
286 default:
287 break;
288
289 }
290
291 Offset += OpCode->Length;
292 }
293 //
294 // The attributes of first FormSet is ready now.
295 //
296 FreePool (List);
297 return;
298
299 break;
300 }
301
302 Package = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) Package + Package->Length);
303 }
304
305 }
306
307
308 EFI_STATUS
309 CreateQuestionIdMap (
310 IN OUT HII_THUNK_CONTEXT *ThunkContext
311 )
312 {
313 EFI_STATUS Status;
314 EFI_HII_PACKAGE_LIST_HEADER *List;
315 EFI_HII_PACKAGE_HEADER *Package;
316 UINTN Size;
317 EFI_IFR_OP_HEADER *OpCode;
318 UINTN Offset;
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;
331 UINT8 OneOfType;
332 EFI_IFR_ONE_OF *OneOfOpcode;
333
334 //
335 // Set to a invalid value.
336 //
337 OneOfType = (UINT8) -1;
338
339
340 Status = HiiLibExportPackageLists (ThunkContext->UefiHiiHandle, &List, &Size);
341 if (EFI_ERROR (Status)) {
342 return Status;
343 }
344
345 //
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
349 //
350
351 //
352 // Skip the package list header.
353 //
354 Package = (EFI_HII_PACKAGE_HEADER *) (List + 1);
355
356 while (Package->Type != EFI_HII_PACKAGE_END) {
357
358 if (Package->Type == EFI_HII_PACKAGE_FORM) {
359
360 //
361 // Skip the package header
362 //
363 Offset = sizeof (EFI_HII_PACKAGE_HEADER);
364 while (Offset < Package->Length) {
365 OpCode = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + Offset);
366
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;
372 break;
373
374 case EFI_IFR_VARSTORE_OP:
375 //
376 // IFR built from Framework VFR only has UEFI Buffer Type Storage
377 //
378 VarStore = (EFI_IFR_VARSTORE *) OpCode;
379 IdMap = AllocateZeroPool (sizeof (QUESTION_ID_MAP));
380 ASSERT (IdMap != NULL);
381
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);
387 break;
388
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);
397
398 if (QuestionIdMapEntryListHead != NULL) {
399 //
400 // If the Question is using Buffer (EFI_IFR_VARSTORE_OP) type VarStore.
401 //
402 IdMapEntry = AllocateZeroPool (sizeof (QUESTION_ID_MAP_ENTRY));
403 ASSERT (IdMapEntry != NULL);
404
405 IdMapEntry->FwQId = Question->VarStoreInfo.VarOffset;
406 IdMapEntry->UefiQid = Question->QuestionId;
407 IdMapEntry->Signature = QUESTION_ID_MAP_ENTRY_SIGNATURE;
408
409 InsertTailList (QuestionIdMapEntryListHead, &IdMapEntry->Link);
410 }
411
412 if (OpCode->OpCode == EFI_IFR_ONE_OF_OP) {
413 OneOfOpcode = (EFI_IFR_ONE_OF *) OpCode;
414 OneOfType = OneOfOpcode->Flags & EFI_IFR_NUMERIC_SIZE;
415 }
416
417 break;
418
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);
427
428 OneOfOptionMap->Signature = ONE_OF_OPTION_MAP_SIGNATURE;
429 OneOfOptionMap->QuestionId = OptionMap->QuestionId;
430
431 //
432 // Make sure OneOfType is initialized.
433 //
434 ASSERT (OneOfType != (UINT8) -1);
435 OneOfOptionMap->ValueType = OneOfType;
436 InitializeListHead (&OneOfOptionMap->OneOfOptionMapEntryListHead);
437 OneOfOptinMapEntryListHead = &OneOfOptionMap->OneOfOptionMapEntryListHead;
438 InsertTailList (&ThunkContext->OneOfOptionMapListHead, &OneOfOptionMap->Link);
439 }
440 OneOfOptionMapEntry = AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP_ENTRY));
441 ASSERT (OneOfOptionMapEntry != NULL);
442
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));
446
447 InsertTailList (OneOfOptinMapEntryListHead, &OneOfOptionMapEntry->Link);
448 }
449 } else if (CompareMem (&OptionMap->Guid, &gTianoHiiIfrGuid, sizeof (EFI_GUID)) == 0) {
450 Class = (EFI_IFR_GUID_CLASS *) OpCode;
451
452 switch (Class->ExtendOpCode) {
453 case EFI_IFR_EXTEND_OP_CLASS:
454 ThunkContext->FormSetClass = Class->Class;
455 break;
456 case EFI_IFR_EXTEND_OP_SUBCLASS:
457 SubClass = (EFI_IFR_GUID_SUBCLASS *) OpCode;
458 ThunkContext->FormSetSubClass = SubClass->SubClass;
459 break;
460
461 default:
462 break;
463 }
464 }
465 break;
466
467 default:
468 break;
469
470 }
471
472 Offset += OpCode->Length;
473 }
474 //
475 // Only Form Package is in a Package List.
476 //
477 break;
478 }
479
480 Package = (EFI_HII_PACKAGE_HEADER *) (UINT8 *) Package + Package->Length;
481 }
482
483 FreePool (List);
484 return EFI_SUCCESS;
485 }
486
487
488 LIST_ENTRY *
489 GetMapEntryListHead (
490 IN CONST HII_THUNK_CONTEXT *ThunkContext,
491 IN UINT16 VarStoreId
492 )
493 {
494 LIST_ENTRY *Link;
495 QUESTION_ID_MAP *Map;
496
497 Link = GetFirstNode (&ThunkContext->QuestionIdMapListHead);
498
499 while (!IsNull (&ThunkContext->QuestionIdMapListHead, Link)) {
500 Map = QUESTION_ID_MAP_FROM_LINK (Link);
501 if (VarStoreId == Map->VarStoreId) {
502 return &Map->MapEntryListHead;
503 }
504 Link = GetNextNode (&ThunkContext->QuestionIdMapListHead, Link);
505 }
506 return NULL;
507 }
508
509
510 HII_THUNK_CONTEXT *
511 CreateThunkContext (
512 IN HII_THUNK_PRIVATE_DATA *Private,
513 IN UINTN StringPackageCount,
514 IN UINTN IfrPackageCount
515 )
516 {
517 EFI_STATUS Status;
518 HII_THUNK_CONTEXT *ThunkContext;
519
520 ThunkContext = AllocateZeroPool (sizeof (HII_THUNK_CONTEXT));
521 ASSERT (ThunkContext != NULL);
522
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)) {
528 return NULL;
529 }
530
531 InitializeListHead (&ThunkContext->QuestionIdMapListHead);
532 InitializeListHead (&ThunkContext->OneOfOptionMapListHead);
533
534
535 return ThunkContext;
536
537 }
538
539 VOID
540 DestroyThunkContext (
541 IN HII_THUNK_CONTEXT *ThunkContext
542 )
543 {
544 ASSERT (ThunkContext != NULL);
545
546 FreeHiiHandle (ThunkContext->FwHiiHandle);
547
548 DestroyQuestionIdMap (&ThunkContext->QuestionIdMapListHead);
549
550 DestoryOneOfOptionMap (&ThunkContext->OneOfOptionMapListHead);
551
552 RemoveEntryList (&ThunkContext->Link);
553
554 FreePool (ThunkContext);
555 }
556
557
558 VOID
559 DestroyQuestionIdMap (
560 IN LIST_ENTRY *QuestionIdMapListHead
561 )
562 {
563 QUESTION_ID_MAP *IdMap;
564 QUESTION_ID_MAP_ENTRY *IdMapEntry;
565 LIST_ENTRY *Link;
566 LIST_ENTRY *Link2;
567
568 while (!IsListEmpty (QuestionIdMapListHead)) {
569 Link = GetFirstNode (QuestionIdMapListHead);
570
571 IdMap = QUESTION_ID_MAP_FROM_LINK (Link);
572
573 while (!IsListEmpty (&IdMap->MapEntryListHead)) {
574 Link2 = GetFirstNode (&IdMap->MapEntryListHead);
575
576 IdMapEntry = QUESTION_ID_MAP_ENTRY_FROM_LINK (Link2);
577
578 RemoveEntryList (Link2);
579
580 FreePool (IdMapEntry);
581 }
582
583 RemoveEntryList (Link);
584 FreePool (IdMap);
585 }
586 }
587
588 VOID
589 DestoryOneOfOptionMap (
590 IN LIST_ENTRY *OneOfOptionMapListHead
591 )
592 {
593 ONE_OF_OPTION_MAP *Map;
594 ONE_OF_OPTION_MAP_ENTRY *MapEntry;
595 LIST_ENTRY *Link;
596 LIST_ENTRY *Link2;
597
598 while (!IsListEmpty (OneOfOptionMapListHead)) {
599 Link = GetFirstNode (OneOfOptionMapListHead);
600
601 Map = ONE_OF_OPTION_MAP_FROM_LINK (Link);
602
603 while (!IsListEmpty (&Map->OneOfOptionMapEntryListHead)) {
604 Link2 = GetFirstNode (&Map->OneOfOptionMapEntryListHead);
605
606 MapEntry = ONE_OF_OPTION_MAP_ENTRY_FROM_LINK (Link2);
607
608 RemoveEntryList (Link2);
609
610 FreePool (MapEntry);
611 }
612
613 RemoveEntryList (Link);
614 FreePool (Map);
615 }
616 }
617
618
619
620