3 Implement all four UEFI Runtime Variable services for the nonvolatile
4 and volatile storage space and install variable architecture protocol
5 based on SMM variable module.
7 Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <Protocol/VariableWrite.h>
19 #include <Protocol/Variable.h>
20 #include <Protocol/SmmCommunication.h>
21 #include <Protocol/SmmVariable.h>
22 #include <Protocol/VariableLock.h>
24 #include <Library/UefiBootServicesTableLib.h>
25 #include <Library/UefiRuntimeServicesTableLib.h>
26 #include <Library/MemoryAllocationLib.h>
27 #include <Library/UefiDriverEntryPoint.h>
28 #include <Library/UefiRuntimeLib.h>
29 #include <Library/BaseMemoryLib.h>
30 #include <Library/DebugLib.h>
31 #include <Library/PcdLib.h>
32 #include <Library/UefiLib.h>
33 #include <Library/BaseLib.h>
35 #include <Guid/EventGroup.h>
36 #include <Guid/VariableFormat.h>
37 #include <Guid/SmmVariableCommon.h>
39 EFI_HANDLE mHandle
= NULL
;
40 EFI_SMM_VARIABLE_PROTOCOL
*mSmmVariable
= NULL
;
41 EFI_EVENT mVirtualAddressChangeEvent
= NULL
;
42 EFI_SMM_COMMUNICATION_PROTOCOL
*mSmmCommunication
= NULL
;
43 UINT8
*mVariableBuffer
= NULL
;
44 UINT8
*mVariableBufferPhysical
= NULL
;
45 UINTN mVariableBufferSize
;
46 UINTN mVariableBufferPayloadSize
;
47 EFI_LOCK mVariableServicesLock
;
48 EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock
;
51 Acquires lock only at boot time. Simply returns at runtime.
53 This is a temperary function that will be removed when
54 EfiAcquireLock() in UefiLib can handle the call in UEFI
55 Runtimer driver in RT phase.
56 It calls EfiAcquireLock() at boot time, and simply returns
59 @param Lock A pointer to the lock to acquire.
63 AcquireLockOnlyAtBootTime (
67 if (!EfiAtRuntime ()) {
68 EfiAcquireLock (Lock
);
73 Releases lock only at boot time. Simply returns at runtime.
75 This is a temperary function which will be removed when
76 EfiReleaseLock() in UefiLib can handle the call in UEFI
77 Runtimer driver in RT phase.
78 It calls EfiReleaseLock() at boot time and simply returns
81 @param Lock A pointer to the lock to release.
85 ReleaseLockOnlyAtBootTime (
89 if (!EfiAtRuntime ()) {
90 EfiReleaseLock (Lock
);
95 Initialize the communicate buffer using DataSize and Function.
97 The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE +
100 @param[out] DataPtr Points to the data in the communicate buffer.
101 @param[in] DataSize The data size to send to SMM.
102 @param[in] Function The function number to initialize the communicate header.
104 @retval EFI_INVALID_PARAMETER The data size is too big.
105 @retval EFI_SUCCESS Find the specified variable.
109 InitCommunicateBuffer (
110 OUT VOID
**DataPtr OPTIONAL
,
115 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
116 SMM_VARIABLE_COMMUNICATE_HEADER
*SmmVariableFunctionHeader
;
119 if (DataSize
+ SMM_COMMUNICATE_HEADER_SIZE
+ SMM_VARIABLE_COMMUNICATE_HEADER_SIZE
> mVariableBufferSize
) {
120 return EFI_INVALID_PARAMETER
;
123 SmmCommunicateHeader
= (EFI_SMM_COMMUNICATE_HEADER
*) mVariableBuffer
;
124 CopyGuid (&SmmCommunicateHeader
->HeaderGuid
, &gEfiSmmVariableProtocolGuid
);
125 SmmCommunicateHeader
->MessageLength
= DataSize
+ SMM_VARIABLE_COMMUNICATE_HEADER_SIZE
;
127 SmmVariableFunctionHeader
= (SMM_VARIABLE_COMMUNICATE_HEADER
*) SmmCommunicateHeader
->Data
;
128 SmmVariableFunctionHeader
->Function
= Function
;
129 if (DataPtr
!= NULL
) {
130 *DataPtr
= SmmVariableFunctionHeader
->Data
;
138 Send the data in communicate buffer to SMM.
140 @param[in] DataSize This size of the function header and the data.
142 @retval EFI_SUCCESS Success is returned from the functin in SMM.
143 @retval Others Failure is returned from the function in SMM.
147 SendCommunicateBuffer (
153 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
154 SMM_VARIABLE_COMMUNICATE_HEADER
*SmmVariableFunctionHeader
;
156 CommSize
= DataSize
+ SMM_COMMUNICATE_HEADER_SIZE
+ SMM_VARIABLE_COMMUNICATE_HEADER_SIZE
;
157 Status
= mSmmCommunication
->Communicate (mSmmCommunication
, mVariableBufferPhysical
, &CommSize
);
158 ASSERT_EFI_ERROR (Status
);
160 SmmCommunicateHeader
= (EFI_SMM_COMMUNICATE_HEADER
*) mVariableBuffer
;
161 SmmVariableFunctionHeader
= (SMM_VARIABLE_COMMUNICATE_HEADER
*)SmmCommunicateHeader
->Data
;
162 return SmmVariableFunctionHeader
->ReturnStatus
;
166 Mark a variable that will become read-only after leaving the DXE phase of execution.
168 @param[in] This The VARIABLE_LOCK_PROTOCOL instance.
169 @param[in] VariableName A pointer to the variable name that will be made read-only subsequently.
170 @param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently.
172 @retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked
173 as pending to be read-only.
174 @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
175 Or VariableName is an empty string.
176 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
177 already been signaled.
178 @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request.
182 VariableLockRequestToLock (
183 IN CONST EDKII_VARIABLE_LOCK_PROTOCOL
*This
,
184 IN CHAR16
*VariableName
,
185 IN EFI_GUID
*VendorGuid
189 UINTN VariableNameSize
;
191 SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE
*VariableToLock
;
193 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
194 return EFI_INVALID_PARAMETER
;
197 VariableNameSize
= StrSize (VariableName
);
200 // If VariableName exceeds SMM payload limit. Return failure
202 if (VariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE
, Name
)) {
203 return EFI_INVALID_PARAMETER
;
206 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
209 // Init the communicate buffer. The buffer data size is:
210 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
212 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE
, Name
) + VariableNameSize
;
213 Status
= InitCommunicateBuffer ((VOID
**) &VariableToLock
, PayloadSize
, SMM_VARIABLE_FUNCTION_LOCK_VARIABLE
);
214 if (EFI_ERROR (Status
)) {
217 ASSERT (VariableToLock
!= NULL
);
219 CopyGuid (&VariableToLock
->Guid
, VendorGuid
);
220 VariableToLock
->NameSize
= VariableNameSize
;
221 CopyMem (VariableToLock
->Name
, VariableName
, VariableToLock
->NameSize
);
226 Status
= SendCommunicateBuffer (PayloadSize
);
229 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
234 This code finds variable in storage blocks (Volatile or Non-Volatile).
236 @param[in] VariableName Name of Variable to be found.
237 @param[in] VendorGuid Variable vendor GUID.
238 @param[out] Attributes Attribute value of the variable found.
239 @param[in, out] DataSize Size of Data found. If size is less than the
240 data, this value contains the required size.
241 @param[out] Data Data pointer.
243 @retval EFI_INVALID_PARAMETER Invalid parameter.
244 @retval EFI_SUCCESS Find the specified variable.
245 @retval EFI_NOT_FOUND Not found.
246 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.
251 RuntimeServiceGetVariable (
252 IN CHAR16
*VariableName
,
253 IN EFI_GUID
*VendorGuid
,
254 OUT UINT32
*Attributes OPTIONAL
,
255 IN OUT UINTN
*DataSize
,
261 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
*SmmVariableHeader
;
263 UINTN VariableNameSize
;
265 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
266 return EFI_INVALID_PARAMETER
;
269 if ((*DataSize
!= 0) && (Data
== NULL
)) {
270 return EFI_INVALID_PARAMETER
;
273 TempDataSize
= *DataSize
;
274 VariableNameSize
= StrSize (VariableName
);
277 // If VariableName exceeds SMM payload limit. Return failure
279 if (VariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
)) {
280 return EFI_INVALID_PARAMETER
;
283 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
286 // Init the communicate buffer. The buffer data size is:
287 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
289 if (TempDataSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - VariableNameSize
) {
291 // If output data buffer exceed SMM payload limit. Trim output buffer to SMM payload size
293 TempDataSize
= mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - VariableNameSize
;
295 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) + VariableNameSize
+ TempDataSize
;
297 Status
= InitCommunicateBuffer ((VOID
**)&SmmVariableHeader
, PayloadSize
, SMM_VARIABLE_FUNCTION_GET_VARIABLE
);
298 if (EFI_ERROR (Status
)) {
301 ASSERT (SmmVariableHeader
!= NULL
);
303 CopyGuid (&SmmVariableHeader
->Guid
, VendorGuid
);
304 SmmVariableHeader
->DataSize
= TempDataSize
;
305 SmmVariableHeader
->NameSize
= VariableNameSize
;
306 if (Attributes
== NULL
) {
307 SmmVariableHeader
->Attributes
= 0;
309 SmmVariableHeader
->Attributes
= *Attributes
;
311 CopyMem (SmmVariableHeader
->Name
, VariableName
, SmmVariableHeader
->NameSize
);
316 Status
= SendCommunicateBuffer (PayloadSize
);
319 // Get data from SMM.
321 if (Status
== EFI_SUCCESS
|| Status
== EFI_BUFFER_TOO_SMALL
) {
323 // SMM CommBuffer DataSize can be a trimed value
324 // Only update DataSize when needed
326 *DataSize
= SmmVariableHeader
->DataSize
;
328 if (Attributes
!= NULL
) {
329 *Attributes
= SmmVariableHeader
->Attributes
;
332 if (EFI_ERROR (Status
)) {
336 CopyMem (Data
, (UINT8
*)SmmVariableHeader
->Name
+ SmmVariableHeader
->NameSize
, SmmVariableHeader
->DataSize
);
339 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
345 This code Finds the Next available variable.
347 @param[in, out] VariableNameSize Size of the variable name.
348 @param[in, out] VariableName Pointer to variable name.
349 @param[in, out] VendorGuid Variable Vendor Guid.
351 @retval EFI_INVALID_PARAMETER Invalid parameter.
352 @retval EFI_SUCCESS Find the specified variable.
353 @retval EFI_NOT_FOUND Not found.
354 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.
359 RuntimeServiceGetNextVariableName (
360 IN OUT UINTN
*VariableNameSize
,
361 IN OUT CHAR16
*VariableName
,
362 IN OUT EFI_GUID
*VendorGuid
367 SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
*SmmGetNextVariableName
;
368 UINTN OutVariableNameSize
;
369 UINTN InVariableNameSize
;
371 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
372 return EFI_INVALID_PARAMETER
;
375 OutVariableNameSize
= *VariableNameSize
;
376 InVariableNameSize
= StrSize (VariableName
);
379 // If input string exceeds SMM payload limit. Return failure
381 if (InVariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
)) {
382 return EFI_INVALID_PARAMETER
;
385 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
388 // Init the communicate buffer. The buffer data size is:
389 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
391 if (OutVariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
)) {
393 // If output buffer exceed SMM payload limit. Trim output buffer to SMM payload size
395 OutVariableNameSize
= mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
);
398 // Payload should be Guid + NameSize + MAX of Input & Output buffer
400 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
) + MAX (OutVariableNameSize
, InVariableNameSize
);
403 Status
= InitCommunicateBuffer ((VOID
**)&SmmGetNextVariableName
, PayloadSize
, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME
);
404 if (EFI_ERROR (Status
)) {
407 ASSERT (SmmGetNextVariableName
!= NULL
);
410 // SMM comm buffer->NameSize is buffer size for return string
412 SmmGetNextVariableName
->NameSize
= OutVariableNameSize
;
414 CopyGuid (&SmmGetNextVariableName
->Guid
, VendorGuid
);
418 CopyMem (SmmGetNextVariableName
->Name
, VariableName
, InVariableNameSize
);
419 if (OutVariableNameSize
> InVariableNameSize
) {
420 ZeroMem ((UINT8
*) SmmGetNextVariableName
->Name
+ InVariableNameSize
, OutVariableNameSize
- InVariableNameSize
);
426 Status
= SendCommunicateBuffer (PayloadSize
);
429 // Get data from SMM.
431 if (Status
== EFI_SUCCESS
|| Status
== EFI_BUFFER_TOO_SMALL
) {
433 // SMM CommBuffer NameSize can be a trimed value
434 // Only update VariableNameSize when needed
436 *VariableNameSize
= SmmGetNextVariableName
->NameSize
;
438 if (EFI_ERROR (Status
)) {
442 CopyGuid (VendorGuid
, &SmmGetNextVariableName
->Guid
);
443 CopyMem (VariableName
, SmmGetNextVariableName
->Name
, SmmGetNextVariableName
->NameSize
);
446 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
451 This code sets variable in storage blocks (Volatile or Non-Volatile).
453 @param[in] VariableName Name of Variable to be found.
454 @param[in] VendorGuid Variable vendor GUID.
455 @param[in] Attributes Attribute value of the variable found
456 @param[in] DataSize Size of Data found. If size is less than the
457 data, this value contains the required size.
458 @param[in] Data Data pointer.
460 @retval EFI_INVALID_PARAMETER Invalid parameter.
461 @retval EFI_SUCCESS Set successfully.
462 @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.
463 @retval EFI_NOT_FOUND Not found.
464 @retval EFI_WRITE_PROTECTED Variable is read-only.
469 RuntimeServiceSetVariable (
470 IN CHAR16
*VariableName
,
471 IN EFI_GUID
*VendorGuid
,
472 IN UINT32 Attributes
,
479 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
*SmmVariableHeader
;
480 UINTN VariableNameSize
;
483 // Check input parameters.
485 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
486 return EFI_INVALID_PARAMETER
;
489 if (DataSize
!= 0 && Data
== NULL
) {
490 return EFI_INVALID_PARAMETER
;
493 VariableNameSize
= StrSize (VariableName
);
496 // If VariableName or DataSize exceeds SMM payload limit. Return failure
498 if ((VariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
)) ||
499 (DataSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - VariableNameSize
)){
500 return EFI_INVALID_PARAMETER
;
503 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
506 // Init the communicate buffer. The buffer data size is:
507 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
509 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) + VariableNameSize
+ DataSize
;
510 Status
= InitCommunicateBuffer ((VOID
**)&SmmVariableHeader
, PayloadSize
, SMM_VARIABLE_FUNCTION_SET_VARIABLE
);
511 if (EFI_ERROR (Status
)) {
514 ASSERT (SmmVariableHeader
!= NULL
);
516 CopyGuid ((EFI_GUID
*) &SmmVariableHeader
->Guid
, VendorGuid
);
517 SmmVariableHeader
->DataSize
= DataSize
;
518 SmmVariableHeader
->NameSize
= VariableNameSize
;
519 SmmVariableHeader
->Attributes
= Attributes
;
520 CopyMem (SmmVariableHeader
->Name
, VariableName
, SmmVariableHeader
->NameSize
);
521 CopyMem ((UINT8
*) SmmVariableHeader
->Name
+ SmmVariableHeader
->NameSize
, Data
, DataSize
);
526 Status
= SendCommunicateBuffer (PayloadSize
);
529 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
535 This code returns information about the EFI variables.
537 @param[in] Attributes Attributes bitmask to specify the type of variables
538 on which to return information.
539 @param[out] MaximumVariableStorageSize Pointer to the maximum size of the storage space available
540 for the EFI variables associated with the attributes specified.
541 @param[out] RemainingVariableStorageSize Pointer to the remaining size of the storage space available
542 for EFI variables associated with the attributes specified.
543 @param[out] MaximumVariableSize Pointer to the maximum size of an individual EFI variables
544 associated with the attributes specified.
546 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.
547 @retval EFI_SUCCESS Query successfully.
548 @retval EFI_UNSUPPORTED The attribute is not supported on this platform.
553 RuntimeServiceQueryVariableInfo (
554 IN UINT32 Attributes
,
555 OUT UINT64
*MaximumVariableStorageSize
,
556 OUT UINT64
*RemainingVariableStorageSize
,
557 OUT UINT64
*MaximumVariableSize
562 SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO
*SmmQueryVariableInfo
;
564 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
|| Attributes
== 0) {
565 return EFI_INVALID_PARAMETER
;
568 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
571 // Init the communicate buffer. The buffer data size is:
572 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize;
574 PayloadSize
= sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO
);
575 Status
= InitCommunicateBuffer ((VOID
**)&SmmQueryVariableInfo
, PayloadSize
, SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO
);
576 if (EFI_ERROR (Status
)) {
579 ASSERT (SmmQueryVariableInfo
!= NULL
);
581 SmmQueryVariableInfo
->Attributes
= Attributes
;
586 Status
= SendCommunicateBuffer (PayloadSize
);
587 if (EFI_ERROR (Status
)) {
592 // Get data from SMM.
594 *MaximumVariableSize
= SmmQueryVariableInfo
->MaximumVariableSize
;
595 *MaximumVariableStorageSize
= SmmQueryVariableInfo
->MaximumVariableStorageSize
;
596 *RemainingVariableStorageSize
= SmmQueryVariableInfo
->RemainingVariableStorageSize
;
599 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
605 Exit Boot Services Event notification handler.
607 Notify SMM variable driver about the event.
609 @param[in] Event Event whose notification function is being invoked.
610 @param[in] Context Pointer to the notification function's context.
621 // Init the communicate buffer. The buffer data size is:
622 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
624 InitCommunicateBuffer (NULL
, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE
);
629 SendCommunicateBuffer (0);
634 On Ready To Boot Services Event notification handler.
636 Notify SMM variable driver about the event.
638 @param[in] Event Event whose notification function is being invoked
639 @param[in] Context Pointer to the notification function's context
650 // Init the communicate buffer. The buffer data size is:
651 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
653 InitCommunicateBuffer (NULL
, 0, SMM_VARIABLE_FUNCTION_READY_TO_BOOT
);
658 SendCommunicateBuffer (0);
663 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
665 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
666 It convers pointer to new virtual address.
668 @param[in] Event Event whose notification function is being invoked.
669 @param[in] Context Pointer to the notification function's context.
674 VariableAddressChangeEvent (
679 EfiConvertPointer (0x0, (VOID
**) &mVariableBuffer
);
680 EfiConvertPointer (0x0, (VOID
**) &mSmmCommunication
);
685 Initialize variable service and install Variable Architectural protocol.
687 @param[in] Event Event whose notification function is being invoked.
688 @param[in] Context Pointer to the notification function's context.
700 Status
= gBS
->LocateProtocol (&gEfiSmmVariableProtocolGuid
, NULL
, (VOID
**)&mSmmVariable
);
701 if (EFI_ERROR (Status
)) {
705 Status
= gBS
->LocateProtocol (&gEfiSmmCommunicationProtocolGuid
, NULL
, (VOID
**) &mSmmCommunication
);
706 ASSERT_EFI_ERROR (Status
);
709 // Allocate memory for variable communicate buffer.
711 mVariableBufferPayloadSize
= MAX (PcdGet32 (PcdMaxVariableSize
), PcdGet32 (PcdMaxHardwareErrorVariableSize
)) +
712 OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - sizeof (VARIABLE_HEADER
);
713 mVariableBufferSize
= SMM_COMMUNICATE_HEADER_SIZE
+ SMM_VARIABLE_COMMUNICATE_HEADER_SIZE
+ mVariableBufferPayloadSize
;
714 mVariableBuffer
= AllocateRuntimePool (mVariableBufferSize
);
715 ASSERT (mVariableBuffer
!= NULL
);
718 // Save the buffer physical address used for SMM conmunication.
720 mVariableBufferPhysical
= mVariableBuffer
;
722 gRT
->GetVariable
= RuntimeServiceGetVariable
;
723 gRT
->GetNextVariableName
= RuntimeServiceGetNextVariableName
;
724 gRT
->SetVariable
= RuntimeServiceSetVariable
;
725 gRT
->QueryVariableInfo
= RuntimeServiceQueryVariableInfo
;
728 // Install the Variable Architectural Protocol on a new handle.
730 Status
= gBS
->InstallProtocolInterface (
732 &gEfiVariableArchProtocolGuid
,
733 EFI_NATIVE_INTERFACE
,
736 ASSERT_EFI_ERROR (Status
);
741 SMM Non-Volatile variable write service is ready notify event handler.
743 @param[in] Event Event whose notification function is being invoked.
744 @param[in] Context Pointer to the notification function's context.
749 SmmVariableWriteReady (
758 // Check whether the protocol is installed or not.
760 Status
= gBS
->LocateProtocol (&gSmmVariableWriteGuid
, NULL
, (VOID
**) &ProtocolOps
);
761 if (EFI_ERROR (Status
)) {
765 Status
= gBS
->InstallProtocolInterface (
767 &gEfiVariableWriteArchProtocolGuid
,
768 EFI_NATIVE_INTERFACE
,
771 ASSERT_EFI_ERROR (Status
);
776 Variable Driver main entry point. The Variable driver places the 4 EFI
777 runtime services in the EFI System Table and installs arch protocols
778 for variable read and write services being available. It also registers
779 a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
781 @param[in] ImageHandle The firmware allocated handle for the EFI image.
782 @param[in] SystemTable A pointer to the EFI System Table.
784 @retval EFI_SUCCESS Variable service successfully initialized.
789 VariableSmmRuntimeInitialize (
790 IN EFI_HANDLE ImageHandle
,
791 IN EFI_SYSTEM_TABLE
*SystemTable
795 VOID
*SmmVariableRegistration
;
796 VOID
*SmmVariableWriteRegistration
;
797 EFI_EVENT OnReadyToBootEvent
;
798 EFI_EVENT ExitBootServiceEvent
;
800 EfiInitializeLock (&mVariableServicesLock
, TPL_NOTIFY
);
802 mVariableLock
.RequestToLock
= VariableLockRequestToLock
;
803 Status
= gBS
->InstallMultipleProtocolInterfaces (
805 &gEdkiiVariableLockProtocolGuid
,
809 ASSERT_EFI_ERROR (Status
);
812 // Smm variable service is ready
814 EfiCreateProtocolNotifyEvent (
815 &gEfiSmmVariableProtocolGuid
,
819 &SmmVariableRegistration
823 // Smm Non-Volatile variable write service is ready
825 EfiCreateProtocolNotifyEvent (
826 &gSmmVariableWriteGuid
,
828 SmmVariableWriteReady
,
830 &SmmVariableWriteRegistration
834 // Register the event to reclaim variable for OS usage.
836 EfiCreateEventReadyToBootEx (
844 // Register the event to inform SMM variable that it is at runtime.
851 &gEfiEventExitBootServicesGuid
,
852 &ExitBootServiceEvent
856 // Register the event to convert the pointer for runtime.
861 VariableAddressChangeEvent
,
863 &gEfiEventVirtualAddressChangeGuid
,
864 &mVirtualAddressChangeEvent