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