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>
23 #include <Library/UefiBootServicesTableLib.h>
24 #include <Library/UefiRuntimeServicesTableLib.h>
25 #include <Library/MemoryAllocationLib.h>
26 #include <Library/UefiDriverEntryPoint.h>
27 #include <Library/UefiRuntimeLib.h>
28 #include <Library/BaseMemoryLib.h>
29 #include <Library/DebugLib.h>
30 #include <Library/PcdLib.h>
31 #include <Library/UefiLib.h>
32 #include <Library/BaseLib.h>
34 #include <Guid/EventGroup.h>
35 #include <Guid/VariableFormat.h>
36 #include <Guid/SmmVariableCommon.h>
38 EFI_HANDLE mHandle
= NULL
;
39 EFI_SMM_VARIABLE_PROTOCOL
*mSmmVariable
= NULL
;
40 EFI_EVENT mVirtualAddressChangeEvent
= NULL
;
41 EFI_SMM_COMMUNICATION_PROTOCOL
*mSmmCommunication
= NULL
;
42 UINT8
*mVariableBuffer
= NULL
;
43 UINT8
*mVariableBufferPhysical
= NULL
;
44 UINTN mVariableBufferSize
;
45 UINTN mVariableBufferPayloadSize
;
46 EFI_LOCK mVariableServicesLock
;
49 Acquires lock only at boot time. Simply returns at runtime.
51 This is a temperary function that will be removed when
52 EfiAcquireLock() in UefiLib can handle the call in UEFI
53 Runtimer driver in RT phase.
54 It calls EfiAcquireLock() at boot time, and simply returns
57 @param Lock A pointer to the lock to acquire.
61 AcquireLockOnlyAtBootTime (
65 if (!EfiAtRuntime ()) {
66 EfiAcquireLock (Lock
);
71 Releases lock only at boot time. Simply returns at runtime.
73 This is a temperary function which will be removed when
74 EfiReleaseLock() in UefiLib can handle the call in UEFI
75 Runtimer driver in RT phase.
76 It calls EfiReleaseLock() at boot time and simply returns
79 @param Lock A pointer to the lock to release.
83 ReleaseLockOnlyAtBootTime (
87 if (!EfiAtRuntime ()) {
88 EfiReleaseLock (Lock
);
93 Initialize the communicate buffer using DataSize and Function.
95 The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE +
98 @param[out] DataPtr Points to the data in the communicate buffer.
99 @param[in] DataSize The data size to send to SMM.
100 @param[in] Function The function number to initialize the communicate header.
102 @retval EFI_INVALID_PARAMETER The data size is too big.
103 @retval EFI_SUCCESS Find the specified variable.
107 InitCommunicateBuffer (
108 OUT VOID
**DataPtr OPTIONAL
,
113 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
114 SMM_VARIABLE_COMMUNICATE_HEADER
*SmmVariableFunctionHeader
;
117 if (DataSize
+ SMM_COMMUNICATE_HEADER_SIZE
+ SMM_VARIABLE_COMMUNICATE_HEADER_SIZE
> mVariableBufferSize
) {
118 return EFI_INVALID_PARAMETER
;
121 SmmCommunicateHeader
= (EFI_SMM_COMMUNICATE_HEADER
*) mVariableBuffer
;
122 CopyGuid (&SmmCommunicateHeader
->HeaderGuid
, &gEfiSmmVariableProtocolGuid
);
123 SmmCommunicateHeader
->MessageLength
= DataSize
+ SMM_VARIABLE_COMMUNICATE_HEADER_SIZE
;
125 SmmVariableFunctionHeader
= (SMM_VARIABLE_COMMUNICATE_HEADER
*) SmmCommunicateHeader
->Data
;
126 SmmVariableFunctionHeader
->Function
= Function
;
127 if (DataPtr
!= NULL
) {
128 *DataPtr
= SmmVariableFunctionHeader
->Data
;
136 Send the data in communicate buffer to SMM.
138 @param[in] DataSize This size of the function header and the data.
140 @retval EFI_SUCCESS Success is returned from the functin in SMM.
141 @retval Others Failure is returned from the function in SMM.
145 SendCommunicateBuffer (
151 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
152 SMM_VARIABLE_COMMUNICATE_HEADER
*SmmVariableFunctionHeader
;
154 CommSize
= DataSize
+ SMM_COMMUNICATE_HEADER_SIZE
+ SMM_VARIABLE_COMMUNICATE_HEADER_SIZE
;
155 Status
= mSmmCommunication
->Communicate (mSmmCommunication
, mVariableBufferPhysical
, &CommSize
);
156 ASSERT_EFI_ERROR (Status
);
158 SmmCommunicateHeader
= (EFI_SMM_COMMUNICATE_HEADER
*) mVariableBuffer
;
159 SmmVariableFunctionHeader
= (SMM_VARIABLE_COMMUNICATE_HEADER
*)SmmCommunicateHeader
->Data
;
160 return SmmVariableFunctionHeader
->ReturnStatus
;
165 This code finds variable in storage blocks (Volatile or Non-Volatile).
167 @param[in] VariableName Name of Variable to be found.
168 @param[in] VendorGuid Variable vendor GUID.
169 @param[out] Attributes Attribute value of the variable found.
170 @param[in, out] DataSize Size of Data found. If size is less than the
171 data, this value contains the required size.
172 @param[out] Data Data pointer.
174 @retval EFI_INVALID_PARAMETER Invalid parameter.
175 @retval EFI_SUCCESS Find the specified variable.
176 @retval EFI_NOT_FOUND Not found.
177 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.
182 RuntimeServiceGetVariable (
183 IN CHAR16
*VariableName
,
184 IN EFI_GUID
*VendorGuid
,
185 OUT UINT32
*Attributes OPTIONAL
,
186 IN OUT UINTN
*DataSize
,
192 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
*SmmVariableHeader
;
194 UINTN VariableNameSize
;
196 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
197 return EFI_INVALID_PARAMETER
;
200 if ((*DataSize
!= 0) && (Data
== NULL
)) {
201 return EFI_INVALID_PARAMETER
;
204 TempDataSize
= *DataSize
;
205 VariableNameSize
= StrSize (VariableName
);
208 // If VariableName exceeds SMM payload limit. Return failure
210 if (VariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
)) {
211 return EFI_INVALID_PARAMETER
;
214 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
217 // Init the communicate buffer. The buffer data size is:
218 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
220 if (TempDataSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - VariableNameSize
) {
222 // If output data buffer exceed SMM payload limit. Trim output buffer to SMM payload size
224 TempDataSize
= mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - VariableNameSize
;
226 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) + VariableNameSize
+ TempDataSize
;
228 Status
= InitCommunicateBuffer ((VOID
**)&SmmVariableHeader
, PayloadSize
, SMM_VARIABLE_FUNCTION_GET_VARIABLE
);
229 if (EFI_ERROR (Status
)) {
232 ASSERT (SmmVariableHeader
!= NULL
);
234 CopyGuid (&SmmVariableHeader
->Guid
, VendorGuid
);
235 SmmVariableHeader
->DataSize
= TempDataSize
;
236 SmmVariableHeader
->NameSize
= VariableNameSize
;
237 if (Attributes
== NULL
) {
238 SmmVariableHeader
->Attributes
= 0;
240 SmmVariableHeader
->Attributes
= *Attributes
;
242 CopyMem (SmmVariableHeader
->Name
, VariableName
, SmmVariableHeader
->NameSize
);
247 Status
= SendCommunicateBuffer (PayloadSize
);
250 // Get data from SMM.
252 if (Status
== EFI_SUCCESS
|| Status
== EFI_BUFFER_TOO_SMALL
) {
254 // SMM CommBuffer DataSize can be a trimed value
255 // Only update DataSize when needed
257 *DataSize
= SmmVariableHeader
->DataSize
;
259 if (Attributes
!= NULL
) {
260 *Attributes
= SmmVariableHeader
->Attributes
;
263 if (EFI_ERROR (Status
)) {
267 CopyMem (Data
, (UINT8
*)SmmVariableHeader
->Name
+ SmmVariableHeader
->NameSize
, SmmVariableHeader
->DataSize
);
270 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
276 This code Finds the Next available variable.
278 @param[in, out] VariableNameSize Size of the variable name.
279 @param[in, out] VariableName Pointer to variable name.
280 @param[in, out] VendorGuid Variable Vendor Guid.
282 @retval EFI_INVALID_PARAMETER Invalid parameter.
283 @retval EFI_SUCCESS Find the specified variable.
284 @retval EFI_NOT_FOUND Not found.
285 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.
290 RuntimeServiceGetNextVariableName (
291 IN OUT UINTN
*VariableNameSize
,
292 IN OUT CHAR16
*VariableName
,
293 IN OUT EFI_GUID
*VendorGuid
298 SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
*SmmGetNextVariableName
;
299 UINTN OutVariableNameSize
;
300 UINTN InVariableNameSize
;
302 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
303 return EFI_INVALID_PARAMETER
;
306 OutVariableNameSize
= *VariableNameSize
;
307 InVariableNameSize
= StrSize (VariableName
);
310 // If input string exceeds SMM payload limit. Return failure
312 if (InVariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
)) {
313 return EFI_INVALID_PARAMETER
;
316 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
319 // Init the communicate buffer. The buffer data size is:
320 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
322 if (OutVariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
)) {
324 // If output buffer exceed SMM payload limit. Trim output buffer to SMM payload size
326 OutVariableNameSize
= mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
);
329 // Payload should be Guid + NameSize + MAX of Input & Output buffer
331 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
) + MAX (OutVariableNameSize
, InVariableNameSize
);
334 Status
= InitCommunicateBuffer ((VOID
**)&SmmGetNextVariableName
, PayloadSize
, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME
);
335 if (EFI_ERROR (Status
)) {
338 ASSERT (SmmGetNextVariableName
!= NULL
);
341 // SMM comm buffer->NameSize is buffer size for return string
343 SmmGetNextVariableName
->NameSize
= OutVariableNameSize
;
345 CopyGuid (&SmmGetNextVariableName
->Guid
, VendorGuid
);
349 CopyMem (SmmGetNextVariableName
->Name
, VariableName
, InVariableNameSize
);
350 if (OutVariableNameSize
> InVariableNameSize
) {
351 ZeroMem ((UINT8
*) SmmGetNextVariableName
->Name
+ InVariableNameSize
, OutVariableNameSize
- InVariableNameSize
);
357 Status
= SendCommunicateBuffer (PayloadSize
);
360 // Get data from SMM.
362 if (Status
== EFI_SUCCESS
|| Status
== EFI_BUFFER_TOO_SMALL
) {
364 // SMM CommBuffer NameSize can be a trimed value
365 // Only update VariableNameSize when needed
367 *VariableNameSize
= SmmGetNextVariableName
->NameSize
;
369 if (EFI_ERROR (Status
)) {
373 CopyGuid (VendorGuid
, &SmmGetNextVariableName
->Guid
);
374 CopyMem (VariableName
, SmmGetNextVariableName
->Name
, SmmGetNextVariableName
->NameSize
);
377 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
382 This code sets variable in storage blocks (Volatile or Non-Volatile).
384 @param[in] VariableName Name of Variable to be found.
385 @param[in] VendorGuid Variable vendor GUID.
386 @param[in] Attributes Attribute value of the variable found
387 @param[in] DataSize Size of Data found. If size is less than the
388 data, this value contains the required size.
389 @param[in] Data Data pointer.
391 @retval EFI_INVALID_PARAMETER Invalid parameter.
392 @retval EFI_SUCCESS Set successfully.
393 @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.
394 @retval EFI_NOT_FOUND Not found.
395 @retval EFI_WRITE_PROTECTED Variable is read-only.
400 RuntimeServiceSetVariable (
401 IN CHAR16
*VariableName
,
402 IN EFI_GUID
*VendorGuid
,
403 IN UINT32 Attributes
,
410 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
*SmmVariableHeader
;
411 UINTN VariableNameSize
;
414 // Check input parameters.
416 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
417 return EFI_INVALID_PARAMETER
;
420 if (DataSize
!= 0 && Data
== NULL
) {
421 return EFI_INVALID_PARAMETER
;
424 VariableNameSize
= StrSize (VariableName
);
427 // If VariableName or DataSize exceeds SMM payload limit. Return failure
429 if ((VariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
)) ||
430 (DataSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - VariableNameSize
)){
431 return EFI_INVALID_PARAMETER
;
434 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
437 // Init the communicate buffer. The buffer data size is:
438 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
440 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) + VariableNameSize
+ DataSize
;
441 Status
= InitCommunicateBuffer ((VOID
**)&SmmVariableHeader
, PayloadSize
, SMM_VARIABLE_FUNCTION_SET_VARIABLE
);
442 if (EFI_ERROR (Status
)) {
445 ASSERT (SmmVariableHeader
!= NULL
);
447 CopyGuid ((EFI_GUID
*) &SmmVariableHeader
->Guid
, VendorGuid
);
448 SmmVariableHeader
->DataSize
= DataSize
;
449 SmmVariableHeader
->NameSize
= VariableNameSize
;
450 SmmVariableHeader
->Attributes
= Attributes
;
451 CopyMem (SmmVariableHeader
->Name
, VariableName
, SmmVariableHeader
->NameSize
);
452 CopyMem ((UINT8
*) SmmVariableHeader
->Name
+ SmmVariableHeader
->NameSize
, Data
, DataSize
);
457 Status
= SendCommunicateBuffer (PayloadSize
);
460 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
466 This code returns information about the EFI variables.
468 @param[in] Attributes Attributes bitmask to specify the type of variables
469 on which to return information.
470 @param[out] MaximumVariableStorageSize Pointer to the maximum size of the storage space available
471 for the EFI variables associated with the attributes specified.
472 @param[out] RemainingVariableStorageSize Pointer to the remaining size of the storage space available
473 for EFI variables associated with the attributes specified.
474 @param[out] MaximumVariableSize Pointer to the maximum size of an individual EFI variables
475 associated with the attributes specified.
477 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.
478 @retval EFI_SUCCESS Query successfully.
479 @retval EFI_UNSUPPORTED The attribute is not supported on this platform.
484 RuntimeServiceQueryVariableInfo (
485 IN UINT32 Attributes
,
486 OUT UINT64
*MaximumVariableStorageSize
,
487 OUT UINT64
*RemainingVariableStorageSize
,
488 OUT UINT64
*MaximumVariableSize
493 SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO
*SmmQueryVariableInfo
;
495 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
|| Attributes
== 0) {
496 return EFI_INVALID_PARAMETER
;
499 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
502 // Init the communicate buffer. The buffer data size is:
503 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize;
505 PayloadSize
= sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO
);
506 Status
= InitCommunicateBuffer ((VOID
**)&SmmQueryVariableInfo
, PayloadSize
, SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO
);
507 if (EFI_ERROR (Status
)) {
510 ASSERT (SmmQueryVariableInfo
!= NULL
);
512 SmmQueryVariableInfo
->Attributes
= Attributes
;
517 Status
= SendCommunicateBuffer (PayloadSize
);
518 if (EFI_ERROR (Status
)) {
523 // Get data from SMM.
525 *MaximumVariableSize
= SmmQueryVariableInfo
->MaximumVariableSize
;
526 *MaximumVariableStorageSize
= SmmQueryVariableInfo
->MaximumVariableStorageSize
;
527 *RemainingVariableStorageSize
= SmmQueryVariableInfo
->RemainingVariableStorageSize
;
530 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
536 Exit Boot Services Event notification handler.
538 Notify SMM variable driver about the event.
540 @param[in] Event Event whose notification function is being invoked.
541 @param[in] Context Pointer to the notification function's context.
552 // Init the communicate buffer. The buffer data size is:
553 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
555 InitCommunicateBuffer (NULL
, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE
);
560 SendCommunicateBuffer (0);
565 On Ready To Boot Services Event notification handler.
567 Notify SMM variable driver about the event.
569 @param[in] Event Event whose notification function is being invoked
570 @param[in] Context Pointer to the notification function's context
581 // Init the communicate buffer. The buffer data size is:
582 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
584 InitCommunicateBuffer (NULL
, 0, SMM_VARIABLE_FUNCTION_READY_TO_BOOT
);
589 SendCommunicateBuffer (0);
594 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
596 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
597 It convers pointer to new virtual address.
599 @param[in] Event Event whose notification function is being invoked.
600 @param[in] Context Pointer to the notification function's context.
605 VariableAddressChangeEvent (
610 EfiConvertPointer (0x0, (VOID
**) &mVariableBuffer
);
611 EfiConvertPointer (0x0, (VOID
**) &mSmmCommunication
);
616 Initialize variable service and install Variable Architectural protocol.
618 @param[in] Event Event whose notification function is being invoked.
619 @param[in] Context Pointer to the notification function's context.
631 Status
= gBS
->LocateProtocol (&gEfiSmmVariableProtocolGuid
, NULL
, (VOID
**)&mSmmVariable
);
632 if (EFI_ERROR (Status
)) {
636 Status
= gBS
->LocateProtocol (&gEfiSmmCommunicationProtocolGuid
, NULL
, (VOID
**) &mSmmCommunication
);
637 ASSERT_EFI_ERROR (Status
);
640 // Allocate memory for variable communicate buffer.
642 mVariableBufferPayloadSize
= MAX (PcdGet32 (PcdMaxVariableSize
), PcdGet32 (PcdMaxHardwareErrorVariableSize
)) +
643 OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - sizeof (VARIABLE_HEADER
);
644 mVariableBufferSize
= SMM_COMMUNICATE_HEADER_SIZE
+ SMM_VARIABLE_COMMUNICATE_HEADER_SIZE
+ mVariableBufferPayloadSize
;
645 mVariableBuffer
= AllocateRuntimePool (mVariableBufferSize
);
646 ASSERT (mVariableBuffer
!= NULL
);
649 // Save the buffer physical address used for SMM conmunication.
651 mVariableBufferPhysical
= mVariableBuffer
;
653 gRT
->GetVariable
= RuntimeServiceGetVariable
;
654 gRT
->GetNextVariableName
= RuntimeServiceGetNextVariableName
;
655 gRT
->SetVariable
= RuntimeServiceSetVariable
;
656 gRT
->QueryVariableInfo
= RuntimeServiceQueryVariableInfo
;
659 // Install the Variable Architectural Protocol on a new handle.
661 Status
= gBS
->InstallProtocolInterface (
663 &gEfiVariableArchProtocolGuid
,
664 EFI_NATIVE_INTERFACE
,
667 ASSERT_EFI_ERROR (Status
);
672 SMM Non-Volatile variable write service is ready notify event handler.
674 @param[in] Event Event whose notification function is being invoked.
675 @param[in] Context Pointer to the notification function's context.
680 SmmVariableWriteReady (
689 // Check whether the protocol is installed or not.
691 Status
= gBS
->LocateProtocol (&gSmmVariableWriteGuid
, NULL
, (VOID
**) &ProtocolOps
);
692 if (EFI_ERROR (Status
)) {
696 Status
= gBS
->InstallProtocolInterface (
698 &gEfiVariableWriteArchProtocolGuid
,
699 EFI_NATIVE_INTERFACE
,
702 ASSERT_EFI_ERROR (Status
);
707 Variable Driver main entry point. The Variable driver places the 4 EFI
708 runtime services in the EFI System Table and installs arch protocols
709 for variable read and write services being available. It also registers
710 a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
712 @param[in] ImageHandle The firmware allocated handle for the EFI image.
713 @param[in] SystemTable A pointer to the EFI System Table.
715 @retval EFI_SUCCESS Variable service successfully initialized.
720 VariableSmmRuntimeInitialize (
721 IN EFI_HANDLE ImageHandle
,
722 IN EFI_SYSTEM_TABLE
*SystemTable
725 VOID
*SmmVariableRegistration
;
726 VOID
*SmmVariableWriteRegistration
;
727 EFI_EVENT OnReadyToBootEvent
;
728 EFI_EVENT ExitBootServiceEvent
;
730 EfiInitializeLock (&mVariableServicesLock
, TPL_NOTIFY
);
733 // Smm variable service is ready
735 EfiCreateProtocolNotifyEvent (
736 &gEfiSmmVariableProtocolGuid
,
740 &SmmVariableRegistration
744 // Smm Non-Volatile variable write service is ready
746 EfiCreateProtocolNotifyEvent (
747 &gSmmVariableWriteGuid
,
749 SmmVariableWriteReady
,
751 &SmmVariableWriteRegistration
755 // Register the event to reclaim variable for OS usage.
757 EfiCreateEventReadyToBootEx (
765 // Register the event to inform SMM variable that it is at runtime.
772 &gEfiEventExitBootServicesGuid
,
773 &ExitBootServiceEvent
777 // Register the event to convert the pointer for runtime.
782 VariableAddressChangeEvent
,
784 &gEfiEventVirtualAddressChangeGuid
,
785 &mVirtualAddressChangeEvent