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