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