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