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