]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/UefiIfrDefault.c
f799dc664a305210a45d55abd3cbfffaf7407a9a
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiToUefiHiiThunk / UefiIfrDefault.c
1 /** @file
2 Function and Macro defintions for to extract default values from UEFI Form package.
3
4 Copyright (c) 2008, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15
16 #include <FrameworkDxe.h>
17
18 #include <Protocol/FrameworkHii.h>
19 #include <Protocol/HiiDatabase.h>
20
21 #include <Library/BaseLib.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/DebugLib.h>
24 #include <Library/MemoryAllocationLib.h>
25 #include <Library/UefiBootServicesTableLib.h>
26
27 #include "UefiIfrParser.h"
28 #include "UefiIfrDefault.h"
29 #include "HiiDatabase.h"
30
31 //
32 // Extern Variables
33 //
34 extern CONST EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
35 extern CONST EFI_HII_IMAGE_PROTOCOL *mHiiImageProtocol;
36 extern CONST EFI_HII_STRING_PROTOCOL *mHiiStringProtocol;
37 extern CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRoutingProtocol;
38
39 extern EFI_GUID gZeroGuid;
40
41 /**
42 Fetch the Ifr binary data of a FormSet.
43
44 @param Handle PackageList Handle
45 @param FormSetGuid GUID of a formset. If not specified (NULL or zero
46 GUID), take the first FormSet found in package
47 list.
48 @param BinaryLength The length of the FormSet IFR binary.
49 @param BinaryData The buffer designed to receive the FormSet.
50
51 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
52 BufferLength was updated.
53 @retval EFI_INVALID_PARAMETER The handle is unknown.
54 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
55 be found with the requested FormId.
56
57 **/
58 EFI_STATUS
59 GetIfrBinaryData (
60 IN EFI_HII_HANDLE Handle,
61 IN OUT EFI_GUID *FormSetGuid,
62 OUT UINTN *BinaryLength,
63 OUT UINT8 **BinaryData
64 )
65 {
66 EFI_STATUS Status;
67 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
68 UINTN BufferSize;
69 UINT8 *Package;
70 UINT8 *OpCodeData;
71 UINT32 Offset;
72 UINT32 Offset2;
73 BOOLEAN ReturnDefault;
74 UINT32 PackageListLength;
75 EFI_HII_PACKAGE_HEADER PackageHeader;
76
77 OpCodeData = NULL;
78 Package = NULL;
79 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;
80
81 //
82 // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list
83 //
84 if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {
85 ReturnDefault = TRUE;
86 } else {
87 ReturnDefault = FALSE;
88 }
89
90 //
91 // Get HII PackageList
92 //
93 BufferSize = 0;
94 HiiPackageList = NULL;
95 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
96 if (Status == EFI_BUFFER_TOO_SMALL) {
97 HiiPackageList = AllocatePool (BufferSize);
98 ASSERT (HiiPackageList != NULL);
99
100 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
101 }
102 if (EFI_ERROR (Status)) {
103 return Status;
104 }
105
106 //
107 // Get Form package from this HII package List
108 //
109 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
110 Offset2 = 0;
111 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
112
113 while (Offset < PackageListLength) {
114 Package = ((UINT8 *) HiiPackageList) + Offset;
115 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
116
117 if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {
118 //
119 // Search FormSet in this Form Package
120 //
121 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
122 while (Offset2 < PackageHeader.Length) {
123 OpCodeData = Package + Offset2;
124
125 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
126 //
127 // Check whether return default FormSet
128 //
129 if (ReturnDefault) {
130 break;
131 }
132
133 //
134 // FormSet GUID is specified, check it
135 //
136 if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
137 break;
138 }
139 }
140
141 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
142 }
143
144 if (Offset2 < PackageHeader.Length) {
145 //
146 // Target formset found
147 //
148 break;
149 }
150 }
151
152 Offset += PackageHeader.Length;
153 }
154
155 if (Offset >= PackageListLength) {
156 //
157 // Form package not found in this Package List
158 //
159 gBS->FreePool (HiiPackageList);
160 return EFI_NOT_FOUND;
161 }
162
163 if (ReturnDefault && FormSetGuid != NULL) {
164 //
165 // Return the default FormSet GUID
166 //
167 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
168 }
169
170 //
171 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
172 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
173 // of the Form Package.
174 //
175 *BinaryLength = PackageHeader.Length - Offset2;
176 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);
177
178 gBS->FreePool (HiiPackageList);
179
180 if (*BinaryData == NULL) {
181 return EFI_OUT_OF_RESOURCES;
182 }
183
184 return EFI_SUCCESS;
185 }
186
187 /**
188 Initialize the internal data structure of a FormSet.
189
190 @param Handle PackageList Handle
191 @param FormSetGuid GUID of a formset. If not specified (NULL or zero
192 GUID), take the first FormSet found in package
193 list.
194 @param FormSet FormSet data structure.
195
196 @retval EFI_SUCCESS The function completed successfully.
197 @retval EFI_NOT_FOUND The specified FormSet could not be found.
198
199 **/
200 EFI_STATUS
201 InitializeFormSet (
202 IN EFI_HII_HANDLE Handle,
203 IN OUT EFI_GUID *FormSetGuid,
204 OUT FORM_BROWSER_FORMSET *FormSet
205 )
206 {
207 EFI_STATUS Status;
208 EFI_HANDLE DriverHandle;
209
210 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
211 if (EFI_ERROR (Status)) {
212 return Status;
213 }
214
215 FormSet->HiiHandle = Handle;
216 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
217
218 //
219 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
220 //
221 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);
222 if (EFI_ERROR (Status)) {
223 return Status;
224 }
225 FormSet->DriverHandle = DriverHandle;
226 Status = gBS->HandleProtocol (
227 DriverHandle,
228 &gEfiHiiConfigAccessProtocolGuid,
229 (VOID **) &FormSet->ConfigAccess
230 );
231 if (EFI_ERROR (Status)) {
232 //
233 // Configuration Driver don't attach ConfigAccess protocol to its HII package
234 // list, then there will be no configuration action required
235 //
236 FormSet->ConfigAccess = NULL;
237 }
238
239 //
240 // Parse the IFR binary OpCodes
241 //
242 Status = ParseOpCodes (FormSet);
243 if (EFI_ERROR (Status)) {
244 return Status;
245 }
246 return Status;
247 }
248
249 /**
250 Set the data position at Offset with Width in Node->Buffer based
251 the value passed in.
252
253 @param Node The Buffer Storage Node.
254 @param Value The input value.
255 @param Offset The offset in Node->Buffer for the update.
256 @param Width The length of the Value.
257
258 @retval VOID
259
260 **/
261 VOID
262 SetNodeBuffer (
263 OUT UEFI_IFR_BUFFER_STORAGE_NODE *Node,
264 IN CONST EFI_HII_VALUE *Value,
265 IN UINTN Offset,
266 IN UINTN Width
267 )
268 {
269 ASSERT (Node->Signature == UEFI_IFR_BUFFER_STORAGE_NODE_SIGNATURE);
270 ASSERT (Offset + Width <= Node->Size);
271
272 CopyMem (Node->Buffer + Offset, &Value->Value.u8, Width);
273 }
274
275
276 /**
277 Reset Question to its default value.
278
279 @param FormSet FormSet data structure.
280 @param DefaultId The Class of the default.
281
282 @retval EFI_SUCCESS Question is reset to default value.
283
284 **/
285 EFI_STATUS
286 GetQuestionDefault (
287 IN FORM_BROWSER_FORMSET *FormSet,
288 IN FORM_BROWSER_FORM *Form,
289 IN FORM_BROWSER_STATEMENT *Question,
290 IN UINT16 DefaultId,
291 IN UINT16 VarStoreId,
292 OUT UEFI_IFR_BUFFER_STORAGE_NODE *Node
293 )
294 {
295 EFI_STATUS Status;
296 LIST_ENTRY *Link;
297 QUESTION_DEFAULT *Default;
298 QUESTION_OPTION *Option;
299 EFI_HII_VALUE *HiiValue;
300
301 Status = EFI_SUCCESS;
302
303 //
304 // Statement don't have storage, skip them
305 //
306 if (Question->QuestionId == 0) {
307 return Status;
308 }
309
310 if (Question->VarStoreId != VarStoreId) {
311 return Status;
312 }
313
314 ASSERT (Question->Storage->Type == EFI_HII_VARSTORE_BUFFER);
315
316 //
317 // There are three ways to specify default value for a Question:
318 // 1, use nested EFI_IFR_DEFAULT (highest priority)
319 // 2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
320 // 3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
321 //
322 HiiValue = &Question->HiiValue;
323
324 //
325 // EFI_IFR_DEFAULT has highest priority
326 //
327 if (!IsListEmpty (&Question->DefaultListHead)) {
328 Link = GetFirstNode (&Question->DefaultListHead);
329 while (!IsNull (&Question->DefaultListHead, Link)) {
330 Default = QUESTION_DEFAULT_FROM_LINK (Link);
331
332 if (Default->DefaultId == DefaultId) {
333 if (Default->ValueExpression != NULL) {
334 //
335 // Default is provided by an Expression, evaluate it
336 //
337 Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);
338 if (EFI_ERROR (Status)) {
339 return Status;
340 }
341
342 CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));
343 } else {
344 //
345 // Default value is embedded in EFI_IFR_DEFAULT
346 //
347 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
348 }
349
350 SetNodeBuffer (Node, HiiValue, Question->VarStoreInfo.VarOffset, Question->StorageWidth);
351 return EFI_SUCCESS;
352 }
353
354 Link = GetNextNode (&Question->DefaultListHead, Link);
355 }
356 }
357
358 //
359 // EFI_ONE_OF_OPTION
360 //
361 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {
362 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
363 //
364 // OneOfOption could only provide Standard and Manufacturing default
365 //
366 Link = GetFirstNode (&Question->OptionListHead);
367 while (!IsNull (&Question->OptionListHead, Link)) {
368 Option = QUESTION_OPTION_FROM_LINK (Link);
369
370 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Option->Flags & EFI_IFR_OPTION_DEFAULT)) ||
371 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG))
372 ) {
373 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
374
375 SetNodeBuffer (Node, HiiValue, Question->VarStoreInfo.VarOffset, Question->StorageWidth);
376 return EFI_SUCCESS;
377 }
378
379 Link = GetNextNode (&Question->OptionListHead, Link);
380 }
381 }
382 }
383
384 //
385 // EFI_IFR_CHECKBOX - lowest priority
386 //
387 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
388 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
389 //
390 // Checkbox could only provide Standard and Manufacturing default
391 //
392 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT)) ||
393 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG))
394 ) {
395 HiiValue->Value.b = TRUE;
396 } else {
397 HiiValue->Value.b = FALSE;
398 }
399
400 SetNodeBuffer (Node, HiiValue, Question->VarStoreInfo.VarOffset, Question->StorageWidth);
401 return EFI_SUCCESS;
402 }
403 }
404
405 return Status;
406 }
407
408
409 /**
410 Reset Questions in a Form to their default value.
411
412 @param FormSet FormSet data structure.
413 @param Form The Form which to be reset.
414 @param DefaultId The Class of the default.
415
416 @retval EFI_SUCCESS The function completed successfully.
417
418 **/
419 EFI_STATUS
420 ExtractFormDefault (
421 IN FORM_BROWSER_FORMSET *FormSet,
422 IN FORM_BROWSER_FORM *Form,
423 IN UINT16 DefaultId,
424 IN UINT16 VarStoreId,
425 OUT UEFI_IFR_BUFFER_STORAGE_NODE *Node
426 )
427 {
428 EFI_STATUS Status;
429 LIST_ENTRY *Link;
430 FORM_BROWSER_STATEMENT *Question;
431
432 Link = GetFirstNode (&Form->StatementListHead);
433 while (!IsNull (&Form->StatementListHead, Link)) {
434 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
435 //
436 // Reset Question to its default value
437 //
438 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId, VarStoreId, Node);
439 if (EFI_ERROR (Status)) {
440 continue;
441 }
442
443 Link = GetNextNode (&Form->StatementListHead, Link);
444 }
445 return EFI_SUCCESS;
446 }
447
448
449 /**
450 Destroy all the buffer allocated for the fileds of
451 UEFI_IFR_BUFFER_STORAGE_NODE. The Node itself
452 will be freed too.
453
454 @param FormSet FormSet data structure.
455 @param DefaultId The Class of the default.
456
457 @retval VOID
458
459 **/
460 VOID
461 DestroyDefaultNode (
462 IN UEFI_IFR_BUFFER_STORAGE_NODE *Node
463 )
464 {
465 FreePool (Node->Buffer);
466 FreePool (Node->Name);
467 FreePool (Node);
468 }
469
470
471 /**
472 Get the default value for Buffer Type storage named by
473 a Default Store and a Storage Store from a FormSet.
474 The result is in the a instance of UEFI_IFR_BUFFER_STORAGE_NODE
475 allocated by this function. It is inserted to the link list.
476
477 @param DefaultStore The Default Store.
478 @param Storage The Storage.
479 @param FormSet The Form Set.
480 @param UefiDefaultsListHead The head of link list for the output.
481
482 @retval EFI_SUCCESS Successful.
483
484 **/
485 EFI_STATUS
486 GetBufferTypeDefaultIdAndStorageId (
487 IN FORMSET_DEFAULTSTORE *DefaultStore,
488 IN FORMSET_STORAGE *Storage,
489 IN FORM_BROWSER_FORMSET *FormSet,
490 OUT LIST_ENTRY *UefiDefaultsListHead
491 )
492 {
493 UEFI_IFR_BUFFER_STORAGE_NODE *Node;
494 LIST_ENTRY *Link;
495 FORM_BROWSER_FORM *Form;
496 EFI_STATUS Status;
497
498 Node = AllocateZeroPool (sizeof (UEFI_IFR_BUFFER_STORAGE_NODE));
499 ASSERT (Node != NULL);
500
501 Node->Signature = UEFI_IFR_BUFFER_STORAGE_NODE_SIGNATURE;
502 Node->Name = AllocateCopyPool (StrSize (Storage->Name), Storage->Name);
503 Node->DefaultId = DefaultStore->DefaultId;
504 Node->StoreId = Storage->VarStoreId;
505 CopyGuid (&Node->Guid, &Storage->Guid);
506 Node->Size = Storage->Size;
507 Node->Buffer = AllocateZeroPool (Node->Size);
508 //
509 // Extract default from IFR binary
510 //
511 Link = GetFirstNode (&FormSet->FormListHead);
512 while (!IsNull (&FormSet->FormListHead, Link)) {
513 Form = FORM_BROWSER_FORM_FROM_LINK (Link);
514
515 Status = ExtractFormDefault (FormSet, Form, DefaultStore->DefaultId, Storage->VarStoreId, Node);
516 ASSERT_EFI_ERROR (Status);
517
518 Link = GetNextNode (&FormSet->FormListHead, Link);
519 }
520
521 InsertTailList (UefiDefaultsListHead, &Node->List);
522
523 return EFI_SUCCESS;
524 }
525
526
527 /**
528 Get the default value for Buffer Type storage named by
529 a Default Store from a FormSet.
530 The result is in the a instance of UEFI_IFR_BUFFER_STORAGE_NODE
531 allocated by this function. The output can be multiple instances
532 of UEFI_IFR_BUFFER_STORAGE_NODE. It is inserted to the link list.
533
534 @param DefaultStore The Default Store.
535 @param FormSet The Form Set.
536 @param UefiDefaultsListHead The head of link list for the output.
537
538 @retval EFI_SUCCESS Successful.
539
540 **/
541 EFI_STATUS
542 GetBufferTypeDefaultId (
543 IN FORMSET_DEFAULTSTORE *DefaultStore,
544 IN FORM_BROWSER_FORMSET *FormSet,
545 OUT LIST_ENTRY *UefiDefaultsListHead
546 )
547 {
548 LIST_ENTRY *StorageLink;
549 FORMSET_STORAGE *Storage;
550 EFI_STATUS Status;
551
552 StorageLink = GetFirstNode (&FormSet->StorageListHead);
553
554 while (!IsNull (&FormSet->StorageListHead, StorageLink)) {
555 Storage = FORMSET_STORAGE_FROM_LINK(StorageLink);
556
557 if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
558 Status = GetBufferTypeDefaultIdAndStorageId (DefaultStore, Storage, FormSet, UefiDefaultsListHead);
559 }
560
561 StorageLink = GetNextNode (&FormSet->StorageListHead, StorageLink);
562 }
563
564 return EFI_SUCCESS;
565 }
566
567
568 /**
569 Get the default value for Buffer Type storage from the first FormSet
570 in the Package List specified by a EFI_HII_HANDLE.
571
572 The results can be multiple instances of UEFI_IFR_BUFFER_STORAGE_NODE.
573 They are inserted to the link list.
574
575 @param UefiHiiHandle The handle for the package list.
576 @param UefiDefaultsListHead The head of link list for the output.
577
578 @retval EFI_SUCCESS Successful.
579
580 **/
581 EFI_STATUS
582 UefiIfrGetBufferTypeDefaults (
583 IN EFI_HII_HANDLE UefiHiiHandle,
584 OUT LIST_ENTRY **UefiDefaults
585 )
586 {
587 FORM_BROWSER_FORMSET *FormSet;
588 EFI_GUID FormSetGuid;
589 LIST_ENTRY *DefaultLink;
590 FORMSET_DEFAULTSTORE *DefaultStore;
591 EFI_STATUS Status;
592
593 ASSERT (UefiDefaults != NULL);
594
595 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
596 ASSERT (FormSet != NULL);
597
598 CopyGuid (&FormSetGuid, &gZeroGuid);
599 Status = InitializeFormSet (UefiHiiHandle, &FormSetGuid, FormSet);
600 ASSERT_EFI_ERROR (Status);
601
602 *UefiDefaults = AllocateZeroPool (sizeof (LIST_ENTRY));
603 ASSERT (UefiDefaults != NULL);
604 InitializeListHead (*UefiDefaults);
605
606 DefaultLink = GetFirstNode (&FormSet->DefaultStoreListHead);
607 while (!IsNull (&FormSet->DefaultStoreListHead, DefaultLink)) {
608 DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink);
609
610 Status = GetBufferTypeDefaultId (DefaultStore, FormSet, *UefiDefaults);
611 ASSERT_EFI_ERROR (Status);
612
613 DefaultLink = GetNextNode (&FormSet->DefaultStoreListHead, DefaultLink);
614 }
615
616 DestroyFormSet (FormSet);
617
618 return EFI_SUCCESS;
619 }
620
621
622 /**
623 Convert the UEFI Buffer Type default values to a Framework HII default
624 values specified by a EFI_HII_VARIABLE_PACK_LIST structure.
625
626 @param ListHead The link list of UEFI_IFR_BUFFER_STORAGE_NODE
627 which contains the default values retrived from
628 a UEFI form set.
629 @param DefaultMask The default mask.
630 The valid values are FRAMEWORK_EFI_IFR_FLAG_DEFAULT
631 and FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING.
632 UEFI spec only map FRAMEWORK_EFI_IFR_FLAG_DEFAULT and FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING
633 from specification to valid default class.
634 @param VariablePackList The output default value in a format defined in Framework.
635
636
637 @retval EFI_SUCCESS Successful.
638 @retval EFI_INVALID_PARAMETER The default mask is not FRAMEWORK_EFI_IFR_FLAG_DEFAULT or
639 FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING.
640 **/
641 EFI_STATUS
642 UefiDefaultsToFwDefaults (
643 IN LIST_ENTRY *ListHead,
644 IN UINTN DefaultMask,
645 OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList
646 )
647 {
648 LIST_ENTRY *List;
649 UEFI_IFR_BUFFER_STORAGE_NODE *Node;
650 UINTN Size;
651 UINTN Count;
652 UINT16 DefaultId;
653 EFI_HII_VARIABLE_PACK *Pack;
654 EFI_HII_VARIABLE_PACK_LIST *PackList;
655 UINTN Index;
656
657 if (DefaultMask == FRAMEWORK_EFI_IFR_FLAG_DEFAULT) {
658 DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
659 } else if (DefaultMask == FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING) {
660 DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
661 } else {
662 //
663 // UEFI spec only map FRAMEWORK_EFI_IFR_FLAG_DEFAULT and FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING
664 // from specification to valid default class.
665 //
666 ASSERT (FALSE);
667 return EFI_INVALID_PARAMETER;
668 }
669
670 //
671 // Calculate the size of the output EFI_HII_VARIABLE_PACK_LIST structure
672 //
673 Size = 0;
674 Count = 0;
675 List = GetFirstNode (ListHead);
676 while (!IsNull (ListHead, List)) {
677 Node = UEFI_IFR_BUFFER_STORAGE_NODE_FROM_LIST(List);
678
679 if (Node->DefaultId == DefaultId) {
680 Size += Node->Size;
681 Size += StrSize (Node->Name);
682
683 Count++;
684 }
685
686 List = GetNextNode (ListHead, List);
687 }
688
689 if (Count == 0) {
690 *VariablePackList = NULL;
691 return EFI_NOT_FOUND;
692 }
693
694 Size = Size + Count * (sizeof (EFI_HII_VARIABLE_PACK_LIST) + sizeof (EFI_HII_VARIABLE_PACK));
695
696 *VariablePackList = AllocateZeroPool (Size);
697 ASSERT (*VariablePackList != NULL);
698
699 List = GetFirstNode (ListHead);
700
701 PackList = (EFI_HII_VARIABLE_PACK_LIST *) *VariablePackList;
702 Pack = (EFI_HII_VARIABLE_PACK *) (PackList + 1);
703 Index = 0;
704 while (!IsNull (ListHead, List)) {
705 Node = UEFI_IFR_BUFFER_STORAGE_NODE_FROM_LIST(List);
706
707 Size = 0;
708 if (Node->DefaultId == DefaultId) {
709 Size += Node->Size;
710 Size += StrSize (Node->Name);
711 Size += sizeof (EFI_HII_VARIABLE_PACK);
712
713 //
714 // In UEFI, 0 is defined to be invalid for EFI_IFR_VARSTORE.VarStoreId.
715 // So the default storage of Var Store in VFR from a Framework module
716 // should be translated to 0xFFEE.
717 //
718 if (Node->StoreId == RESERVED_VARSTORE_ID) {
719 Pack->VariableId = 0;
720 } else {
721 Pack->VariableId = Node->StoreId;
722 }
723 //
724 // Initialize EFI_HII_VARIABLE_PACK
725 //
726 Pack->Header.Type = 0;
727 Pack->Header.Length = (UINT32) Size;
728 Pack->VariableNameLength = (UINT32) StrSize (Node->Name);
729 CopyMem (&Pack->VariableGuid, &Node->Guid, sizeof (EFI_GUID));
730
731 CopyMem ((UINT8 *) Pack + sizeof (EFI_HII_VARIABLE_PACK), Node->Name, StrSize (Node->Name));
732 CopyMem ((UINT8 *) Pack + sizeof (EFI_HII_VARIABLE_PACK) + Pack->VariableNameLength, Node->Buffer, Node->Size);
733
734 Size += sizeof (EFI_HII_VARIABLE_PACK_LIST);
735
736 //
737 // Initialize EFI_HII_VARIABLE_PACK_LIST
738 //
739 PackList->VariablePack = Pack;
740 Index++;
741 if (Index < Count) {
742 PackList->NextVariablePack = (EFI_HII_VARIABLE_PACK_LIST *)((UINT8 *) PackList + Size);
743 }
744
745 }
746
747 List = GetNextNode (ListHead, List);
748 }
749
750
751 return EFI_SUCCESS;
752 }
753
754
755 /**
756 Free up all buffer allocated for the link list of UEFI_IFR_BUFFER_STORAGE_NODE.
757
758 @param ListHead The link list of UEFI_IFR_BUFFER_STORAGE_NODE
759 which contains the default values retrived from
760 a UEFI form set.
761
762
763 @retval VOID
764 **/
765 VOID
766 FreeDefaultList (
767 IN LIST_ENTRY *ListHead
768 )
769 {
770 LIST_ENTRY *Link;
771 UEFI_IFR_BUFFER_STORAGE_NODE *Default;
772
773 while (!IsListEmpty (ListHead)) {
774 Link = GetFirstNode (ListHead);
775
776 Default = UEFI_IFR_BUFFER_STORAGE_NODE_FROM_LIST(Link);
777
778 RemoveEntryList (Link);
779
780 DestroyDefaultNode (Default);
781 }
782
783 FreePool (ListHead);
784 }
785