1 /** @file
2
3 This file contains the keyboard processing code to the HII database.
4
5 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
6 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 #include <Guid/ZeroGuid.h>
21
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 outputted 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
ListPackageLists(IN UINT8 PackageType,IN CONST EFI_GUID * PackageGuid,IN OUT UINTN * HandleBufferLength,OUT EFI_HII_HANDLE ** HandleBuffer)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
ExportPackageLists(IN EFI_HII_HANDLE Handle,OUT EFI_HII_PACKAGE_LIST_HEADER ** PackageListHeader,OUT UINTN * PackageListSize)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 (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
ExtractGuidFromHiiHandle(IN EFI_HII_HANDLE Handle,OUT EFI_GUID * Guid)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
FwHiiHandleToUefiHiiHandle(IN CONST HII_THUNK_PRIVATE_DATA * Private,IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle)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 *
FwHiiHandleToThunkContext(IN CONST HII_THUNK_PRIVATE_DATA * Private,IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle)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 *
UefiHiiHandleToThunkContext(IN CONST HII_THUNK_PRIVATE_DATA * Private,IN EFI_HII_HANDLE UefiHiiHandle)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 *
TagGuidToIfrPackThunkContext(IN CONST HII_THUNK_PRIVATE_DATA * Private,IN CONST EFI_GUID * Guid)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
DestroyThunkContextForUefiHiiHandle(IN HII_THUNK_PRIVATE_DATA * Private,IN EFI_HII_HANDLE UefiHiiHandle)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 the input UEFI HiiHandle
393 that is created when a package list registered by a module calling
394 EFI_HII_DATABASE_PROTOCOL.NewPackageList.
395 This function records the PackageListGuid of EFI_HII_PACKAGE_LIST_HEADER
396 into the TagGuid of the created HII_THUNK_CONTEXT.
397
398 @param UefiHiiHandle The UEFI HII Handle.
399
400 @return the new created Hii thunk context.
401
402 **/
403 HII_THUNK_CONTEXT *
CreateThunkContextForUefiHiiHandle(IN EFI_HII_HANDLE UefiHiiHandle)404 CreateThunkContextForUefiHiiHandle (
405 IN EFI_HII_HANDLE UefiHiiHandle
406 )
407 {
408 EFI_STATUS Status;
409 EFI_GUID PackageGuid;
410 HII_THUNK_CONTEXT *ThunkContext;
411
412 ThunkContext = AllocateZeroPool (sizeof (*ThunkContext));
413 ASSERT (ThunkContext != NULL);
414
415 ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE;
416
417 Status = AllocateHiiHandle (&ThunkContext->FwHiiHandle);
418 if (EFI_ERROR (Status)) {
419 return NULL;
420 }
421
422 ThunkContext->UefiHiiHandle = UefiHiiHandle;
423
424 Status = ExtractGuidFromHiiHandle (UefiHiiHandle, &PackageGuid);
425 ASSERT_EFI_ERROR (Status);
426
427 CopyGuid(&ThunkContext->TagGuid, &PackageGuid);
428
429 return ThunkContext;
430 }
431
432
433 /**
434 Get the number of HII Package for a Package type.
435
436 @param PackageListHeader The Package List.
437 @param PackageType The Package Type.
438
439 @return The number of Package for given type.
440 **/
441 UINTN
GetPackageCountByType(IN CONST EFI_HII_PACKAGE_LIST_HEADER * PackageListHeader,IN UINT8 PackageType)442 GetPackageCountByType (
443 IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader,
444 IN UINT8 PackageType
445 )
446 {
447 UINTN Count;
448 EFI_HII_PACKAGE_HEADER *PackageHeader;
449
450 PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageListHeader + sizeof (EFI_HII_PACKAGE_LIST_HEADER));
451 Count = 0;
452
453 while (PackageHeader->Type != EFI_HII_PACKAGE_END) {
454 if (PackageHeader->Type == PackageType ) {
455 Count++;
456 }
457 PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHeader + PackageHeader->Length);
458 }
459
460
461 return Count;
462 }
463
464 /**
465 Get the Form Package from a Framework Package List.
466
467 @param Packages Framework Package List.
468
469 @return The Form Package Header found.
470 **/
471 EFI_HII_PACKAGE_HEADER *
GetIfrPackage(IN CONST EFI_HII_PACKAGES * Packages)472 GetIfrPackage (
473 IN CONST EFI_HII_PACKAGES *Packages
474 )
475 {
476 UINTN Index;
477 TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;
478
479 ASSERT (Packages != NULL);
480
481 TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId));
482
483 for (Index = 0; Index < Packages->NumberOfPackages; Index++) {
484 //
485 // The current UEFI HII build tool generate a binary in the format defined by
486 // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in
487 // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount
488 // may not be the exact number of valid package number in the binary generated
489 // by HII Build tool.
490 //
491 switch (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type) {
492 case EFI_HII_IFR:
493 return &TianoAutogenPackageHdrArray[Index]->PackageHeader;
494 break;
495 case EFI_HII_STRING:
496 case EFI_HII_FONT:
497 break;
498
499 default:
500 ASSERT (FALSE);
501 return NULL;
502 break;
503 }
504 }
505
506 return NULL;
507 }
508
509 /**
510 Get FormSet GUID.
511
512 ASSERT if no FormSet Opcode is found.
513
514 @param Packages Form Framework Package.
515 @param FormSetGuid Return the FormSet Guid.
516
517 **/
518 VOID
GetFormSetGuid(IN EFI_HII_PACKAGE_HEADER * Package,OUT EFI_GUID * FormSetGuid)519 GetFormSetGuid (
520 IN EFI_HII_PACKAGE_HEADER *Package,
521 OUT EFI_GUID *FormSetGuid
522 )
523 {
524 UINTN Offset;
525 EFI_IFR_OP_HEADER *OpCode;
526 EFI_IFR_FORM_SET *FormSet;
527
528 Offset = sizeof (EFI_HII_PACKAGE_HEADER);
529 while (Offset < Package->Length) {
530 OpCode = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + Offset);
531
532 switch (OpCode->OpCode) {
533 case EFI_IFR_FORM_SET_OP:
534 FormSet = (EFI_IFR_FORM_SET *) OpCode;
535 CopyGuid (FormSetGuid, (EFI_GUID *)(VOID *)&FormSet->Guid);
536 return;
537
538 default:
539 break;
540
541 }
542 Offset += OpCode->Length;
543 }
544
545 //
546 // A proper IFR must have a formset opcode.
547 //
548 ASSERT (FALSE);
549
550 }
551
552 /**
553 Creat a Thunk Context.
554
555 ASSERT if no FormSet Opcode is found.
556
557 @param Private The HII Thunk Private Context.
558 @param StringPackageCount The String package count.
559 @param IfrPackageCount The IFR Package count.
560
561 @return A newly created Thunk Context.
562 @retval NULL No resource to create a new Thunk Context.
563 **/
564 HII_THUNK_CONTEXT *
CreateThunkContext(IN HII_THUNK_PRIVATE_DATA * Private,IN UINTN StringPackageCount,IN UINTN IfrPackageCount)565 CreateThunkContext (
566 IN HII_THUNK_PRIVATE_DATA *Private,
567 IN UINTN StringPackageCount,
568 IN UINTN IfrPackageCount
569 )
570 {
571 EFI_STATUS Status;
572 HII_THUNK_CONTEXT *ThunkContext;
573
574 ThunkContext = AllocateZeroPool (sizeof (HII_THUNK_CONTEXT));
575 ASSERT (ThunkContext != NULL);
576
577 ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE;
578 ThunkContext->IfrPackageCount = IfrPackageCount;
579 ThunkContext->StringPackageCount = StringPackageCount;
580 Status = AllocateHiiHandle (&ThunkContext->FwHiiHandle);
581 if (EFI_ERROR (Status)) {
582 return NULL;
583 }
584
585 return ThunkContext;
586
587 }
588
589 /**
590 Destroy the Thunk Context and free up all resource.
591
592 @param ThunkContext The HII Thunk Private Context to be freed.
593
594 **/
595 VOID
DestroyThunkContext(IN HII_THUNK_CONTEXT * ThunkContext)596 DestroyThunkContext (
597 IN HII_THUNK_CONTEXT *ThunkContext
598 )
599 {
600 ASSERT (ThunkContext != NULL);
601
602 FreeHiiHandle (ThunkContext->FwHiiHandle);
603
604 RemoveEntryList (&ThunkContext->Link);
605
606 if (ThunkContext->FormSet != NULL) {
607 DestroyFormSet (ThunkContext->FormSet);
608 }
609
610 FreePool (ThunkContext);
611 }
612
613 /**
614 Get the FormSet's Default Varstore ID based on the rule (Descending Priority):
615
616 1) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01) is found, Var Store ID is used.
617 2) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID is not found, First Var Store ID is used
618 as the default Var Store ID.
619
620 @param FormSet The Form Set. The Default Varstore ID is updated if found.
621
622 **/
623 VOID
GetFormsetDefaultVarstoreId(IN OUT FORM_BROWSER_FORMSET * FormSet)624 GetFormsetDefaultVarstoreId (
625 IN OUT FORM_BROWSER_FORMSET * FormSet
626 )
627 {
628 LIST_ENTRY *StorageList;
629 FORMSET_STORAGE *Storage;
630
631 //
632 // VarStoreId 0 is invalid in UEFI IFR.
633 //
634 FormSet->DefaultVarStoreId = 0;
635 StorageList = GetFirstNode (&FormSet->StorageListHead);
636
637 while (!IsNull (&FormSet->StorageListHead, StorageList)) {
638 Storage = FORMSET_STORAGE_FROM_LINK (StorageList);
639
640 DEBUG ((EFI_D_INFO, "FormSet %g: Found Varstore ID %x Name %s Size 0x%x\n", &FormSet->Guid, Storage->VarStoreId, Storage->Name, Storage->Size));
641
642 if (Storage->VarStoreId == FRAMEWORK_RESERVED_VARSTORE_ID) {
643 //
644 // 1) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01) is found, Var Store ID is used.
645 //
646 FormSet->DefaultVarStoreId = FRAMEWORK_RESERVED_VARSTORE_ID;
647 break;
648 }
649
650 StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);
651 }
652
653 if (FormSet->DefaultVarStoreId != FRAMEWORK_RESERVED_VARSTORE_ID) {
654 //
655 //
656 // 2) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID is not found, First Var Store ID is used
657 // as the default Var Store ID.
658 //
659 StorageList = GetFirstNode (&FormSet->StorageListHead);
660 if (!IsNull (&FormSet->StorageListHead, StorageList)) {
661 Storage = FORMSET_STORAGE_FROM_LINK (StorageList);
662 FormSet->DefaultVarStoreId = Storage->VarStoreId;
663 }
664
665 }
666
667 if (FormSet->DefaultVarStoreId == 0) {
668 DEBUG ((EFI_D_INFO, "FormSet %g: No Varstore Found\n", &FormSet->Guid));
669 }
670
671 return;
672 }
673
674 /**
675 Fetch the Ifr binary data of a FormSet.
676
677 @param Handle PackageList Handle
678 @param FormSetGuid GUID of a formset. If not specified (NULL or zero
679 GUID), take the first FormSet found in package
680 list.
681 @param BinaryLength The length of the FormSet IFR binary.
682 @param BinaryData The buffer designed to receive the FormSet.
683
684 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
685 BufferLength was updated.
686 @retval EFI_INVALID_PARAMETER The handle is unknown.
687 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
688 be found with the requested FormId.
689
690 **/
691 EFI_STATUS
GetIfrBinaryData(IN EFI_HII_HANDLE Handle,IN OUT EFI_GUID * FormSetGuid,OUT UINTN * BinaryLength,OUT UINT8 ** BinaryData)692 GetIfrBinaryData (
693 IN EFI_HII_HANDLE Handle,
694 IN OUT EFI_GUID *FormSetGuid,
695 OUT UINTN *BinaryLength,
696 OUT UINT8 **BinaryData
697 )
698 {
699 EFI_STATUS Status;
700 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
701 UINTN BufferSize;
702 UINT8 *Package;
703 UINT8 *OpCodeData;
704 UINT32 Offset;
705 UINT32 Offset2;
706 BOOLEAN ReturnDefault;
707 UINT32 PackageListLength;
708 EFI_HII_PACKAGE_HEADER PackageHeader;
709
710 OpCodeData = NULL;
711 Package = NULL;
712 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;
713
714 //
715 // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list
716 //
717 if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {
718 ReturnDefault = TRUE;
719 } else {
720 ReturnDefault = FALSE;
721 }
722
723 //
724 // Get HII PackageList
725 //
726 BufferSize = 0;
727 HiiPackageList = NULL;
728 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
729 if (Status == EFI_BUFFER_TOO_SMALL) {
730 HiiPackageList = AllocatePool (BufferSize);
731 ASSERT (HiiPackageList != NULL);
732
733 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
734 }
735 if (EFI_ERROR (Status) || HiiPackageList == NULL) {
736 return EFI_NOT_FOUND;
737 }
738
739 //
740 // Get Form package from this HII package List
741 //
742 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
743 Offset2 = 0;
744 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
745
746 while (Offset < PackageListLength) {
747 Package = ((UINT8 *) HiiPackageList) + Offset;
748 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
749
750 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
751 //
752 // Search FormSet in this Form Package
753 //
754 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
755 while (Offset2 < PackageHeader.Length) {
756 OpCodeData = Package + Offset2;
757
758 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
759 //
760 // Check whether return default FormSet
761 //
762 if (ReturnDefault) {
763 break;
764 }
765
766 //
767 // FormSet GUID is specified, check it
768 //
769 if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
770 break;
771 }
772 }
773
774 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
775 }
776
777 if (Offset2 < PackageHeader.Length) {
778 //
779 // Target formset found
780 //
781 break;
782 }
783 }
784
785 Offset += PackageHeader.Length;
786 }
787
788 if (Offset >= PackageListLength) {
789 //
790 // Form package not found in this Package List
791 //
792 gBS->FreePool (HiiPackageList);
793 return EFI_NOT_FOUND;
794 }
795
796 if (ReturnDefault && FormSetGuid != NULL) {
797 //
798 // Return the default FormSet GUID
799 //
800 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
801 }
802
803 //
804 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
805 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
806 // of the Form Package.
807 //
808 *BinaryLength = PackageHeader.Length - Offset2;
809 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);
810
811 gBS->FreePool (HiiPackageList);
812
813 if (*BinaryData == NULL) {
814 return EFI_OUT_OF_RESOURCES;
815 }
816
817 return EFI_SUCCESS;
818 }
819
820 /**
821 Initialize the internal data structure of a FormSet.
822
823 @param Handle PackageList Handle
824 @param FormSetGuid GUID of a formset. If not specified (NULL or zero
825 GUID), take the first FormSet found in package
826 list.
827 @param FormSet FormSet data structure.
828
829 @retval EFI_SUCCESS The function completed successfully.
830 @retval EFI_NOT_FOUND The specified FormSet could not be found.
831
832 **/
833 EFI_STATUS
InitializeFormSet(IN EFI_HII_HANDLE Handle,IN OUT EFI_GUID * FormSetGuid,OUT FORM_BROWSER_FORMSET * FormSet)834 InitializeFormSet (
835 IN EFI_HII_HANDLE Handle,
836 IN OUT EFI_GUID *FormSetGuid,
837 OUT FORM_BROWSER_FORMSET *FormSet
838 )
839 {
840 EFI_STATUS Status;
841
842 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
843 if (EFI_ERROR (Status)) {
844 return Status;
845 }
846
847 FormSet->HiiHandle = Handle;
848 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
849
850 //
851 // Parse the IFR binary OpCodes
852 //
853 Status = ParseOpCodes (FormSet);
854 if (EFI_ERROR (Status)) {
855 return Status;
856 }
857
858 GetFormsetDefaultVarstoreId (FormSet);
859 return Status;
860 }
861
862 /**
863 Parse the Form Package and build a FORM_BROWSER_FORMSET structure.
864
865 @param UefiHiiHandle PackageList Handle
866
867 @return A pointer to FORM_BROWSER_FORMSET.
868
869 **/
870 FORM_BROWSER_FORMSET *
ParseFormSet(IN EFI_HII_HANDLE UefiHiiHandle)871 ParseFormSet (
872 IN EFI_HII_HANDLE UefiHiiHandle
873 )
874 {
875 FORM_BROWSER_FORMSET *FormSet;
876 EFI_GUID FormSetGuid;
877 EFI_STATUS Status;
878
879 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
880 ASSERT (FormSet != NULL);
881
882 CopyGuid (&FormSetGuid, &gZeroGuid);
883 Status = InitializeFormSet (UefiHiiHandle, &FormSetGuid, FormSet);
884 if (EFI_ERROR (Status)) {
885 FreePool (FormSet);
886 return NULL;
887 }
888
889 return FormSet;
890 }
891
892