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
190 SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE
*VariableToLock
;
192 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
193 return EFI_INVALID_PARAMETER
;
196 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
199 // Init the communicate buffer. The buffer data size is:
200 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
202 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE
, Name
) + StrSize (VariableName
);
203 Status
= InitCommunicateBuffer ((VOID
**) &VariableToLock
, PayloadSize
, SMM_VARIABLE_FUNCTION_LOCK_VARIABLE
);
204 if (EFI_ERROR (Status
)) {
207 ASSERT (VariableToLock
!= NULL
);
209 CopyGuid (&VariableToLock
->Guid
, VendorGuid
);
210 VariableToLock
->NameSize
= StrSize (VariableName
);
211 CopyMem (VariableToLock
->Name
, VariableName
, VariableToLock
->NameSize
);
216 Status
= SendCommunicateBuffer (PayloadSize
);
219 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
224 This code finds variable in storage blocks (Volatile or Non-Volatile).
226 @param[in] VariableName Name of Variable to be found.
227 @param[in] VendorGuid Variable vendor GUID.
228 @param[out] Attributes Attribute value of the variable found.
229 @param[in, out] DataSize Size of Data found. If size is less than the
230 data, this value contains the required size.
231 @param[out] Data Data pointer.
233 @retval EFI_INVALID_PARAMETER Invalid parameter.
234 @retval EFI_SUCCESS Find the specified variable.
235 @retval EFI_NOT_FOUND Not found.
236 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.
241 RuntimeServiceGetVariable (
242 IN CHAR16
*VariableName
,
243 IN EFI_GUID
*VendorGuid
,
244 OUT UINT32
*Attributes OPTIONAL
,
245 IN OUT UINTN
*DataSize
,
251 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
*SmmVariableHeader
;
253 UINTN VariableNameSize
;
255 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
256 return EFI_INVALID_PARAMETER
;
259 if ((*DataSize
!= 0) && (Data
== NULL
)) {
260 return EFI_INVALID_PARAMETER
;
263 TempDataSize
= *DataSize
;
264 VariableNameSize
= StrSize (VariableName
);
267 // If VariableName exceeds SMM payload limit. Return failure
269 if (VariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
)) {
270 return EFI_INVALID_PARAMETER
;
273 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
276 // Init the communicate buffer. The buffer data size is:
277 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
279 if (TempDataSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - VariableNameSize
) {
281 // If output data buffer exceed SMM payload limit. Trim output buffer to SMM payload size
283 TempDataSize
= mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - VariableNameSize
;
285 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) + VariableNameSize
+ TempDataSize
;
287 Status
= InitCommunicateBuffer ((VOID
**)&SmmVariableHeader
, PayloadSize
, SMM_VARIABLE_FUNCTION_GET_VARIABLE
);
288 if (EFI_ERROR (Status
)) {
291 ASSERT (SmmVariableHeader
!= NULL
);
293 CopyGuid (&SmmVariableHeader
->Guid
, VendorGuid
);
294 SmmVariableHeader
->DataSize
= TempDataSize
;
295 SmmVariableHeader
->NameSize
= VariableNameSize
;
296 if (Attributes
== NULL
) {
297 SmmVariableHeader
->Attributes
= 0;
299 SmmVariableHeader
->Attributes
= *Attributes
;
301 CopyMem (SmmVariableHeader
->Name
, VariableName
, SmmVariableHeader
->NameSize
);
306 Status
= SendCommunicateBuffer (PayloadSize
);
309 // Get data from SMM.
311 if (Status
== EFI_SUCCESS
|| Status
== EFI_BUFFER_TOO_SMALL
) {
313 // SMM CommBuffer DataSize can be a trimed value
314 // Only update DataSize when needed
316 *DataSize
= SmmVariableHeader
->DataSize
;
318 if (Attributes
!= NULL
) {
319 *Attributes
= SmmVariableHeader
->Attributes
;
322 if (EFI_ERROR (Status
)) {
326 CopyMem (Data
, (UINT8
*)SmmVariableHeader
->Name
+ SmmVariableHeader
->NameSize
, SmmVariableHeader
->DataSize
);
329 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
335 This code Finds the Next available variable.
337 @param[in, out] VariableNameSize Size of the variable name.
338 @param[in, out] VariableName Pointer to variable name.
339 @param[in, out] VendorGuid Variable Vendor Guid.
341 @retval EFI_INVALID_PARAMETER Invalid parameter.
342 @retval EFI_SUCCESS Find the specified variable.
343 @retval EFI_NOT_FOUND Not found.
344 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.
349 RuntimeServiceGetNextVariableName (
350 IN OUT UINTN
*VariableNameSize
,
351 IN OUT CHAR16
*VariableName
,
352 IN OUT EFI_GUID
*VendorGuid
357 SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
*SmmGetNextVariableName
;
358 UINTN OutVariableNameSize
;
359 UINTN InVariableNameSize
;
361 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
362 return EFI_INVALID_PARAMETER
;
365 OutVariableNameSize
= *VariableNameSize
;
366 InVariableNameSize
= StrSize (VariableName
);
369 // If input string exceeds SMM payload limit. Return failure
371 if (InVariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
)) {
372 return EFI_INVALID_PARAMETER
;
375 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
378 // Init the communicate buffer. The buffer data size is:
379 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
381 if (OutVariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
)) {
383 // If output buffer exceed SMM payload limit. Trim output buffer to SMM payload size
385 OutVariableNameSize
= mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
);
388 // Payload should be Guid + NameSize + MAX of Input & Output buffer
390 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
) + MAX (OutVariableNameSize
, InVariableNameSize
);
393 Status
= InitCommunicateBuffer ((VOID
**)&SmmGetNextVariableName
, PayloadSize
, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME
);
394 if (EFI_ERROR (Status
)) {
397 ASSERT (SmmGetNextVariableName
!= NULL
);
400 // SMM comm buffer->NameSize is buffer size for return string
402 SmmGetNextVariableName
->NameSize
= OutVariableNameSize
;
404 CopyGuid (&SmmGetNextVariableName
->Guid
, VendorGuid
);
408 CopyMem (SmmGetNextVariableName
->Name
, VariableName
, InVariableNameSize
);
409 if (OutVariableNameSize
> InVariableNameSize
) {
410 ZeroMem ((UINT8
*) SmmGetNextVariableName
->Name
+ InVariableNameSize
, OutVariableNameSize
- InVariableNameSize
);
416 Status
= SendCommunicateBuffer (PayloadSize
);
419 // Get data from SMM.
421 if (Status
== EFI_SUCCESS
|| Status
== EFI_BUFFER_TOO_SMALL
) {
423 // SMM CommBuffer NameSize can be a trimed value
424 // Only update VariableNameSize when needed
426 *VariableNameSize
= SmmGetNextVariableName
->NameSize
;
428 if (EFI_ERROR (Status
)) {
432 CopyGuid (VendorGuid
, &SmmGetNextVariableName
->Guid
);
433 CopyMem (VariableName
, SmmGetNextVariableName
->Name
, SmmGetNextVariableName
->NameSize
);
436 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
441 This code sets variable in storage blocks (Volatile or Non-Volatile).
443 @param[in] VariableName Name of Variable to be found.
444 @param[in] VendorGuid Variable vendor GUID.
445 @param[in] Attributes Attribute value of the variable found
446 @param[in] DataSize Size of Data found. If size is less than the
447 data, this value contains the required size.
448 @param[in] Data Data pointer.
450 @retval EFI_INVALID_PARAMETER Invalid parameter.
451 @retval EFI_SUCCESS Set successfully.
452 @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.
453 @retval EFI_NOT_FOUND Not found.
454 @retval EFI_WRITE_PROTECTED Variable is read-only.
459 RuntimeServiceSetVariable (
460 IN CHAR16
*VariableName
,
461 IN EFI_GUID
*VendorGuid
,
462 IN UINT32 Attributes
,
469 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
*SmmVariableHeader
;
470 UINTN VariableNameSize
;
473 // Check input parameters.
475 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
476 return EFI_INVALID_PARAMETER
;
479 if (DataSize
!= 0 && Data
== NULL
) {
480 return EFI_INVALID_PARAMETER
;
483 VariableNameSize
= StrSize (VariableName
);
486 // If VariableName or DataSize exceeds SMM payload limit. Return failure
488 if ((VariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
)) ||
489 (DataSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - VariableNameSize
)){
490 return EFI_INVALID_PARAMETER
;
493 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
496 // Init the communicate buffer. The buffer data size is:
497 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
499 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) + VariableNameSize
+ DataSize
;
500 Status
= InitCommunicateBuffer ((VOID
**)&SmmVariableHeader
, PayloadSize
, SMM_VARIABLE_FUNCTION_SET_VARIABLE
);
501 if (EFI_ERROR (Status
)) {
504 ASSERT (SmmVariableHeader
!= NULL
);
506 CopyGuid ((EFI_GUID
*) &SmmVariableHeader
->Guid
, VendorGuid
);
507 SmmVariableHeader
->DataSize
= DataSize
;
508 SmmVariableHeader
->NameSize
= VariableNameSize
;
509 SmmVariableHeader
->Attributes
= Attributes
;
510 CopyMem (SmmVariableHeader
->Name
, VariableName
, SmmVariableHeader
->NameSize
);
511 CopyMem ((UINT8
*) SmmVariableHeader
->Name
+ SmmVariableHeader
->NameSize
, Data
, DataSize
);
516 Status
= SendCommunicateBuffer (PayloadSize
);
519 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
525 This code returns information about the EFI variables.
527 @param[in] Attributes Attributes bitmask to specify the type of variables
528 on which to return information.
529 @param[out] MaximumVariableStorageSize Pointer to the maximum size of the storage space available
530 for the EFI variables associated with the attributes specified.
531 @param[out] RemainingVariableStorageSize Pointer to the remaining size of the storage space available
532 for EFI variables associated with the attributes specified.
533 @param[out] MaximumVariableSize Pointer to the maximum size of an individual EFI variables
534 associated with the attributes specified.
536 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.
537 @retval EFI_SUCCESS Query successfully.
538 @retval EFI_UNSUPPORTED The attribute is not supported on this platform.
543 RuntimeServiceQueryVariableInfo (
544 IN UINT32 Attributes
,
545 OUT UINT64
*MaximumVariableStorageSize
,
546 OUT UINT64
*RemainingVariableStorageSize
,
547 OUT UINT64
*MaximumVariableSize
552 SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO
*SmmQueryVariableInfo
;
554 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
|| Attributes
== 0) {
555 return EFI_INVALID_PARAMETER
;
558 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
561 // Init the communicate buffer. The buffer data size is:
562 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize;
564 PayloadSize
= sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO
);
565 Status
= InitCommunicateBuffer ((VOID
**)&SmmQueryVariableInfo
, PayloadSize
, SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO
);
566 if (EFI_ERROR (Status
)) {
569 ASSERT (SmmQueryVariableInfo
!= NULL
);
571 SmmQueryVariableInfo
->Attributes
= Attributes
;
576 Status
= SendCommunicateBuffer (PayloadSize
);
577 if (EFI_ERROR (Status
)) {
582 // Get data from SMM.
584 *MaximumVariableSize
= SmmQueryVariableInfo
->MaximumVariableSize
;
585 *MaximumVariableStorageSize
= SmmQueryVariableInfo
->MaximumVariableStorageSize
;
586 *RemainingVariableStorageSize
= SmmQueryVariableInfo
->RemainingVariableStorageSize
;
589 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
595 Exit Boot Services Event notification handler.
597 Notify SMM variable driver about the event.
599 @param[in] Event Event whose notification function is being invoked.
600 @param[in] Context Pointer to the notification function's context.
611 // Init the communicate buffer. The buffer data size is:
612 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
614 InitCommunicateBuffer (NULL
, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE
);
619 SendCommunicateBuffer (0);
624 On Ready To Boot Services Event notification handler.
626 Notify SMM variable driver about the event.
628 @param[in] Event Event whose notification function is being invoked
629 @param[in] Context Pointer to the notification function's context
640 // Init the communicate buffer. The buffer data size is:
641 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
643 InitCommunicateBuffer (NULL
, 0, SMM_VARIABLE_FUNCTION_READY_TO_BOOT
);
648 SendCommunicateBuffer (0);
653 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
655 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
656 It convers pointer to new virtual address.
658 @param[in] Event Event whose notification function is being invoked.
659 @param[in] Context Pointer to the notification function's context.
664 VariableAddressChangeEvent (
669 EfiConvertPointer (0x0, (VOID
**) &mVariableBuffer
);
670 EfiConvertPointer (0x0, (VOID
**) &mSmmCommunication
);
675 Initialize variable service and install Variable Architectural protocol.
677 @param[in] Event Event whose notification function is being invoked.
678 @param[in] Context Pointer to the notification function's context.
690 Status
= gBS
->LocateProtocol (&gEfiSmmVariableProtocolGuid
, NULL
, (VOID
**)&mSmmVariable
);
691 if (EFI_ERROR (Status
)) {
695 Status
= gBS
->LocateProtocol (&gEfiSmmCommunicationProtocolGuid
, NULL
, (VOID
**) &mSmmCommunication
);
696 ASSERT_EFI_ERROR (Status
);
699 // Allocate memory for variable communicate buffer.
701 mVariableBufferPayloadSize
= MAX (PcdGet32 (PcdMaxVariableSize
), PcdGet32 (PcdMaxHardwareErrorVariableSize
)) +
702 OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - sizeof (VARIABLE_HEADER
);
703 mVariableBufferSize
= SMM_COMMUNICATE_HEADER_SIZE
+ SMM_VARIABLE_COMMUNICATE_HEADER_SIZE
+ mVariableBufferPayloadSize
;
704 mVariableBuffer
= AllocateRuntimePool (mVariableBufferSize
);
705 ASSERT (mVariableBuffer
!= NULL
);
708 // Save the buffer physical address used for SMM conmunication.
710 mVariableBufferPhysical
= mVariableBuffer
;
712 gRT
->GetVariable
= RuntimeServiceGetVariable
;
713 gRT
->GetNextVariableName
= RuntimeServiceGetNextVariableName
;
714 gRT
->SetVariable
= RuntimeServiceSetVariable
;
715 gRT
->QueryVariableInfo
= RuntimeServiceQueryVariableInfo
;
718 // Install the Variable Architectural Protocol on a new handle.
720 Status
= gBS
->InstallProtocolInterface (
722 &gEfiVariableArchProtocolGuid
,
723 EFI_NATIVE_INTERFACE
,
726 ASSERT_EFI_ERROR (Status
);
731 SMM Non-Volatile variable write service is ready notify event handler.
733 @param[in] Event Event whose notification function is being invoked.
734 @param[in] Context Pointer to the notification function's context.
739 SmmVariableWriteReady (
748 // Check whether the protocol is installed or not.
750 Status
= gBS
->LocateProtocol (&gSmmVariableWriteGuid
, NULL
, (VOID
**) &ProtocolOps
);
751 if (EFI_ERROR (Status
)) {
755 Status
= gBS
->InstallProtocolInterface (
757 &gEfiVariableWriteArchProtocolGuid
,
758 EFI_NATIVE_INTERFACE
,
761 ASSERT_EFI_ERROR (Status
);
766 Variable Driver main entry point. The Variable driver places the 4 EFI
767 runtime services in the EFI System Table and installs arch protocols
768 for variable read and write services being available. It also registers
769 a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
771 @param[in] ImageHandle The firmware allocated handle for the EFI image.
772 @param[in] SystemTable A pointer to the EFI System Table.
774 @retval EFI_SUCCESS Variable service successfully initialized.
779 VariableSmmRuntimeInitialize (
780 IN EFI_HANDLE ImageHandle
,
781 IN EFI_SYSTEM_TABLE
*SystemTable
785 VOID
*SmmVariableRegistration
;
786 VOID
*SmmVariableWriteRegistration
;
787 EFI_EVENT OnReadyToBootEvent
;
788 EFI_EVENT ExitBootServiceEvent
;
790 EfiInitializeLock (&mVariableServicesLock
, TPL_NOTIFY
);
792 mVariableLock
.RequestToLock
= VariableLockRequestToLock
;
793 Status
= gBS
->InstallMultipleProtocolInterfaces (
795 &gEdkiiVariableLockProtocolGuid
,
799 ASSERT_EFI_ERROR (Status
);
802 // Smm variable service is ready
804 EfiCreateProtocolNotifyEvent (
805 &gEfiSmmVariableProtocolGuid
,
809 &SmmVariableRegistration
813 // Smm Non-Volatile variable write service is ready
815 EfiCreateProtocolNotifyEvent (
816 &gSmmVariableWriteGuid
,
818 SmmVariableWriteReady
,
820 &SmmVariableWriteRegistration
824 // Register the event to reclaim variable for OS usage.
826 EfiCreateEventReadyToBootEx (
834 // Register the event to inform SMM variable that it is at runtime.
841 &gEfiEventExitBootServicesGuid
,
842 &ExitBootServiceEvent
846 // Register the event to convert the pointer for runtime.
851 VariableAddressChangeEvent
,
853 &gEfiEventVirtualAddressChangeGuid
,
854 &mVirtualAddressChangeEvent