]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Utility.c
remove the DEBUG_CODE_BEGIN and DEBUG_CODE_END due to the logic between them are...
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiOnUefiHiiThunk / 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 CONST CHAR16 FrameworkReservedVarstoreName[] = FRAMEWORK_RESERVED_VARSTORE_NAME;
23
24 /**
25
26 This function returns a list of the package handles of the
27 specified type that are currently active in the HII database. The
28 pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package
29 handles to be listed.
30
31 If HandleBufferLength is NULL, then ASSERT.
32 If HandleBuffer is NULL, the ASSERT.
33 If PackageType is EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is
34 NULL, then ASSERT.
35 If PackageType is not EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is not
36 NULL, then ASSERT.
37
38
39 @param PackageType Specifies the package type of the packages
40 to list or EFI_HII_PACKAGE_TYPE_ALL for
41 all packages to be listed.
42
43 @param PackageGuid If PackageType is
44 EFI_HII_PACKAGE_TYPE_GUID, then this is
45 the pointer to the GUID which must match
46 the Guid field of
47 EFI_HII_PACKAGE_GUID_HEADER. Otherwise, it
48 must be NULL.
49
50 @param HandleBufferLength On output, the length of the handle buffer
51 that is required for the handles found.
52
53 @param HandleBuffer On output, an array of EFI_HII_HANDLE instances returned.
54 The caller is responcible to free this pointer allocated.
55
56 @retval EFI_SUCCESS The matching handles are outputed successfully.
57 HandleBufferLength is updated with the actual length.
58 @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operation.
59 @retval EFI_NOT_FOUND No matching handle could not be found in database.
60 **/
61 EFI_STATUS
62 EFIAPI
63 ListPackageLists (
64 IN UINT8 PackageType,
65 IN CONST EFI_GUID *PackageGuid,
66 IN OUT UINTN *HandleBufferLength,
67 OUT EFI_HII_HANDLE **HandleBuffer
68 )
69 {
70 EFI_STATUS Status;
71
72 ASSERT (HandleBufferLength != NULL);
73 ASSERT (HandleBuffer != NULL);
74
75 *HandleBufferLength = 0;
76 *HandleBuffer = NULL;
77
78 if (PackageType == EFI_HII_PACKAGE_TYPE_GUID) {
79 ASSERT (PackageGuid != NULL);
80 } else {
81 ASSERT (PackageGuid == NULL);
82 }
83
84 Status = mHiiDatabase->ListPackageLists (
85 mHiiDatabase,
86 PackageType,
87 PackageGuid,
88 HandleBufferLength,
89 *HandleBuffer
90 );
91 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
92 //
93 // No packages is registered to UEFI HII Database, just return.
94 //
95 //
96 return Status;
97 }
98
99 *HandleBuffer = AllocateZeroPool (*HandleBufferLength);
100
101 if (*HandleBuffer == NULL) {
102 return EFI_OUT_OF_RESOURCES;
103 }
104
105 return mHiiDatabase->ListPackageLists (
106 mHiiDatabase,
107 PackageType,
108 PackageGuid,
109 HandleBufferLength,
110 *HandleBuffer
111 );
112
113 }
114
115 /**
116 Exports the contents of one or all package lists in the HII database into a buffer.
117
118 If Handle is not NULL and not a valid EFI_HII_HANDLE registered in the database,
119 then ASSERT.
120 If PackageListHeader is NULL, then ASSERT.
121 If PackageListSize is NULL, then ASSERT.
122
123 @param Handle The HII Handle.
124 @param PackageListHeader A pointer to a buffer that will contain the results of
125 the export function.
126 @param PackageListSize On output, the length of the buffer that is required for the exported data.
127
128 @retval EFI_SUCCESS Package exported.
129
130 @retval EFI_OUT_OF_RESOURCES Not enought memory to complete the operations.
131
132 **/
133 EFI_STATUS
134 EFIAPI
135 ExportPackageLists (
136 IN EFI_HII_HANDLE Handle,
137 OUT EFI_HII_PACKAGE_LIST_HEADER **PackageListHeader,
138 OUT UINTN *PackageListSize
139 )
140 {
141 EFI_STATUS Status;
142 UINTN Size;
143 EFI_HII_PACKAGE_LIST_HEADER *PackageListHdr;
144
145 ASSERT (PackageListSize != NULL);
146 ASSERT (PackageListHeader != NULL);
147
148 Size = 0;
149 PackageListHdr = NULL;
150 Status = mHiiDatabase->ExportPackageLists (
151 mHiiDatabase,
152 Handle,
153 &Size,
154 PackageListHdr
155 );
156 ASSERT_EFI_ERROR (Status != EFI_BUFFER_TOO_SMALL);
157
158 if (Status == EFI_BUFFER_TOO_SMALL) {
159 PackageListHdr = AllocateZeroPool (Size);
160
161 if (PackageListHeader == NULL) {
162 return EFI_OUT_OF_RESOURCES;
163 } else {
164 Status = mHiiDatabase->ExportPackageLists (
165 mHiiDatabase,
166 Handle,
167 &Size,
168 PackageListHdr
169 );
170 }
171 }
172
173 if (!EFI_ERROR (Status)) {
174 *PackageListHeader = PackageListHdr;
175 *PackageListSize = Size;
176 } else {
177 FreePool (PackageListHdr);
178 }
179
180 return Status;
181 }
182
183 /**
184 Extract Hii package list GUID for given HII handle.
185
186 If HiiHandle could not be found in the HII database, then ASSERT.
187 If Guid is NULL, then ASSERT.
188
189 @param Handle Hii handle
190 @param Guid Package list GUID
191
192 @retval EFI_SUCCESS Successfully extract GUID from Hii database.
193
194 **/
195 EFI_STATUS
196 EFIAPI
197 ExtractGuidFromHiiHandle (
198 IN EFI_HII_HANDLE Handle,
199 OUT EFI_GUID *Guid
200 )
201 {
202 EFI_STATUS Status;
203 UINTN BufferSize;
204 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
205
206 ASSERT (Guid != NULL);
207 ASSERT (Handle != NULL);
208
209 //
210 // Get HII PackageList
211 //
212 BufferSize = 0;
213 HiiPackageList = NULL;
214
215 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
216 ASSERT (Status != EFI_NOT_FOUND);
217
218 if (Status == EFI_BUFFER_TOO_SMALL) {
219 HiiPackageList = AllocatePool (BufferSize);
220 ASSERT (HiiPackageList != NULL);
221
222 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
223 }
224 if (EFI_ERROR (Status)) {
225 FreePool (HiiPackageList);
226 return Status;
227 }
228
229 //
230 // Extract GUID
231 //
232 CopyGuid (Guid, &HiiPackageList->PackageListGuid);
233
234 FreePool (HiiPackageList);
235
236 return EFI_SUCCESS;
237 }
238
239 /**
240 Find the corressponding UEFI HII Handle from a Framework HII Handle given.
241
242 @param Private The HII Thunk Module Private context.
243 @param FwHiiHandle The Framemwork HII Handle.
244
245 @return NULL If Framework HII Handle is invalid.
246 @return The corresponding UEFI HII Handle.
247 **/
248 EFI_HII_HANDLE
249 FwHiiHandleToUefiHiiHandle (
250 IN CONST HII_THUNK_PRIVATE_DATA *Private,
251 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
252 )
253 {
254 HII_THUNK_CONTEXT *ThunkContext;
255
256 ASSERT (FwHiiHandle != (FRAMEWORK_EFI_HII_HANDLE) 0);
257 ASSERT (Private != NULL);
258
259 ThunkContext = FwHiiHandleToThunkContext (Private, FwHiiHandle);
260
261 if (ThunkContext != NULL) {
262 return ThunkContext->UefiHiiHandle;
263 }
264
265 return (EFI_HII_HANDLE) NULL;
266 }
267
268
269 /**
270 Find the corressponding HII Thunk Context from a Framework HII Handle given.
271
272 @param Private The HII Thunk Module Private context.
273 @param FwHiiHandle The Framemwork HII Handle.
274
275 @return NULL If Framework HII Handle is invalid.
276 @return The corresponding HII Thunk Context.
277 **/
278 HII_THUNK_CONTEXT *
279 FwHiiHandleToThunkContext (
280 IN CONST HII_THUNK_PRIVATE_DATA *Private,
281 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
282 )
283 {
284 LIST_ENTRY *Link;
285 HII_THUNK_CONTEXT *ThunkContext;
286
287
288 Link = GetFirstNode (&Private->ThunkContextListHead);
289
290 while (!IsNull (&Private->ThunkContextListHead, Link)) {
291 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
292
293 if (FwHiiHandle == ThunkContext->FwHiiHandle) {
294 return ThunkContext;
295 }
296
297 Link = GetNextNode (&Private->ThunkContextListHead, Link);
298 }
299
300 return NULL;
301 }
302
303 /**
304 Find the corressponding HII Thunk Context from a UEFI HII Handle given.
305
306 @param Private The HII Thunk Module Private context.
307 @param UEFIHiiHandle The UEFI HII Handle.
308
309 @return NULL If UEFI HII Handle is invalid.
310 @return The corresponding HII Thunk Context.
311 **/
312 HII_THUNK_CONTEXT *
313 UefiHiiHandleToThunkContext (
314 IN CONST HII_THUNK_PRIVATE_DATA *Private,
315 IN EFI_HII_HANDLE UefiHiiHandle
316 )
317 {
318 LIST_ENTRY *Link;
319 HII_THUNK_CONTEXT *ThunkContext;
320
321 Link = GetFirstNode (&Private->ThunkContextListHead);
322
323 while (!IsNull (&Private->ThunkContextListHead, Link)) {
324 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
325
326 if (UefiHiiHandle == ThunkContext->UefiHiiHandle) {
327 return ThunkContext;
328 }
329 Link = GetNextNode (&Private->ThunkContextListHead, Link);
330 }
331
332 return NULL;
333 }
334
335 /**
336 Find the corressponding HII Thunk Context from a Tag GUID.
337
338 @param Private The HII Thunk Module Private context.
339 @param Guid The Tag GUID.
340
341 @return NULL No HII Thunk Context matched the Tag GUID.
342 @return The corresponding HII Thunk Context.
343 **/
344 HII_THUNK_CONTEXT *
345 TagGuidToIfrPackThunkContext (
346 IN CONST HII_THUNK_PRIVATE_DATA *Private,
347 IN CONST EFI_GUID *Guid
348 )
349 {
350 LIST_ENTRY *Link;
351 HII_THUNK_CONTEXT *ThunkContext;
352
353 Link = GetFirstNode (&Private->ThunkContextListHead);
354
355 while (!IsNull (&Private->ThunkContextListHead, Link)) {
356 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
357
358 if (CompareGuid (Guid, &ThunkContext->TagGuid) && (ThunkContext->IfrPackageCount != 0)) {
359 return ThunkContext;
360 }
361
362 Link = GetNextNode (&Private->ThunkContextListHead, Link);
363 }
364
365 return NULL;
366
367 }
368
369 /**
370 Clean up the HII Thunk Context for a UEFI HII Handle.
371
372 @param Private The HII Thunk Module Private context.
373 @param UEFIHiiHandle The UEFI HII Handle.
374
375 **/
376 VOID
377 DestroyThunkContextForUefiHiiHandle (
378 IN HII_THUNK_PRIVATE_DATA *Private,
379 IN EFI_HII_HANDLE UefiHiiHandle
380 )
381 {
382 HII_THUNK_CONTEXT *ThunkContext;
383
384 ThunkContext = UefiHiiHandleToThunkContext (Private, UefiHiiHandle);
385 ASSERT (ThunkContext != NULL);
386
387 DestroyThunkContext (ThunkContext);
388 }
389
390
391 /**
392 This function create a HII_THUNK_CONTEXT for a package list registered
393 by a module calling EFI_HII_DATABASE_PROTOCOL.NewPackageList. It records
394 the PackageListGuid in EFI_HII_PACKAGE_LIST_HEADER in the TagGuid in
395 HII_THUNK_CONTEXT created. This TagGuid will be used as a key to s
396
397 **/
398 HII_THUNK_CONTEXT *
399 CreateThunkContextForUefiHiiHandle (
400 IN EFI_HII_HANDLE UefiHiiHandle
401 )
402 {
403 EFI_STATUS Status;
404 EFI_GUID PackageGuid;
405 HII_THUNK_CONTEXT *ThunkContext;
406
407 ThunkContext = AllocateZeroPool (sizeof (*ThunkContext));
408 ASSERT (ThunkContext != NULL);
409
410 ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE;
411
412 Status = AllocateHiiHandle (&ThunkContext->FwHiiHandle);
413 if (EFI_ERROR (Status)) {
414 return NULL;
415 }
416
417 ThunkContext->UefiHiiHandle = UefiHiiHandle;
418
419 Status = ExtractGuidFromHiiHandle (UefiHiiHandle, &PackageGuid);
420 ASSERT_EFI_ERROR (Status);
421
422 CopyGuid(&ThunkContext->TagGuid, &PackageGuid);
423
424 return ThunkContext;
425 }
426
427
428 /**
429 Get the number of HII Package for a Package type.
430
431 @param PackageListHeader The Package List.
432 @param PackageType The Package Type.
433
434 @return The number of Package for given type.
435 **/
436 UINTN
437 GetPackageCountByType (
438 IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader,
439 IN UINT8 PackageType
440 )
441 {
442 UINTN Count;
443 EFI_HII_PACKAGE_HEADER *PackageHeader;
444
445 PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageListHeader + sizeof (EFI_HII_PACKAGE_LIST_HEADER));
446 Count = 0;
447
448 while (PackageHeader->Type != EFI_HII_PACKAGE_END) {
449 if (PackageHeader->Type == PackageType ) {
450 Count++;
451 }
452 PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHeader + PackageHeader->Length);
453 }
454
455
456 return Count;
457 }
458
459 /**
460 Get the Form Package from a Framework Package List.
461
462 @param Packages Framework Package List.
463
464 @return The Form Package Header found.
465 **/
466 EFI_HII_PACKAGE_HEADER *
467 GetIfrPackage (
468 IN CONST EFI_HII_PACKAGES *Packages
469 )
470 {
471 UINTN Index;
472 TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;
473
474 ASSERT (Packages != NULL);
475
476 TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId));
477
478 for (Index = 0; Index < Packages->NumberOfPackages; Index++) {
479 //
480 // The current UEFI HII build tool generate a binary in the format defined by
481 // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in
482 // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount
483 // may not be the exact number of valid package number in the binary generated
484 // by HII Build tool.
485 //
486 switch (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type) {
487 case EFI_HII_IFR:
488 return &TianoAutogenPackageHdrArray[Index]->PackageHeader;
489 break;
490 case EFI_HII_STRING:
491 case EFI_HII_FONT:
492 break;
493
494 default:
495 ASSERT (FALSE);
496 return NULL;
497 break;
498 }
499 }
500
501 return NULL;
502 }
503
504 /**
505 Get FormSet GUID.
506
507 ASSERT if no FormSet Opcode is found.
508
509 @param Packages Form Framework Package.
510 @param FormSetGuid Return the FormSet Guid.
511
512 **/
513 VOID
514 GetFormSetGuid (
515 IN EFI_HII_PACKAGE_HEADER *Package,
516 OUT EFI_GUID *FormSetGuid
517 )
518 {
519 UINTN Offset;
520 EFI_IFR_OP_HEADER *OpCode;
521 EFI_IFR_FORM_SET *FormSet;
522
523 Offset = sizeof (EFI_HII_PACKAGE_HEADER);
524 while (Offset < Package->Length) {
525 OpCode = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + Offset);
526
527 switch (OpCode->OpCode) {
528 case EFI_IFR_FORM_SET_OP:
529 FormSet = (EFI_IFR_FORM_SET *) OpCode;
530 CopyGuid (FormSetGuid, (EFI_GUID *)(VOID *)&FormSet->Guid);
531 return;
532
533 default:
534 break;
535
536 }
537 Offset += OpCode->Length;
538 }
539
540 //
541 // A proper IFR must have a formset opcode.
542 //
543 ASSERT (FALSE);
544
545 }
546
547 /**
548 Creat a Thunk Context.
549
550 ASSERT if no FormSet Opcode is found.
551
552 @param Private The HII Thunk Private Context.
553 @param StringPackageCount The String package count.
554 @param FormSetGuid The IFR Package count.
555
556 @return A newly created Thunk Context.
557 @retval NULL No resource to create a new Thunk Context.
558 **/
559 HII_THUNK_CONTEXT *
560 CreateThunkContext (
561 IN HII_THUNK_PRIVATE_DATA *Private,
562 IN UINTN StringPackageCount,
563 IN UINTN IfrPackageCount
564 )
565 {
566 EFI_STATUS Status;
567 HII_THUNK_CONTEXT *ThunkContext;
568
569 ThunkContext = AllocateZeroPool (sizeof (HII_THUNK_CONTEXT));
570 ASSERT (ThunkContext != NULL);
571
572 ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE;
573 ThunkContext->IfrPackageCount = IfrPackageCount;
574 ThunkContext->StringPackageCount = StringPackageCount;
575 Status = AllocateHiiHandle (&ThunkContext->FwHiiHandle);
576 if (EFI_ERROR (Status)) {
577 return NULL;
578 }
579
580 return ThunkContext;
581
582 }
583
584 /**
585 Destroy the Thunk Context and free up all resource.
586
587 @param ThunkContext The HII Thunk Private Context to be freed.
588
589 **/
590 VOID
591 DestroyThunkContext (
592 IN HII_THUNK_CONTEXT *ThunkContext
593 )
594 {
595 ASSERT (ThunkContext != NULL);
596
597 FreeHiiHandle (ThunkContext->FwHiiHandle);
598
599 RemoveEntryList (&ThunkContext->Link);
600
601 if (ThunkContext->FormSet != NULL) {
602 DestroyFormSet (ThunkContext->FormSet);
603 }
604
605 FreePool (ThunkContext);
606 }
607
608 /**
609 Get the FormSet's Default Varstore ID based on the rule (Descending Priority):
610
611 1) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01) is found, Var Store ID is used.
612 2) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID is not found, First Var Store ID is used
613 as the default Var Store ID.
614
615 @param FormSet The Form Set. The Default Varstore ID is updated if found.
616
617 **/
618 VOID
619 GetFormsetDefaultVarstoreId (
620 IN OUT FORM_BROWSER_FORMSET * FormSet
621 )
622 {
623 LIST_ENTRY *StorageList;
624 FORMSET_STORAGE *Storage;
625 FORMSET_STORAGE *DefaultStorage;
626
627 //
628 // VarStoreId 0 is invalid in UEFI IFR.
629 //
630 DefaultStorage= NULL;
631 FormSet->DefaultVarStoreId = 0;
632 StorageList = GetFirstNode (&FormSet->StorageListHead);
633
634 while (!IsNull (&FormSet->StorageListHead, StorageList)) {
635 Storage = FORMSET_STORAGE_FROM_LINK (StorageList);
636
637 DEBUG ((EFI_D_INFO, "FormSet %g: Found Varstore ID %x Name %s Size 0x%x\n", &FormSet->Guid, Storage->VarStoreId, Storage->Name, Storage->Size));
638
639 if (Storage->VarStoreId == FRAMEWORK_RESERVED_VARSTORE_ID) {
640 //
641 // 1) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01) is found, Var Store ID is used.
642 //
643 FormSet->DefaultVarStoreId = FRAMEWORK_RESERVED_VARSTORE_ID;
644 DefaultStorage = Storage;
645 break;
646 }
647
648 StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);
649 }
650
651 if (FormSet->DefaultVarStoreId != FRAMEWORK_RESERVED_VARSTORE_ID) {
652 //
653 //
654 // 2) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID is not found, First Var Store ID is used
655 // as the default Var Store ID.
656 //
657 StorageList = GetFirstNode (&FormSet->StorageListHead);
658 if (!IsNull (&FormSet->StorageListHead, StorageList)) {
659 Storage = FORMSET_STORAGE_FROM_LINK (StorageList);
660 FormSet->DefaultVarStoreId = Storage->VarStoreId;
661 DefaultStorage = Storage;
662 }
663
664 }
665
666 if (FormSet->DefaultVarStoreId == 0) {
667 DEBUG ((EFI_D_INFO, "FormSet %g: No Varstore Found\n", &FormSet->Guid));
668 } else {
669 // The name of default VARSTORE with a Explicit declaration statement will be updated to L"Setup" to make sure
670 // the Framework HII Setup module will run correctly. Framework HII Setup module always assumed that default
671 // VARSTORE to have L"Setup" as name, Formset GUID as GUID.
672
673 DEBUG ((EFI_D_INFO, "FormSet %g: Default Varstore ID (0x%x) N(%s) G(%g)\n", &FormSet->Guid, FormSet->DefaultVarStoreId, DefaultStorage->Name, &DefaultStorage->Guid));
674
675 if (StrCmp (DefaultStorage->Name, FrameworkReservedVarstoreName) != 0) {
676 DEBUG ((EFI_D_INFO, " : Name is updated from %s to %s.\n", DefaultStorage->Name, FrameworkReservedVarstoreName));
677 FormSet->OriginalDefaultVarStoreName = DefaultStorage->Name;
678 DefaultStorage->Name = AllocateCopyPool (StrSize (FrameworkReservedVarstoreName), FrameworkReservedVarstoreName);
679 }
680 }
681
682 return;
683 }
684
685 /**
686 Fetch the Ifr binary data of a FormSet.
687
688 @param Handle PackageList Handle
689 @param FormSetGuid GUID of a formset. If not specified (NULL or zero
690 GUID), take the first FormSet found in package
691 list.
692 @param BinaryLength The length of the FormSet IFR binary.
693 @param BinaryData The buffer designed to receive the FormSet.
694
695 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
696 BufferLength was updated.
697 @retval EFI_INVALID_PARAMETER The handle is unknown.
698 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
699 be found with the requested FormId.
700
701 **/
702 EFI_STATUS
703 GetIfrBinaryData (
704 IN EFI_HII_HANDLE Handle,
705 IN OUT EFI_GUID *FormSetGuid,
706 OUT UINTN *BinaryLength,
707 OUT UINT8 **BinaryData
708 )
709 {
710 EFI_STATUS Status;
711 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
712 UINTN BufferSize;
713 UINT8 *Package;
714 UINT8 *OpCodeData;
715 UINT32 Offset;
716 UINT32 Offset2;
717 BOOLEAN ReturnDefault;
718 UINT32 PackageListLength;
719 EFI_HII_PACKAGE_HEADER PackageHeader;
720
721 OpCodeData = NULL;
722 Package = NULL;
723 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;
724
725 //
726 // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list
727 //
728 if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {
729 ReturnDefault = TRUE;
730 } else {
731 ReturnDefault = FALSE;
732 }
733
734 //
735 // Get HII PackageList
736 //
737 BufferSize = 0;
738 HiiPackageList = NULL;
739 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
740 if (Status == EFI_BUFFER_TOO_SMALL) {
741 HiiPackageList = AllocatePool (BufferSize);
742 ASSERT (HiiPackageList != NULL);
743
744 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
745 }
746 if (EFI_ERROR (Status)) {
747 return Status;
748 }
749
750 //
751 // Get Form package from this HII package List
752 //
753 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
754 Offset2 = 0;
755 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
756
757 while (Offset < PackageListLength) {
758 Package = ((UINT8 *) HiiPackageList) + Offset;
759 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
760
761 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
762 //
763 // Search FormSet in this Form Package
764 //
765 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
766 while (Offset2 < PackageHeader.Length) {
767 OpCodeData = Package + Offset2;
768
769 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
770 //
771 // Check whether return default FormSet
772 //
773 if (ReturnDefault) {
774 break;
775 }
776
777 //
778 // FormSet GUID is specified, check it
779 //
780 if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
781 break;
782 }
783 }
784
785 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
786 }
787
788 if (Offset2 < PackageHeader.Length) {
789 //
790 // Target formset found
791 //
792 break;
793 }
794 }
795
796 Offset += PackageHeader.Length;
797 }
798
799 if (Offset >= PackageListLength) {
800 //
801 // Form package not found in this Package List
802 //
803 gBS->FreePool (HiiPackageList);
804 return EFI_NOT_FOUND;
805 }
806
807 if (ReturnDefault && FormSetGuid != NULL) {
808 //
809 // Return the default FormSet GUID
810 //
811 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
812 }
813
814 //
815 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
816 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
817 // of the Form Package.
818 //
819 *BinaryLength = PackageHeader.Length - Offset2;
820 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);
821
822 gBS->FreePool (HiiPackageList);
823
824 if (*BinaryData == NULL) {
825 return EFI_OUT_OF_RESOURCES;
826 }
827
828 return EFI_SUCCESS;
829 }
830
831 /**
832 Initialize the internal data structure of a FormSet.
833
834 @param Handle PackageList Handle
835 @param FormSetGuid GUID of a formset. If not specified (NULL or zero
836 GUID), take the first FormSet found in package
837 list.
838 @param FormSet FormSet data structure.
839
840 @retval EFI_SUCCESS The function completed successfully.
841 @retval EFI_NOT_FOUND The specified FormSet could not be found.
842
843 **/
844 EFI_STATUS
845 InitializeFormSet (
846 IN EFI_HII_HANDLE Handle,
847 IN OUT EFI_GUID *FormSetGuid,
848 OUT FORM_BROWSER_FORMSET *FormSet
849 )
850 {
851 EFI_STATUS Status;
852
853 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
854 if (EFI_ERROR (Status)) {
855 return Status;
856 }
857
858 FormSet->HiiHandle = Handle;
859 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
860
861 //
862 // Parse the IFR binary OpCodes
863 //
864 Status = ParseOpCodes (FormSet);
865 if (EFI_ERROR (Status)) {
866 return Status;
867 }
868
869 GetFormsetDefaultVarstoreId (FormSet);
870 return Status;
871 }
872
873 /**
874 Parse the Form Package and build a FORM_BROWSER_FORMSET structure.
875
876 @param UefiHiiHandle PackageList Handle
877
878 @return A pointer to FORM_BROWSER_FORMSET.
879
880 **/
881 FORM_BROWSER_FORMSET *
882 ParseFormSet (
883 IN EFI_HII_HANDLE UefiHiiHandle
884 )
885 {
886 FORM_BROWSER_FORMSET *FormSet;
887 EFI_GUID FormSetGuid;
888 EFI_STATUS Status;
889
890 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
891 ASSERT (FormSet != NULL);
892
893 CopyGuid (&FormSetGuid, &gZeroGuid);
894 Status = InitializeFormSet (UefiHiiHandle, &FormSetGuid, FormSet);
895 if (EFI_ERROR (Status)) {
896 FreePool (FormSet);
897 return NULL;
898 }
899
900 return FormSet;
901 }
902