]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/VariablePei/Variable.c
Add VariablePei into IntelFrameworkModulePkg
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / VariablePei / Variable.c
CommitLineData
7ba905c9 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
21\r
22#include "Variable.h"\r
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_READ_ONLY_VARIABLE2_PPI mVariable2Ppi = {\r
33 PeiGetVariable2,\r
34 PeiGetNextVariableName2\r
35};\r
36\r
37static EFI_PEI_PPI_DESCRIPTOR mPpiListVariable[] = {\r
38 {\r
39 (EFI_PEI_PPI_DESCRIPTOR_PPI),\r
40 &gEfiPeiReadOnlyVariable2PpiGuid,\r
41 &mVariable2Ppi\r
42 },\r
43 {\r
44 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
45 &gEfiPeiReadOnlyVariablePpiGuid,\r
46 &mVariablePpi\r
47 }\r
48};\r
49\r
50EFI_GUID mEfiVariableIndexTableGuid = EFI_VARIABLE_INDEX_TABLE_GUID;\r
51\r
52EFI_STATUS\r
53EFIAPI\r
54PeimInitializeVariableServices (\r
55 IN EFI_FFS_FILE_HEADER *FfsHeader,\r
56 IN EFI_PEI_SERVICES **PeiServices\r
57 )\r
58/*++\r
59\r
60Routine Description:\r
61\r
62 Provide the functionality of the variable services.\r
63\r
64Arguments:\r
65\r
66 FfsHeadher - The FFS file header\r
67 PeiServices - General purpose services available to every PEIM.\r
68\r
69Returns:\r
70\r
71 Status - EFI_SUCCESS if the interface could be successfully\r
72 installed\r
73\r
74--*/\r
75{\r
76 //\r
77 // Publish the variable capability to other modules\r
78 //\r
79 return (**PeiServices).InstallPpi (PeiServices, &mPpiListVariable[0]);\r
80\r
81}\r
82\r
83STATIC\r
84VARIABLE_HEADER *\r
85GetNextVariablePtr (\r
86 IN VARIABLE_HEADER *Variable\r
87 )\r
88/*++\r
89\r
90Routine Description:\r
91\r
92 This code checks if variable header is valid or not.\r
93\r
94Arguments:\r
95 Variable Pointer to the Variable Header.\r
96\r
97Returns:\r
98 TRUE Variable header is valid.\r
99 FALSE Variable header is not valid.\r
100\r
101--*/\r
102{\r
103 return (VARIABLE_HEADER *) ((UINTN) GET_VARIABLE_DATA_PTR (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));\r
104}\r
105\r
106STATIC\r
107BOOLEAN\r
108EFIAPI\r
109IsValidVariableHeader (\r
110 IN VARIABLE_HEADER *Variable\r
111 )\r
112/*++\r
113\r
114Routine Description:\r
115\r
116 This code checks if variable header is valid or not.\r
117\r
118Arguments:\r
119 Variable Pointer to the Variable Header.\r
120\r
121Returns:\r
122 TRUE Variable header is valid.\r
123 FALSE Variable header is not valid.\r
124\r
125--*/\r
126{\r
127 if (Variable == NULL ||\r
128 Variable->StartId != VARIABLE_DATA ||\r
129 (sizeof (VARIABLE_HEADER) + Variable->DataSize + Variable->NameSize) > MAX_VARIABLE_SIZE\r
130 ) {\r
131 return FALSE;\r
132 }\r
133\r
134 return TRUE;\r
135}\r
136\r
137STATIC\r
138VARIABLE_STORE_STATUS\r
139EFIAPI\r
140GetVariableStoreStatus (\r
141 IN VARIABLE_STORE_HEADER *VarStoreHeader\r
142 )\r
143/*++\r
144\r
145Routine Description:\r
146\r
147 This code gets the pointer to the variable name.\r
148\r
149Arguments:\r
150\r
151 VarStoreHeader Pointer to the Variable Store Header.\r
152\r
153Returns:\r
154\r
155 EfiRaw Variable store is raw\r
156 EfiValid Variable store is valid\r
157 EfiInvalid Variable store is invalid\r
158\r
159--*/\r
160{\r
161 if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE &&\r
162 VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&\r
163 VarStoreHeader->State == VARIABLE_STORE_HEALTHY\r
164 ) {\r
165\r
166 return EfiValid;\r
167 }\r
168\r
169 if (VarStoreHeader->Signature == 0xffffffff &&\r
170 VarStoreHeader->Size == 0xffffffff &&\r
171 VarStoreHeader->Format == 0xff &&\r
172 VarStoreHeader->State == 0xff\r
173 ) {\r
174\r
175 return EfiRaw;\r
176 } else {\r
177 return EfiInvalid;\r
178 }\r
179}\r
180\r
181STATIC\r
182EFI_STATUS\r
183CompareWithValidVariable (\r
184 IN VARIABLE_HEADER *Variable,\r
185 IN CONST CHAR16 *VariableName,\r
186 IN CONST EFI_GUID *VendorGuid,\r
187 OUT VARIABLE_POINTER_TRACK *PtrTrack\r
188 )\r
189/*++\r
190\r
191Routine Description:\r
192\r
193 This function compares a variable with variable entries in database\r
194\r
195Arguments:\r
196\r
197 Variable - Pointer to the variable in our database\r
198 VariableName - Name of the variable to compare to 'Variable'\r
199 VendorGuid - GUID of the variable to compare to 'Variable'\r
200 PtrTrack - Variable Track Pointer structure that contains\r
201 Variable Information.\r
202\r
203Returns:\r
204\r
205 EFI_SUCCESS - Found match variable\r
206 EFI_NOT_FOUND - Variable not found\r
207\r
208--*/\r
209{\r
210 if (VariableName[0] == 0) {\r
211 PtrTrack->CurrPtr = Variable;\r
212 return EFI_SUCCESS;\r
213 } else {\r
214 //\r
215 // Don't use CompareGuid function here for performance reasons.\r
216 // Instead we compare the GUID a UINT32 at a time and branch\r
217 // on the first failed comparison.\r
218 //\r
219 if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &Variable->VendorGuid)[0]) &&\r
220 (((INT32 *) VendorGuid)[1] == ((INT32 *) &Variable->VendorGuid)[1]) &&\r
221 (((INT32 *) VendorGuid)[2] == ((INT32 *) &Variable->VendorGuid)[2]) &&\r
222 (((INT32 *) VendorGuid)[3] == ((INT32 *) &Variable->VendorGuid)[3])\r
223 ) {\r
224 if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable), Variable->NameSize)) {\r
225 PtrTrack->CurrPtr = Variable;\r
226 return EFI_SUCCESS;\r
227 }\r
228 }\r
229 }\r
230\r
231 return EFI_NOT_FOUND;\r
232}\r
233\r
234STATIC\r
235EFI_STATUS\r
236EFIAPI\r
237FindVariable (\r
238 IN EFI_PEI_SERVICES **PeiServices,\r
239 IN CONST CHAR16 *VariableName,\r
240 IN CONST EFI_GUID *VendorGuid,\r
241 OUT VARIABLE_POINTER_TRACK *PtrTrack\r
242 )\r
243/*++\r
244\r
245Routine Description:\r
246\r
247 This code finds variable in storage blocks (Non-Volatile)\r
248\r
249Arguments:\r
250\r
251 PeiServices - General purpose services available to every PEIM.\r
252 VariableName - Name of the variable to be found\r
253 VendorGuid - Vendor GUID to be found.\r
254 PtrTrack - Variable Track Pointer structure that contains\r
255 Variable Information.\r
256\r
257Returns:\r
258\r
259 EFI_SUCCESS - Variable found successfully\r
260 EFI_NOT_FOUND - Variable not found\r
261 EFI_INVALID_PARAMETER - Invalid variable name\r
262\r
263--*/\r
264{\r
265 EFI_HOB_GUID_TYPE *GuidHob;\r
266 VARIABLE_STORE_HEADER *VariableStoreHeader;\r
267 VARIABLE_HEADER *Variable;\r
268 VARIABLE_HEADER *MaxIndex;\r
269 VARIABLE_INDEX_TABLE *IndexTable;\r
270 UINT32 Count;\r
271 UINT8 *VariableBase;\r
272\r
273 if (VariableName != 0 && VendorGuid == NULL) {\r
274 return EFI_INVALID_PARAMETER;\r
275 }\r
276 //\r
277 // No Variable Address equals zero, so 0 as initial value is safe.\r
278 //\r
279 MaxIndex = 0;\r
280\r
281 GuidHob = GetFirstGuidHob (&mEfiVariableIndexTableGuid);\r
282 if (GuidHob == NULL) {\r
283 IndexTable = BuildGuidHob (&mEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));\r
284 IndexTable->Length = 0;\r
285 IndexTable->StartPtr = NULL;\r
286 IndexTable->EndPtr = NULL;\r
287 IndexTable->GoneThrough = 0;\r
288 } else {\r
289 IndexTable = GET_GUID_HOB_DATA (GuidHob);\r
290 for (Count = 0; Count < IndexTable->Length; Count++)\r
291 {\r
292 MaxIndex = GetVariableByIndex (IndexTable, Count);\r
293\r
294 if (CompareWithValidVariable (MaxIndex, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
295 PtrTrack->StartPtr = IndexTable->StartPtr;\r
296 PtrTrack->EndPtr = IndexTable->EndPtr;\r
297\r
298 return EFI_SUCCESS;\r
299 }\r
300 }\r
301\r
302 if (IndexTable->GoneThrough) {\r
303 return EFI_NOT_FOUND;\r
304 }\r
305 }\r
306 //\r
307 // If not found in HOB, then let's start from the MaxIndex we've found.\r
308 //\r
309 if (MaxIndex != NULL) {\r
310 Variable = GetNextVariablePtr (MaxIndex);\r
311 } else {\r
312 if (IndexTable->StartPtr || IndexTable->EndPtr) {\r
313 Variable = IndexTable->StartPtr;\r
314 } else {\r
315 VariableBase = (UINT8 *) (UINTN) PcdGet32 (PcdFlashNvStorageVariableBase);\r
316 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (VariableBase + \\r
317 ((EFI_FIRMWARE_VOLUME_HEADER *) (VariableBase)) -> HeaderLength);\r
318\r
319 if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {\r
320 return EFI_UNSUPPORTED;\r
321 }\r
322\r
323 if (~VariableStoreHeader->Size == 0) {\r
324 return EFI_NOT_FOUND;\r
325 }\r
326 //\r
327 // Find the variable by walk through non-volatile variable store\r
328 //\r
329 IndexTable->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
330 IndexTable->EndPtr = (VARIABLE_HEADER *) ((UINTN) VariableStoreHeader + VariableStoreHeader->Size);\r
331\r
332 //\r
333 // Start Pointers for the variable.\r
334 // Actual Data Pointer where data can be written.\r
335 //\r
336 Variable = IndexTable->StartPtr;\r
337 }\r
338 }\r
339 //\r
340 // Find the variable by walk through non-volatile variable store\r
341 //\r
342 PtrTrack->StartPtr = IndexTable->StartPtr;\r
343 PtrTrack->EndPtr = IndexTable->EndPtr;\r
344\r
345 while (IsValidVariableHeader (Variable) && (Variable <= IndexTable->EndPtr)) {\r
346 if (Variable->State == VAR_ADDED) {\r
347 //\r
348 // Record Variable in VariableIndex HOB\r
349 //\r
350 if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME)\r
351 {\r
352 VariableIndexTableUpdate (IndexTable, Variable);\r
353 }\r
354\r
355 if (CompareWithValidVariable (Variable, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
356 return EFI_SUCCESS;\r
357 }\r
358 }\r
359\r
360 Variable = GetNextVariablePtr (Variable);\r
361 }\r
362 //\r
363 // If gone through the VariableStore, that means we never find in Firmware any more.\r
364 //\r
365 if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME) {\r
366 IndexTable->GoneThrough = 1;\r
367 }\r
368\r
369 PtrTrack->CurrPtr = NULL;\r
370\r
371 return EFI_NOT_FOUND;\r
372}\r
373\r
374EFI_STATUS\r
375EFIAPI\r
376PeiGetVariable (\r
377 IN EFI_PEI_SERVICES **PeiServices,\r
378 IN CHAR16 *VariableName,\r
379 IN EFI_GUID * VendorGuid,\r
380 OUT UINT32 *Attributes OPTIONAL,\r
381 IN OUT UINTN *DataSize,\r
382 OUT VOID *Data\r
383 )\r
384/*++\r
385\r
386Routine Description:\r
387\r
388 Provide the read variable functionality of the variable services.\r
389\r
390Arguments:\r
391\r
392 PeiServices - General purpose services available to every PEIM.\r
393\r
394 VariableName - The variable name\r
395\r
396 VendorGuid - The vendor's GUID\r
397\r
398 Attributes - Pointer to the attribute\r
399\r
400 DataSize - Size of data\r
401\r
402 Data - Pointer to data\r
403\r
404Returns:\r
405\r
406 EFI_SUCCESS - The interface could be successfully installed\r
407\r
408 EFI_NOT_FOUND - The variable could not be discovered\r
409\r
410 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough\r
411\r
412--*/\r
413{\r
414 VARIABLE_POINTER_TRACK Variable;\r
415 UINTN VarDataSize;\r
416 EFI_STATUS Status;\r
417\r
418 if (VariableName == NULL || VendorGuid == NULL) {\r
419 return EFI_INVALID_PARAMETER;\r
420 }\r
421 //\r
422 // Find existing variable\r
423 //\r
424 Status = FindVariable (PeiServices, VariableName, VendorGuid, &Variable);\r
425\r
426 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {\r
427 return Status;\r
428 }\r
429 //\r
430 // Get data size\r
431 //\r
432 VarDataSize = Variable.CurrPtr->DataSize;\r
433 if (*DataSize >= VarDataSize) {\r
434 (*PeiServices)->CopyMem (Data, GET_VARIABLE_DATA_PTR (Variable.CurrPtr), VarDataSize);\r
435\r
436 if (Attributes != NULL) {\r
437 *Attributes = Variable.CurrPtr->Attributes;\r
438 }\r
439\r
440 *DataSize = VarDataSize;\r
441 return EFI_SUCCESS;\r
442 } else {\r
443 *DataSize = VarDataSize;\r
444 return EFI_BUFFER_TOO_SMALL;\r
445 }\r
446}\r
447\r
448\r
449EFI_STATUS\r
450EFIAPI\r
451PeiGetVariable2 (\r
452 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,\r
453 IN CONST CHAR16 *VariableName,\r
454 IN CONST EFI_GUID *VariableGuid,\r
455 OUT UINT32 *Attributes,\r
456 IN OUT UINTN *DataSize,\r
457 OUT VOID *Data\r
458 )\r
459/*++\r
460\r
461Routine Description:\r
462\r
463 Provide the read variable functionality of the variable services.\r
464\r
465Arguments:\r
466\r
467 PeiServices - General purpose services available to every PEIM.\r
468\r
469 VariableName - The variable name\r
470\r
471 VendorGuid - The vendor's GUID\r
472\r
473 Attributes - Pointer to the attribute\r
474\r
475 DataSize - Size of data\r
476\r
477 Data - Pointer to data\r
478\r
479Returns:\r
480\r
481 EFI_SUCCESS - The interface could be successfully installed\r
482\r
483 EFI_NOT_FOUND - The variable could not be discovered\r
484\r
485 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough\r
486\r
487--*/\r
488{\r
489 return PeiGetVariable (\r
490 GetPeiServicesTablePointer (),\r
491 (CHAR16*)VariableName,\r
492 (EFI_GUID*)VariableGuid,\r
493 Attributes,\r
494 DataSize,\r
495 Data\r
496 );\r
497}\r
498\r
499EFI_STATUS\r
500EFIAPI\r
501PeiGetNextVariableName (\r
502 IN EFI_PEI_SERVICES **PeiServices,\r
503 IN OUT UINTN *VariableNameSize,\r
504 IN OUT CHAR16 *VariableName,\r
505 IN OUT EFI_GUID *VendorGuid\r
506 )\r
507/*++\r
508\r
509Routine Description:\r
510\r
511 Provide the get next variable functionality of the variable services.\r
512\r
513Arguments:\r
514\r
515 PeiServices - General purpose services available to every PEIM.\r
516 VariabvleNameSize - The variable name's size.\r
517 VariableName - A pointer to the variable's name.\r
518 VendorGuid - A pointer to the EFI_GUID structure.\r
519\r
520 VariableNameSize - Size of the variable name\r
521\r
522 VariableName - The variable name\r
523\r
524 VendorGuid - The vendor's GUID\r
525\r
526Returns:\r
527\r
528 EFI_SUCCESS - The interface could be successfully installed\r
529\r
530 EFI_NOT_FOUND - The variable could not be discovered\r
531\r
532--*/\r
533{\r
534 VARIABLE_POINTER_TRACK Variable;\r
535 UINTN VarNameSize;\r
536 EFI_STATUS Status;\r
537\r
538 if (VariableName == NULL) {\r
539 return EFI_INVALID_PARAMETER;\r
540 }\r
541\r
542 Status = FindVariable (PeiServices, VariableName, VendorGuid, &Variable);\r
543\r
544 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {\r
545 return Status;\r
546 }\r
547\r
548 if (VariableName[0] != 0) {\r
549 //\r
550 // If variable name is not NULL, get next variable\r
551 //\r
552 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
553 }\r
554\r
555 while (!(Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL)) {\r
556 if (IsValidVariableHeader (Variable.CurrPtr)) {\r
557 if (Variable.CurrPtr->State == VAR_ADDED) {\r
558 VarNameSize = (UINTN) Variable.CurrPtr->NameSize;\r
559 if (VarNameSize <= *VariableNameSize) {\r
560 (*PeiServices)->CopyMem (VariableName, GET_VARIABLE_NAME_PTR (Variable.CurrPtr), VarNameSize);\r
561\r
562 (*PeiServices)->CopyMem (VendorGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));\r
563\r
564 Status = EFI_SUCCESS;\r
565 } else {\r
566 Status = EFI_BUFFER_TOO_SMALL;\r
567 }\r
568\r
569 *VariableNameSize = VarNameSize;\r
570 return Status;\r
571 //\r
572 // Variable is found\r
573 //\r
574 } else {\r
575 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
576 }\r
577 } else {\r
578 break;\r
579 }\r
580 }\r
581\r
582 return EFI_NOT_FOUND;\r
583}\r
584\r
585EFI_STATUS\r
586EFIAPI\r
587PeiGetNextVariableName2 (\r
588 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,\r
589 IN OUT UINTN *VariableNameSize,\r
590 IN OUT CHAR16 *VariableName,\r
591 IN OUT EFI_GUID *VariableGuid\r
592 )\r
593/*++\r
594\r
595Routine Description:\r
596\r
597 Provide the get next variable functionality of the variable services.\r
598\r
599Arguments:\r
600\r
601 PeiServices - General purpose services available to every PEIM.\r
602 VariabvleNameSize - The variable name's size.\r
603 VariableName - A pointer to the variable's name.\r
604 VariableGuid - A pointer to the EFI_GUID structure.\r
605\r
606 VariableNameSize - Size of the variable name\r
607\r
608 VariableName - The variable name\r
609\r
610 VendorGuid - The vendor's GUID\r
611\r
612Returns:\r
613\r
614 EFI_SUCCESS - The interface could be successfully installed\r
615\r
616 EFI_NOT_FOUND - The variable could not be discovered\r
617\r
618--*/\r
619{\r
620 return PeiGetNextVariableName (\r
621 GetPeiServicesTablePointer (),\r
622 VariableNameSize,\r
623 VariableName,\r
624 VariableGuid\r
625 );\r
626}