]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/Variable/Pei/Variable.c
1. Add scroll bars to Package Library Class Declarations editor.
[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
71VARIABLE_HEADER *\r
72GetNextVariablePtr (\r
73 IN VARIABLE_HEADER *Variable\r
74 )\r
75/*++\r
76\r
77Routine Description:\r
78\r
79 This code checks if variable header is valid or not.\r
80\r
81Arguments:\r
82 Variable Pointer to the Variable Header.\r
83\r
84Returns:\r
85 TRUE Variable header is valid.\r
86 FALSE Variable header is not valid.\r
87\r
88--*/\r
89{\r
90 return (VARIABLE_HEADER *) ((UINTN) GET_VARIABLE_DATA_PTR (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));\r
91}\r
92\r
93BOOLEAN\r
94EFIAPI\r
95IsValidVariableHeader (\r
96 IN VARIABLE_HEADER *Variable\r
97 )\r
98/*++\r
99\r
100Routine Description:\r
101\r
102 This code checks if variable header is valid or not.\r
103\r
104Arguments:\r
105 Variable Pointer to the Variable Header.\r
106\r
107Returns:\r
108 TRUE Variable header is valid.\r
109 FALSE Variable header is not valid.\r
110\r
111--*/\r
112{\r
113 if (Variable == NULL ||\r
114 Variable->StartId != VARIABLE_DATA ||\r
115 (sizeof (VARIABLE_HEADER) + Variable->DataSize + Variable->NameSize) > MAX_VARIABLE_SIZE\r
116 ) {\r
117 return FALSE;\r
118 }\r
119\r
120 return TRUE;\r
121}\r
122\r
123VARIABLE_STORE_STATUS\r
124EFIAPI\r
125GetVariableStoreStatus (\r
126 IN VARIABLE_STORE_HEADER *VarStoreHeader\r
127 )\r
128/*++\r
129\r
130Routine Description:\r
131\r
132 This code gets the pointer to the variable name.\r
133\r
134Arguments:\r
135\r
136 VarStoreHeader Pointer to the Variable Store Header.\r
137\r
138Returns:\r
139\r
140 EfiRaw Variable store is raw\r
141 EfiValid Variable store is valid\r
142 EfiInvalid Variable store is invalid\r
143\r
144--*/\r
145{\r
146 if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE &&\r
147 VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&\r
148 VarStoreHeader->State == VARIABLE_STORE_HEALTHY\r
149 ) {\r
150\r
151 return EfiValid;\r
152 }\r
153\r
154 if (VarStoreHeader->Signature == 0xffffffff &&\r
155 VarStoreHeader->Size == 0xffffffff &&\r
156 VarStoreHeader->Format == 0xff &&\r
157 VarStoreHeader->State == 0xff\r
158 ) {\r
159\r
160 return EfiRaw;\r
161 } else {\r
162 return EfiInvalid;\r
163 }\r
164}\r
165\r
166EFI_STATUS\r
167CompareWithValidVariable (\r
168 IN VARIABLE_HEADER *Variable,\r
169 IN CHAR16 *VariableName,\r
170 IN EFI_GUID *VendorGuid,\r
171 OUT VARIABLE_POINTER_TRACK *PtrTrack\r
172 )\r
173/*++\r
174\r
175Routine Description:\r
176\r
177 This function compares a variable with variable entries in database\r
178\r
179Arguments:\r
180\r
181 Variable - Pointer to the variable in our database\r
182 VariableName - Name of the variable to compare to 'Variable'\r
183 VendorGuid - GUID of the variable to compare to 'Variable'\r
184 PtrTrack - Variable Track Pointer structure that contains\r
185 Variable Information.\r
186\r
187Returns:\r
188\r
189 EFI_SUCCESS - Found match variable\r
190 EFI_NOT_FOUND - Variable not found\r
191 \r
192--*/\r
193{\r
194 if (VariableName[0] == 0) {\r
195 PtrTrack->CurrPtr = Variable;\r
196 return EFI_SUCCESS;\r
197 } else {\r
198 //\r
199 // Don't use CompareGuid function here for performance reasons.\r
200 // Instead we compare the GUID a UINT32 at a time and branch\r
201 // on the first failed comparison.\r
202 //\r
203 if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &Variable->VendorGuid)[0]) &&\r
204 (((INT32 *) VendorGuid)[1] == ((INT32 *) &Variable->VendorGuid)[1]) &&\r
205 (((INT32 *) VendorGuid)[2] == ((INT32 *) &Variable->VendorGuid)[2]) &&\r
206 (((INT32 *) VendorGuid)[3] == ((INT32 *) &Variable->VendorGuid)[3])\r
207 ) {\r
208 if (!StrCmp (VariableName, GET_VARIABLE_NAME_PTR (Variable))) {\r
209 PtrTrack->CurrPtr = Variable;\r
210 return EFI_SUCCESS;\r
211 }\r
212 }\r
213 }\r
214\r
215 return EFI_NOT_FOUND;\r
216}\r
217\r
218EFI_STATUS\r
219EFIAPI\r
220FindVariable (\r
221 IN EFI_PEI_SERVICES **PeiServices,\r
222 IN CHAR16 *VariableName,\r
223 IN EFI_GUID *VendorGuid,\r
224 OUT VARIABLE_POINTER_TRACK *PtrTrack\r
225 )\r
226/*++\r
227\r
228Routine Description:\r
229\r
230 This code finds variable in storage blocks (Non-Volatile)\r
231\r
232Arguments:\r
233\r
234 PeiServices - General purpose services available to every PEIM.\r
235 VariableName - Name of the variable to be found\r
236 VendorGuid - Vendor GUID to be found.\r
237 PtrTrack - Variable Track Pointer structure that contains\r
238 Variable Information.\r
239\r
240Returns:\r
241\r
242 EFI_SUCCESS - Variable found successfully\r
243 EFI_NOT_FOUND - Variable not found\r
244 EFI_INVALID_PARAMETER - Invalid variable name\r
245\r
246--*/\r
247{\r
248 PEI_FLASH_MAP_PPI *FlashMapPpi;\r
249 EFI_FLASH_SUBAREA_ENTRY *VariableStoreEntry;\r
250 UINT32 NumEntries;\r
251 EFI_HOB_GUID_TYPE *GuidHob;\r
252 VARIABLE_STORE_HEADER *VariableStoreHeader;\r
253 VARIABLE_HEADER *Variable;\r
254\r
255 EFI_STATUS Status;\r
256\r
257 VARIABLE_HEADER *MaxIndex;\r
258 VARIABLE_INDEX_TABLE *IndexTable;\r
259 UINT32 Count;\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 (&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
308 //\r
309 // Locate FlashMap PPI\r
310 //\r
311 Status = (**PeiServices).LocatePpi (\r
312 PeiServices,\r
313 &gPeiFlashMapPpiGuid,\r
314 0,\r
315 NULL,\r
316 (VOID **) &FlashMapPpi\r
317 );\r
318 ASSERT_EFI_ERROR (Status);\r
319\r
320 //\r
321 // Get flash area info for variables\r
322 //\r
323 Status = FlashMapPpi->GetAreaInfo (\r
324 PeiServices,\r
325 FlashMapPpi,\r
326 EFI_FLASH_AREA_EFI_VARIABLES,\r
327 NULL,\r
328 &NumEntries,\r
329 &VariableStoreEntry\r
330 );\r
331\r
332 //\r
333 // Currently only one non-volatile variable store is supported\r
334 //\r
335 if (NumEntries != 1) {\r
336 return EFI_UNSUPPORTED;\r
337 }\r
338\r
339 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (UINTN) (VariableStoreEntry->Base);\r
340\r
341 if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {\r
342 return EFI_UNSUPPORTED;\r
343 }\r
344\r
345 if (~VariableStoreHeader->Size == 0) {\r
346 return EFI_NOT_FOUND;\r
347 }\r
348 //\r
349 // Find the variable by walk through non-volatile variable store\r
350 //\r
351 IndexTable->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
352 IndexTable->EndPtr = (VARIABLE_HEADER *) ((UINTN) VariableStoreHeader + VariableStoreHeader->Size);\r
353\r
354 //\r
355 // Start Pointers for the variable.\r
356 // Actual Data Pointer where data can be written.\r
357 //\r
358 Variable = IndexTable->StartPtr;\r
359 }\r
360 }\r
361 //\r
362 // Find the variable by walk through non-volatile variable store\r
363 //\r
364 PtrTrack->StartPtr = IndexTable->StartPtr;\r
365 PtrTrack->EndPtr = IndexTable->EndPtr;\r
366\r
367 while (IsValidVariableHeader (Variable) && (Variable <= IndexTable->EndPtr)) {\r
368 if (Variable->State == VAR_ADDED) {\r
369 //\r
370 // Record Variable in VariableIndex HOB\r
371 //\r
372 if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME)\r
373 {\r
374#if ALIGNMENT <= 1\r
375 IndexTable->Index[IndexTable->Length++] = (UINT16) (UINTN) Variable;\r
376#else\r
377#if ALIGNMENT >= 4\r
378 IndexTable->Index[IndexTable->Length++] = (UINT16) (((UINT32)(UINTN) Variable) >> 2);\r
379#endif\r
380#endif\r
381 }\r
382\r
383 if (CompareWithValidVariable (Variable, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
384 return EFI_SUCCESS;\r
385 }\r
386 }\r
387\r
388 Variable = GetNextVariablePtr (Variable);\r
389 }\r
390 //\r
391 // If gone through the VariableStore, that means we never find in Firmware any more.\r
392 //\r
393 if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME) {\r
394 IndexTable->GoneThrough = 1;\r
395 }\r
396\r
397 PtrTrack->CurrPtr = NULL;\r
398\r
399 return EFI_NOT_FOUND;\r
400}\r
401\r
402EFI_STATUS\r
403EFIAPI\r
404PeiGetVariable (\r
405 IN EFI_PEI_SERVICES **PeiServices,\r
406 IN CHAR16 *VariableName,\r
407 IN EFI_GUID * VendorGuid,\r
408 OUT UINT32 *Attributes OPTIONAL,\r
409 IN OUT UINTN *DataSize,\r
410 OUT VOID *Data\r
411 )\r
412/*++\r
413\r
414Routine Description:\r
415\r
416 Provide the read variable functionality of the variable services.\r
417\r
418Arguments:\r
419\r
420 PeiServices - General purpose services available to every PEIM.\r
421\r
422 VariableName - The variable name\r
423\r
424 VendorGuid - The vendor's GUID\r
425\r
426 Attributes - Pointer to the attribute\r
427\r
428 DataSize - Size of data\r
429\r
430 Data - Pointer to data\r
431\r
432Returns:\r
433\r
434 EFI_SUCCESS - The interface could be successfully installed\r
435\r
436 EFI_NOT_FOUND - The variable could not be discovered\r
437\r
438 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough\r
439\r
440--*/\r
441{\r
442 VARIABLE_POINTER_TRACK Variable;\r
443 UINTN VarDataSize;\r
444 EFI_STATUS Status;\r
445\r
446 if (VariableName == NULL || VendorGuid == NULL) {\r
447 return EFI_INVALID_PARAMETER;\r
448 }\r
449 //\r
450 // Find existing variable\r
451 //\r
452 Status = FindVariable (PeiServices, VariableName, VendorGuid, &Variable);\r
453\r
454 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {\r
455 return Status;\r
456 }\r
457 //\r
458 // Get data size\r
459 //\r
460 VarDataSize = Variable.CurrPtr->DataSize;\r
461 if (*DataSize >= VarDataSize) {\r
462 (*PeiServices)->CopyMem (Data, GET_VARIABLE_DATA_PTR (Variable.CurrPtr), VarDataSize);\r
463\r
464 if (Attributes != NULL) {\r
465 *Attributes = Variable.CurrPtr->Attributes;\r
466 }\r
467\r
468 *DataSize = VarDataSize;\r
469 return EFI_SUCCESS;\r
470 } else {\r
471 *DataSize = VarDataSize;\r
472 return EFI_BUFFER_TOO_SMALL;\r
473 }\r
474}\r
475\r
476EFI_STATUS\r
477EFIAPI\r
478PeiGetNextVariableName (\r
479 IN EFI_PEI_SERVICES **PeiServices,\r
480 IN OUT UINTN *VariableNameSize,\r
481 IN OUT CHAR16 *VariableName,\r
482 IN OUT EFI_GUID *VendorGuid\r
483 )\r
484/*++\r
485\r
486Routine Description:\r
487\r
488 Provide the get next variable functionality of the variable services.\r
489\r
490Arguments:\r
491\r
492 PeiServices - General purpose services available to every PEIM.\r
493 VariabvleNameSize - The variable name's size.\r
494 VariableName - A pointer to the variable's name.\r
495 VendorGuid - A pointer to the EFI_GUID structure.\r
496\r
497 VariableNameSize - Size of the variable name\r
498\r
499 VariableName - The variable name\r
500\r
501 VendorGuid - The vendor's GUID\r
502\r
503Returns:\r
504\r
505 EFI_SUCCESS - The interface could be successfully installed\r
506\r
507 EFI_NOT_FOUND - The variable could not be discovered\r
508\r
509--*/\r
510{\r
511 VARIABLE_POINTER_TRACK Variable;\r
512 UINTN VarNameSize;\r
513 EFI_STATUS Status;\r
514\r
515 if (VariableName == NULL) {\r
516 return EFI_INVALID_PARAMETER;\r
517 }\r
518\r
519 Status = FindVariable (PeiServices, VariableName, VendorGuid, &Variable);\r
520\r
521 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {\r
522 return Status;\r
523 }\r
524\r
525 if (VariableName[0] != 0) {\r
526 //\r
527 // If variable name is not NULL, get next variable\r
528 //\r
529 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
530 }\r
531\r
532 while (!(Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL)) {\r
533 if (IsValidVariableHeader (Variable.CurrPtr)) {\r
534 if (Variable.CurrPtr->State == VAR_ADDED) {\r
535 VarNameSize = (UINTN) Variable.CurrPtr->NameSize;\r
536 if (VarNameSize <= *VariableNameSize) {\r
537 (*PeiServices)->CopyMem (VariableName, GET_VARIABLE_NAME_PTR (Variable.CurrPtr), VarNameSize);\r
538\r
539 (*PeiServices)->CopyMem (VendorGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));\r
540\r
541 Status = EFI_SUCCESS;\r
542 } else {\r
543 Status = EFI_BUFFER_TOO_SMALL;\r
544 }\r
545\r
546 *VariableNameSize = VarNameSize;\r
547 return Status;\r
548 //\r
549 // Variable is found\r
550 //\r
551 } else {\r
552 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
553 }\r
554 } else {\r
555 break;\r
556 }\r
557 }\r
558\r
559 return EFI_NOT_FOUND;\r
560}\r