]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/FCE/TimeBasedVariable.c
BaseTools/FCE: Add a tool FCE
[mirror_edk2.git] / BaseTools / Source / C / FCE / TimeBasedVariable.c
1 /** @file
2
3 Read and edit the time-base authenticated variables.
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 "TimeBasedVariable.h"
12
13 extern LIST_ENTRY mAllVarListEntry;
14 extern MULTI_PLATFORM_PARAMETERS mMultiPlatformParam;
15 extern G_EFI_FD_INFO gEfiFdInfo;
16
17 EFI_GUID gEfiAuthenticatedVariableBasedTimeGuid = EFI_AUTHENTICATED_VARIABLE_BASED_TIME_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 return (CHAR16 *) (Variable + 1);
153 }
154
155 /**
156
157 This code gets the pointer to the variable data.
158
159 @param Variable Pointer to the Variable Header.
160
161 @return Pointer to Variable Data.
162
163 **/
164 static
165 UINT8 *
166 GetVariableDataPtr (
167 IN VARIABLE_HEADER *Variable
168 )
169 {
170 UINTN Value;
171
172 //
173 // Be careful about pad size for alignment.
174 //
175 Value = (UINTN) GetVariableNamePtr (Variable);
176 Value += NameSizeOfVariable (Variable);
177 Value += GET_PAD_SIZE (NameSizeOfVariable (Variable));
178
179 return (UINT8 *) Value;
180 }
181
182 /**
183
184 This code gets the pointer to the next variable header.
185
186 @param Variable Pointer to the Variable Header.
187
188 @return Pointer to next variable header.
189
190 **/
191 static
192 VARIABLE_HEADER *
193 GetNextVariablePtr (
194 IN VARIABLE_HEADER *Variable
195 )
196 {
197 UINTN Value;
198
199 if (!IsValidVariableHeader (Variable)) {
200 return NULL;
201 }
202
203 Value = (UINTN) GetVariableDataPtr (Variable);
204 Value += DataSizeOfVariable (Variable);
205 Value += GET_PAD_SIZE (DataSizeOfVariable (Variable));
206
207 //
208 // Be careful about pad size for alignment.
209 //
210 return (VARIABLE_HEADER *) HEADER_ALIGN (Value);
211 }
212
213 /**
214 Search and get a free space in the EFI variable zone
215
216 @param VariableStoreHeader The start of a EFI variable zone.
217 @param VarListSize The size of a variables needs to be allocated.
218 @param FreeBeginVar The dual pointer to the free NV space.
219
220 @retval EFI_SUCCESS Return the beginning of a free variable space.
221 @retval RETURN_BUFFER_TOO_SMALL Failed.
222 **/
223 static
224 EFI_STATUS
225 GetVariableVar (
226 IN VARIABLE_STORE_HEADER *VariableStoreHeader,
227 IN UINT32 VarListSize,
228 IN OUT CHAR8 **FreeBeginVar
229 )
230 {
231 BOOLEAN Flag;
232 VARIABLE_HEADER *Variable;
233 VARIABLE_HEADER *EndOfVariable;
234 CHAR8 *BeginVar;
235
236 BeginVar = NULL;
237 Flag = FALSE;
238 Variable = NULL;
239 EndOfVariable = NULL;
240 *FreeBeginVar = NULL;
241
242 if (VariableStoreHeader == NULL) {
243 *FreeBeginVar = NULL;
244 return RETURN_INVALID_PARAMETER;
245 }
246 Variable = GetStartPointer (VariableStoreHeader);
247 EndOfVariable = GetEndPointer(VariableStoreHeader);
248 //
249 //Search the beginning of free NV
250 //
251 while (Variable != EndOfVariable) {
252 BeginVar = (CHAR8 *)Variable;
253 Variable = GetNextVariablePtr (Variable);
254 if (Variable == NULL) {
255 Flag = TRUE;
256 break;
257 }
258 }
259 //
260 // Check whether the free space is more than what we want
261 //
262 if ((CHAR8 *)BeginVar + VarListSize > (CHAR8 *)EndOfVariable) {
263 return RETURN_BUFFER_TOO_SMALL;
264 }
265 //
266 // If not find the available space, return NULL
267 //
268 if (!Flag) {
269 return RETURN_BUFFER_TOO_SMALL;
270 }
271 *FreeBeginVar = BeginVar;
272
273 return EFI_SUCCESS;
274 }
275
276 /**
277 Search whether the variable in VarList has existed in current NV.
278
279 Parse the FFS or Fd image, and find the valid variable pointer.
280
281 @param VariableStoreHeader The start of a EFI variable zone.
282 @param VarList The pointer to the VarList
283
284 @retval address If the variable existed in current NV, return address
285 @return NULL Otherwise, return NULL
286 **/
287 static
288 VARIABLE_HEADER *
289 FindVariableInNv (
290 IN VARIABLE_STORE_HEADER *VariableStoreHeader,
291 IN FORMSET_STORAGE *Storage
292 )
293 {
294 BOOLEAN Flag;
295 VARIABLE_HEADER *Variable;
296 VARIABLE_HEADER *EndOfVariable;
297 CHAR16 *VariableName;
298
299 Flag = FALSE;
300 Variable = NULL;
301 EndOfVariable = NULL;
302 VariableName = NULL;
303
304 if ((VariableStoreHeader == NULL) || (Storage == NULL) || (Storage->Name == NULL)) {
305 return NULL;
306 }
307 Variable = GetStartPointer (VariableStoreHeader);
308 EndOfVariable = GetEndPointer(VariableStoreHeader);
309 //
310 // Parse and compare the variable in the NV space one by one
311 //
312 while ((Variable != EndOfVariable) && (Variable != NULL)) {
313 VariableName = (CHAR16 *)((CHAR8 *)Variable + sizeof (VARIABLE_HEADER));
314 if (!CompareGuid (&Variable->VendorGuid, &Storage->Guid) \
315 && !FceStrCmp (Storage->Name, VariableName) \
316 && (Variable->State == VAR_ADDED)
317 ) {
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 time stamp 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 @retval EFI_INVALID_PARAMETER Invalid variable name.
341 **/
342
343 EFI_STATUS
344 SynAuthEfiVariableBasedTime (
345 IN BOOLEAN VarToList,
346 IN LIST_ENTRY *StorageListHead
347 )
348 {
349 EFI_FIRMWARE_VOLUME_HEADER *VarAddr;
350 LIST_ENTRY *StorageLink;
351 FORMSET_STORAGE *Storage;
352 EFI_STATUS Status;
353 CHAR8 *NewAvailableAddr;
354 CHAR8 *DataBase;
355 VARIABLE_HEADER *VariableHeader;
356 VARIABLE_STORE_HEADER *VariableStoreHeader;
357 UINTN VarNameSize;
358
359 Status = EFI_SUCCESS;
360 DataBase = NULL;
361 NewAvailableAddr = NULL;
362 VarNameSize = 0;
363 VariableHeader = NULL;
364 VarAddr = (EFI_FIRMWARE_VOLUME_HEADER *) gEfiFdInfo.EfiVariableAddr;
365 VariableStoreHeader = (VARIABLE_STORE_HEADER *)((CHAR8 *)VarAddr + VarAddr->HeaderLength);
366 //
367 //Parse the variable range, and check whether there is some existed ones.
368 //
369 StorageLink = GetFirstNode (StorageListHead);
370 while (!IsNull (StorageListHead, StorageLink)) {
371 Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
372 //
373 // Ignore the invalid varlist node
374 //
375 if (Storage->Buffer == NULL) {
376 StorageLink = GetNextNode (StorageListHead, StorageLink);
377 continue;
378 }
379 //
380 // Report error, if the variable name is invalid.
381 //
382 if ((Storage->Name == NULL) || (FceStrLen(Storage->Name) == 0)) {
383 printf ("Error. One variable name is NULL. Its GUID is: ");
384 PrintGuid(&(Storage->Guid));
385 return EFI_INVALID_PARAMETER;
386 }
387 VariableHeader = FindVariableInNv (
388 VariableStoreHeader,
389 Storage
390 );
391
392 if (VarToList) {
393 //
394 //Copy the data from NV to the VarList.
395 //
396 if (VariableHeader != NULL) {
397 if (Storage->Buffer == NULL) {
398 Storage->Buffer = calloc (Storage->Size, sizeof (CHAR8));
399 ASSERT (Storage->Buffer != NULL);
400 }
401 //
402 // The variable in VarList is CHAR8, but in the EFI variable is CHAR16.
403 //
404 DataBase = (CHAR8 *)GetVariableDataPtr (VariableHeader);
405 memcpy (
406 Storage->Buffer,
407 (VOID *) DataBase,
408 Storage->Size
409 );
410 }
411 } else {
412 //
413 //If existed, copy the List data to the variable in NV directly. If not found, create a new one.
414 //
415 VarNameSize = 2 * (FceStrLen (Storage->Name) + 1);
416 //
417 //If this variable has existed in current FD, the data in VarList has
418 // been updated, and this variable is not authenticated type, then
419 // update it from VarList to the FD.
420 //
421 if ((VariableHeader != NULL) \
422 && (Storage->Buffer != NULL)
423 ) {
424 if (!(VariableHeader->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)) {
425 DataBase = (CHAR8 *)GetVariableDataPtr (VariableHeader);
426 memcpy (
427 (VOID *) DataBase,
428 Storage->Buffer,
429 Storage->Size
430 );
431 } else {
432 printf ("Error. Not support to update authenticated variables.\n");
433 return EFI_INVALID_PARAMETER;
434 }
435 } else if ((VariableHeader == NULL) && (Storage->Buffer != NULL)){
436 //
437 //If EfiVarstore is not EFI_VARIABLE_NON_VOLATILE, only skip it.
438 //
439 if (Storage->NewEfiVarstore
440 && ((Storage->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0)
441 ) {
442 StorageLink = GetNextNode (StorageListHead, StorageLink);
443 continue;
444 }
445 //
446 // Try to get the available zone from the efi variables
447 //
448 Status = GetVariableVar (
449 VariableStoreHeader,
450 Storage->Size + sizeof (VARIABLE_HEADER),
451 &NewAvailableAddr
452 );
453
454 if (!EFI_ERROR (Status)) {
455 //
456 // Create the authenticated variable header
457 //
458 VariableHeader = (VARIABLE_HEADER *) NewAvailableAddr;
459 VariableHeader->StartId = VARIABLE_DATA;
460 VariableHeader->State = VAR_ADDED;
461 VariableHeader->Reserved = 0x0;
462 VariableHeader->MonotonicCount = 0x0;
463 memset (&(VariableHeader->TimeStamp), 0, sizeof (EFI_TIME));
464 VariableHeader->PubKeyIndex = 0x0;
465 if (Storage->NewEfiVarstore) {
466 VariableHeader->Attributes = Storage->Attributes;
467 } else {
468 VariableHeader->Attributes = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
469 }
470 VariableHeader->NameSize = VarNameSize;
471 VariableHeader->DataSize = Storage->Size;
472 //
473 //Copy the Guid, variable name, and data in sequence.
474 //
475 memcpy (
476 (VOID *)&(VariableHeader->VendorGuid),
477 &(Storage->Guid),
478 sizeof (EFI_GUID)
479 );
480 NewAvailableAddr = NewAvailableAddr + sizeof (VARIABLE_HEADER);
481 memcpy (
482 (VOID *) NewAvailableAddr,
483 Storage->Name,
484 VarNameSize
485 );
486
487 NewAvailableAddr = NewAvailableAddr + VarNameSize + GET_PAD_SIZE (VarNameSize);
488 memcpy (
489 (VOID *) NewAvailableAddr,
490 Storage->Buffer,
491 Storage->Size * sizeof (CHAR8)
492 );
493 } else {
494 printf ("Error. No available space in NV ram.\n");
495 return EFI_OUT_OF_RESOURCES;
496 }
497 }
498 }
499 StorageLink = GetNextNode (StorageListHead, StorageLink);
500 }
501 return Status;
502 }
503
504 /**
505 Remove the variable from Efi variable
506
507 Found the variable with the same name in StorageListHead and remove it.
508
509 @param StorageListHead Decide which variale list be removed.
510
511 @retval EFI_SUCCESS Remove the variables successfully.
512 **/
513 EFI_STATUS
514 RemoveAuthEfiVariableBasedTime (
515 IN LIST_ENTRY *StorageListHead
516 )
517 {
518 EFI_FIRMWARE_VOLUME_HEADER *VarAddr;
519 LIST_ENTRY *StorageLink;
520 FORMSET_STORAGE *Storage;
521 VARIABLE_HEADER *VariableHeader;
522 VARIABLE_STORE_HEADER *VariableStoreHeader;
523
524 VariableHeader = NULL;
525 VarAddr = (EFI_FIRMWARE_VOLUME_HEADER *) gEfiFdInfo.EfiVariableAddr;
526 VariableStoreHeader = (VARIABLE_STORE_HEADER *)((CHAR8 *)VarAddr + VarAddr->HeaderLength);
527 //
528 //Parse the variable range, and check whether there is some existed ones.
529 //
530 StorageLink = GetFirstNode (StorageListHead);
531 while (!IsNull (StorageListHead, StorageLink)) {
532 Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
533 //
534 // Ignore the invalid varlist node
535 //
536 if (Storage->Buffer == NULL) {
537 StorageLink = GetNextNode (StorageListHead, StorageLink);
538 continue;
539 }
540 //
541 // Report error, if the variable name is invalid.
542 //
543 if ((Storage->Name == NULL) || (FceStrLen(Storage->Name) == 0)) {
544 printf ("Error. One variable name is NULL. Its GUID is: ");
545 PrintGuid(&(Storage->Guid));
546 return EFI_INVALID_PARAMETER;
547 }
548 VariableHeader = FindVariableInNv (
549 VariableStoreHeader,
550 Storage
551 );
552 if (VariableHeader != NULL) {
553 VariableHeader->State = VAR_DELETED;
554 }
555 StorageLink = GetNextNode (StorageListHead, StorageLink);
556 }
557 return EFI_SUCCESS;
558 }
559
560 /**
561 Check the store variable is Time stamp authenticated or not
562
563 @param VarToList The pointer to the header of Variable Store.
564
565 @retval TRUE If authenticated, return TRUE.
566 @retval FALSE Otherwise, return FALSE.
567 **/
568
569 BOOLEAN
570 CheckTimeBasedVarStoreOrNot (
571 IN VOID *VariableStoreHeader
572 )
573 {
574 if (!CompareGuid (
575 &gEfiAuthenticatedVariableBasedTimeGuid,
576 &((VARIABLE_STORE_HEADER *)VariableStoreHeader)->Signature)
577 ) {
578 return TRUE;
579 } else {
580 return FALSE;
581 }
582 }
583
584 /**
585 Copy time-based authenticated variable to binary in multi-platform mode
586
587 @param Storage The pointer to a storage in storage list.
588 @param StorageBeginning The pointer to the beginning of storage under specifed platformId and defaultId
589 @param Index The number of the storage. If the Index is 0, record the variable header to
590 the binary. Or else, only record the storage.
591
592 @return length The length of storage
593 **/
594 UINT32
595 CopyTimeBasedVariableToBinary (
596 IN FORMSET_STORAGE *Storage,
597 IN OUT UINT8 *StorageBeginning,
598 IN UINT32 Index
599 )
600 {
601 EFI_STATUS Status;
602 CHAR8 *NewAvailableAddr;
603 VARIABLE_HEADER *VariableHeader;
604 VARIABLE_STORE_HEADER *VariableStoreHeader;
605 UINTN VarNameSize;
606 UINT32 HeaderLength;
607
608 Status = EFI_SUCCESS;
609 NewAvailableAddr = NULL;
610 VarNameSize = 0;
611 HeaderLength = 0;
612 VariableHeader = NULL;
613 VariableStoreHeader = NULL;
614
615 if ((Storage->Name == NULL) || (FceStrLen(Storage->Name) == 0)) {
616 printf ("Error. One variable name is NULL. Its GUID is: ");
617 PrintGuid(&(Storage->Guid));
618 return 0;
619 }
620 //
621 // If the first storage under one specified platformId and defaultId, create the variable header
622 //
623 if (Index == 0) {
624 HeaderLength = WriteDefaultAndPlatformId (StorageBeginning, Storage);
625 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (StorageBeginning + HeaderLength);
626 //
627 //Create the Variable Storage header
628 //
629 memcpy (&(VariableStoreHeader->Signature), &gEfiAuthenticatedVariableBasedTimeGuid, sizeof (EFI_GUID));
630 VariableStoreHeader->Format = 0x5A;
631 VariableStoreHeader->State = 0xFE;
632 //
633 //Assign a big size here. It will be fixed after the storage under a specifed platformId and defaultId are all written.
634 //
635 VariableStoreHeader->Size = gEfiFdInfo.FdSize;
636 }
637
638 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (StorageBeginning + *(UINT16 *)StorageBeginning);
639
640 Status = GetVariableVar (
641 VariableStoreHeader,
642 Storage->Size + sizeof (VARIABLE_HEADER),
643 &NewAvailableAddr
644 );
645
646 if (EFI_ERROR (Status)) {
647 return FAIL;
648 }
649 //
650 // Create the variable header
651 //
652 VarNameSize = 2 * (FceStrLen (Storage->Name) + 1);
653 VariableHeader = (VARIABLE_HEADER *) NewAvailableAddr;
654 VariableHeader->StartId = VARIABLE_DATA;
655 VariableHeader->State = VAR_ADDED;
656 VariableHeader->Reserved = 0x0;
657 VariableHeader->MonotonicCount = 0x0;
658 memset (&(VariableHeader->TimeStamp), 0, sizeof (EFI_TIME));
659 VariableHeader->PubKeyIndex = 0x0;
660
661 if (Storage->NewEfiVarstore) {
662 VariableHeader->Attributes = Storage->Attributes;
663 } else {
664 VariableHeader->Attributes = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
665 }
666 VariableHeader->NameSize = VarNameSize;
667 VariableHeader->DataSize = Storage->Size;
668 //
669 //Copy the Guid, variable name, and data in sequence.
670 //
671 memcpy (
672 (VOID *)&(VariableHeader->VendorGuid),
673 &(Storage->Guid),
674 sizeof (EFI_GUID)
675 );
676 NewAvailableAddr = NewAvailableAddr + sizeof (VARIABLE_HEADER);
677 memcpy (
678 (VOID *) NewAvailableAddr,
679 Storage->Name,
680 VarNameSize
681 );
682
683 NewAvailableAddr = NewAvailableAddr + VarNameSize + GET_PAD_SIZE (VarNameSize);
684 memcpy (
685 (VOID *) NewAvailableAddr,
686 Storage->Buffer,
687 Storage->Size * sizeof (CHAR8)
688 );
689 //
690 // Return the length which is from the beginning of Binary
691 //
692 return ((UINT32) ((UINT8*)NewAvailableAddr - StorageBeginning) + Storage->Size);
693 }
694
695 /**
696 Read time-based authenticated variable to storage list in multi-platform mode
697
698 @param Binary The pointer to the header of storage under specifed platformId and defaultId
699 @param StorageListEntry The pointer to the storage list.
700
701 @return length The length of storage
702 **/
703 UINT32
704 ReadTimeBasedVariableToList (
705 IN UINT8 *Binary,
706 IN LIST_ENTRY *StorageListEntry
707 )
708 {
709 VARIABLE_HEADER *EndOfVariable;
710 VARIABLE_HEADER *Variable;
711 VARIABLE_STORE_HEADER *VariableStoreHeader;
712 FORMSET_STORAGE *Storage;
713 BOOLEAN ReadIdHeaderFlag;
714 UINT32 Length;
715 EFI_COMMON_SECTION_HEADER *SectionHeader;
716 UINT8 *DataBase;
717 static UINT16 PreDefaultId[MAX_PLATFORM_DEFAULT_ID_NUM];
718 static UINT64 PrePlatformId[MAX_PLATFORM_DEFAULT_ID_NUM];
719
720 VariableStoreHeader = NULL;
721 Variable = NULL;
722 ReadIdHeaderFlag = TRUE;
723 Length = 0;
724 SectionHeader = (EFI_COMMON_SECTION_HEADER *)Binary;
725 DataBase = Binary + sizeof (EFI_COMMON_SECTION_HEADER);
726 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (DataBase + *(UINT16 *)DataBase);
727 EndOfVariable = GetEndPointer(VariableStoreHeader);
728
729 for (Variable = GetStartPointer (VariableStoreHeader);
730 Length < VariableStoreHeader->Size;
731 Length += sizeof (VARIABLE_HEADER) + Variable->NameSize + Variable->DataSize
732 ) {
733 //
734 // Create the storage
735 //
736 Storage = NULL;
737 Storage = calloc (sizeof (FORMSET_STORAGE), sizeof (CHAR8));
738 if (Storage == NULL) {
739 printf ("Allocate memory failed.\n");
740 return FAIL;
741 }
742 //
743 // If access the first storage, read the platformId and defaultId
744 //
745 if (ReadIdHeaderFlag) {
746 ReadDefaultAndPlatformIdFromBfv (DataBase, Storage);
747 Length += sizeof (VARIABLE_HEADER) + Variable->NameSize + Variable->DataSize;
748 ReadIdHeaderFlag = FALSE;
749 memcpy (PreDefaultId, Storage->DefaultId, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT16));
750 memcpy (PrePlatformId, Storage->PlatformId, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT64));
751 } else {
752 //
753 // Store the DefaultId and PlatformId collected from the header to Storage.
754 //
755 memcpy (Storage->DefaultId, PreDefaultId, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT16));
756 memcpy (Storage->PlatformId, PrePlatformId, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT64));
757 }
758 Storage->Attributes = Variable->Attributes;
759 Storage->Size = (UINT16)Variable->DataSize;
760 Storage->Name = calloc (Variable->NameSize, sizeof (UINT8));
761 ASSERT (Storage->Name != NULL);
762 Storage->Buffer = calloc (Variable->DataSize, sizeof (UINT8));
763 ASSERT (Storage->Buffer != NULL);
764 memcpy (
765 &(Storage->Guid),
766 &(Variable->VendorGuid),
767 sizeof (EFI_GUID)
768 );
769 memcpy (
770 Storage->Name,
771 (UINT8 *)Variable + sizeof (VARIABLE_HEADER),
772 Variable->NameSize
773 );
774 memcpy (
775 Storage->Buffer,
776 (UINT8 *)Variable + sizeof (VARIABLE_HEADER) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize),
777 Storage->Size * sizeof (CHAR8)
778 );
779 //
780 // Assigned the value for comparison in verify mode
781 //
782 Storage->Type = EFI_IFR_VARSTORE_EFI_OP;
783 Storage->NewEfiVarstore = TRUE;
784 InitializeListHead (&Storage->NameValueListHead);
785
786 InsertTailList(StorageListEntry, &Storage->Link);
787 //
788 // If the last variable, exit.
789 //
790 if (Variable == EndOfVariable) {
791 break;
792 }
793
794 Variable = GetNextVariablePtr (Variable);
795 assert (Variable != NULL);
796 }
797 //
798 // Return the length which is from the beginning of Binary
799 //
800 Length = FvBufExpand3ByteSize (SectionHeader->Size);
801
802 return Length;
803 }
804
805 /**
806 Check whether exists the valid time-based variables in NvStorage or not.
807
808 @retval TRUE If existed, return TRUE.
809 @retval FALSE Others
810 **/
811 BOOLEAN
812 ExistTimeBasedEfiVarOrNot (
813 IN LIST_ENTRY *StorageListHead
814 )
815 {
816 EFI_FIRMWARE_VOLUME_HEADER *VarAddr;
817 LIST_ENTRY *StorageLink;
818 FORMSET_STORAGE *Storage;
819 VARIABLE_HEADER *VariableHeader;
820 VARIABLE_STORE_HEADER *VariableStoreHeader;
821
822 VariableHeader = NULL;
823 VarAddr = (EFI_FIRMWARE_VOLUME_HEADER *) gEfiFdInfo.EfiVariableAddr;
824 VariableStoreHeader = (VARIABLE_STORE_HEADER *)((CHAR8 *)VarAddr + VarAddr->HeaderLength);
825 //
826 //Parse the variable range, and check whether there is some existed ones.
827 //
828 StorageLink = GetFirstNode (StorageListHead);
829 while (!IsNull (StorageListHead, StorageLink)) {
830 Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
831 //
832 // Ignore the invalid varlist node
833 //
834 if ((Storage->Buffer == NULL)
835 || (Storage->Name == NULL)
836 || (FceStrLen(Storage->Name) == 0)
837 ) {
838 StorageLink = GetNextNode (StorageListHead, StorageLink);
839 continue;
840 }
841 //
842 // Report error, if the variable name is invalid.
843 //
844 if ((Storage->Name == NULL) || (FceStrLen(Storage->Name) == 0)) {
845 StorageLink = GetNextNode (StorageListHead, StorageLink);
846 continue;
847 }
848 VariableHeader = FindVariableInNv (
849 VariableStoreHeader,
850 Storage
851 );
852
853 if ((VariableHeader != NULL)) {
854 return TRUE;
855 }
856 StorageLink = GetNextNode (StorageListHead, StorageLink);
857 }
858 return FALSE;
859 }
860
861 /**
862 Fix the size of time-based variable header.
863
864 @param Binary The pointer to the header of storage under specifed platformId and defaultId
865 @param Length The length of binary.
866
867 **/
868 VOID
869 FixBasedTimeVariableHeaderSize (
870 IN UINT8 *BinaryBeginning,
871 IN UINT32 Length
872 )
873 {
874 VARIABLE_STORE_HEADER *VariableStoreHeader;
875
876 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (BinaryBeginning + *(UINT16 *)BinaryBeginning);
877 VariableStoreHeader->Size = Length - *(UINT16 *)BinaryBeginning;
878 }