]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c
Patch to remove STATIC modifier. This is on longer recommended by EFI Framework codin...
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / EmuRuntimeDxe / EmuVariable.c
1 /** @file
2
3 Emulation Variable services operate on the runtime volatile memory.
4 The nonvolatile variable space doesn't exist.
5
6 Copyright (c) 2006 - 2008, Intel Corporation
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
15 **/
16
17 #include "Variable.h"
18
19 //
20 // Don't use module globals after the SetVirtualAddress map is signaled
21 //
22 ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal;
23
24 //
25 // This is a temperary function which will be removed
26 // when EfiAcquireLock in UefiLib can handle the
27 // the call in UEFI Runtimer driver in RT phase.
28 //
29 VOID
30 AcquireLockOnlyAtBootTime (
31 IN EFI_LOCK *Lock
32 )
33 {
34 if (!EfiAtRuntime ()) {
35 EfiAcquireLock (Lock);
36 }
37 }
38
39 //
40 // This is a temperary function which will be removed
41 // when EfiAcquireLock in UefiLib can handle the
42 // the call in UEFI Runtimer driver in RT phase.
43 //
44 VOID
45 ReleaseLockOnlyAtBootTime (
46 IN EFI_LOCK *Lock
47 )
48 {
49 if (!EfiAtRuntime ()) {
50 EfiReleaseLock (Lock);
51 }
52 }
53
54 UINT8 *
55 GetVariableDataPtr (
56 IN VARIABLE_HEADER *Variable
57 )
58 /*++
59
60 Routine Description:
61
62 This code gets the pointer to the variable data.
63
64 Arguments:
65
66 Variable Pointer to the Variable Header.
67
68 Returns:
69
70 UINT8* Pointer to Variable Data
71
72 --*/
73 {
74 if (Variable->StartId != VARIABLE_DATA) {
75 return NULL;
76 }
77 //
78 // Be careful about pad size for alignment
79 //
80 return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize));
81 }
82
83 VARIABLE_HEADER *
84 GetNextVariablePtr (
85 IN VARIABLE_HEADER *Variable
86 )
87 /*++
88
89 Routine Description:
90
91 This code gets the pointer to the next variable header.
92
93 Arguments:
94
95 Variable Pointer to the Variable Header.
96
97 Returns:
98
99 VARIABLE_HEADER* Pointer to next variable header.
100
101 --*/
102 {
103 VARIABLE_HEADER *VarHeader;
104
105 if (Variable->StartId != VARIABLE_DATA) {
106 return NULL;
107 }
108 //
109 // Be careful about pad size for alignment
110 //
111 VarHeader = (VARIABLE_HEADER *) (GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));
112
113 if (VarHeader->StartId != VARIABLE_DATA ||
114 (sizeof (VARIABLE_HEADER) + VarHeader->DataSize + VarHeader->NameSize) > MAX_VARIABLE_SIZE
115 ) {
116 return NULL;
117 }
118
119 return VarHeader;
120 }
121
122 VARIABLE_HEADER *
123 GetEndPointer (
124 IN VARIABLE_STORE_HEADER *VolHeader
125 )
126 /*++
127
128 Routine Description:
129
130 This code gets the pointer to the last variable memory pointer byte
131
132 Arguments:
133
134 Variable Pointer to the Variable Header.
135
136 Returns:
137
138 VARIABLE_HEADER* Pointer to last unavailable Variable Header
139
140 --*/
141 {
142 //
143 // The end of variable store
144 //
145 return (VARIABLE_HEADER *) ((UINTN) VolHeader + VolHeader->Size);
146 }
147
148 EFI_STATUS
149 FindVariable (
150 IN CHAR16 *VariableName,
151 IN EFI_GUID *VendorGuid,
152 OUT VARIABLE_POINTER_TRACK *PtrTrack,
153 IN VARIABLE_GLOBAL *Global
154 )
155 /*++
156
157 Routine Description:
158
159 This code finds variable in storage blocks (Volatile or Non-Volatile)
160
161 Arguments:
162
163 VariableName Name of the variable to be found
164 VendorGuid Vendor GUID to be found.
165 PtrTrack Variable Track Pointer structure that contains
166 Variable Information.
167 Contains the pointer of Variable header.
168 Global VARIABLE_GLOBAL pointer
169
170 Returns:
171
172 EFI STATUS
173
174 --*/
175 {
176 VARIABLE_HEADER *Variable[2];
177 VARIABLE_STORE_HEADER *VariableStoreHeader[2];
178 UINTN Index;
179
180 //
181 // We aquire the lock at the entry of FindVariable as GetVariable, GetNextVariableName
182 // SetVariable all call FindVariable at entry point. Please move "Aquire Lock" to
183 // the correct places if this assumption does not hold TRUE anymore.
184 //
185 AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);
186
187 //
188 // 0: Non-Volatile, 1: Volatile
189 //
190 VariableStoreHeader[0] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);
191 VariableStoreHeader[1] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);
192
193 //
194 // Start Pointers for the variable.
195 // Actual Data Pointer where data can be written.
196 //
197 Variable[0] = (VARIABLE_HEADER *) (VariableStoreHeader[0] + 1);
198 Variable[1] = (VARIABLE_HEADER *) (VariableStoreHeader[1] + 1);
199
200 if (VariableName[0] != 0 && VendorGuid == NULL) {
201 return EFI_INVALID_PARAMETER;
202 }
203 //
204 // Find the variable by walk through non-volatile and volatile variable store
205 //
206 for (Index = 0; Index < 2; Index++) {
207 PtrTrack->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader[Index] + 1);
208 PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]);
209
210 while ((Variable[Index] != NULL) && (Variable[Index] <= GetEndPointer (VariableStoreHeader[Index]))) {
211 if (Variable[Index]->StartId == VARIABLE_DATA && Variable[Index]->State == VAR_ADDED) {
212 if (!(EfiAtRuntime () && !(Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {
213 if (VariableName[0] == 0) {
214 PtrTrack->CurrPtr = Variable[Index];
215 PtrTrack->Volatile = (BOOLEAN) Index;
216 return EFI_SUCCESS;
217 } else {
218 if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) {
219 if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), Variable[Index]->NameSize)) {
220 PtrTrack->CurrPtr = Variable[Index];
221 PtrTrack->Volatile = (BOOLEAN) Index;
222 return EFI_SUCCESS;
223 }
224 }
225 }
226 }
227 }
228
229 Variable[Index] = GetNextVariablePtr (Variable[Index]);
230 }
231 }
232 PtrTrack->CurrPtr = NULL;
233 return EFI_NOT_FOUND;
234 }
235
236 EFI_STATUS
237 EFIAPI
238 GetVariable (
239 IN CHAR16 *VariableName,
240 IN EFI_GUID * VendorGuid,
241 OUT UINT32 *Attributes OPTIONAL,
242 IN OUT UINTN *DataSize,
243 OUT VOID *Data,
244 IN VARIABLE_GLOBAL * Global,
245 IN UINT32 Instance
246 )
247 /*++
248
249 Routine Description:
250
251 This code finds variable in storage blocks (Volatile or Non-Volatile)
252
253 Arguments:
254
255 VariableName Name of Variable to be found
256 VendorGuid Variable vendor GUID
257 Attributes OPTIONAL Attribute value of the variable found
258 DataSize Size of Data found. If size is less than the
259 data, this value contains the required size.
260 Data Data pointer
261 Global Pointer to VARIABLE_GLOBAL structure
262 Instance Instance of the Firmware Volume.
263
264 Returns:
265
266 EFI_INVALID_PARAMETER - Invalid parameter
267 EFI_SUCCESS - Find the specified variable
268 EFI_NOT_FOUND - Not found
269 EFI_BUFFER_TO_SMALL - DataSize is too small for the result
270
271
272 --*/
273 {
274 VARIABLE_POINTER_TRACK Variable;
275 UINTN VarDataSize;
276 EFI_STATUS Status;
277
278 if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {
279 return EFI_INVALID_PARAMETER;
280 }
281 //
282 // Find existing variable
283 //
284 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);
285
286 if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {
287 goto Done;
288 }
289 //
290 // Get data size
291 //
292 VarDataSize = Variable.CurrPtr->DataSize;
293 if (*DataSize >= VarDataSize) {
294 if (Data == NULL) {
295 Status = EFI_INVALID_PARAMETER;
296 goto Done;
297 }
298
299 CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);
300 if (Attributes != NULL) {
301 *Attributes = Variable.CurrPtr->Attributes;
302 }
303
304 *DataSize = VarDataSize;
305 Status = EFI_SUCCESS;
306 goto Done;
307 } else {
308 *DataSize = VarDataSize;
309 Status = EFI_BUFFER_TOO_SMALL;
310 goto Done;
311 }
312
313 Done:
314 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);
315 return Status;
316 }
317
318 EFI_STATUS
319 EFIAPI
320 GetNextVariableName (
321 IN OUT UINTN *VariableNameSize,
322 IN OUT CHAR16 *VariableName,
323 IN OUT EFI_GUID *VendorGuid,
324 IN VARIABLE_GLOBAL *Global,
325 IN UINT32 Instance
326 )
327 /*++
328
329 Routine Description:
330
331 This code Finds the Next available variable
332
333 Arguments:
334
335 VariableNameSize Size of the variable
336 VariableName Pointer to variable name
337 VendorGuid Variable Vendor Guid
338 Global VARIABLE_GLOBAL structure pointer.
339 Instance FV instance
340
341 Returns:
342
343 EFI STATUS
344
345 --*/
346 {
347 VARIABLE_POINTER_TRACK Variable;
348 UINTN VarNameSize;
349 EFI_STATUS Status;
350
351 if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {
352 return EFI_INVALID_PARAMETER;
353 }
354
355 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);
356
357 if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {
358 goto Done;
359 }
360
361 while (TRUE) {
362 if (VariableName[0] != 0) {
363 //
364 // If variable name is not NULL, get next variable
365 //
366 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
367 }
368 //
369 // If both volatile and non-volatile variable store are parsed,
370 // return not found
371 //
372 if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) {
373 Variable.Volatile = (BOOLEAN) (Variable.Volatile ^ ((BOOLEAN) 0x1));
374 if (Variable.Volatile) {
375 Variable.StartPtr = (VARIABLE_HEADER *) ((UINTN) (Global->VolatileVariableBase + sizeof (VARIABLE_STORE_HEADER)));
376 Variable.EndPtr = (VARIABLE_HEADER *) GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase));
377 } else {
378 Status = EFI_NOT_FOUND;
379 goto Done;
380 }
381
382 Variable.CurrPtr = Variable.StartPtr;
383 if (Variable.CurrPtr->StartId != VARIABLE_DATA) {
384 continue;
385 }
386 }
387 //
388 // Variable is found
389 //
390 if (Variable.CurrPtr->StartId == VARIABLE_DATA && Variable.CurrPtr->State == VAR_ADDED) {
391 if (!(EfiAtRuntime () && !(Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {
392 VarNameSize = Variable.CurrPtr->NameSize;
393 if (VarNameSize <= *VariableNameSize) {
394 CopyMem (
395 VariableName,
396 GET_VARIABLE_NAME_PTR (Variable.CurrPtr),
397 VarNameSize
398 );
399 CopyMem (
400 VendorGuid,
401 &Variable.CurrPtr->VendorGuid,
402 sizeof (EFI_GUID)
403 );
404 Status = EFI_SUCCESS;
405 } else {
406 Status = EFI_BUFFER_TOO_SMALL;
407 }
408
409 *VariableNameSize = VarNameSize;
410 goto Done;
411 }
412 }
413 }
414
415 Done:
416 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);
417 return Status;
418
419 }
420
421 EFI_STATUS
422 EFIAPI
423 SetVariable (
424 IN CHAR16 *VariableName,
425 IN EFI_GUID *VendorGuid,
426 IN UINT32 Attributes,
427 IN UINTN DataSize,
428 IN VOID *Data,
429 IN VARIABLE_GLOBAL *Global,
430 IN UINTN *VolatileOffset,
431 IN UINTN *NonVolatileOffset,
432 IN UINT32 Instance
433 )
434 /*++
435
436 Routine Description:
437
438 This code sets variable in storage blocks (Volatile or Non-Volatile)
439
440 Arguments:
441
442 VariableName Name of Variable to be found
443 VendorGuid Variable vendor GUID
444 Attributes Attribute value of the variable found
445 DataSize Size of Data found. If size is less than the
446 data, this value contains the required size.
447 Data Data pointer
448 Global Pointer to VARIABLE_GLOBAL structure
449 VolatileOffset The offset of last volatile variable
450 NonVolatileOffset The offset of last non-volatile variable
451 Instance Instance of the Firmware Volume.
452
453 Returns:
454
455 EFI_INVALID_PARAMETER - Invalid parameter
456 EFI_SUCCESS - Set successfully
457 EFI_OUT_OF_RESOURCES - Resource not enough to set variable
458 EFI_NOT_FOUND - Not found
459 EFI_DEVICE_ERROR - Variable can not be saved due to hardware failure
460 EFI_WRITE_PROTECTED - Variable is read-only
461
462 --*/
463 {
464 VARIABLE_POINTER_TRACK Variable;
465 EFI_STATUS Status;
466 VARIABLE_HEADER *NextVariable;
467 UINTN VarNameSize;
468 UINTN VarNameOffset;
469 UINTN VarDataOffset;
470 UINTN VarSize;
471
472 //
473 // Check input parameters
474 //
475 if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
476 return EFI_INVALID_PARAMETER;
477 }
478 //
479 // Make sure if runtime bit is set, boot service bit is set also
480 //
481 if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
482 return EFI_INVALID_PARAMETER;
483 }
484 //
485 // The size of the VariableName, including the Unicode Null in bytes plus
486 // the DataSize is limited to maximum size of MAX_HARDWARE_ERROR_VARIABLE_SIZE (32K)
487 // bytes for HwErrRec, and MAX_VARIABLE_SIZE (1024) bytes for the others.
488 //
489 if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
490 if ((DataSize > MAX_HARDWARE_ERROR_VARIABLE_SIZE) ||
491 (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > MAX_HARDWARE_ERROR_VARIABLE_SIZE)) {
492 return EFI_INVALID_PARAMETER;
493 }
494 } else {
495 //
496 // The size of the VariableName, including the Unicode Null in bytes plus
497 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
498 //
499 if ((DataSize > MAX_VARIABLE_SIZE) ||
500 (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > MAX_VARIABLE_SIZE)) {
501 return EFI_INVALID_PARAMETER;
502 }
503 }
504 //
505 // Check whether the input variable is already existed
506 //
507
508 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);
509
510 if (Status == EFI_SUCCESS && Variable.CurrPtr != NULL) {
511 //
512 // Update/Delete existing variable
513 //
514
515 if (EfiAtRuntime ()) {
516 //
517 // If EfiAtRuntime and the variable is Volatile and Runtime Access,
518 // the volatile is ReadOnly, and SetVariable should be aborted and
519 // return EFI_WRITE_PROTECTED.
520 //
521 if (Variable.Volatile) {
522 Status = EFI_WRITE_PROTECTED;
523 goto Done;
524 }
525 //
526 // Only variable have NV attribute can be updated/deleted in Runtime
527 //
528 if (!(Variable.CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE)) {
529 Status = EFI_INVALID_PARAMETER;
530 goto Done;
531 }
532 }
533
534 //
535 // Setting a data variable with no access, or zero DataSize attributes
536 // specified causes it to be deleted.
537 //
538 if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {
539 Variable.CurrPtr->State &= VAR_DELETED;
540 Status = EFI_SUCCESS;
541 goto Done;
542 }
543
544 //
545 // If the variable is marked valid and the same data has been passed in
546 // then return to the caller immediately.
547 //
548 if (Variable.CurrPtr->DataSize == DataSize &&
549 !CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize)
550 ) {
551 Status = EFI_SUCCESS;
552 goto Done;
553 } else if (Variable.CurrPtr->State == VAR_ADDED) {
554 //
555 // Mark the old variable as in delete transition
556 //
557 Variable.CurrPtr->State &= VAR_IN_DELETED_TRANSITION;
558 }
559
560 } else if (Status == EFI_NOT_FOUND) {
561 //
562 // Create a new variable
563 //
564
565 //
566 // Make sure we are trying to create a new variable.
567 // Setting a data variable with no access, or zero DataSize attributes means to delete it.
568 //
569 if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {
570 Status = EFI_NOT_FOUND;
571 goto Done;
572 }
573
574 //
575 // Only variable have NV|RT attribute can be created in Runtime
576 //
577 if (EfiAtRuntime () &&
578 (!(Attributes & EFI_VARIABLE_RUNTIME_ACCESS) || !(Attributes & EFI_VARIABLE_NON_VOLATILE))) {
579 Status = EFI_INVALID_PARAMETER;
580 goto Done;
581 }
582 } else {
583 //
584 // Status should be EFI_INVALID_PARAMETER here according to return status of FindVariable().
585 //
586 ASSERT (Status == EFI_INVALID_PARAMETER);
587 goto Done;
588 }
589
590 //
591 // Function part - create a new variable and copy the data.
592 // Both update a variable and create a variable will come here.
593 //
594
595 VarNameOffset = sizeof (VARIABLE_HEADER);
596 VarNameSize = StrSize (VariableName);
597 VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);
598 VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);
599
600 if (Attributes & EFI_VARIABLE_NON_VOLATILE) {
601 if ((UINT32) (VarSize +*NonVolatileOffset) >
602 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size
603 ) {
604 Status = EFI_OUT_OF_RESOURCES;
605 goto Done;
606 }
607
608 NextVariable = (VARIABLE_HEADER *) (UINT8 *) (*NonVolatileOffset + (UINTN) Global->NonVolatileVariableBase);
609 *NonVolatileOffset = *NonVolatileOffset + VarSize;
610 } else {
611 if ((UINT32) (VarSize +*VolatileOffset) >
612 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size
613 ) {
614 Status = EFI_OUT_OF_RESOURCES;
615 goto Done;
616 }
617
618 NextVariable = (VARIABLE_HEADER *) (UINT8 *) (*VolatileOffset + (UINTN) Global->VolatileVariableBase);
619 *VolatileOffset = *VolatileOffset + VarSize;
620 }
621
622 NextVariable->StartId = VARIABLE_DATA;
623 NextVariable->Attributes = Attributes;
624 NextVariable->State = VAR_ADDED;
625 NextVariable->Reserved = 0;
626
627 //
628 // There will be pad bytes after Data, the NextVariable->NameSize and
629 // NextVariable->NameSize should not include pad size so that variable
630 // service can get actual size in GetVariable
631 //
632 NextVariable->NameSize = (UINT32)VarNameSize;
633 NextVariable->DataSize = (UINT32)DataSize;
634
635 CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID));
636 CopyMem (
637 (UINT8 *) ((UINTN) NextVariable + VarNameOffset),
638 VariableName,
639 VarNameSize
640 );
641 CopyMem (
642 (UINT8 *) ((UINTN) NextVariable + VarDataOffset),
643 Data,
644 DataSize
645 );
646
647 //
648 // Mark the old variable as deleted
649 //
650 if (!EFI_ERROR (Status)) {
651 Variable.CurrPtr->State &= VAR_DELETED;
652 }
653
654 Status = EFI_SUCCESS;
655 Done:
656 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);
657 return Status;
658 }
659
660 EFI_STATUS
661 EFIAPI
662 QueryVariableInfo (
663 IN UINT32 Attributes,
664 OUT UINT64 *MaximumVariableStorageSize,
665 OUT UINT64 *RemainingVariableStorageSize,
666 OUT UINT64 *MaximumVariableSize,
667 IN VARIABLE_GLOBAL *Global,
668 IN UINT32 Instance
669 )
670 /*++
671
672 Routine Description:
673
674 This code returns information about the EFI variables.
675
676 Arguments:
677
678 Attributes Attributes bitmask to specify the type of variables
679 on which to return information.
680 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
681 for the EFI variables associated with the attributes specified.
682 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
683 for EFI variables associated with the attributes specified.
684 MaximumVariableSize Pointer to the maximum size of an individual EFI variables
685 associated with the attributes specified.
686 Global Pointer to VARIABLE_GLOBAL structure.
687 Instance Instance of the Firmware Volume.
688
689 Returns:
690
691 EFI STATUS
692 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
693 EFI_SUCCESS - Query successfully.
694 EFI_UNSUPPORTED - The attribute is not supported on this platform.
695
696 --*/
697 {
698 VARIABLE_HEADER *Variable;
699 VARIABLE_HEADER *NextVariable;
700 UINT64 VariableSize;
701 VARIABLE_STORE_HEADER *VariableStoreHeader;
702
703 if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {
704 return EFI_INVALID_PARAMETER;
705 }
706
707 if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == 0) {
708 //
709 // Make sure the Attributes combination is supported by the platform.
710 //
711 return EFI_UNSUPPORTED;
712 } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
713 //
714 // Make sure if runtime bit is set, boot service bit is set also.
715 //
716 return EFI_INVALID_PARAMETER;
717 } else if (EfiAtRuntime () && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {
718 //
719 // Make sure RT Attribute is set if we are in Runtime phase.
720 //
721 return EFI_INVALID_PARAMETER;
722 }
723
724 AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);
725
726 if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
727 //
728 // Query is Volatile related.
729 //
730 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);
731 } else {
732 //
733 // Query is Non-Volatile related.
734 //
735 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);
736 }
737
738 //
739 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
740 // with the storage size (excluding the storage header size)
741 //
742 *MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);
743 *RemainingVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);
744
745 //
746 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE with the exception of the variable header size.
747 //
748 *MaximumVariableSize = MAX_VARIABLE_SIZE - sizeof (VARIABLE_HEADER);
749
750 //
751 // Harware error record variable needs larger size.
752 //
753 if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
754 *MaximumVariableSize = MAX_HARDWARE_ERROR_VARIABLE_SIZE - sizeof (VARIABLE_HEADER);
755 }
756
757 //
758 // Point to the starting address of the variables.
759 //
760 Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);
761
762 //
763 // Now walk through the related variable store.
764 //
765 while (Variable < GetEndPointer (VariableStoreHeader)) {
766 if (Variable->StartId != VARIABLE_DATA) {
767 break;
768 }
769
770 NextVariable = (VARIABLE_HEADER *) (GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));
771 VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;
772
773 if (Variable->State == VAR_ADDED) {
774 *RemainingVariableStorageSize -= VariableSize;
775 }
776
777 //
778 // Go to the next one.
779 //
780 Variable = NextVariable;
781 }
782
783 if (*RemainingVariableStorageSize < sizeof (VARIABLE_HEADER)) {
784 *MaximumVariableSize = 0;
785 } else if ((*RemainingVariableStorageSize - sizeof (VARIABLE_HEADER)) < *MaximumVariableSize) {
786 *MaximumVariableSize = *RemainingVariableStorageSize - sizeof (VARIABLE_HEADER);
787 }
788
789 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);
790 return EFI_SUCCESS;
791 }
792
793 EFI_STATUS
794 InitializeVariableStore (
795 OUT EFI_PHYSICAL_ADDRESS *VariableBase,
796 OUT UINTN *LastVariableOffset
797 )
798 /*++
799
800 Routine Description:
801 This function initializes variable store
802
803 Arguments:
804
805 Returns:
806
807 --*/
808 {
809 VARIABLE_STORE_HEADER *VariableStore;
810
811 //
812 // Allocate memory for volatile variable store
813 //
814 VariableStore = (VARIABLE_STORE_HEADER *) AllocateRuntimePool (
815 VARIABLE_STORE_SIZE
816 );
817 if (NULL == VariableStore) {
818 return EFI_OUT_OF_RESOURCES;
819 }
820
821 SetMem (VariableStore, VARIABLE_STORE_SIZE, 0xff);
822
823 //
824 // Variable Specific Data
825 //
826 *VariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStore;
827 *LastVariableOffset = sizeof (VARIABLE_STORE_HEADER);
828
829 VariableStore->Signature = VARIABLE_STORE_SIGNATURE;
830 VariableStore->Size = VARIABLE_STORE_SIZE;
831 VariableStore->Format = VARIABLE_STORE_FORMATTED;
832 VariableStore->State = VARIABLE_STORE_HEALTHY;
833 VariableStore->Reserved = 0;
834 VariableStore->Reserved1 = 0;
835
836 return EFI_SUCCESS;
837 }
838
839 EFI_STATUS
840 EFIAPI
841 VariableCommonInitialize (
842 IN EFI_HANDLE ImageHandle,
843 IN EFI_SYSTEM_TABLE *SystemTable
844 )
845 /*++
846
847 Routine Description:
848 This function does common initialization for variable services
849
850 Arguments:
851
852 Returns:
853
854 --*/
855 {
856 EFI_STATUS Status;
857
858 //
859 // Allocate memory for mVariableModuleGlobal
860 //
861 mVariableModuleGlobal = (ESAL_VARIABLE_GLOBAL *) AllocateRuntimePool (
862 sizeof (ESAL_VARIABLE_GLOBAL)
863 );
864 if (NULL == mVariableModuleGlobal) {
865 return EFI_OUT_OF_RESOURCES;
866 }
867
868 EfiInitializeLock(&mVariableModuleGlobal->VariableGlobal[Physical].VariableServicesLock, TPL_NOTIFY);
869
870 //
871 // Intialize volatile variable store
872 //
873 Status = InitializeVariableStore (
874 &mVariableModuleGlobal->VariableGlobal[Physical].VolatileVariableBase,
875 &mVariableModuleGlobal->VolatileLastVariableOffset
876 );
877
878 if (EFI_ERROR (Status)) {
879 return Status;
880 }
881 //
882 // Intialize non volatile variable store
883 //
884 Status = InitializeVariableStore (
885 &mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase,
886 &mVariableModuleGlobal->NonVolatileLastVariableOffset
887 );
888
889 return Status;
890 }