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