]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/VariablePei/Variable.c
Removed CommonHeader.h from MdePkg & MdeModulePkg
[mirror_edk2.git] / MdeModulePkg / Universal / VariablePei / Variable.c
CommitLineData
7ff7768d 1/*++\r
2\r
3Copyright (c) 2006 - 2007 Intel Corporation. <BR>\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
11Module Name:\r
12\r
13 Variable.c\r
14\r
15Abstract:\r
16\r
17 Framework PEIM to provide the Variable functionality\r
18\r
19--*/\r
20\r
7ff7768d 21\r
ba237732 22#include "Variable.h"\r
7ff7768d 23\r
24//\r
25// Module globals\r
26//\r
ba237732 27static EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariablePpi = {\r
7ff7768d 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
ba237732 34 &gEfiPeiReadOnlyVariable2PpiGuid,\r
7ff7768d 35 &mVariablePpi\r
36};\r
37\r
38EFI_GUID mEfiVariableIndexTableGuid = 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
71STATIC\r
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
94STATIC\r
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
125STATIC\r
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
169STATIC\r
170EFI_STATUS\r
171CompareWithValidVariable (\r
ba237732
A
172 IN VARIABLE_HEADER *Variable,\r
173 IN CONST CHAR16 *VariableName,\r
174 IN CONST EFI_GUID *VendorGuid,\r
175 OUT VARIABLE_POINTER_TRACK *PtrTrack\r
7ff7768d 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 (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable), Variable->NameSize)) {\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
222STATIC\r
223EFI_STATUS\r
224EFIAPI\r
225FindVariable (\r
226 IN EFI_PEI_SERVICES **PeiServices,\r
ba237732
A
227 IN CONST CHAR16 *VariableName,\r
228 IN CONST EFI_GUID *VendorGuid,\r
7ff7768d 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
253 EFI_HOB_GUID_TYPE *GuidHob;\r
254 VARIABLE_STORE_HEADER *VariableStoreHeader;\r
255 VARIABLE_HEADER *Variable;\r
256 VARIABLE_HEADER *MaxIndex;\r
257 VARIABLE_INDEX_TABLE *IndexTable;\r
258 UINT32 Count;\r
259 UINT8 *VariableBase;\r
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 (&mEfiVariableIndexTableGuid);\r
270 if (GuidHob == NULL) {\r
271 IndexTable = BuildGuidHob (&mEfiVariableIndexTableGuid, 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 MaxIndex = GetVariableByIndex (IndexTable, Count);\r
281\r
282 if (CompareWithValidVariable (MaxIndex, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
283 PtrTrack->StartPtr = IndexTable->StartPtr;\r
284 PtrTrack->EndPtr = IndexTable->EndPtr;\r
285\r
286 return EFI_SUCCESS;\r
287 }\r
288 }\r
289\r
290 if (IndexTable->GoneThrough) {\r
291 return EFI_NOT_FOUND;\r
292 }\r
293 }\r
294 //\r
295 // If not found in HOB, then let's start from the MaxIndex we've found.\r
296 //\r
297 if (MaxIndex != NULL) {\r
298 Variable = GetNextVariablePtr (MaxIndex);\r
299 } else {\r
300 if (IndexTable->StartPtr || IndexTable->EndPtr) {\r
301 Variable = IndexTable->StartPtr;\r
302 } else {\r
303 VariableBase = (UINT8 *) (UINTN) PcdGet32 (PcdFlashNvStorageVariableBase);\r
304 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (VariableBase + \\r
305 ((EFI_FIRMWARE_VOLUME_HEADER *) (VariableBase)) -> HeaderLength);\r
306\r
307 if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {\r
308 return EFI_UNSUPPORTED;\r
309 }\r
310\r
311 if (~VariableStoreHeader->Size == 0) {\r
312 return EFI_NOT_FOUND;\r
313 }\r
314 //\r
315 // Find the variable by walk through non-volatile variable store\r
316 //\r
317 IndexTable->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
318 IndexTable->EndPtr = (VARIABLE_HEADER *) ((UINTN) VariableStoreHeader + VariableStoreHeader->Size);\r
319\r
320 //\r
321 // Start Pointers for the variable.\r
322 // Actual Data Pointer where data can be written.\r
323 //\r
324 Variable = IndexTable->StartPtr;\r
325 }\r
326 }\r
327 //\r
328 // Find the variable by walk through non-volatile variable store\r
329 //\r
330 PtrTrack->StartPtr = IndexTable->StartPtr;\r
331 PtrTrack->EndPtr = IndexTable->EndPtr;\r
332\r
333 while (IsValidVariableHeader (Variable) && (Variable <= IndexTable->EndPtr)) {\r
334 if (Variable->State == VAR_ADDED) {\r
335 //\r
336 // Record Variable in VariableIndex HOB\r
337 //\r
338 if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME)\r
339 {\r
340 VariableIndexTableUpdate (IndexTable, Variable);\r
341 }\r
342\r
343 if (CompareWithValidVariable (Variable, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
344 return EFI_SUCCESS;\r
345 }\r
346 }\r
347\r
348 Variable = GetNextVariablePtr (Variable);\r
349 }\r
350 //\r
351 // If gone through the VariableStore, that means we never find in Firmware any more.\r
352 //\r
353 if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME) {\r
354 IndexTable->GoneThrough = 1;\r
355 }\r
356\r
357 PtrTrack->CurrPtr = NULL;\r
358\r
359 return EFI_NOT_FOUND;\r
360}\r
361\r
362EFI_STATUS\r
363EFIAPI\r
364PeiGetVariable (\r
ba237732
A
365 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,\r
366 IN CONST CHAR16 *VariableName,\r
367 IN CONST EFI_GUID *VariableGuid,\r
368 OUT UINT32 *Attributes,\r
369 IN OUT UINTN *DataSize,\r
370 OUT VOID *Data\r
7ff7768d 371 )\r
372/*++\r
373\r
374Routine Description:\r
375\r
376 Provide the read variable functionality of the variable services.\r
377\r
378Arguments:\r
379\r
380 PeiServices - General purpose services available to every PEIM.\r
381\r
382 VariableName - The variable name\r
383\r
384 VendorGuid - The vendor's GUID\r
385\r
386 Attributes - Pointer to the attribute\r
387\r
388 DataSize - Size of data\r
389\r
390 Data - Pointer to data\r
391\r
392Returns:\r
393\r
394 EFI_SUCCESS - The interface could be successfully installed\r
395\r
396 EFI_NOT_FOUND - The variable could not be discovered\r
397\r
398 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough\r
399\r
400--*/\r
401{\r
402 VARIABLE_POINTER_TRACK Variable;\r
403 UINTN VarDataSize;\r
404 EFI_STATUS Status;\r
ba237732 405 EFI_PEI_SERVICES **PeiServices;\r
7ff7768d 406\r
ba237732
A
407 PeiServices = GetPeiServicesTablePointer ();\r
408 if (VariableName == NULL || VariableGuid == NULL) {\r
7ff7768d 409 return EFI_INVALID_PARAMETER;\r
410 }\r
411 //\r
412 // Find existing variable\r
413 //\r
ba237732 414 Status = FindVariable (PeiServices, VariableName, VariableGuid, &Variable);\r
7ff7768d 415 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {\r
416 return Status;\r
417 }\r
418 //\r
419 // Get data size\r
420 //\r
421 VarDataSize = Variable.CurrPtr->DataSize;\r
422 if (*DataSize >= VarDataSize) {\r
423 (*PeiServices)->CopyMem (Data, GET_VARIABLE_DATA_PTR (Variable.CurrPtr), VarDataSize);\r
424\r
425 if (Attributes != NULL) {\r
426 *Attributes = Variable.CurrPtr->Attributes;\r
427 }\r
428\r
429 *DataSize = VarDataSize;\r
430 return EFI_SUCCESS;\r
431 } else {\r
432 *DataSize = VarDataSize;\r
433 return EFI_BUFFER_TOO_SMALL;\r
434 }\r
435}\r
436\r
437EFI_STATUS\r
438EFIAPI\r
439PeiGetNextVariableName (\r
ba237732
A
440 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,\r
441 IN OUT UINTN *VariableNameSize,\r
442 IN OUT CHAR16 *VariableName,\r
443 IN OUT EFI_GUID *VariableGuid\r
7ff7768d 444 )\r
445/*++\r
446\r
447Routine Description:\r
448\r
449 Provide the get next variable functionality of the variable services.\r
450\r
451Arguments:\r
452\r
453 PeiServices - General purpose services available to every PEIM.\r
454 VariabvleNameSize - The variable name's size.\r
455 VariableName - A pointer to the variable's name.\r
ba237732 456 VariableGuid - A pointer to the EFI_GUID structure.\r
7ff7768d 457\r
458 VariableNameSize - Size of the variable name\r
459\r
460 VariableName - The variable name\r
461\r
462 VendorGuid - The vendor's GUID\r
463\r
464Returns:\r
465\r
466 EFI_SUCCESS - The interface could be successfully installed\r
467\r
468 EFI_NOT_FOUND - The variable could not be discovered\r
469\r
470--*/\r
471{\r
472 VARIABLE_POINTER_TRACK Variable;\r
473 UINTN VarNameSize;\r
474 EFI_STATUS Status;\r
ba237732 475 EFI_PEI_SERVICES **PeiServices;\r
7ff7768d 476\r
ba237732 477 PeiServices = GetPeiServicesTablePointer ();\r
7ff7768d 478 if (VariableName == NULL) {\r
479 return EFI_INVALID_PARAMETER;\r
480 }\r
481\r
ba237732 482 Status = FindVariable (PeiServices, VariableName, VariableGuid, &Variable);\r
7ff7768d 483 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {\r
484 return Status;\r
485 }\r
486\r
487 if (VariableName[0] != 0) {\r
488 //\r
489 // If variable name is not NULL, get next variable\r
490 //\r
491 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
492 }\r
493\r
494 while (!(Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL)) {\r
495 if (IsValidVariableHeader (Variable.CurrPtr)) {\r
496 if (Variable.CurrPtr->State == VAR_ADDED) {\r
497 VarNameSize = (UINTN) Variable.CurrPtr->NameSize;\r
498 if (VarNameSize <= *VariableNameSize) {\r
499 (*PeiServices)->CopyMem (VariableName, GET_VARIABLE_NAME_PTR (Variable.CurrPtr), VarNameSize);\r
500\r
ba237732 501 (*PeiServices)->CopyMem (VariableGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));\r
7ff7768d 502\r
503 Status = EFI_SUCCESS;\r
504 } else {\r
505 Status = EFI_BUFFER_TOO_SMALL;\r
506 }\r
507\r
508 *VariableNameSize = VarNameSize;\r
509 return Status;\r
510 //\r
511 // Variable is found\r
512 //\r
513 } else {\r
514 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
515 }\r
516 } else {\r
517 break;\r
518 }\r
519 }\r
520\r
521 return EFI_NOT_FOUND;\r
522}\r