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