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