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