]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/Variable/Pei/Variable.c
1. Refresh applicable library instances after one illegal library instance is removed.
[mirror_edk2.git] / EdkModulePkg / Universal / Variable / Pei / Variable.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 Variable.c\r
15\r
16Abstract:\r
17\r
18 Framework PEIM to provide the Variable functionality\r
19\r
20--*/\r
21\r
878ddf1f 22#include <Variable.h>\r
878ddf1f 23\r
24//\r
25// Module globals\r
26//\r
27static EFI_PEI_READ_ONLY_VARIABLE_PPI mVariablePpi = {\r
28 PeiGetVariable,\r
29 PeiGetNextVariableName\r
30};\r
31\r
32static EFI_PEI_PPI_DESCRIPTOR mPpiListVariable = {\r
33 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
34 &gEfiPeiReadOnlyVariablePpiGuid,\r
35 &mVariablePpi\r
36};\r
37\r
38EFI_GUID gEfiVariableIndexTableGuid = EFI_VARIABLE_INDEX_TABLE_GUID;\r
39\r
40EFI_STATUS\r
41EFIAPI\r
42PeimInitializeVariableServices (\r
43 IN EFI_FFS_FILE_HEADER *FfsHeader,\r
44 IN EFI_PEI_SERVICES **PeiServices\r
45 )\r
46/*++\r
47\r
48Routine Description:\r
49\r
50 Provide the functionality of the variable services.\r
51\r
52Arguments:\r
53 \r
54 FfsHeadher - The FFS file header\r
55 PeiServices - General purpose services available to every PEIM.\r
56\r
57Returns:\r
58\r
59 Status - EFI_SUCCESS if the interface could be successfully\r
60 installed\r
61\r
62--*/\r
63{\r
64 //\r
65 // Publish the variable capability to other modules\r
66 //\r
67 return (**PeiServices).InstallPpi (PeiServices, &mPpiListVariable);\r
68\r
69}\r
70\r
1cc8ee78 71STATIC\r
878ddf1f 72VARIABLE_HEADER *\r
73GetNextVariablePtr (\r
74 IN VARIABLE_HEADER *Variable\r
75 )\r
76/*++\r
77\r
78Routine Description:\r
79\r
80 This code checks if variable header is valid or not.\r
81\r
82Arguments:\r
83 Variable Pointer to the Variable Header.\r
84\r
85Returns:\r
86 TRUE Variable header is valid.\r
87 FALSE Variable header is not valid.\r
88\r
89--*/\r
90{\r
91 return (VARIABLE_HEADER *) ((UINTN) GET_VARIABLE_DATA_PTR (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));\r
92}\r
93\r
1cc8ee78 94STATIC\r
878ddf1f 95BOOLEAN\r
96EFIAPI\r
97IsValidVariableHeader (\r
98 IN VARIABLE_HEADER *Variable\r
99 )\r
100/*++\r
101\r
102Routine Description:\r
103\r
104 This code checks if variable header is valid or not.\r
105\r
106Arguments:\r
107 Variable Pointer to the Variable Header.\r
108\r
109Returns:\r
110 TRUE Variable header is valid.\r
111 FALSE Variable header is not valid.\r
112\r
113--*/\r
114{\r
115 if (Variable == NULL ||\r
116 Variable->StartId != VARIABLE_DATA ||\r
117 (sizeof (VARIABLE_HEADER) + Variable->DataSize + Variable->NameSize) > MAX_VARIABLE_SIZE\r
118 ) {\r
119 return FALSE;\r
120 }\r
121\r
122 return TRUE;\r
123}\r
124\r
1cc8ee78 125STATIC\r
878ddf1f 126VARIABLE_STORE_STATUS\r
127EFIAPI\r
128GetVariableStoreStatus (\r
129 IN VARIABLE_STORE_HEADER *VarStoreHeader\r
130 )\r
131/*++\r
132\r
133Routine Description:\r
134\r
135 This code gets the pointer to the variable name.\r
136\r
137Arguments:\r
138\r
139 VarStoreHeader Pointer to the Variable Store Header.\r
140\r
141Returns:\r
142\r
143 EfiRaw Variable store is raw\r
144 EfiValid Variable store is valid\r
145 EfiInvalid Variable store is invalid\r
146\r
147--*/\r
148{\r
149 if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE &&\r
150 VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&\r
151 VarStoreHeader->State == VARIABLE_STORE_HEALTHY\r
152 ) {\r
153\r
154 return EfiValid;\r
155 }\r
156\r
157 if (VarStoreHeader->Signature == 0xffffffff &&\r
158 VarStoreHeader->Size == 0xffffffff &&\r
159 VarStoreHeader->Format == 0xff &&\r
160 VarStoreHeader->State == 0xff\r
161 ) {\r
162\r
163 return EfiRaw;\r
164 } else {\r
165 return EfiInvalid;\r
166 }\r
167}\r
168\r
1cc8ee78 169STATIC\r
878ddf1f 170EFI_STATUS\r
171CompareWithValidVariable (\r
172 IN VARIABLE_HEADER *Variable,\r
173 IN CHAR16 *VariableName,\r
174 IN EFI_GUID *VendorGuid,\r
175 OUT VARIABLE_POINTER_TRACK *PtrTrack\r
176 )\r
177/*++\r
178\r
179Routine Description:\r
180\r
181 This function compares a variable with variable entries in database\r
182\r
183Arguments:\r
184\r
185 Variable - Pointer to the variable in our database\r
186 VariableName - Name of the variable to compare to 'Variable'\r
187 VendorGuid - GUID of the variable to compare to 'Variable'\r
188 PtrTrack - Variable Track Pointer structure that contains\r
189 Variable Information.\r
190\r
191Returns:\r
192\r
193 EFI_SUCCESS - Found match variable\r
194 EFI_NOT_FOUND - Variable not found\r
195 \r
196--*/\r
197{\r
198 if (VariableName[0] == 0) {\r
199 PtrTrack->CurrPtr = Variable;\r
200 return EFI_SUCCESS;\r
201 } else {\r
202 //\r
203 // Don't use CompareGuid function here for performance reasons.\r
204 // Instead we compare the GUID a UINT32 at a time and branch\r
205 // on the first failed comparison.\r
206 //\r
207 if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &Variable->VendorGuid)[0]) &&\r
208 (((INT32 *) VendorGuid)[1] == ((INT32 *) &Variable->VendorGuid)[1]) &&\r
209 (((INT32 *) VendorGuid)[2] == ((INT32 *) &Variable->VendorGuid)[2]) &&\r
210 (((INT32 *) VendorGuid)[3] == ((INT32 *) &Variable->VendorGuid)[3])\r
211 ) {\r
212 if (!StrCmp (VariableName, GET_VARIABLE_NAME_PTR (Variable))) {\r
213 PtrTrack->CurrPtr = Variable;\r
214 return EFI_SUCCESS;\r
215 }\r
216 }\r
217 }\r
218\r
219 return EFI_NOT_FOUND;\r
220}\r
221\r
1cc8ee78 222STATIC\r
878ddf1f 223EFI_STATUS\r
224EFIAPI\r
225FindVariable (\r
226 IN EFI_PEI_SERVICES **PeiServices,\r
227 IN CHAR16 *VariableName,\r
228 IN EFI_GUID *VendorGuid,\r
229 OUT VARIABLE_POINTER_TRACK *PtrTrack\r
230 )\r
231/*++\r
232\r
233Routine Description:\r
234\r
235 This code finds variable in storage blocks (Non-Volatile)\r
236\r
237Arguments:\r
238\r
239 PeiServices - General purpose services available to every PEIM.\r
240 VariableName - Name of the variable to be found\r
241 VendorGuid - Vendor GUID to be found.\r
242 PtrTrack - Variable Track Pointer structure that contains\r
243 Variable Information.\r
244\r
245Returns:\r
246\r
247 EFI_SUCCESS - Variable found successfully\r
248 EFI_NOT_FOUND - Variable not found\r
249 EFI_INVALID_PARAMETER - Invalid variable name\r
250\r
251--*/\r
252{\r
878ddf1f 253 EFI_HOB_GUID_TYPE *GuidHob;\r
254 VARIABLE_STORE_HEADER *VariableStoreHeader;\r
255 VARIABLE_HEADER *Variable;\r
878ddf1f 256 VARIABLE_HEADER *MaxIndex;\r
257 VARIABLE_INDEX_TABLE *IndexTable;\r
258 UINT32 Count;\r
5dd2d779 259 UINT8 *VariableBase;\r
878ddf1f 260\r
261 if (VariableName != 0 && VendorGuid == NULL) {\r
262 return EFI_INVALID_PARAMETER;\r
263 }\r
264 //\r
265 // No Variable Address equals zero, so 0 as initial value is safe.\r
266 //\r
267 MaxIndex = 0;\r
268 \r
269 GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);\r
270 if (GuidHob == NULL) {\r
271 IndexTable = BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));\r
272 IndexTable->Length = 0;\r
273 IndexTable->StartPtr = NULL;\r
274 IndexTable->EndPtr = NULL;\r
275 IndexTable->GoneThrough = 0;\r
276 } else {\r
277 IndexTable = GET_GUID_HOB_DATA (GuidHob);\r
278 for (Count = 0; Count < IndexTable->Length; Count++)\r
279 {\r
280#if ALIGNMENT <= 1\r
281 MaxIndex = (VARIABLE_HEADER *) (UINTN) (IndexTable->Index[Count] + ((UINTN) IndexTable->StartPtr & 0xFFFF0000));\r
282#else\r
283#if ALIGNMENT >= 4\r
284 MaxIndex = (VARIABLE_HEADER *) (UINTN) ((((UINT32)IndexTable->Index[Count]) << 2) + ((UINT32)(UINTN)IndexTable->StartPtr & 0xFFFC0000) ); \r
285#endif\r
286#endif\r
287 if (CompareWithValidVariable (MaxIndex, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
288 PtrTrack->StartPtr = IndexTable->StartPtr;\r
289 PtrTrack->EndPtr = IndexTable->EndPtr;\r
290\r
291 return EFI_SUCCESS;\r
292 }\r
293 }\r
294\r
295 if (IndexTable->GoneThrough) {\r
296 return EFI_NOT_FOUND;\r
297 }\r
298 }\r
299 //\r
300 // If not found in HOB, then let's start from the MaxIndex we've found.\r
301 //\r
302 if (MaxIndex != NULL) {\r
303 Variable = GetNextVariablePtr (MaxIndex);\r
304 } else {\r
305 if (IndexTable->StartPtr || IndexTable->EndPtr) {\r
306 Variable = IndexTable->StartPtr;\r
307 } else {\r
5dd2d779 308 VariableBase = (UINT8 *) (UINTN) PcdGet32 (PcdFlashNvStorageVariableBase);\r
309 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (VariableBase + \\r
310 ((EFI_FIRMWARE_VOLUME_HEADER *) (VariableBase)) -> HeaderLength);\r
311 \r
878ddf1f 312 if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {\r
313 return EFI_UNSUPPORTED;\r
314 }\r
315\r
316 if (~VariableStoreHeader->Size == 0) {\r
317 return EFI_NOT_FOUND;\r
318 }\r
319 //\r
320 // Find the variable by walk through non-volatile variable store\r
321 //\r
322 IndexTable->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
323 IndexTable->EndPtr = (VARIABLE_HEADER *) ((UINTN) VariableStoreHeader + VariableStoreHeader->Size);\r
324\r
325 //\r
326 // Start Pointers for the variable.\r
327 // Actual Data Pointer where data can be written.\r
328 //\r
329 Variable = IndexTable->StartPtr;\r
330 }\r
331 }\r
332 //\r
333 // Find the variable by walk through non-volatile variable store\r
334 //\r
335 PtrTrack->StartPtr = IndexTable->StartPtr;\r
336 PtrTrack->EndPtr = IndexTable->EndPtr;\r
337\r
338 while (IsValidVariableHeader (Variable) && (Variable <= IndexTable->EndPtr)) {\r
339 if (Variable->State == VAR_ADDED) {\r
340 //\r
341 // Record Variable in VariableIndex HOB\r
342 //\r
343 if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME)\r
344 {\r
345#if ALIGNMENT <= 1\r
346 IndexTable->Index[IndexTable->Length++] = (UINT16) (UINTN) Variable;\r
347#else\r
348#if ALIGNMENT >= 4\r
349 IndexTable->Index[IndexTable->Length++] = (UINT16) (((UINT32)(UINTN) Variable) >> 2);\r
350#endif\r
351#endif\r
352 }\r
353\r
354 if (CompareWithValidVariable (Variable, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
355 return EFI_SUCCESS;\r
356 }\r
357 }\r
358\r
359 Variable = GetNextVariablePtr (Variable);\r
360 }\r
361 //\r
362 // If gone through the VariableStore, that means we never find in Firmware any more.\r
363 //\r
364 if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME) {\r
365 IndexTable->GoneThrough = 1;\r
366 }\r
367\r
368 PtrTrack->CurrPtr = NULL;\r
369\r
370 return EFI_NOT_FOUND;\r
371}\r
372\r
373EFI_STATUS\r
374EFIAPI\r
375PeiGetVariable (\r
376 IN EFI_PEI_SERVICES **PeiServices,\r
377 IN CHAR16 *VariableName,\r
378 IN EFI_GUID * VendorGuid,\r
379 OUT UINT32 *Attributes OPTIONAL,\r
380 IN OUT UINTN *DataSize,\r
381 OUT VOID *Data\r
382 )\r
383/*++\r
384\r
385Routine Description:\r
386\r
387 Provide the read variable functionality of the variable services.\r
388\r
389Arguments:\r
390\r
391 PeiServices - General purpose services available to every PEIM.\r
392\r
393 VariableName - The variable name\r
394\r
395 VendorGuid - The vendor's GUID\r
396\r
397 Attributes - Pointer to the attribute\r
398\r
399 DataSize - Size of data\r
400\r
401 Data - Pointer to data\r
402\r
403Returns:\r
404\r
405 EFI_SUCCESS - The interface could be successfully installed\r
406\r
407 EFI_NOT_FOUND - The variable could not be discovered\r
408\r
409 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough\r
410\r
411--*/\r
412{\r
413 VARIABLE_POINTER_TRACK Variable;\r
414 UINTN VarDataSize;\r
415 EFI_STATUS Status;\r
416\r
417 if (VariableName == NULL || VendorGuid == NULL) {\r
418 return EFI_INVALID_PARAMETER;\r
419 }\r
420 //\r
421 // Find existing variable\r
422 //\r
423 Status = FindVariable (PeiServices, VariableName, VendorGuid, &Variable);\r
424\r
425 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {\r
426 return Status;\r
427 }\r
428 //\r
429 // Get data size\r
430 //\r
431 VarDataSize = Variable.CurrPtr->DataSize;\r
432 if (*DataSize >= VarDataSize) {\r
433 (*PeiServices)->CopyMem (Data, GET_VARIABLE_DATA_PTR (Variable.CurrPtr), VarDataSize);\r
434\r
435 if (Attributes != NULL) {\r
436 *Attributes = Variable.CurrPtr->Attributes;\r
437 }\r
438\r
439 *DataSize = VarDataSize;\r
440 return EFI_SUCCESS;\r
441 } else {\r
442 *DataSize = VarDataSize;\r
443 return EFI_BUFFER_TOO_SMALL;\r
444 }\r
445}\r
446\r
447EFI_STATUS\r
448EFIAPI\r
449PeiGetNextVariableName (\r
450 IN EFI_PEI_SERVICES **PeiServices,\r
451 IN OUT UINTN *VariableNameSize,\r
452 IN OUT CHAR16 *VariableName,\r
453 IN OUT EFI_GUID *VendorGuid\r
454 )\r
455/*++\r
456\r
457Routine Description:\r
458\r
459 Provide the get next variable functionality of the variable services.\r
460\r
461Arguments:\r
462\r
463 PeiServices - General purpose services available to every PEIM.\r
464 VariabvleNameSize - The variable name's size.\r
465 VariableName - A pointer to the variable's name.\r
466 VendorGuid - A pointer to the EFI_GUID structure.\r
467\r
468 VariableNameSize - Size of the variable name\r
469\r
470 VariableName - The variable name\r
471\r
472 VendorGuid - The vendor's GUID\r
473\r
474Returns:\r
475\r
476 EFI_SUCCESS - The interface could be successfully installed\r
477\r
478 EFI_NOT_FOUND - The variable could not be discovered\r
479\r
480--*/\r
481{\r
482 VARIABLE_POINTER_TRACK Variable;\r
483 UINTN VarNameSize;\r
484 EFI_STATUS Status;\r
485\r
486 if (VariableName == NULL) {\r
487 return EFI_INVALID_PARAMETER;\r
488 }\r
489\r
490 Status = FindVariable (PeiServices, VariableName, VendorGuid, &Variable);\r
491\r
492 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {\r
493 return Status;\r
494 }\r
495\r
496 if (VariableName[0] != 0) {\r
497 //\r
498 // If variable name is not NULL, get next variable\r
499 //\r
500 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
501 }\r
502\r
503 while (!(Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL)) {\r
504 if (IsValidVariableHeader (Variable.CurrPtr)) {\r
505 if (Variable.CurrPtr->State == VAR_ADDED) {\r
506 VarNameSize = (UINTN) Variable.CurrPtr->NameSize;\r
507 if (VarNameSize <= *VariableNameSize) {\r
508 (*PeiServices)->CopyMem (VariableName, GET_VARIABLE_NAME_PTR (Variable.CurrPtr), VarNameSize);\r
509\r
510 (*PeiServices)->CopyMem (VendorGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));\r
511\r
512 Status = EFI_SUCCESS;\r
513 } else {\r
514 Status = EFI_BUFFER_TOO_SMALL;\r
515 }\r
516\r
517 *VariableNameSize = VarNameSize;\r
518 return Status;\r
519 //\r
520 // Variable is found\r
521 //\r
522 } else {\r
523 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
524 }\r
525 } else {\r
526 break;\r
527 }\r
528 }\r
529\r
530 return EFI_NOT_FOUND;\r
531}\r