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