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