]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Utility.c
OptionMap->Guid may not align on UINT32 baundary.
[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 EFI_HII_HANDLE *
94 TagGuidToUefiHiiHandle (
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->UefiHiiHandle;
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 (CompareGuid (&Class->Guid, &gTianoHiiIfrGuid)) {
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
332
333 Status = HiiLibExportPackageLists (ThunkContext->UefiHiiHandle, &List, &Size);
334 if (EFI_ERROR (Status)) {
335 return Status;
336 }
337
338 //
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
342 //
343
344 //
345 // Skip the package list header.
346 //
347 Package = (EFI_HII_PACKAGE_HEADER *) (List + 1);
348
349 while (Package->Type != EFI_HII_PACKAGE_END) {
350
351 if (Package->Type == EFI_HII_PACKAGE_FORM) {
352
353 //
354 // Skip the package header
355 //
356 Offset = sizeof (EFI_HII_PACKAGE_HEADER);
357 while (Offset < Package->Length) {
358 OpCode = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + Offset);
359
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;
365 break;
366
367 case EFI_IFR_VARSTORE_OP:
368 //
369 // IFR built from Framework VFR only has UEFI Buffer Type Storage
370 //
371 VarStore = (EFI_IFR_VARSTORE *) OpCode;
372 IdMap = AllocateZeroPool (sizeof (QUESTION_ID_MAP));
373 ASSERT (IdMap != NULL);
374
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);
380 break;
381
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);
390
391 if (QuestionIdMapEntryListHead != NULL) {
392 //
393 // If the Question is using Buffer (EFI_IFR_VARSTORE_OP) type VarStore.
394 //
395 IdMapEntry = AllocateZeroPool (sizeof (QUESTION_ID_MAP_ENTRY));
396 ASSERT (IdMapEntry != NULL);
397
398 IdMapEntry->FwQId = Question->VarStoreInfo.VarOffset;
399 IdMapEntry->UefiQid = Question->QuestionId;
400 IdMapEntry->Signature = QUESTION_ID_MAP_ENTRY_SIGNATURE;
401
402 InsertTailList (QuestionIdMapEntryListHead, &IdMapEntry->Link);
403 }
404
405 break;
406
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);
415
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);
422 }
423 OneOfOptionMapEntry = AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP_ENTRY));
424 ASSERT (OneOfOptionMapEntry != NULL);
425
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));
429
430 InsertTailList (OneOfOptinMapEntryListHead, &OneOfOptionMapEntry->Link);
431 }
432 }else if (CompareMem (&OptionMap->Guid, &gTianoHiiIfrGuid, sizeof (EFI_GUID))) {
433 Class = (EFI_IFR_GUID_CLASS *) OpCode;
434
435 switch (Class->ExtendOpCode) {
436 case EFI_IFR_EXTEND_OP_CLASS:
437 ThunkContext->FormSetClass = Class->Class;
438 break;
439 case EFI_IFR_EXTEND_OP_SUBCLASS:
440 SubClass = (EFI_IFR_GUID_SUBCLASS *) OpCode;
441 ThunkContext->FormSetSubClass = SubClass->SubClass;
442 break;
443
444 default:
445 break;
446 }
447 }
448 break;
449
450 default:
451 break;
452
453 }
454
455 Offset += OpCode->Length;
456 }
457 //
458 // Only Form Package is in a Package List.
459 //
460 break;
461 }
462
463 Package = (EFI_HII_PACKAGE_HEADER *) (UINT8 *) Package + Package->Length;
464 }
465
466 FreePool (List);
467 return EFI_SUCCESS;
468 }
469
470
471 LIST_ENTRY *
472 GetMapEntryListHead (
473 IN CONST HII_THUNK_CONTEXT *ThunkContext,
474 IN UINT16 VarStoreId
475 )
476 {
477 LIST_ENTRY *Link;
478 QUESTION_ID_MAP *Map;
479
480 Link = GetFirstNode (&ThunkContext->QuestionIdMapListHead);
481
482 while (!IsNull (&ThunkContext->QuestionIdMapListHead, Link)) {
483 Map = QUESTION_ID_MAP_FROM_LINK (Link);
484 if (VarStoreId == Map->VarStoreId) {
485 return &Map->MapEntryListHead;
486 }
487 Link = GetNextNode (&ThunkContext->QuestionIdMapListHead, Link);
488 }
489 return NULL;
490 }
491
492
493 HII_THUNK_CONTEXT *
494 CreateThunkContext (
495 IN HII_THUNK_PRIVATE_DATA *Private,
496 IN UINTN StringPackageCount,
497 IN UINTN IfrPackageCount
498 )
499 {
500 EFI_STATUS Status;
501 HII_THUNK_CONTEXT *ThunkContext;
502
503 ThunkContext = AllocateZeroPool (sizeof (HII_THUNK_CONTEXT));
504 ASSERT (ThunkContext != NULL);
505
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)) {
511 return NULL;
512 }
513
514 InitializeListHead (&ThunkContext->QuestionIdMapListHead);
515 InitializeListHead (&ThunkContext->OneOfOptionMapListHead);
516
517
518 return ThunkContext;
519
520 }
521
522 VOID
523 DestroyThunkContext (
524 IN HII_THUNK_CONTEXT *ThunkContext
525 )
526 {
527 ASSERT (ThunkContext != NULL);
528
529 FreeHiiHandle (ThunkContext->FwHiiHandle);
530
531 DestroyQuestionIdMap (&ThunkContext->QuestionIdMapListHead);
532
533 DestoryOneOfOptionMap (&ThunkContext->OneOfOptionMapListHead);
534
535 RemoveEntryList (&ThunkContext->Link);
536
537 FreePool (ThunkContext);
538 }
539
540
541 VOID
542 DestroyQuestionIdMap (
543 IN LIST_ENTRY *QuestionIdMapListHead
544 )
545 {
546 QUESTION_ID_MAP *IdMap;
547 QUESTION_ID_MAP_ENTRY *IdMapEntry;
548 LIST_ENTRY *Link;
549 LIST_ENTRY *Link2;
550
551 while (!IsListEmpty (QuestionIdMapListHead)) {
552 Link = GetFirstNode (QuestionIdMapListHead);
553
554 IdMap = QUESTION_ID_MAP_FROM_LINK (Link);
555
556 while (!IsListEmpty (&IdMap->MapEntryListHead)) {
557 Link2 = GetFirstNode (&IdMap->MapEntryListHead);
558
559 IdMapEntry = QUESTION_ID_MAP_ENTRY_FROM_LINK (Link2);
560
561 RemoveEntryList (Link2);
562
563 FreePool (IdMapEntry);
564 }
565
566 RemoveEntryList (Link);
567 FreePool (IdMap);
568 }
569 }
570
571 VOID
572 DestoryOneOfOptionMap (
573 IN LIST_ENTRY *OneOfOptionMapListHead
574 )
575 {
576 ONE_OF_OPTION_MAP *Map;
577 ONE_OF_OPTION_MAP_ENTRY *MapEntry;
578 LIST_ENTRY *Link;
579 LIST_ENTRY *Link2;
580
581 while (!IsListEmpty (OneOfOptionMapListHead)) {
582 Link = GetFirstNode (OneOfOptionMapListHead);
583
584 Map = ONE_OF_OPTION_MAP_FROM_LINK (Link);
585
586 while (!IsListEmpty (&Map->OneOfOptionMapEntryListHead)) {
587 Link2 = GetFirstNode (&Map->OneOfOptionMapEntryListHead);
588
589 MapEntry = ONE_OF_OPTION_MAP_ENTRY_FROM_LINK (Link2);
590
591 RemoveEntryList (Link2);
592
593 FreePool (MapEntry);
594 }
595
596 RemoveEntryList (Link);
597 FreePool (Map);
598 }
599 }
600
601
602
603