]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/FCE/Variable.c
BaseTools/FCE: Add a tool FCE
[mirror_edk2.git] / BaseTools / Source / C / FCE / Variable.c
1 /** @file
2
3 Read and edit the EFI variable.
4
5 Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "Fce.h"
11 #include "Variable.h"
12
13 extern LIST_ENTRY mAllVarListEntry;
14 extern MULTI_PLATFORM_PARAMETERS mMultiPlatformParam;
15 extern G_EFI_FD_INFO gEfiFdInfo;
16
17 EFI_GUID gEfiVariableGuid = EFI_VARIABLE_GUID;
18 /**
19
20 Gets the pointer to the first variable header in given variable store area.
21
22 @param VarStoreHeader Pointer to the Variable Store Header.
23
24 @return Pointer to the first variable header.
25
26 **/
27 static
28 VARIABLE_HEADER *
29 GetStartPointer (
30 IN VARIABLE_STORE_HEADER *VarStoreHeader
31 )
32 {
33 //
34 // The end of variable store.
35 //
36 return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);
37 }
38
39 /**
40
41 Gets the pointer to the end of the variable storage area.
42
43 This function gets pointer to the end of the variable storage
44 area, according to the input variable store header.
45
46 @param VarStoreHeader Pointer to the Variable Store Header.
47
48 @return Pointer to the end of the variable storage area.
49
50 **/
51 static
52 VARIABLE_HEADER *
53 GetEndPointer (
54 IN VARIABLE_STORE_HEADER *VarStoreHeader
55 )
56 {
57 //
58 // The end of variable store
59 //
60 return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size);
61 }
62
63
64 /**
65
66 This code checks if variable header is valid or not.
67
68 @param Variable Pointer to the Variable Header.
69
70 @retval TRUE Variable header is valid.
71 @retval FALSE Variable header is not valid.
72
73 **/
74 static
75 BOOLEAN
76 IsValidVariableHeader (
77 IN VARIABLE_HEADER *Variable
78 )
79 {
80 if ((Variable == NULL) || (Variable->StartId != VARIABLE_DATA)) {
81 return FALSE;
82 }
83
84 return TRUE;
85 }
86
87 /**
88
89 This code gets the size of name of variable.
90
91 @param Variable Pointer to the Variable Header.
92
93 @return UINTN Size of variable in bytes.
94
95 **/
96 static
97 UINTN
98 NameSizeOfVariable (
99 IN VARIABLE_HEADER *Variable
100 )
101 {
102 if ((Variable->State == (UINT8) (-1)) ||
103 (Variable->DataSize == (UINT32) (-1)) ||
104 (Variable->NameSize == (UINT32) (-1)) ||
105 (Variable->Attributes == (UINT32) (-1))
106 ) {
107 return 0;
108 }
109 return (UINTN) Variable->NameSize;
110 }
111
112 /**
113
114 This code gets the size of variable data.
115
116 @param Variable Pointer to the Variable Header.
117
118 @return Size of variable in bytes.
119
120 **/
121 static
122 UINTN
123 DataSizeOfVariable (
124 IN VARIABLE_HEADER *Variable
125 )
126 {
127 if ((Variable->State == (UINT8) (-1)) ||
128 (Variable->DataSize == (UINT32) (-1)) ||
129 (Variable->NameSize == (UINT32) (-1)) ||
130 (Variable->Attributes == (UINT32) (-1))
131 ) {
132 return 0;
133 }
134 return (UINTN) Variable->DataSize;
135 }
136
137 /**
138
139 This code gets the pointer to the variable name.
140
141 @param Variable Pointer to the Variable Header.
142
143 @return Pointer to Variable Name which is Unicode encoding.
144
145 **/
146 static
147 CHAR16 *
148 GetVariableNamePtr (
149 IN VARIABLE_HEADER *Variable
150 )
151 {
152
153 return (CHAR16 *) (Variable + 1);
154 }
155
156 /**
157
158 This code gets the pointer to the variable data.
159
160 @param Variable Pointer to the Variable Header.
161
162 @return Pointer to Variable Data.
163
164 **/
165 static
166 UINT8 *
167 GetVariableDataPtr (
168 IN VARIABLE_HEADER *Variable
169 )
170 {
171 UINTN Value;
172
173 //
174 // Be careful about pad size for alignment.
175 //
176 Value = (UINTN) GetVariableNamePtr (Variable);
177 Value += NameSizeOfVariable (Variable);
178 Value += GET_PAD_SIZE (NameSizeOfVariable (Variable));
179
180 return (UINT8 *) Value;
181 }
182
183 /**
184
185 This code gets the pointer to the next variable header.
186
187 @param Variable Pointer to the Variable Header.
188
189 @return Pointer to next variable header.
190
191 **/
192 static
193 VARIABLE_HEADER *
194 GetNextVariablePtr (
195 IN VARIABLE_HEADER *Variable
196 )
197 {
198 UINTN Value;
199
200 if (!IsValidVariableHeader (Variable)) {
201 return NULL;
202 }
203
204 Value = (UINTN) GetVariableDataPtr (Variable);
205 Value += DataSizeOfVariable (Variable);
206 Value += GET_PAD_SIZE (DataSizeOfVariable (Variable));
207
208 //
209 // Be careful about pad size for alignment.
210 //
211 return (VARIABLE_HEADER *) HEADER_ALIGN (Value);
212 }
213
214 /**
215 Search and get a free space in the EFI variable zone
216
217 @param VariableStoreHeader The start of a EFI variable zone.
218 @param VarListSize The size of a variables needs to be allocated.
219 @param FreeBeginVar The dual pointer to the free NV space.
220
221 @retval EFI_SUCCESS Return the beginning of a free variable space.
222 @retval RETURN_BUFFER_TOO_SMALL Failed.
223 **/
224 static
225 EFI_STATUS
226 GetVariableVar (
227 IN VARIABLE_STORE_HEADER *VariableStoreHeader,
228 IN UINT32 VarListSize,
229 IN OUT CHAR8 **FreeBeginVar
230 )
231 {
232 BOOLEAN Flag;
233 VARIABLE_HEADER *Variable;
234 VARIABLE_HEADER *EndOfVariable;
235 CHAR8 *BeginVar;
236
237 BeginVar = NULL;
238 Flag = FALSE;
239 Variable = NULL;
240 EndOfVariable = NULL;
241 *FreeBeginVar = NULL;
242
243 if (VariableStoreHeader == NULL) {
244 *FreeBeginVar = NULL;
245 return RETURN_INVALID_PARAMETER;
246 }
247 Variable = GetStartPointer (VariableStoreHeader);
248 EndOfVariable = GetEndPointer(VariableStoreHeader);
249 //
250 //Search the beginning of free NV
251 //
252 while (Variable != EndOfVariable) {
253 BeginVar = (CHAR8 *)Variable;
254 Variable = GetNextVariablePtr (Variable);
255 if (Variable == NULL) {
256 Flag = TRUE;
257 break;
258 }
259 }
260 //
261 // Check whether the free space is more than what we want
262 //
263 if ((CHAR8 *)BeginVar + VarListSize > (CHAR8 *)EndOfVariable) {
264 return RETURN_BUFFER_TOO_SMALL;
265 }
266 //
267 // If not find the available space, return NULL
268 //
269 if (!Flag) {
270 return RETURN_BUFFER_TOO_SMALL;
271 }
272 *FreeBeginVar = BeginVar;
273
274 return EFI_SUCCESS;
275 }
276
277 /**
278 Search whether the variable in VarList has existed in current NV.
279
280 Parse the FFS or Fd image, and find the valid variable pointer.
281
282 @param VariableStoreHeader The start of a EFI variable zone.
283 @param VarList The pointer to the VarList
284
285 @retval address If the variable existed in current NV, return address
286 @return NULL Otherwise, return NULL
287 **/
288 static
289 VARIABLE_HEADER *
290 FindVariableInNv (
291 IN VARIABLE_STORE_HEADER *VariableStoreHeader,
292 IN FORMSET_STORAGE *Storage
293 )
294 {
295 BOOLEAN Flag;
296 VARIABLE_HEADER *Variable;
297 VARIABLE_HEADER *EndOfVariable;
298 CHAR16 *VariableName;
299
300 Flag = FALSE;
301 Variable = NULL;
302 EndOfVariable = NULL;
303 VariableName = NULL;
304
305 if ((VariableStoreHeader == NULL) || (Storage == NULL) || (Storage->Name == NULL)) {
306 return NULL;
307 }
308 Variable = GetStartPointer (VariableStoreHeader);
309 EndOfVariable = GetEndPointer(VariableStoreHeader);
310 //
311 // Parse and compare the variable in the NV space one by one
312 //
313 while ((Variable != EndOfVariable) && (Variable != NULL)) {
314 VariableName = (CHAR16 *)((CHAR8 *)Variable + sizeof (VARIABLE_HEADER));
315 if (!CompareGuid (&Variable->VendorGuid, &Storage->Guid) \
316 && !FceStrCmp (Storage->Name, VariableName) \
317 && (Variable->State == VAR_ADDED)) {
318 Flag = TRUE;
319 break;
320 }
321 Variable = GetNextVariablePtr (Variable);
322 }
323 if (!Flag) {
324 return NULL;
325 }
326 return Variable;
327 }
328 /**
329 Exchange the data between Efi variable and the data of VarList when the
330 variable use the authenticated variable header
331
332 If VarToList is TRUE, copy the efi variable data to the VarList; Otherwise,
333 update the data from varlist to efi variable.
334
335 @param VarToList The flag to control the direction of exchange.
336 @param StorageListHead Decide which variale list be updated
337
338 @retval EFI_SUCCESS Get the address successfully.
339 @retval EFI_OUT_OF_RESOURCES No available in the EFI variable zone.
340 **/
341
342 EFI_STATUS
343 SynEfiVariable (
344 IN BOOLEAN VarToList,
345 IN LIST_ENTRY *StorageListHead
346 )
347 {
348 EFI_FIRMWARE_VOLUME_HEADER *VarAddr;
349 LIST_ENTRY *StorageLink;
350 FORMSET_STORAGE *Storage;
351 EFI_STATUS Status;
352 CHAR8 *NewAvailableAddr;
353 CHAR8 *DataBase;
354 VARIABLE_HEADER *VariableHeader;
355 VARIABLE_STORE_HEADER *VariableStoreHeader;
356 UINTN VarNameSize;
357
358 Status = EFI_SUCCESS;
359 DataBase = NULL;
360 NewAvailableAddr = NULL;
361 VarNameSize = 0;
362 VariableHeader = NULL;
363 VarAddr = (EFI_FIRMWARE_VOLUME_HEADER *) gEfiFdInfo.EfiVariableAddr;
364 VariableStoreHeader = (VARIABLE_STORE_HEADER *)((CHAR8 *)VarAddr + VarAddr->HeaderLength);
365 //
366 //Parse the variable range, and check whether there is some existed ones.
367 //
368 StorageLink = GetFirstNode (StorageListHead);
369 while (!IsNull (StorageListHead, StorageLink)) {
370 Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
371 //
372 // Ignore the invalid varlist node
373 //
374 if (Storage->Buffer == NULL) {
375 StorageLink = GetNextNode (StorageListHead, StorageLink);
376 continue;
377 }
378 //
379 // Report error, if the variable name is invalid.
380 //
381 if ((Storage->Name == NULL) || (FceStrLen(Storage->Name) == 0)) {
382 printf ("Error. One variable name is NULL. Its GUID is: ");
383 PrintGuid(&(Storage->Guid));
384 return EFI_INVALID_PARAMETER;
385 }
386 VariableHeader = FindVariableInNv (
387 VariableStoreHeader,
388 Storage
389 );
390
391 if (VarToList) {
392 //
393 //Copy the data from NV to the VarList.
394 //
395 if (VariableHeader != NULL) {
396 if (Storage->Buffer == NULL) {
397 Storage->Buffer = calloc (Storage->Size, sizeof (CHAR8));
398 ASSERT (Storage->Buffer != NULL);
399 }
400 DataBase = (CHAR8*)GetVariableDataPtr (VariableHeader);
401 memcpy (
402 Storage->Buffer,
403 (VOID *) DataBase,
404 Storage->Size
405 );
406 }
407 } else {
408 //
409 //If existed, copy the List data to the variable in NV directly. If not found, create a new one.
410 //
411 VarNameSize = 2 * (FceStrLen (Storage->Name) + 1);
412 //
413 //If this variable has existed in current FD, the data in VarList has
414 // been updated, and this variable is not authenticated type, then
415 // update it from VarList to the FD.
416 //
417 if ((VariableHeader != NULL) \
418 && (Storage->Buffer != NULL)
419 ) {
420 DataBase = (CHAR8*)GetVariableDataPtr (VariableHeader);
421 memcpy (
422 (VOID *) DataBase,
423 Storage->Buffer,
424 Storage->Size
425 );
426 } else if ((VariableHeader == NULL) && (Storage->Buffer != NULL)){
427 //
428 //If EfiVarstore is not EFI_VARIABLE_NON_VOLATILE, only skip it.
429 //
430 if (Storage->NewEfiVarstore
431 && ((Storage->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0)
432 ) {
433 StorageLink = GetNextNode (StorageListHead, StorageLink);
434 continue;
435 }
436 //
437 // Try to get the available zone from the efi variables
438 //
439 Status = GetVariableVar (
440 VariableStoreHeader,
441 Storage->Size + sizeof (VARIABLE_HEADER),
442 &NewAvailableAddr
443 );
444
445 if (!EFI_ERROR (Status)) {
446 //
447 // Create the variable header
448 //
449 VariableHeader = (VARIABLE_HEADER *) NewAvailableAddr;
450 VariableHeader->StartId = VARIABLE_DATA;
451 VariableHeader->State = VAR_ADDED;
452 VariableHeader->Reserved = 0x0;
453 if (Storage->NewEfiVarstore) {
454 VariableHeader->Attributes = Storage->Attributes;
455 } else {
456 VariableHeader->Attributes = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
457 }
458 VariableHeader->NameSize = VarNameSize;
459 VariableHeader->DataSize = Storage->Size;
460 //
461 //Copy the Guid, variable name, and data in sequence.
462 //
463 memcpy (
464 (VOID *)&(VariableHeader->VendorGuid),
465 &(Storage->Guid),
466 sizeof (EFI_GUID)
467 );
468 NewAvailableAddr = NewAvailableAddr + sizeof (VARIABLE_HEADER);
469 memcpy (
470 (VOID *) NewAvailableAddr,
471 Storage->Name,
472 VarNameSize
473 );
474
475 NewAvailableAddr = NewAvailableAddr + VarNameSize + GET_PAD_SIZE (VarNameSize);
476 memcpy (
477 (VOID *) NewAvailableAddr,
478 Storage->Buffer,
479 Storage->Size * sizeof (CHAR8)
480 );
481 } else {
482 printf ("Error. No available space in NV ram.\n");
483 return EFI_OUT_OF_RESOURCES;
484 }
485 }
486 }
487 StorageLink = GetNextNode (StorageListHead, StorageLink);
488 }
489 return Status;
490 }
491
492 /**
493 Remove the variable from Efi variable
494
495 Found the variable with the same name in StorageListHead and remove it.
496
497 @param StorageListHead Decide which variale list be removed.
498
499 @retval EFI_SUCCESS Remove the variables successfully.
500 **/
501 EFI_STATUS
502 RemoveNormalEfiVariable (
503 IN LIST_ENTRY *StorageListHead
504 )
505 {
506 EFI_FIRMWARE_VOLUME_HEADER *VarAddr;
507 LIST_ENTRY *StorageLink;
508 FORMSET_STORAGE *Storage;
509 VARIABLE_HEADER *VariableHeader;
510 VARIABLE_STORE_HEADER *VariableStoreHeader;
511
512 VariableHeader = NULL;
513 VarAddr = (EFI_FIRMWARE_VOLUME_HEADER *) gEfiFdInfo.EfiVariableAddr;
514 VariableStoreHeader = (VARIABLE_STORE_HEADER *)((CHAR8 *)VarAddr + VarAddr->HeaderLength);
515 //
516 //Parse the variable range, and check whether there is some existed ones.
517 //
518 StorageLink = GetFirstNode (StorageListHead);
519 while (!IsNull (StorageListHead, StorageLink)) {
520 Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
521 //
522 // Ignore the invalid varlist node
523 //
524 if (Storage->Buffer == NULL) {
525 StorageLink = GetNextNode (StorageListHead, StorageLink);
526 continue;
527 }
528 //
529 // Report error, if the variable name is invalid.
530 //
531 if ((Storage->Name == NULL) || (FceStrLen(Storage->Name) == 0)) {
532 printf ("Error. One variable name is NULL. Its GUID is: ");
533 PrintGuid(&(Storage->Guid));
534 return EFI_INVALID_PARAMETER;
535 }
536 VariableHeader = FindVariableInNv (
537 VariableStoreHeader,
538 Storage
539 );
540 if (VariableHeader != NULL) {
541 VariableHeader->State = VAR_DELETED;
542 }
543 StorageLink = GetNextNode (StorageListHead, StorageLink);
544 }
545 return EFI_SUCCESS;
546 }
547
548 /**
549 Check the store variable is no-authenticated or not
550
551 @param VarToList The pointer to the header of Variable Store.
552
553 @retval TRUE If no-authenticated, return TRUE.
554 @retval FALSE Otherwise, return FALSE.
555 **/
556
557 BOOLEAN
558 CheckNormalVarStoreOrNot (
559 IN VOID *VariableStoreHeader
560 )
561 {
562 if (!CompareGuid (
563 &gEfiVariableGuid,
564 &((VARIABLE_STORE_HEADER *)VariableStoreHeader)->Signature)
565 ) {
566 return TRUE;
567 } else {
568 return FALSE;
569 }
570 }
571
572 /**
573 Copy variable to binary in multi-platform mode
574
575 @param Storage The pointer to a storage in storage list.
576 @param StorageBeginning The pointer to the beginning of storage under specifed platformId and defaultId
577 @param Index The number of the storage. If the Index is 0, record the variable header to
578 the binary. Or else, only record the storage.
579
580 @return length The length of storage
581 **/
582 UINT32
583 CopyVariableToBinary (
584 IN FORMSET_STORAGE *Storage,
585 IN OUT UINT8 *StorageBeginning,
586 IN UINT32 Index
587 )
588 {
589 EFI_STATUS Status;
590 CHAR8 *NewAvailableAddr;
591 VARIABLE_HEADER *VariableHeader;
592 VARIABLE_STORE_HEADER *VariableStoreHeader;
593 UINTN VarNameSize;
594 UINT32 HeaderLength;
595
596 Status = EFI_SUCCESS;
597 NewAvailableAddr = NULL;
598 VarNameSize = 0;
599 HeaderLength = 0;
600 VariableHeader = NULL;
601 VariableStoreHeader = NULL;
602
603 if ((Storage->Name == NULL) || (FceStrLen(Storage->Name) == 0)) {
604 printf ("Error. One variable name is NULL. Its GUID is: ");
605 PrintGuid(&(Storage->Guid));
606 return 0;
607 }
608 //
609 // If the first storage under one specified platformId and defaultId, create the variable header
610 //
611 if (Index == 0) {
612 HeaderLength = WriteDefaultAndPlatformId (StorageBeginning, Storage);
613 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (StorageBeginning + HeaderLength);
614 //
615 //Create the Variable Storage header
616 //
617 memcpy (&(VariableStoreHeader->Signature), &gEfiVariableGuid, sizeof (EFI_GUID));
618 VariableStoreHeader->Format = 0x5A;
619 VariableStoreHeader->State = 0xFE;
620 //
621 //Assign a big size here. It will be fixed after the storage under a specifed platformId and defaultId are all written.
622 //
623 VariableStoreHeader->Size = gEfiFdInfo.FdSize;
624 }
625
626 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (StorageBeginning + *(UINT16 *)StorageBeginning);
627
628 Status = GetVariableVar (
629 VariableStoreHeader,
630 Storage->Size + sizeof (VARIABLE_HEADER),
631 &NewAvailableAddr
632 );
633 if (EFI_ERROR (Status)) {
634 return FAIL;
635 }
636 //
637 // Create the variable header
638 //
639 VarNameSize = 2 * (FceStrLen (Storage->Name) + 1);
640 VariableHeader = (VARIABLE_HEADER *) NewAvailableAddr;
641 VariableHeader->StartId = VARIABLE_DATA;
642 VariableHeader->State = VAR_ADDED;
643 VariableHeader->Reserved = 0x0;
644 if (Storage->NewEfiVarstore) {
645 VariableHeader->Attributes = Storage->Attributes;
646 } else {
647 VariableHeader->Attributes = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
648 }
649 VariableHeader->NameSize = VarNameSize;
650 VariableHeader->DataSize = Storage->Size;
651 //
652 //Copy the Guid, variable name, and data in sequence.
653 //
654 memcpy (
655 (VOID *)&(VariableHeader->VendorGuid),
656 &(Storage->Guid),
657 sizeof (EFI_GUID)
658 );
659 NewAvailableAddr = NewAvailableAddr + sizeof (VARIABLE_HEADER);
660 memcpy (
661 (VOID *) NewAvailableAddr,
662 Storage->Name,
663 VarNameSize
664 );
665
666 NewAvailableAddr = NewAvailableAddr + VarNameSize + GET_PAD_SIZE (VarNameSize);
667 memcpy (
668 (VOID *) NewAvailableAddr,
669 Storage->Buffer,
670 Storage->Size * sizeof (CHAR8)
671 );
672 //
673 // Return the length which is from the beginning of Binary
674 //
675 return ((UINT32) ((UINT8*)NewAvailableAddr - StorageBeginning) + Storage->Size);
676 }
677 /**
678 Copy variable to binary in multi-platform mode
679
680 @param Storage The pointer to a storage in storage list.
681 @param StorageBeginning The pointer to the beginning of storage under specifed platformId and defaultId
682 @param Index The number of the storage. If the Index is 0, record the variable header to
683 the binary. Or else, only record the storage.
684
685 @return length The length of storage
686 **/
687 UINT32
688 CopyVariableToNvStoreBinary (
689 IN FORMSET_STORAGE *Storage,
690 IN OUT UINT8 *StorageBeginning,
691 IN UINT32 Index
692 )
693 {
694 EFI_STATUS Status;
695 CHAR8 *NewAvailableAddr;
696 VARIABLE_HEADER *VariableHeader;
697 VARIABLE_STORE_HEADER *VariableStoreHeader;
698 UINTN VarNameSize;
699 UINT32 HeaderLength;
700 PCD_DEFAULT_DATA *PcdDefaultDataHeader;
701
702 Status = EFI_SUCCESS;
703 NewAvailableAddr = NULL;
704 VarNameSize = 0;
705 HeaderLength = 0;
706 VariableHeader = NULL;
707 VariableStoreHeader = NULL;
708
709 if ((Storage->Name == NULL) || (FceStrLen(Storage->Name) == 0)) {
710 printf ("Error. One variable name is NULL. Its GUID is: ");
711 PrintGuid(&(Storage->Guid));
712 return 0;
713 }
714 //
715 // If the first storage under one specified platformId and defaultId, create the variable header
716 //
717 if (Index == 0) {
718 HeaderLength = WriteNvStoreDefaultAndPlatformId (StorageBeginning, Storage);
719 PcdDefaultDataHeader = (PCD_DEFAULT_DATA *)StorageBeginning;
720 PcdDefaultDataHeader->HeaderSize = HeaderLength;
721 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (StorageBeginning + HeaderLength + 4);
722 //
723 //Create the Variable Storage header
724 //
725 memcpy (&(VariableStoreHeader->Signature), &gEfiVariableGuid, sizeof (EFI_GUID));
726 VariableStoreHeader->Format = 0x5A;
727 VariableStoreHeader->State = 0xFE;
728 //
729 //Assign a big size here. It will be fixed after the storage under a specifed platformId and defaultId are all written.
730 //
731 VariableStoreHeader->Size = gEfiFdInfo.FdSize;
732 }
733 PcdDefaultDataHeader = (PCD_DEFAULT_DATA *)StorageBeginning;
734 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (StorageBeginning + PcdDefaultDataHeader->HeaderSize + 4);
735 Status = GetVariableVar (
736 VariableStoreHeader,
737 Storage->Size + sizeof (VARIABLE_HEADER),
738 &NewAvailableAddr
739 );
740 if (EFI_ERROR (Status)) {
741 return FAIL;
742 }
743 //
744 // Create the variable header
745 //
746 VarNameSize = 2 * (FceStrLen (Storage->Name) + 1);
747 VariableHeader = (VARIABLE_HEADER *) NewAvailableAddr;
748 VariableHeader->StartId = VARIABLE_DATA;
749 VariableHeader->State = VAR_ADDED;
750 VariableHeader->Reserved = 0x0;
751 if (Storage->NewEfiVarstore) {
752 VariableHeader->Attributes = Storage->Attributes;
753 } else {
754 VariableHeader->Attributes = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
755 }
756 VariableHeader->NameSize = VarNameSize;
757 VariableHeader->DataSize = Storage->Size;
758 //
759 //Copy the Guid, variable name, and data in sequence.
760 //
761 memcpy (
762 (VOID *)&(VariableHeader->VendorGuid),
763 &(Storage->Guid),
764 sizeof (EFI_GUID)
765 );
766
767 NewAvailableAddr = NewAvailableAddr + sizeof (VARIABLE_HEADER);
768 memcpy (
769 (VOID *) NewAvailableAddr,
770 Storage->Name,
771 VarNameSize
772 );
773
774 NewAvailableAddr = NewAvailableAddr + VarNameSize + GET_PAD_SIZE (VarNameSize);
775 memcpy (
776 (VOID *) NewAvailableAddr,
777 Storage->Buffer,
778 Storage->Size * sizeof (CHAR8)
779 );
780 //
781 // Return the length which is from the beginning of Binary
782 //
783 return ((UINT32) ((UINT8*)NewAvailableAddr - StorageBeginning - PcdDefaultDataHeader->HeaderSize - 4) + Storage->Size);
784 }
785 /**
786 Read variable to storage list in multi-platform mode
787
788 @param Binary The pointer to the header of storage under specifed platformId and defaultId
789 @param StorageListEntry The pointer to the storage list.
790
791 @return length The length of storage
792 **/
793 UINT32
794 ReadNvStoreVariableToList (
795 IN UINT8 *Binary,
796 IN LIST_ENTRY *StorageListEntry
797 )
798 {
799 VARIABLE_HEADER *EndOfVariable;
800 VARIABLE_HEADER *Variable;
801 VARIABLE_STORE_HEADER *VariableStoreHeader;
802 FORMSET_STORAGE *Storage;
803 UINT32 Length;
804 PCD_DEFAULT_DATA *PcdDefaultData;
805 UINT8 *DataBase;
806 static UINT16 PreDefaultId;
807 static UINT64 PrePlatformId;
808
809 VariableStoreHeader = NULL;
810 Variable = NULL;
811 Length = 0;
812 DataBase = Binary;
813
814 PcdDefaultData = (PCD_DEFAULT_DATA *)DataBase;
815 PrePlatformId = PcdDefaultData->DefaultInfo[0].SkuId;
816 PreDefaultId = PcdDefaultData->DefaultInfo[0].DefaultId;
817 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (DataBase + PcdDefaultData->HeaderSize + 4);
818 EndOfVariable = GetEndPointer(VariableStoreHeader);
819
820 for (Variable = GetStartPointer (VariableStoreHeader);
821 Length < VariableStoreHeader->Size;
822 Length += sizeof (VARIABLE_HEADER) + Variable->NameSize + Variable->DataSize
823 ) {
824 //
825 // Create the storage
826 //
827 Storage = NULL;
828 Storage = calloc (sizeof (FORMSET_STORAGE), sizeof (CHAR8));
829 if (Storage == NULL) {
830 printf ("Allocate memory failed.\n");
831 return FAIL;
832 }
833 //
834 // Store the DefaultId and PlatformId collected from the header to Storage.
835 //
836 Storage->DefaultId[0] = PreDefaultId;
837 Storage->PlatformId[0] = PrePlatformId;
838 Storage->DefaultPlatformIdNum = 0;
839
840 Storage->Attributes = Variable->Attributes;
841 Storage->Size = (UINT16)Variable->DataSize;
842 Storage->Name = calloc (Variable->NameSize, sizeof (UINT8));
843 ASSERT (Storage->Name != NULL);
844 Storage->Buffer = calloc (Variable->DataSize, sizeof (UINT8));
845 ASSERT (Storage->Buffer != NULL);
846 memcpy (
847 &(Storage->Guid),
848 &(Variable->VendorGuid),
849 sizeof (EFI_GUID)
850 );
851 memcpy (
852 Storage->Name,
853 (UINT8 *)Variable + sizeof (VARIABLE_HEADER),
854 Variable->NameSize
855 );
856 memcpy (
857 Storage->Buffer,
858 (UINT8 *)Variable + sizeof (VARIABLE_HEADER) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize),
859 Storage->Size * sizeof (CHAR8)
860 );
861 //
862 // Assigned the value for comparison in verify mode
863 //
864 Storage->Type = EFI_IFR_VARSTORE_EFI_OP;
865 Storage->NewEfiVarstore = TRUE;
866 InitializeListHead (&Storage->NameValueListHead);
867
868 InsertTailList(StorageListEntry, &Storage->Link);
869 //
870 // If the last variable, exit.
871 //
872 if (Variable == EndOfVariable) {
873 break;
874 }
875
876 Variable = GetNextVariablePtr (Variable);
877 assert (Variable != NULL);
878 if (!IsValidVariableHeader(Variable)) {
879 break;
880 }
881 }
882
883 return Length;
884 }
885 /**
886 Read variable to storage list in multi-platform mode
887
888 @param Binary The pointer to the header of storage under specifed platformId and defaultId
889 @param StorageListEntry The pointer to the storage list.
890
891 @return length The length of storage
892 **/
893 UINT32
894 ReadVariableToList (
895 IN UINT8 *Binary,
896 IN LIST_ENTRY *StorageListEntry
897 )
898 {
899 VARIABLE_HEADER *EndOfVariable;
900 VARIABLE_HEADER *Variable;
901 VARIABLE_STORE_HEADER *VariableStoreHeader;
902 FORMSET_STORAGE *Storage;
903 BOOLEAN ReadIdHeaderFlag;
904 UINT32 Length;
905 EFI_COMMON_SECTION_HEADER *SectionHeader;
906 UINT8 *DataBase;
907 static UINT16 PreDefaultId[MAX_PLATFORM_DEFAULT_ID_NUM];
908 static UINT64 PrePlatformId[MAX_PLATFORM_DEFAULT_ID_NUM];
909
910 VariableStoreHeader = NULL;
911 Variable = NULL;
912 ReadIdHeaderFlag = TRUE;
913 Length = 0;
914 SectionHeader = (EFI_COMMON_SECTION_HEADER *)Binary;
915 DataBase = Binary + sizeof (EFI_COMMON_SECTION_HEADER);
916 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (DataBase + *(UINT16 *)DataBase);
917 EndOfVariable = GetEndPointer(VariableStoreHeader);
918
919 for (Variable = GetStartPointer (VariableStoreHeader);
920 Length < VariableStoreHeader->Size;
921 Length += sizeof (VARIABLE_HEADER) + Variable->NameSize + Variable->DataSize
922 ) {
923 //
924 // Create the storage
925 //
926 Storage = NULL;
927 Storage = calloc (sizeof (FORMSET_STORAGE), sizeof (CHAR8));
928 if (Storage == NULL) {
929 printf ("Allocate memory failed.\n");
930 return FAIL;
931 }
932 //
933 // If access the first storage, read the platformId and defaultId
934 //
935 if (ReadIdHeaderFlag) {
936 ReadDefaultAndPlatformIdFromBfv (DataBase, Storage);
937 Length += sizeof (VARIABLE_HEADER) + Variable->NameSize + Variable->DataSize;
938 ReadIdHeaderFlag = FALSE;
939 memcpy (PreDefaultId, Storage->DefaultId, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT16));
940 memcpy (PrePlatformId, Storage->PlatformId, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT64));
941 } else {
942 //
943 // Store the DefaultId and PlatformId collected from the header to Storage.
944 //
945 memcpy (Storage->DefaultId, PreDefaultId, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT16));
946 memcpy (Storage->PlatformId, PrePlatformId, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT64));
947 }
948 Storage->Attributes = Variable->Attributes;
949 Storage->Size = (UINT16)Variable->DataSize;
950 Storage->Name = calloc (Variable->NameSize, sizeof (UINT8));
951 ASSERT (Storage->Name != NULL);
952 Storage->Buffer = calloc (Variable->DataSize, sizeof (UINT8));
953 ASSERT (Storage->Buffer != NULL);
954 memcpy (
955 &(Storage->Guid),
956 &(Variable->VendorGuid),
957 sizeof (EFI_GUID)
958 );
959 memcpy (
960 Storage->Name,
961 (UINT8 *)Variable + sizeof (VARIABLE_HEADER),
962 Variable->NameSize
963 );
964 memcpy (
965 Storage->Buffer,
966 (UINT8 *)Variable + sizeof (VARIABLE_HEADER) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize),
967 Storage->Size * sizeof (CHAR8)
968 );
969 //
970 // Assigned the value for comparison in verify mode
971 //
972 Storage->Type = EFI_IFR_VARSTORE_EFI_OP;
973 Storage->NewEfiVarstore = TRUE;
974 InitializeListHead (&Storage->NameValueListHead);
975
976 InsertTailList(StorageListEntry, &Storage->Link);
977 //
978 // If the last variable, exit.
979 //
980 if (Variable == EndOfVariable) {
981 break;
982 }
983
984 Variable = GetNextVariablePtr (Variable);
985 assert (Variable != NULL);
986 }
987 //
988 // Return the length which is from the beginning of Binary
989 //
990 Length = FvBufExpand3ByteSize (SectionHeader->Size);
991
992 return Length;
993 }
994
995 /**
996 Check whether exists the valid normal variables in NvStorage or not.
997
998 @retval TRUE If existed, return TRUE.
999 @retval FALSE Others
1000 **/
1001 BOOLEAN
1002 ExistNormalEfiVarOrNot (
1003 IN LIST_ENTRY *StorageListHead
1004 )
1005 {
1006 EFI_FIRMWARE_VOLUME_HEADER *VarAddr;
1007 LIST_ENTRY *StorageLink;
1008 FORMSET_STORAGE *Storage;
1009 VARIABLE_HEADER *VariableHeader;
1010 VARIABLE_STORE_HEADER *VariableStoreHeader;
1011
1012 VariableHeader = NULL;
1013 VarAddr = (EFI_FIRMWARE_VOLUME_HEADER *) gEfiFdInfo.EfiVariableAddr;
1014 VariableStoreHeader = (VARIABLE_STORE_HEADER *)((CHAR8 *)VarAddr + VarAddr->HeaderLength);
1015 //
1016 //Parse the variable range, and check whether there is some existed ones.
1017 //
1018 StorageLink = GetFirstNode (StorageListHead);
1019 while (!IsNull (StorageListHead, StorageLink)) {
1020 Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
1021 //
1022 // Ignore the invalid varlist node
1023 //
1024 if ((Storage->Buffer == NULL)
1025 || (Storage->Name == NULL)
1026 || (FceStrLen(Storage->Name) == 0)
1027 ) {
1028 StorageLink = GetNextNode (StorageListHead, StorageLink);
1029 continue;
1030 }
1031 //
1032 // Report error, if the variable name is invalid.
1033 //
1034 if ((Storage->Name == NULL) || (FceStrLen(Storage->Name) == 0)) {
1035 StorageLink = GetNextNode (StorageListHead, StorageLink);
1036 continue;
1037 }
1038 VariableHeader = FindVariableInNv (
1039 VariableStoreHeader,
1040 Storage
1041 );
1042
1043 if ((VariableHeader != NULL)) {
1044 return TRUE;
1045 }
1046 StorageLink = GetNextNode (StorageListHead, StorageLink);
1047 }
1048 return FALSE;
1049 }
1050
1051 /**
1052 Fix the size of variable header.
1053
1054 @param Binary The pointer to the header of storage under specifed platformId and defaultId
1055 @param Length The length of binary.
1056
1057 **/
1058 VOID
1059 FixVariableHeaderSize (
1060 IN UINT8 *BinaryBeginning,
1061 IN UINT32 Length
1062 )
1063 {
1064 VARIABLE_STORE_HEADER *VariableStoreHeader;
1065
1066 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (BinaryBeginning + *(UINT16 *)BinaryBeginning);
1067 VariableStoreHeader->Size = Length - *(UINT16 *)BinaryBeginning;
1068 }
1069
1070 /**
1071 Fix the size of variable header.
1072
1073 @param Binary The pointer to the header of storage under specifed platformId and defaultId
1074 @param Length The length of binary.
1075
1076 **/
1077 VOID
1078 FixNvStoreVariableHeaderSize (
1079 IN UINT8 *BinaryBeginning,
1080 IN UINT32 Length
1081 )
1082 {
1083 VARIABLE_STORE_HEADER *VariableStoreHeader;
1084 PCD_DEFAULT_DATA *PcdDefaultDataHeader;
1085
1086 PcdDefaultDataHeader = (PCD_DEFAULT_DATA *)(BinaryBeginning);
1087 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (BinaryBeginning + PcdDefaultDataHeader->HeaderSize + 4);
1088 VariableStoreHeader->Size = Length;
1089 PcdDefaultDataHeader->DataSize = VariableStoreHeader->Size + PcdDefaultDataHeader->HeaderSize + 4;
1090 }
1091