]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Variable/Pei/Variable.c
MdeModulePkg: Change use of EFI_D_* to DEBUG_*
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / Pei / Variable.c
1 /** @file
2 Implement ReadOnly Variable Services required by PEIM and install
3 PEI ReadOnly Varaiable2 PPI. These services operates the non volatile storage space.
4
5 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
6 Copyright (c) Microsoft Corporation.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11
12 #include "Variable.h"
13
14 //
15 // Module globals
16 //
17 EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariablePpi = {
18 PeiGetVariable,
19 PeiGetNextVariableName
20 };
21
22 EFI_PEI_PPI_DESCRIPTOR mPpiListVariable = {
23 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
24 &gEfiPeiReadOnlyVariable2PpiGuid,
25 &mVariablePpi
26 };
27
28
29 /**
30 Provide the functionality of the variable services.
31
32 @param FileHandle Handle of the file being invoked.
33 Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile().
34 @param PeiServices General purpose services available to every PEIM.
35
36 @retval EFI_SUCCESS If the interface could be successfully installed
37 @retval Others Returned from PeiServicesInstallPpi()
38 **/
39 EFI_STATUS
40 EFIAPI
41 PeimInitializeVariableServices (
42 IN EFI_PEI_FILE_HANDLE FileHandle,
43 IN CONST EFI_PEI_SERVICES **PeiServices
44 )
45 {
46 return PeiServicesInstallPpi (&mPpiListVariable);
47 }
48
49 /**
50
51 Gets the pointer to the first variable header in given variable store area.
52
53 @param VarStoreHeader Pointer to the Variable Store Header.
54
55 @return Pointer to the first variable header.
56
57 **/
58 VARIABLE_HEADER *
59 GetStartPointer (
60 IN VARIABLE_STORE_HEADER *VarStoreHeader
61 )
62 {
63 //
64 // The start of variable store
65 //
66 return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);
67 }
68
69
70 /**
71
72 Gets the pointer to the end of the variable storage area.
73
74 This function gets pointer to the end of the variable storage
75 area, according to the input variable store header.
76
77 @param VarStoreHeader Pointer to the Variable Store Header.
78
79 @return Pointer to the end of the variable storage area.
80
81 **/
82 VARIABLE_HEADER *
83 GetEndPointer (
84 IN VARIABLE_STORE_HEADER *VarStoreHeader
85 )
86 {
87 //
88 // The end of variable store
89 //
90 return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size);
91 }
92
93
94 /**
95 This code checks if variable header is valid or not.
96
97 @param Variable Pointer to the Variable Header.
98
99 @retval TRUE Variable header is valid.
100 @retval FALSE Variable header is not valid.
101
102 **/
103 BOOLEAN
104 IsValidVariableHeader (
105 IN VARIABLE_HEADER *Variable
106 )
107 {
108 if (Variable == NULL || Variable->StartId != VARIABLE_DATA ) {
109 return FALSE;
110 }
111
112 return TRUE;
113 }
114
115 /**
116 This code gets the size of variable header.
117
118 @param AuthFlag Authenticated variable flag.
119
120 @return Size of variable header in bytes in type UINTN.
121
122 **/
123 UINTN
124 GetVariableHeaderSize (
125 IN BOOLEAN AuthFlag
126 )
127 {
128 UINTN Value;
129
130 if (AuthFlag) {
131 Value = sizeof (AUTHENTICATED_VARIABLE_HEADER);
132 } else {
133 Value = sizeof (VARIABLE_HEADER);
134 }
135
136 return Value;
137 }
138
139 /**
140 This code gets the size of name of variable.
141
142 @param Variable Pointer to the Variable Header.
143 @param AuthFlag Authenticated variable flag.
144
145 @return Size of variable in bytes in type UINTN.
146
147 **/
148 UINTN
149 NameSizeOfVariable (
150 IN VARIABLE_HEADER *Variable,
151 IN BOOLEAN AuthFlag
152 )
153 {
154 AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
155
156 AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;
157 if (AuthFlag) {
158 if (AuthVariable->State == (UINT8) (-1) ||
159 AuthVariable->DataSize == (UINT32) (-1) ||
160 AuthVariable->NameSize == (UINT32) (-1) ||
161 AuthVariable->Attributes == (UINT32) (-1)) {
162 return 0;
163 }
164 return (UINTN) AuthVariable->NameSize;
165 } else {
166 if (Variable->State == (UINT8) (-1) ||
167 Variable->DataSize == (UINT32) (-1) ||
168 Variable->NameSize == (UINT32) (-1) ||
169 Variable->Attributes == (UINT32) (-1)) {
170 return 0;
171 }
172 return (UINTN) Variable->NameSize;
173 }
174 }
175
176
177 /**
178 This code gets the size of data of variable.
179
180 @param Variable Pointer to the Variable Header.
181 @param AuthFlag Authenticated variable flag.
182
183 @return Size of variable in bytes in type UINTN.
184
185 **/
186 UINTN
187 DataSizeOfVariable (
188 IN VARIABLE_HEADER *Variable,
189 IN BOOLEAN AuthFlag
190 )
191 {
192 AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
193
194 AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;
195 if (AuthFlag) {
196 if (AuthVariable->State == (UINT8) (-1) ||
197 AuthVariable->DataSize == (UINT32) (-1) ||
198 AuthVariable->NameSize == (UINT32) (-1) ||
199 AuthVariable->Attributes == (UINT32) (-1)) {
200 return 0;
201 }
202 return (UINTN) AuthVariable->DataSize;
203 } else {
204 if (Variable->State == (UINT8) (-1) ||
205 Variable->DataSize == (UINT32) (-1) ||
206 Variable->NameSize == (UINT32) (-1) ||
207 Variable->Attributes == (UINT32) (-1)) {
208 return 0;
209 }
210 return (UINTN) Variable->DataSize;
211 }
212 }
213
214 /**
215 This code gets the pointer to the variable name.
216
217 @param Variable Pointer to the Variable Header.
218 @param AuthFlag Authenticated variable flag.
219
220 @return A CHAR16* pointer to Variable Name.
221
222 **/
223 CHAR16 *
224 GetVariableNamePtr (
225 IN VARIABLE_HEADER *Variable,
226 IN BOOLEAN AuthFlag
227 )
228 {
229 return (CHAR16 *) ((UINTN) Variable + GetVariableHeaderSize (AuthFlag));
230 }
231
232 /**
233 This code gets the pointer to the variable guid.
234
235 @param Variable Pointer to the Variable Header.
236 @param AuthFlag Authenticated variable flag.
237
238 @return A EFI_GUID* pointer to Vendor Guid.
239
240 **/
241 EFI_GUID *
242 GetVendorGuidPtr (
243 IN VARIABLE_HEADER *Variable,
244 IN BOOLEAN AuthFlag
245 )
246 {
247 AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
248
249 AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;
250 if (AuthFlag) {
251 return &AuthVariable->VendorGuid;
252 } else {
253 return &Variable->VendorGuid;
254 }
255 }
256
257 /**
258 This code gets the pointer to the variable data.
259
260 @param Variable Pointer to the Variable Header.
261 @param VariableHeader Pointer to the Variable Header that has consecutive content.
262 @param AuthFlag Authenticated variable flag.
263
264 @return A UINT8* pointer to Variable Data.
265
266 **/
267 UINT8 *
268 GetVariableDataPtr (
269 IN VARIABLE_HEADER *Variable,
270 IN VARIABLE_HEADER *VariableHeader,
271 IN BOOLEAN AuthFlag
272 )
273 {
274 UINTN Value;
275
276 //
277 // Be careful about pad size for alignment
278 //
279 Value = (UINTN) GetVariableNamePtr (Variable, AuthFlag);
280 Value += NameSizeOfVariable (VariableHeader, AuthFlag);
281 Value += GET_PAD_SIZE (NameSizeOfVariable (VariableHeader, AuthFlag));
282
283 return (UINT8 *) Value;
284 }
285
286
287 /**
288 This code gets the pointer to the next variable header.
289
290 @param StoreInfo Pointer to variable store info structure.
291 @param Variable Pointer to the Variable Header.
292 @param VariableHeader Pointer to the Variable Header that has consecutive content.
293
294 @return A VARIABLE_HEADER* pointer to next variable header.
295
296 **/
297 VARIABLE_HEADER *
298 GetNextVariablePtr (
299 IN VARIABLE_STORE_INFO *StoreInfo,
300 IN VARIABLE_HEADER *Variable,
301 IN VARIABLE_HEADER *VariableHeader
302 )
303 {
304 EFI_PHYSICAL_ADDRESS TargetAddress;
305 EFI_PHYSICAL_ADDRESS SpareAddress;
306 UINTN Value;
307
308 Value = (UINTN) GetVariableDataPtr (Variable, VariableHeader, StoreInfo->AuthFlag);
309 Value += DataSizeOfVariable (VariableHeader, StoreInfo->AuthFlag);
310 Value += GET_PAD_SIZE (DataSizeOfVariable (VariableHeader, StoreInfo->AuthFlag));
311 //
312 // Be careful about pad size for alignment
313 //
314 Value = HEADER_ALIGN (Value);
315
316 if (StoreInfo->FtwLastWriteData != NULL) {
317 TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
318 SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
319 if (((UINTN) Variable < (UINTN) TargetAddress) && (Value >= (UINTN) TargetAddress)) {
320 //
321 // Next variable is in spare block.
322 //
323 Value = (UINTN) SpareAddress + (Value - (UINTN) TargetAddress);
324 }
325 }
326
327 return (VARIABLE_HEADER *) Value;
328 }
329
330 /**
331 Get variable store status.
332
333 @param VarStoreHeader Pointer to the Variable Store Header.
334
335 @retval EfiRaw Variable store is raw
336 @retval EfiValid Variable store is valid
337 @retval EfiInvalid Variable store is invalid
338
339 **/
340 VARIABLE_STORE_STATUS
341 GetVariableStoreStatus (
342 IN VARIABLE_STORE_HEADER *VarStoreHeader
343 )
344 {
345 if ((CompareGuid (&VarStoreHeader->Signature, &gEfiAuthenticatedVariableGuid) ||
346 CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid)) &&
347 VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
348 VarStoreHeader->State == VARIABLE_STORE_HEALTHY
349 ) {
350
351 return EfiValid;
352 }
353
354 if (((UINT32 *)(&VarStoreHeader->Signature))[0] == 0xffffffff &&
355 ((UINT32 *)(&VarStoreHeader->Signature))[1] == 0xffffffff &&
356 ((UINT32 *)(&VarStoreHeader->Signature))[2] == 0xffffffff &&
357 ((UINT32 *)(&VarStoreHeader->Signature))[3] == 0xffffffff &&
358 VarStoreHeader->Size == 0xffffffff &&
359 VarStoreHeader->Format == 0xff &&
360 VarStoreHeader->State == 0xff
361 ) {
362
363 return EfiRaw;
364 } else {
365 return EfiInvalid;
366 }
367 }
368
369 /**
370 Compare two variable names, one of them may be inconsecutive.
371
372 @param StoreInfo Pointer to variable store info structure.
373 @param Name1 Pointer to one variable name.
374 @param Name2 Pointer to another variable name.
375 @param NameSize Variable name size.
376
377 @retval TRUE Name1 and Name2 are identical.
378 @retval FALSE Name1 and Name2 are not identical.
379
380 **/
381 BOOLEAN
382 CompareVariableName (
383 IN VARIABLE_STORE_INFO *StoreInfo,
384 IN CONST CHAR16 *Name1,
385 IN CONST CHAR16 *Name2,
386 IN UINTN NameSize
387 )
388 {
389 EFI_PHYSICAL_ADDRESS TargetAddress;
390 EFI_PHYSICAL_ADDRESS SpareAddress;
391 UINTN PartialNameSize;
392
393 if (StoreInfo->FtwLastWriteData != NULL) {
394 TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
395 SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
396 if (((UINTN) Name1 < (UINTN) TargetAddress) && (((UINTN) Name1 + NameSize) > (UINTN) TargetAddress)) {
397 //
398 // Name1 is inconsecutive.
399 //
400 PartialNameSize = (UINTN) TargetAddress - (UINTN) Name1;
401 //
402 // Partial content is in NV storage.
403 //
404 if (CompareMem ((UINT8 *) Name1, (UINT8 *) Name2, PartialNameSize) == 0) {
405 //
406 // Another partial content is in spare block.
407 //
408 if (CompareMem ((UINT8 *) (UINTN) SpareAddress, (UINT8 *) Name2 + PartialNameSize, NameSize - PartialNameSize) == 0) {
409 return TRUE;
410 }
411 }
412 return FALSE;
413 } else if (((UINTN) Name2 < (UINTN) TargetAddress) && (((UINTN) Name2 + NameSize) > (UINTN) TargetAddress)) {
414 //
415 // Name2 is inconsecutive.
416 //
417 PartialNameSize = (UINTN) TargetAddress - (UINTN) Name2;
418 //
419 // Partial content is in NV storage.
420 //
421 if (CompareMem ((UINT8 *) Name2, (UINT8 *) Name1, PartialNameSize) == 0) {
422 //
423 // Another partial content is in spare block.
424 //
425 if (CompareMem ((UINT8 *) (UINTN) SpareAddress, (UINT8 *) Name1 + PartialNameSize, NameSize - PartialNameSize) == 0) {
426 return TRUE;
427 }
428 }
429 return FALSE;
430 }
431 }
432
433 //
434 // Both Name1 and Name2 are consecutive.
435 //
436 if (CompareMem ((UINT8 *) Name1, (UINT8 *) Name2, NameSize) == 0) {
437 return TRUE;
438 }
439 return FALSE;
440 }
441
442 /**
443 This function compares a variable with variable entries in database.
444
445 @param StoreInfo Pointer to variable store info structure.
446 @param Variable Pointer to the variable in our database
447 @param VariableHeader Pointer to the Variable Header that has consecutive content.
448 @param VariableName Name of the variable to compare to 'Variable'
449 @param VendorGuid GUID of the variable to compare to 'Variable'
450 @param PtrTrack Variable Track Pointer structure that contains Variable Information.
451
452 @retval EFI_SUCCESS Found match variable
453 @retval EFI_NOT_FOUND Variable not found
454
455 **/
456 EFI_STATUS
457 CompareWithValidVariable (
458 IN VARIABLE_STORE_INFO *StoreInfo,
459 IN VARIABLE_HEADER *Variable,
460 IN VARIABLE_HEADER *VariableHeader,
461 IN CONST CHAR16 *VariableName,
462 IN CONST EFI_GUID *VendorGuid,
463 OUT VARIABLE_POINTER_TRACK *PtrTrack
464 )
465 {
466 VOID *Point;
467 EFI_GUID *TempVendorGuid;
468
469 TempVendorGuid = GetVendorGuidPtr (VariableHeader, StoreInfo->AuthFlag);
470
471 if (VariableName[0] == 0) {
472 PtrTrack->CurrPtr = Variable;
473 return EFI_SUCCESS;
474 } else {
475 //
476 // Don't use CompareGuid function here for performance reasons.
477 // Instead we compare the GUID a UINT32 at a time and branch
478 // on the first failed comparison.
479 //
480 if ((((INT32 *) VendorGuid)[0] == ((INT32 *) TempVendorGuid)[0]) &&
481 (((INT32 *) VendorGuid)[1] == ((INT32 *) TempVendorGuid)[1]) &&
482 (((INT32 *) VendorGuid)[2] == ((INT32 *) TempVendorGuid)[2]) &&
483 (((INT32 *) VendorGuid)[3] == ((INT32 *) TempVendorGuid)[3])
484 ) {
485 ASSERT (NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag) != 0);
486 Point = (VOID *) GetVariableNamePtr (Variable, StoreInfo->AuthFlag);
487 if (CompareVariableName (StoreInfo, VariableName, Point, NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag))) {
488 PtrTrack->CurrPtr = Variable;
489 return EFI_SUCCESS;
490 }
491 }
492 }
493
494 return EFI_NOT_FOUND;
495 }
496
497 /**
498 Get HOB variable store.
499
500 @param[out] StoreInfo Return the store info.
501 @param[out] VariableStoreHeader Return variable store header.
502
503 **/
504 VOID
505 GetHobVariableStore (
506 OUT VARIABLE_STORE_INFO *StoreInfo,
507 OUT VARIABLE_STORE_HEADER **VariableStoreHeader
508 )
509 {
510 EFI_HOB_GUID_TYPE *GuidHob;
511
512 //
513 // Make sure there is no more than one Variable HOB.
514 //
515 DEBUG_CODE (
516 GuidHob = GetFirstGuidHob (&gEfiAuthenticatedVariableGuid);
517 if (GuidHob != NULL) {
518 if ((GetNextGuidHob (&gEfiAuthenticatedVariableGuid, GET_NEXT_HOB (GuidHob)) != NULL)) {
519 DEBUG ((DEBUG_ERROR, "ERROR: Found two Auth Variable HOBs\n"));
520 ASSERT (FALSE);
521 } else if (GetFirstGuidHob (&gEfiVariableGuid) != NULL) {
522 DEBUG ((DEBUG_ERROR, "ERROR: Found one Auth + one Normal Variable HOBs\n"));
523 ASSERT (FALSE);
524 }
525 } else {
526 GuidHob = GetFirstGuidHob (&gEfiVariableGuid);
527 if (GuidHob != NULL) {
528 if ((GetNextGuidHob (&gEfiVariableGuid, GET_NEXT_HOB (GuidHob)) != NULL)) {
529 DEBUG ((DEBUG_ERROR, "ERROR: Found two Normal Variable HOBs\n"));
530 ASSERT (FALSE);
531 }
532 }
533 }
534 );
535
536 GuidHob = GetFirstGuidHob (&gEfiAuthenticatedVariableGuid);
537 if (GuidHob != NULL) {
538 *VariableStoreHeader = (VARIABLE_STORE_HEADER *) GET_GUID_HOB_DATA (GuidHob);
539 StoreInfo->AuthFlag = TRUE;
540 } else {
541 GuidHob = GetFirstGuidHob (&gEfiVariableGuid);
542 if (GuidHob != NULL) {
543 *VariableStoreHeader = (VARIABLE_STORE_HEADER *) GET_GUID_HOB_DATA (GuidHob);
544 StoreInfo->AuthFlag = FALSE;
545 }
546 }
547 }
548
549 /**
550 Return the variable store header and the store info based on the Index.
551
552 @param Type The type of the variable store.
553 @param StoreInfo Return the store info.
554
555 @return Pointer to the variable store header.
556 **/
557 VARIABLE_STORE_HEADER *
558 GetVariableStore (
559 IN VARIABLE_STORE_TYPE Type,
560 OUT VARIABLE_STORE_INFO *StoreInfo
561 )
562 {
563 EFI_HOB_GUID_TYPE *GuidHob;
564 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
565 VARIABLE_STORE_HEADER *VariableStoreHeader;
566 EFI_PHYSICAL_ADDRESS NvStorageBase;
567 UINT32 NvStorageSize;
568 FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData;
569 UINT32 BackUpOffset;
570
571 StoreInfo->IndexTable = NULL;
572 StoreInfo->FtwLastWriteData = NULL;
573 StoreInfo->AuthFlag = FALSE;
574 VariableStoreHeader = NULL;
575 switch (Type) {
576 case VariableStoreTypeHob:
577 GetHobVariableStore (StoreInfo, &VariableStoreHeader);
578
579 break;
580
581 case VariableStoreTypeNv:
582 if (!PcdGetBool (PcdEmuVariableNvModeEnable)) {
583 //
584 // Emulated non-volatile variable mode is not enabled.
585 //
586
587 NvStorageSize = PcdGet32 (PcdFlashNvStorageVariableSize);
588 NvStorageBase = (EFI_PHYSICAL_ADDRESS) (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0 ?
589 PcdGet64 (PcdFlashNvStorageVariableBase64) :
590 PcdGet32 (PcdFlashNvStorageVariableBase)
591 );
592 ASSERT (NvStorageBase != 0);
593
594 //
595 // First let FvHeader point to NV storage base.
596 //
597 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) NvStorageBase;
598
599 //
600 // Check the FTW last write data hob.
601 //
602 BackUpOffset = 0;
603 GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);
604 if (GuidHob != NULL) {
605 FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *) GET_GUID_HOB_DATA (GuidHob);
606 if (FtwLastWriteData->TargetAddress == NvStorageBase) {
607 //
608 // Let FvHeader point to spare block.
609 //
610 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FtwLastWriteData->SpareAddress;
611 DEBUG ((DEBUG_INFO, "PeiVariable: NV storage is backed up in spare block: 0x%x\n", (UINTN) FtwLastWriteData->SpareAddress));
612 } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) && (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) {
613 StoreInfo->FtwLastWriteData = FtwLastWriteData;
614 //
615 // Flash NV storage from the offset is backed up in spare block.
616 //
617 BackUpOffset = (UINT32) (FtwLastWriteData->TargetAddress - NvStorageBase);
618 DEBUG ((DEBUG_INFO, "PeiVariable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN) FtwLastWriteData->SpareAddress));
619 //
620 // At least one block data in flash NV storage is still valid, so still leave FvHeader point to NV storage base.
621 //
622 }
623 }
624
625 //
626 // Check if the Firmware Volume is not corrupted
627 //
628 if ((FvHeader->Signature != EFI_FVH_SIGNATURE) || (!CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))) {
629 DEBUG ((DEBUG_ERROR, "Firmware Volume for Variable Store is corrupted\n"));
630 break;
631 }
632
633 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINT8 *) FvHeader + FvHeader->HeaderLength);
634
635 StoreInfo->AuthFlag = (BOOLEAN) (CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid));
636
637 GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);
638 if (GuidHob != NULL) {
639 StoreInfo->IndexTable = GET_GUID_HOB_DATA (GuidHob);
640 } else {
641 //
642 // If it's the first time to access variable region in flash, create a guid hob to record
643 // VAR_ADDED type variable info.
644 // Note that as the resource of PEI phase is limited, only store the limited number of
645 // VAR_ADDED type variables to reduce access time.
646 //
647 StoreInfo->IndexTable = (VARIABLE_INDEX_TABLE *) BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));
648 StoreInfo->IndexTable->Length = 0;
649 StoreInfo->IndexTable->StartPtr = GetStartPointer (VariableStoreHeader);
650 StoreInfo->IndexTable->EndPtr = GetEndPointer (VariableStoreHeader);
651 StoreInfo->IndexTable->GoneThrough = 0;
652 }
653 }
654 break;
655
656 default:
657 ASSERT (FALSE);
658 break;
659 }
660
661 StoreInfo->VariableStoreHeader = VariableStoreHeader;
662 return VariableStoreHeader;
663 }
664
665 /**
666 Get variable header that has consecutive content.
667
668 @param StoreInfo Pointer to variable store info structure.
669 @param Variable Pointer to the Variable Header.
670 @param VariableHeader Pointer to Pointer to the Variable Header that has consecutive content.
671
672 @retval TRUE Variable header is valid.
673 @retval FALSE Variable header is not valid.
674
675 **/
676 BOOLEAN
677 GetVariableHeader (
678 IN VARIABLE_STORE_INFO *StoreInfo,
679 IN VARIABLE_HEADER *Variable,
680 OUT VARIABLE_HEADER **VariableHeader
681 )
682 {
683 EFI_PHYSICAL_ADDRESS TargetAddress;
684 EFI_PHYSICAL_ADDRESS SpareAddress;
685 EFI_HOB_GUID_TYPE *GuidHob;
686 UINTN PartialHeaderSize;
687
688 if (Variable == NULL) {
689 return FALSE;
690 }
691
692 //
693 // First assume variable header pointed by Variable is consecutive.
694 //
695 *VariableHeader = Variable;
696
697 if (StoreInfo->FtwLastWriteData != NULL) {
698 TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
699 SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
700 if (((UINTN) Variable > (UINTN) SpareAddress) &&
701 (((UINTN) Variable - (UINTN) SpareAddress + (UINTN) TargetAddress) >= (UINTN) GetEndPointer (StoreInfo->VariableStoreHeader))) {
702 //
703 // Reach the end of variable store.
704 //
705 return FALSE;
706 }
707 if (((UINTN) Variable < (UINTN) TargetAddress) && (((UINTN) Variable + GetVariableHeaderSize (StoreInfo->AuthFlag)) > (UINTN) TargetAddress)) {
708 //
709 // Variable header pointed by Variable is inconsecutive,
710 // create a guid hob to combine the two partial variable header content together.
711 //
712 GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);
713 if (GuidHob != NULL) {
714 *VariableHeader = (VARIABLE_HEADER *) GET_GUID_HOB_DATA (GuidHob);
715 } else {
716 *VariableHeader = (VARIABLE_HEADER *) BuildGuidHob (&gEfiCallerIdGuid, GetVariableHeaderSize (StoreInfo->AuthFlag));
717 PartialHeaderSize = (UINTN) TargetAddress - (UINTN) Variable;
718 //
719 // Partial content is in NV storage.
720 //
721 CopyMem ((UINT8 *) *VariableHeader, (UINT8 *) Variable, PartialHeaderSize);
722 //
723 // Another partial content is in spare block.
724 //
725 CopyMem ((UINT8 *) *VariableHeader + PartialHeaderSize, (UINT8 *) (UINTN) SpareAddress, GetVariableHeaderSize (StoreInfo->AuthFlag) - PartialHeaderSize);
726 }
727 }
728 } else {
729 if (Variable >= GetEndPointer (StoreInfo->VariableStoreHeader)) {
730 //
731 // Reach the end of variable store.
732 //
733 return FALSE;
734 }
735 }
736
737 return IsValidVariableHeader (*VariableHeader);
738 }
739
740 /**
741 Get variable name or data to output buffer.
742
743 @param StoreInfo Pointer to variable store info structure.
744 @param NameOrData Pointer to the variable name/data that may be inconsecutive.
745 @param Size Variable name/data size.
746 @param Buffer Pointer to output buffer to hold the variable name/data.
747
748 **/
749 VOID
750 GetVariableNameOrData (
751 IN VARIABLE_STORE_INFO *StoreInfo,
752 IN UINT8 *NameOrData,
753 IN UINTN Size,
754 OUT UINT8 *Buffer
755 )
756 {
757 EFI_PHYSICAL_ADDRESS TargetAddress;
758 EFI_PHYSICAL_ADDRESS SpareAddress;
759 UINTN PartialSize;
760
761 if (StoreInfo->FtwLastWriteData != NULL) {
762 TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
763 SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
764 if (((UINTN) NameOrData < (UINTN) TargetAddress) && (((UINTN) NameOrData + Size) > (UINTN) TargetAddress)) {
765 //
766 // Variable name/data is inconsecutive.
767 //
768 PartialSize = (UINTN) TargetAddress - (UINTN) NameOrData;
769 //
770 // Partial content is in NV storage.
771 //
772 CopyMem (Buffer, NameOrData, PartialSize);
773 //
774 // Another partial content is in spare block.
775 //
776 CopyMem (Buffer + PartialSize, (UINT8 *) (UINTN) SpareAddress, Size - PartialSize);
777 return;
778 }
779 }
780
781 //
782 // Variable name/data is consecutive.
783 //
784 CopyMem (Buffer, NameOrData, Size);
785 }
786
787 /**
788 Find the variable in the specified variable store.
789
790 @param StoreInfo Pointer to the store info structure.
791 @param VariableName Name of the variable to be found
792 @param VendorGuid Vendor GUID to be found.
793 @param PtrTrack Variable Track Pointer structure that contains Variable Information.
794
795 @retval EFI_SUCCESS Variable found successfully
796 @retval EFI_NOT_FOUND Variable not found
797 @retval EFI_INVALID_PARAMETER Invalid variable name
798
799 **/
800 EFI_STATUS
801 FindVariableEx (
802 IN VARIABLE_STORE_INFO *StoreInfo,
803 IN CONST CHAR16 *VariableName,
804 IN CONST EFI_GUID *VendorGuid,
805 OUT VARIABLE_POINTER_TRACK *PtrTrack
806 )
807 {
808 VARIABLE_HEADER *Variable;
809 VARIABLE_HEADER *LastVariable;
810 VARIABLE_HEADER *MaxIndex;
811 UINTN Index;
812 UINTN Offset;
813 BOOLEAN StopRecord;
814 VARIABLE_HEADER *InDeletedVariable;
815 VARIABLE_STORE_HEADER *VariableStoreHeader;
816 VARIABLE_INDEX_TABLE *IndexTable;
817 VARIABLE_HEADER *VariableHeader;
818
819 VariableStoreHeader = StoreInfo->VariableStoreHeader;
820
821 if (VariableStoreHeader == NULL) {
822 return EFI_INVALID_PARAMETER;
823 }
824
825 if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {
826 return EFI_UNSUPPORTED;
827 }
828
829 if (~VariableStoreHeader->Size == 0) {
830 return EFI_NOT_FOUND;
831 }
832
833 IndexTable = StoreInfo->IndexTable;
834 PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader);
835 PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader);
836
837 InDeletedVariable = NULL;
838
839 //
840 // No Variable Address equals zero, so 0 as initial value is safe.
841 //
842 MaxIndex = NULL;
843 VariableHeader = NULL;
844
845 if (IndexTable != NULL) {
846 //
847 // traverse the variable index table to look for varible.
848 // The IndexTable->Index[Index] records the distance of two neighbouring VAR_ADDED type variables.
849 //
850 for (Offset = 0, Index = 0; Index < IndexTable->Length; Index++) {
851 ASSERT (Index < sizeof (IndexTable->Index) / sizeof (IndexTable->Index[0]));
852 Offset += IndexTable->Index[Index];
853 MaxIndex = (VARIABLE_HEADER *) ((UINT8 *) IndexTable->StartPtr + Offset);
854 GetVariableHeader (StoreInfo, MaxIndex, &VariableHeader);
855 if (CompareWithValidVariable (StoreInfo, MaxIndex, VariableHeader, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
856 if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
857 InDeletedVariable = PtrTrack->CurrPtr;
858 } else {
859 return EFI_SUCCESS;
860 }
861 }
862 }
863
864 if (IndexTable->GoneThrough != 0) {
865 //
866 // If the table has all the existing variables indexed, return.
867 //
868 PtrTrack->CurrPtr = InDeletedVariable;
869 return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;
870 }
871 }
872
873 if (MaxIndex != NULL) {
874 //
875 // HOB exists but the variable cannot be found in HOB
876 // If not found in HOB, then let's start from the MaxIndex we've found.
877 //
878 Variable = GetNextVariablePtr (StoreInfo, MaxIndex, VariableHeader);
879 LastVariable = MaxIndex;
880 } else {
881 //
882 // Start Pointers for the variable.
883 // Actual Data Pointer where data can be written.
884 //
885 Variable = PtrTrack->StartPtr;
886 LastVariable = PtrTrack->StartPtr;
887 }
888
889 //
890 // Find the variable by walk through variable store
891 //
892 StopRecord = FALSE;
893 while (GetVariableHeader (StoreInfo, Variable, &VariableHeader)) {
894 if (VariableHeader->State == VAR_ADDED || VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
895 //
896 // Record Variable in VariableIndex HOB
897 //
898 if ((IndexTable != NULL) && !StopRecord) {
899 Offset = (UINTN) Variable - (UINTN) LastVariable;
900 if ((Offset > 0x0FFFF) || (IndexTable->Length >= sizeof (IndexTable->Index) / sizeof (IndexTable->Index[0]))) {
901 //
902 // Stop to record if the distance of two neighbouring VAR_ADDED variable is larger than the allowable scope(UINT16),
903 // or the record buffer is full.
904 //
905 StopRecord = TRUE;
906 } else {
907 IndexTable->Index[IndexTable->Length++] = (UINT16) Offset;
908 LastVariable = Variable;
909 }
910 }
911
912 if (CompareWithValidVariable (StoreInfo, Variable, VariableHeader, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
913 if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
914 InDeletedVariable = PtrTrack->CurrPtr;
915 } else {
916 return EFI_SUCCESS;
917 }
918 }
919 }
920
921 Variable = GetNextVariablePtr (StoreInfo, Variable, VariableHeader);
922 }
923 //
924 // If gone through the VariableStore, that means we never find in Firmware any more.
925 //
926 if ((IndexTable != NULL) && !StopRecord) {
927 IndexTable->GoneThrough = 1;
928 }
929
930 PtrTrack->CurrPtr = InDeletedVariable;
931
932 return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;
933 }
934
935 /**
936 Find the variable in HOB and Non-Volatile variable storages.
937
938 @param VariableName Name of the variable to be found
939 @param VendorGuid Vendor GUID to be found.
940 @param PtrTrack Variable Track Pointer structure that contains Variable Information.
941 @param StoreInfo Return the store info.
942
943 @retval EFI_SUCCESS Variable found successfully
944 @retval EFI_NOT_FOUND Variable not found
945 @retval EFI_INVALID_PARAMETER Invalid variable name
946 **/
947 EFI_STATUS
948 FindVariable (
949 IN CONST CHAR16 *VariableName,
950 IN CONST EFI_GUID *VendorGuid,
951 OUT VARIABLE_POINTER_TRACK *PtrTrack,
952 OUT VARIABLE_STORE_INFO *StoreInfo
953 )
954 {
955 EFI_STATUS Status;
956 VARIABLE_STORE_TYPE Type;
957
958 if (VariableName[0] != 0 && VendorGuid == NULL) {
959 return EFI_INVALID_PARAMETER;
960 }
961
962 for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
963 GetVariableStore (Type, StoreInfo);
964 Status = FindVariableEx (
965 StoreInfo,
966 VariableName,
967 VendorGuid,
968 PtrTrack
969 );
970 if (!EFI_ERROR (Status)) {
971 return Status;
972 }
973 }
974
975 return EFI_NOT_FOUND;
976 }
977
978 /**
979 This service retrieves a variable's value using its name and GUID.
980
981 Read the specified variable from the UEFI variable store. If the Data
982 buffer is too small to hold the contents of the variable, the error
983 EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buffer
984 size to obtain the data.
985
986 @param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
987 @param VariableName A pointer to a null-terminated string that is the variable's name.
988 @param VariableGuid A pointer to an EFI_GUID that is the variable's GUID. The combination of
989 VariableGuid and VariableName must be unique.
990 @param Attributes If non-NULL, on return, points to the variable's attributes.
991 @param DataSize On entry, points to the size in bytes of the Data buffer.
992 On return, points to the size of the data returned in Data.
993 @param Data Points to the buffer which will hold the returned variable value.
994 May be NULL with a zero DataSize in order to determine the size of the buffer needed.
995
996 @retval EFI_SUCCESS The variable was read successfully.
997 @retval EFI_NOT_FOUND The variable was be found.
998 @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the resulting data.
999 DataSize is updated with the size required for
1000 the specified variable.
1001 @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Data is NULL.
1002 @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error.
1003
1004 **/
1005 EFI_STATUS
1006 EFIAPI
1007 PeiGetVariable (
1008 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
1009 IN CONST CHAR16 *VariableName,
1010 IN CONST EFI_GUID *VariableGuid,
1011 OUT UINT32 *Attributes,
1012 IN OUT UINTN *DataSize,
1013 OUT VOID *Data OPTIONAL
1014 )
1015 {
1016 VARIABLE_POINTER_TRACK Variable;
1017 UINTN VarDataSize;
1018 EFI_STATUS Status;
1019 VARIABLE_STORE_INFO StoreInfo;
1020 VARIABLE_HEADER *VariableHeader;
1021
1022 if (VariableName == NULL || VariableGuid == NULL || DataSize == NULL) {
1023 return EFI_INVALID_PARAMETER;
1024 }
1025
1026 if (VariableName[0] == 0) {
1027 return EFI_NOT_FOUND;
1028 }
1029
1030 VariableHeader = NULL;
1031
1032 //
1033 // Find existing variable
1034 //
1035 Status = FindVariable (VariableName, VariableGuid, &Variable, &StoreInfo);
1036 if (EFI_ERROR (Status)) {
1037 return Status;
1038 }
1039 GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader);
1040
1041 //
1042 // Get data size
1043 //
1044 VarDataSize = DataSizeOfVariable (VariableHeader, StoreInfo.AuthFlag);
1045 if (*DataSize >= VarDataSize) {
1046 if (Data == NULL) {
1047 return EFI_INVALID_PARAMETER;
1048 }
1049
1050 GetVariableNameOrData (&StoreInfo, GetVariableDataPtr (Variable.CurrPtr, VariableHeader, StoreInfo.AuthFlag), VarDataSize, Data);
1051 Status = EFI_SUCCESS;
1052 } else {
1053 Status = EFI_BUFFER_TOO_SMALL;
1054 }
1055
1056 if (Attributes != NULL) {
1057 *Attributes = VariableHeader->Attributes;
1058 }
1059 *DataSize = VarDataSize;
1060
1061 return Status;
1062 }
1063
1064 /**
1065 Return the next variable name and GUID.
1066
1067 This function is called multiple times to retrieve the VariableName
1068 and VariableGuid of all variables currently available in the system.
1069 On each call, the previous results are passed into the interface,
1070 and, on return, the interface returns the data for the next
1071 interface. When the entire variable list has been returned,
1072 EFI_NOT_FOUND is returned.
1073
1074 @param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
1075
1076 @param VariableNameSize On entry, points to the size of the buffer pointed to by VariableName.
1077 On return, the size of the variable name buffer.
1078 @param VariableName On entry, a pointer to a null-terminated string that is the variable's name.
1079 On return, points to the next variable's null-terminated name string.
1080 @param VariableGuid On entry, a pointer to an EFI_GUID that is the variable's GUID.
1081 On return, a pointer to the next variable's GUID.
1082
1083 @retval EFI_SUCCESS The variable was read successfully.
1084 @retval EFI_NOT_FOUND The variable could not be found.
1085 @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the resulting
1086 data. VariableNameSize is updated with the size
1087 required for the specified variable.
1088 @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or
1089 VariableNameSize is NULL.
1090 @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error.
1091
1092 **/
1093 EFI_STATUS
1094 EFIAPI
1095 PeiGetNextVariableName (
1096 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
1097 IN OUT UINTN *VariableNameSize,
1098 IN OUT CHAR16 *VariableName,
1099 IN OUT EFI_GUID *VariableGuid
1100 )
1101 {
1102 VARIABLE_STORE_TYPE Type;
1103 VARIABLE_POINTER_TRACK Variable;
1104 VARIABLE_POINTER_TRACK VariableInHob;
1105 VARIABLE_POINTER_TRACK VariablePtrTrack;
1106 UINTN VarNameSize;
1107 EFI_STATUS Status;
1108 VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];
1109 VARIABLE_HEADER *VariableHeader;
1110 VARIABLE_STORE_INFO StoreInfo;
1111 VARIABLE_STORE_INFO StoreInfoForNv;
1112 VARIABLE_STORE_INFO StoreInfoForHob;
1113
1114 if (VariableName == NULL || VariableGuid == NULL || VariableNameSize == NULL) {
1115 return EFI_INVALID_PARAMETER;
1116 }
1117
1118 VariableHeader = NULL;
1119
1120 Status = FindVariable (VariableName, VariableGuid, &Variable, &StoreInfo);
1121 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {
1122 return Status;
1123 }
1124
1125 if (VariableName[0] != 0) {
1126 //
1127 // If variable name is not NULL, get next variable
1128 //
1129 GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader);
1130 Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
1131 }
1132
1133 VariableStoreHeader[VariableStoreTypeHob] = GetVariableStore (VariableStoreTypeHob, &StoreInfoForHob);
1134 VariableStoreHeader[VariableStoreTypeNv] = GetVariableStore (VariableStoreTypeNv, &StoreInfoForNv);
1135
1136 while (TRUE) {
1137 //
1138 // Switch from HOB to Non-Volatile.
1139 //
1140 while (!GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader)) {
1141 //
1142 // Find current storage index
1143 //
1144 for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
1145 if ((VariableStoreHeader[Type] != NULL) && (Variable.StartPtr == GetStartPointer (VariableStoreHeader[Type]))) {
1146 break;
1147 }
1148 }
1149 ASSERT (Type < VariableStoreTypeMax);
1150 //
1151 // Switch to next storage
1152 //
1153 for (Type++; Type < VariableStoreTypeMax; Type++) {
1154 if (VariableStoreHeader[Type] != NULL) {
1155 break;
1156 }
1157 }
1158 //
1159 // Capture the case that
1160 // 1. current storage is the last one, or
1161 // 2. no further storage
1162 //
1163 if (Type == VariableStoreTypeMax) {
1164 return EFI_NOT_FOUND;
1165 }
1166 Variable.StartPtr = GetStartPointer (VariableStoreHeader[Type]);
1167 Variable.EndPtr = GetEndPointer (VariableStoreHeader[Type]);
1168 Variable.CurrPtr = Variable.StartPtr;
1169 GetVariableStore (Type, &StoreInfo);
1170 }
1171
1172 if (VariableHeader->State == VAR_ADDED || VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
1173 if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
1174 //
1175 // If it is a IN_DELETED_TRANSITION variable,
1176 // and there is also a same ADDED one at the same time,
1177 // don't return it.
1178 //
1179 Status = FindVariableEx (
1180 &StoreInfo,
1181 GetVariableNamePtr (Variable.CurrPtr, StoreInfo.AuthFlag),
1182 GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag),
1183 &VariablePtrTrack
1184 );
1185 if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr != Variable.CurrPtr) {
1186 Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
1187 continue;
1188 }
1189 }
1190
1191 //
1192 // Don't return NV variable when HOB overrides it
1193 //
1194 if ((VariableStoreHeader[VariableStoreTypeHob] != NULL) && (VariableStoreHeader[VariableStoreTypeNv] != NULL) &&
1195 (Variable.StartPtr == GetStartPointer (VariableStoreHeader[VariableStoreTypeNv]))
1196 ) {
1197 Status = FindVariableEx (
1198 &StoreInfoForHob,
1199 GetVariableNamePtr (Variable.CurrPtr, StoreInfo.AuthFlag),
1200 GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag),
1201 &VariableInHob
1202 );
1203 if (!EFI_ERROR (Status)) {
1204 Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
1205 continue;
1206 }
1207 }
1208
1209 VarNameSize = NameSizeOfVariable (VariableHeader, StoreInfo.AuthFlag);
1210 ASSERT (VarNameSize != 0);
1211
1212 if (VarNameSize <= *VariableNameSize) {
1213 GetVariableNameOrData (&StoreInfo, (UINT8 *) GetVariableNamePtr (Variable.CurrPtr, StoreInfo.AuthFlag), VarNameSize, (UINT8 *) VariableName);
1214
1215 CopyMem (VariableGuid, GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag), sizeof (EFI_GUID));
1216
1217 Status = EFI_SUCCESS;
1218 } else {
1219 Status = EFI_BUFFER_TOO_SMALL;
1220 }
1221
1222 *VariableNameSize = VarNameSize;
1223 //
1224 // Variable is found
1225 //
1226 return Status;
1227 } else {
1228 Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
1229 }
1230 }
1231 }