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