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