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