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