]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Utility.c
1) Add in support for Framework VFR file which specify all VAR Store correctly. This...
[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 #include <Library/DebugLib.h>
20
21 CONST EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
22
23 /**
24 Find the corressponding UEFI HII Handle from a Framework HII Handle given.
25
26 @param Private The HII Thunk Module Private context.
27 @param FwHiiHandle The Framemwork HII Handle.
28
29 @return NULL If Framework HII Handle is invalid.
30 @return The corresponding UEFI HII Handle.
31 **/
32 EFI_HII_HANDLE
33 FwHiiHandleToUefiHiiHandle (
34 IN CONST HII_THUNK_PRIVATE_DATA *Private,
35 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
36 )
37 {
38 HII_THUNK_CONTEXT *ThunkContext;
39
40 ASSERT (FwHiiHandle != (FRAMEWORK_EFI_HII_HANDLE) 0);
41 ASSERT (Private != NULL);
42
43 ThunkContext = FwHiiHandleToThunkContext (Private, FwHiiHandle);
44
45 if (ThunkContext != NULL) {
46 return ThunkContext->UefiHiiHandle;
47 }
48
49 return (EFI_HII_HANDLE) NULL;
50 }
51
52
53 /**
54 Find the corressponding HII Thunk Context from a Framework HII Handle given.
55
56 @param Private The HII Thunk Module Private context.
57 @param FwHiiHandle The Framemwork HII Handle.
58
59 @return NULL If Framework HII Handle is invalid.
60 @return The corresponding HII Thunk Context.
61 **/
62 HII_THUNK_CONTEXT *
63 FwHiiHandleToThunkContext (
64 IN CONST HII_THUNK_PRIVATE_DATA *Private,
65 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
66 )
67 {
68 LIST_ENTRY *Link;
69 HII_THUNK_CONTEXT *ThunkContext;
70
71
72 Link = GetFirstNode (&Private->ThunkContextListHead);
73
74 while (!IsNull (&Private->ThunkContextListHead, Link)) {
75 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
76
77 if (FwHiiHandle == ThunkContext->FwHiiHandle) {
78 return ThunkContext;
79 }
80
81 Link = GetNextNode (&Private->ThunkContextListHead, Link);
82 }
83
84 return NULL;
85 }
86
87 /**
88 Find the corressponding HII Thunk Context from a UEFI HII Handle given.
89
90 @param Private The HII Thunk Module Private context.
91 @param UEFIHiiHandle The UEFI HII Handle.
92
93 @return NULL If UEFI HII Handle is invalid.
94 @return The corresponding HII Thunk Context.
95 **/
96 HII_THUNK_CONTEXT *
97 UefiHiiHandleToThunkContext (
98 IN CONST HII_THUNK_PRIVATE_DATA *Private,
99 IN EFI_HII_HANDLE UefiHiiHandle
100 )
101 {
102 LIST_ENTRY *Link;
103 HII_THUNK_CONTEXT *ThunkContext;
104
105 Link = GetFirstNode (&Private->ThunkContextListHead);
106
107 while (!IsNull (&Private->ThunkContextListHead, Link)) {
108 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
109
110 if (UefiHiiHandle == ThunkContext->UefiHiiHandle) {
111 return ThunkContext;
112 }
113 Link = GetNextNode (&Private->ThunkContextListHead, Link);
114 }
115
116 return NULL;
117 }
118
119 /**
120 Find the corressponding HII Thunk Context from a Tag GUID.
121
122 @param Private The HII Thunk Module Private context.
123 @param Guid The Tag GUID.
124
125 @return NULL No HII Thunk Context matched the Tag GUID.
126 @return The corresponding HII Thunk Context.
127 **/
128 HII_THUNK_CONTEXT *
129 TagGuidToIfrPackThunkContext (
130 IN CONST HII_THUNK_PRIVATE_DATA *Private,
131 IN CONST EFI_GUID *Guid
132 )
133 {
134 LIST_ENTRY *Link;
135 HII_THUNK_CONTEXT *ThunkContext;
136
137 Link = GetFirstNode (&Private->ThunkContextListHead);
138
139 while (!IsNull (&Private->ThunkContextListHead, Link)) {
140 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
141
142 if (CompareGuid (Guid, &ThunkContext->TagGuid) && (ThunkContext->IfrPackageCount != 0)) {
143 return ThunkContext;
144 }
145
146 Link = GetNextNode (&Private->ThunkContextListHead, Link);
147 }
148
149 return NULL;
150
151 }
152
153 /**
154 Clean up the HII Thunk Context for a UEFI HII Handle.
155
156 @param Private The HII Thunk Module Private context.
157 @param UEFIHiiHandle The UEFI HII Handle.
158
159 **/
160 VOID
161 DestroyThunkContextForUefiHiiHandle (
162 IN HII_THUNK_PRIVATE_DATA *Private,
163 IN EFI_HII_HANDLE UefiHiiHandle
164 )
165 {
166 HII_THUNK_CONTEXT *ThunkContext;
167
168 ThunkContext = UefiHiiHandleToThunkContext (Private, UefiHiiHandle);
169 ASSERT (ThunkContext != NULL);
170
171 DestroyThunkContext (ThunkContext);
172 }
173
174
175 /**
176 This function create a HII_THUNK_CONTEXT for a package list registered
177 by a module calling EFI_HII_DATABASE_PROTOCOL.NewPackageList. It records
178 the PackageListGuid in EFI_HII_PACKAGE_LIST_HEADER in the TagGuid in
179 HII_THUNK_CONTEXT created. This TagGuid will be used as a key to s
180
181 **/
182 HII_THUNK_CONTEXT *
183 CreateThunkContextForUefiHiiHandle (
184 IN EFI_HII_HANDLE UefiHiiHandle
185 )
186 {
187 EFI_STATUS Status;
188 EFI_GUID PackageGuid;
189 HII_THUNK_CONTEXT *ThunkContext;
190
191 ThunkContext = AllocateZeroPool (sizeof (*ThunkContext));
192 ASSERT (ThunkContext != NULL);
193
194 ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE;
195
196 Status = AllocateHiiHandle (&ThunkContext->FwHiiHandle);
197 if (EFI_ERROR (Status)) {
198 return NULL;
199 }
200
201 ThunkContext->UefiHiiHandle = UefiHiiHandle;
202
203 Status = HiiLibExtractGuidFromHiiHandle (UefiHiiHandle, &PackageGuid);
204 ASSERT_EFI_ERROR (Status);
205
206 CopyGuid(&ThunkContext->TagGuid, &PackageGuid);
207
208 return ThunkContext;
209 }
210
211
212 /**
213 Get the number of HII Package for a Package type.
214
215 @param PackageListHeader The Package List.
216 @param PackageType The Package Type.
217
218 @return The number of Package for given type.
219 **/
220 UINTN
221 GetPackageCountByType (
222 IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader,
223 IN UINT8 PackageType
224 )
225 {
226 UINTN Count;
227 EFI_HII_PACKAGE_HEADER *PackageHeader;
228
229 PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageListHeader + sizeof (EFI_HII_PACKAGE_LIST_HEADER));
230 Count = 0;
231
232 while (PackageHeader->Type != EFI_HII_PACKAGE_END) {
233 if (PackageHeader->Type == PackageType ) {
234 Count++;
235 }
236 PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHeader + PackageHeader->Length);
237 }
238
239
240 return Count;
241 }
242
243 /**
244 Get the Form Package from a Framework Package List.
245
246 @param Packages Framework Package List.
247
248 @return The Form Package Header found.
249 **/
250 EFI_HII_PACKAGE_HEADER *
251 GetIfrPackage (
252 IN CONST EFI_HII_PACKAGES *Packages
253 )
254 {
255 UINTN Index;
256 TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;
257
258 ASSERT (Packages != NULL);
259
260 TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId));
261
262 for (Index = 0; Index < Packages->NumberOfPackages; Index++) {
263 //
264 // The current UEFI HII build tool generate a binary in the format defined by
265 // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in
266 // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount
267 // may not be the exact number of valid package number in the binary generated
268 // by HII Build tool.
269 //
270 switch (TianoAutogenPackageHdrArray[Index]->PackageHeader.Type) {
271 case EFI_HII_PACKAGE_FORMS:
272 return &TianoAutogenPackageHdrArray[Index]->PackageHeader;
273 break;
274 case EFI_HII_PACKAGE_STRINGS:
275 case EFI_HII_PACKAGE_SIMPLE_FONTS:
276 break;
277
278 //
279 // The following fonts are invalid for a module that using Framework to UEFI thunk layer.
280 //
281 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
282 case EFI_HII_PACKAGE_FONTS:
283 case EFI_HII_PACKAGE_IMAGES:
284 default:
285 ASSERT (FALSE);
286 return NULL;
287 break;
288 }
289 }
290
291 return NULL;
292 }
293
294 /**
295 Get FormSet GUID.
296
297 ASSERT if no FormSet Opcode is found.
298
299 @param Packages Form Framework Package.
300 @param FormSetGuid Return the FormSet Guid.
301
302 **/
303 VOID
304 GetFormSetGuid (
305 IN EFI_HII_PACKAGE_HEADER *Package,
306 OUT EFI_GUID *FormSetGuid
307 )
308 {
309 UINTN Offset;
310 EFI_IFR_OP_HEADER *OpCode;
311 EFI_IFR_FORM_SET *FormSet;
312
313 Offset = sizeof (EFI_HII_PACKAGE_HEADER);
314 while (Offset < Package->Length) {
315 OpCode = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + Offset);
316
317 switch (OpCode->OpCode) {
318 case EFI_IFR_FORM_SET_OP:
319 FormSet = (EFI_IFR_FORM_SET *) OpCode;
320 CopyGuid (FormSetGuid, (EFI_GUID *)(VOID *)&FormSet->Guid);
321 return;
322
323 default:
324 break;
325
326 }
327 Offset += OpCode->Length;
328 }
329
330 //
331 // A proper IFR must have a formset opcode.
332 //
333 ASSERT (FALSE);
334
335 }
336
337 /**
338 Creat a Thunk Context.
339
340 ASSERT if no FormSet Opcode is found.
341
342 @param Private The HII Thunk Private Context.
343 @param StringPackageCount The String package count.
344 @param FormSetGuid The IFR Package count.
345
346 @return A newly created Thunk Context.
347 @retval NULL No resource to create a new Thunk Context.
348 **/
349 HII_THUNK_CONTEXT *
350 CreateThunkContext (
351 IN HII_THUNK_PRIVATE_DATA *Private,
352 IN UINTN StringPackageCount,
353 IN UINTN IfrPackageCount
354 )
355 {
356 EFI_STATUS Status;
357 HII_THUNK_CONTEXT *ThunkContext;
358
359 ThunkContext = AllocateZeroPool (sizeof (HII_THUNK_CONTEXT));
360 ASSERT (ThunkContext != NULL);
361
362 ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE;
363 ThunkContext->IfrPackageCount = IfrPackageCount;
364 ThunkContext->StringPackageCount = StringPackageCount;
365 Status = AllocateHiiHandle (&ThunkContext->FwHiiHandle);
366 if (EFI_ERROR (Status)) {
367 return NULL;
368 }
369
370 return ThunkContext;
371
372 }
373
374 /**
375 Destroy the Thunk Context and free up all resource.
376
377 @param ThunkContext The HII Thunk Private Context to be freed.
378
379 **/
380 VOID
381 DestroyThunkContext (
382 IN HII_THUNK_CONTEXT *ThunkContext
383 )
384 {
385 ASSERT (ThunkContext != NULL);
386
387 FreeHiiHandle (ThunkContext->FwHiiHandle);
388
389 RemoveEntryList (&ThunkContext->Link);
390
391 if (ThunkContext->FormSet != NULL) {
392 DestroyFormSet (ThunkContext->FormSet);
393 }
394
395 FreePool (ThunkContext);
396 }
397
398 /**
399 Get the FormSet's Default Varstore ID based on the rule (Descending Priority):
400
401 1) Var Store ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01).
402 2) First Var Store ID.
403
404 @param FormSet The Form Set.
405
406 **/
407 VOID
408 GetFormsetDefaultVarstoreId (
409 IN OUT FORM_BROWSER_FORMSET * FormSet
410 )
411 {
412 LIST_ENTRY *StorageList;
413 FORMSET_STORAGE *Storage;
414 EFI_VARSTORE_ID FirstVarStoreId;
415
416 //
417 // VarStoreId 0 is invalid in UEFI IFR.
418 //
419 FormSet->DefaultVarStoreId = 0;
420 StorageList = GetFirstNode (&FormSet->StorageListHead);
421
422 while (!IsNull (&FormSet->StorageListHead, StorageList)) {
423 Storage = FORMSET_STORAGE_FROM_LINK (StorageList);
424
425 DEBUG ((EFI_D_INFO, "FormSet %g: Found Varstore ID %x\n", &FormSet->Guid, Storage->VarStoreId));
426
427 if (Storage->VarStoreId == FRAMEWORK_RESERVED_VARSTORE_ID) {
428 FormSet->DefaultVarStoreId = FRAMEWORK_RESERVED_VARSTORE_ID;
429 break;
430 }
431
432 StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);
433 }
434
435 if (FormSet->DefaultVarStoreId != FRAMEWORK_RESERVED_VARSTORE_ID) {
436 StorageList = GetFirstNode (&FormSet->StorageListHead);
437 if (!IsNull (&FormSet->StorageListHead, StorageList)) {
438 Storage = FORMSET_STORAGE_FROM_LINK (StorageList);
439 FirstVarStoreId = Storage->VarStoreId;
440 }
441
442 }
443
444 DEBUG_CODE_BEGIN ();
445 if (FormSet->DefaultVarStoreId == 0) {
446 DEBUG ((EFI_D_INFO, "FormSet %g: No Varstore Found\n", &FormSet->Guid));
447 } else {
448 DEBUG ((EFI_D_INFO, "FormSet %g: Default Varstore ID is %x\n", &FormSet->Guid, FormSet->DefaultVarStoreId));
449 }
450 DEBUG_CODE_END ();
451
452 return;
453 }
454
455 /**
456 Fetch the Ifr binary data of a FormSet.
457
458 @param Handle PackageList Handle
459 @param FormSetGuid GUID of a formset. If not specified (NULL or zero
460 GUID), take the first FormSet found in package
461 list.
462 @param BinaryLength The length of the FormSet IFR binary.
463 @param BinaryData The buffer designed to receive the FormSet.
464
465 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
466 BufferLength was updated.
467 @retval EFI_INVALID_PARAMETER The handle is unknown.
468 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
469 be found with the requested FormId.
470
471 **/
472 EFI_STATUS
473 GetIfrBinaryData (
474 IN EFI_HII_HANDLE Handle,
475 IN OUT EFI_GUID *FormSetGuid,
476 OUT UINTN *BinaryLength,
477 OUT UINT8 **BinaryData
478 )
479 {
480 EFI_STATUS Status;
481 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
482 UINTN BufferSize;
483 UINT8 *Package;
484 UINT8 *OpCodeData;
485 UINT32 Offset;
486 UINT32 Offset2;
487 BOOLEAN ReturnDefault;
488 UINT32 PackageListLength;
489 EFI_HII_PACKAGE_HEADER PackageHeader;
490
491 OpCodeData = NULL;
492 Package = NULL;
493 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;
494
495 //
496 // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list
497 //
498 if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {
499 ReturnDefault = TRUE;
500 } else {
501 ReturnDefault = FALSE;
502 }
503
504 //
505 // Get HII PackageList
506 //
507 BufferSize = 0;
508 HiiPackageList = NULL;
509 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
510 if (Status == EFI_BUFFER_TOO_SMALL) {
511 HiiPackageList = AllocatePool (BufferSize);
512 ASSERT (HiiPackageList != NULL);
513
514 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
515 }
516 if (EFI_ERROR (Status)) {
517 return Status;
518 }
519
520 //
521 // Get Form package from this HII package List
522 //
523 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
524 Offset2 = 0;
525 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
526
527 while (Offset < PackageListLength) {
528 Package = ((UINT8 *) HiiPackageList) + Offset;
529 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
530
531 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
532 //
533 // Search FormSet in this Form Package
534 //
535 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
536 while (Offset2 < PackageHeader.Length) {
537 OpCodeData = Package + Offset2;
538
539 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
540 //
541 // Check whether return default FormSet
542 //
543 if (ReturnDefault) {
544 break;
545 }
546
547 //
548 // FormSet GUID is specified, check it
549 //
550 if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
551 break;
552 }
553 }
554
555 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
556 }
557
558 if (Offset2 < PackageHeader.Length) {
559 //
560 // Target formset found
561 //
562 break;
563 }
564 }
565
566 Offset += PackageHeader.Length;
567 }
568
569 if (Offset >= PackageListLength) {
570 //
571 // Form package not found in this Package List
572 //
573 gBS->FreePool (HiiPackageList);
574 return EFI_NOT_FOUND;
575 }
576
577 if (ReturnDefault && FormSetGuid != NULL) {
578 //
579 // Return the default FormSet GUID
580 //
581 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
582 }
583
584 //
585 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
586 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
587 // of the Form Package.
588 //
589 *BinaryLength = PackageHeader.Length - Offset2;
590 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);
591
592 gBS->FreePool (HiiPackageList);
593
594 if (*BinaryData == NULL) {
595 return EFI_OUT_OF_RESOURCES;
596 }
597
598 return EFI_SUCCESS;
599 }
600
601 /**
602 Initialize the internal data structure of a FormSet.
603
604 @param Handle PackageList Handle
605 @param FormSetGuid GUID of a formset. If not specified (NULL or zero
606 GUID), take the first FormSet found in package
607 list.
608 @param FormSet FormSet data structure.
609
610 @retval EFI_SUCCESS The function completed successfully.
611 @retval EFI_NOT_FOUND The specified FormSet could not be found.
612
613 **/
614 EFI_STATUS
615 InitializeFormSet (
616 IN EFI_HII_HANDLE Handle,
617 IN OUT EFI_GUID *FormSetGuid,
618 OUT FORM_BROWSER_FORMSET *FormSet
619 )
620 {
621 EFI_STATUS Status;
622
623 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
624 if (EFI_ERROR (Status)) {
625 return Status;
626 }
627
628 FormSet->HiiHandle = Handle;
629 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
630
631 //
632 // Parse the IFR binary OpCodes
633 //
634 Status = ParseOpCodes (FormSet);
635 if (EFI_ERROR (Status)) {
636 return Status;
637 }
638
639 GetFormsetDefaultVarstoreId (FormSet);
640 return Status;
641 }
642
643 /**
644 Parse the Form Package and build a FORM_BROWSER_FORMSET structure.
645
646 @param UefiHiiHandle PackageList Handle
647
648 @return A pointer to FORM_BROWSER_FORMSET.
649
650 **/
651 FORM_BROWSER_FORMSET *
652 ParseFormSet (
653 IN EFI_HII_HANDLE UefiHiiHandle
654 )
655 {
656 FORM_BROWSER_FORMSET *FormSet;
657 EFI_GUID FormSetGuid;
658 EFI_STATUS Status;
659
660 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
661 ASSERT (FormSet != NULL);
662
663 CopyGuid (&FormSetGuid, &gZeroGuid);
664 Status = InitializeFormSet (UefiHiiHandle, &FormSetGuid, FormSet);
665 ASSERT_EFI_ERROR (Status);
666
667 return FormSet;
668 }
669