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