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 - 2014, 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
);
198 VariableToLock
= NULL
;
201 // If VariableName exceeds SMM payload limit. Return failure
203 if (VariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE
, Name
)) {
204 return EFI_INVALID_PARAMETER
;
207 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
210 // Init the communicate buffer. The buffer data size is:
211 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
213 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE
, Name
) + VariableNameSize
;
214 Status
= InitCommunicateBuffer ((VOID
**) &VariableToLock
, PayloadSize
, SMM_VARIABLE_FUNCTION_LOCK_VARIABLE
);
215 if (EFI_ERROR (Status
)) {
218 ASSERT (VariableToLock
!= NULL
);
220 CopyGuid (&VariableToLock
->Guid
, VendorGuid
);
221 VariableToLock
->NameSize
= VariableNameSize
;
222 CopyMem (VariableToLock
->Name
, VariableName
, VariableToLock
->NameSize
);
227 Status
= SendCommunicateBuffer (PayloadSize
);
230 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
235 This code finds variable in storage blocks (Volatile or Non-Volatile).
237 @param[in] VariableName Name of Variable to be found.
238 @param[in] VendorGuid Variable vendor GUID.
239 @param[out] Attributes Attribute value of the variable found.
240 @param[in, out] DataSize Size of Data found. If size is less than the
241 data, this value contains the required size.
242 @param[out] Data Data pointer.
244 @retval EFI_INVALID_PARAMETER Invalid parameter.
245 @retval EFI_SUCCESS Find the specified variable.
246 @retval EFI_NOT_FOUND Not found.
247 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.
252 RuntimeServiceGetVariable (
253 IN CHAR16
*VariableName
,
254 IN EFI_GUID
*VendorGuid
,
255 OUT UINT32
*Attributes OPTIONAL
,
256 IN OUT UINTN
*DataSize
,
262 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
*SmmVariableHeader
;
264 UINTN VariableNameSize
;
266 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
267 return EFI_INVALID_PARAMETER
;
270 if ((*DataSize
!= 0) && (Data
== NULL
)) {
271 return EFI_INVALID_PARAMETER
;
274 TempDataSize
= *DataSize
;
275 VariableNameSize
= StrSize (VariableName
);
276 SmmVariableHeader
= NULL
;
279 // If VariableName exceeds SMM payload limit. Return failure
281 if (VariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
)) {
282 return EFI_INVALID_PARAMETER
;
285 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
288 // Init the communicate buffer. The buffer data size is:
289 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
291 if (TempDataSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - VariableNameSize
) {
293 // If output data buffer exceed SMM payload limit. Trim output buffer to SMM payload size
295 TempDataSize
= mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - VariableNameSize
;
297 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) + VariableNameSize
+ TempDataSize
;
299 Status
= InitCommunicateBuffer ((VOID
**)&SmmVariableHeader
, PayloadSize
, SMM_VARIABLE_FUNCTION_GET_VARIABLE
);
300 if (EFI_ERROR (Status
)) {
303 ASSERT (SmmVariableHeader
!= NULL
);
305 CopyGuid (&SmmVariableHeader
->Guid
, VendorGuid
);
306 SmmVariableHeader
->DataSize
= TempDataSize
;
307 SmmVariableHeader
->NameSize
= VariableNameSize
;
308 if (Attributes
== NULL
) {
309 SmmVariableHeader
->Attributes
= 0;
311 SmmVariableHeader
->Attributes
= *Attributes
;
313 CopyMem (SmmVariableHeader
->Name
, VariableName
, SmmVariableHeader
->NameSize
);
318 Status
= SendCommunicateBuffer (PayloadSize
);
321 // Get data from SMM.
323 if (Status
== EFI_SUCCESS
|| Status
== EFI_BUFFER_TOO_SMALL
) {
325 // SMM CommBuffer DataSize can be a trimed value
326 // Only update DataSize when needed
328 *DataSize
= SmmVariableHeader
->DataSize
;
330 if (Attributes
!= NULL
) {
331 *Attributes
= SmmVariableHeader
->Attributes
;
334 if (EFI_ERROR (Status
)) {
338 CopyMem (Data
, (UINT8
*)SmmVariableHeader
->Name
+ SmmVariableHeader
->NameSize
, SmmVariableHeader
->DataSize
);
341 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
347 This code Finds the Next available variable.
349 @param[in, out] VariableNameSize Size of the variable name.
350 @param[in, out] VariableName Pointer to variable name.
351 @param[in, out] VendorGuid Variable Vendor Guid.
353 @retval EFI_INVALID_PARAMETER Invalid parameter.
354 @retval EFI_SUCCESS Find the specified variable.
355 @retval EFI_NOT_FOUND Not found.
356 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.
361 RuntimeServiceGetNextVariableName (
362 IN OUT UINTN
*VariableNameSize
,
363 IN OUT CHAR16
*VariableName
,
364 IN OUT EFI_GUID
*VendorGuid
369 SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
*SmmGetNextVariableName
;
370 UINTN OutVariableNameSize
;
371 UINTN InVariableNameSize
;
373 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
374 return EFI_INVALID_PARAMETER
;
377 OutVariableNameSize
= *VariableNameSize
;
378 InVariableNameSize
= StrSize (VariableName
);
379 SmmGetNextVariableName
= NULL
;
382 // If input string exceeds SMM payload limit. Return failure
384 if (InVariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
)) {
385 return EFI_INVALID_PARAMETER
;
388 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
391 // Init the communicate buffer. The buffer data size is:
392 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
394 if (OutVariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
)) {
396 // If output buffer exceed SMM payload limit. Trim output buffer to SMM payload size
398 OutVariableNameSize
= mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
);
401 // Payload should be Guid + NameSize + MAX of Input & Output buffer
403 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
) + MAX (OutVariableNameSize
, InVariableNameSize
);
406 Status
= InitCommunicateBuffer ((VOID
**)&SmmGetNextVariableName
, PayloadSize
, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME
);
407 if (EFI_ERROR (Status
)) {
410 ASSERT (SmmGetNextVariableName
!= NULL
);
413 // SMM comm buffer->NameSize is buffer size for return string
415 SmmGetNextVariableName
->NameSize
= OutVariableNameSize
;
417 CopyGuid (&SmmGetNextVariableName
->Guid
, VendorGuid
);
421 CopyMem (SmmGetNextVariableName
->Name
, VariableName
, InVariableNameSize
);
422 if (OutVariableNameSize
> InVariableNameSize
) {
423 ZeroMem ((UINT8
*) SmmGetNextVariableName
->Name
+ InVariableNameSize
, OutVariableNameSize
- InVariableNameSize
);
429 Status
= SendCommunicateBuffer (PayloadSize
);
432 // Get data from SMM.
434 if (Status
== EFI_SUCCESS
|| Status
== EFI_BUFFER_TOO_SMALL
) {
436 // SMM CommBuffer NameSize can be a trimed value
437 // Only update VariableNameSize when needed
439 *VariableNameSize
= SmmGetNextVariableName
->NameSize
;
441 if (EFI_ERROR (Status
)) {
445 CopyGuid (VendorGuid
, &SmmGetNextVariableName
->Guid
);
446 CopyMem (VariableName
, SmmGetNextVariableName
->Name
, SmmGetNextVariableName
->NameSize
);
449 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
454 This code sets variable in storage blocks (Volatile or Non-Volatile).
456 @param[in] VariableName Name of Variable to be found.
457 @param[in] VendorGuid Variable vendor GUID.
458 @param[in] Attributes Attribute value of the variable found
459 @param[in] DataSize Size of Data found. If size is less than the
460 data, this value contains the required size.
461 @param[in] Data Data pointer.
463 @retval EFI_INVALID_PARAMETER Invalid parameter.
464 @retval EFI_SUCCESS Set successfully.
465 @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.
466 @retval EFI_NOT_FOUND Not found.
467 @retval EFI_WRITE_PROTECTED Variable is read-only.
472 RuntimeServiceSetVariable (
473 IN CHAR16
*VariableName
,
474 IN EFI_GUID
*VendorGuid
,
475 IN UINT32 Attributes
,
482 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
*SmmVariableHeader
;
483 UINTN VariableNameSize
;
486 // Check input parameters.
488 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
489 return EFI_INVALID_PARAMETER
;
492 if (DataSize
!= 0 && Data
== NULL
) {
493 return EFI_INVALID_PARAMETER
;
496 VariableNameSize
= StrSize (VariableName
);
497 SmmVariableHeader
= NULL
;
500 // If VariableName or DataSize exceeds SMM payload limit. Return failure
502 if ((VariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
)) ||
503 (DataSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - VariableNameSize
)){
504 return EFI_INVALID_PARAMETER
;
507 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
510 // Init the communicate buffer. The buffer data size is:
511 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
513 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) + VariableNameSize
+ DataSize
;
514 Status
= InitCommunicateBuffer ((VOID
**)&SmmVariableHeader
, PayloadSize
, SMM_VARIABLE_FUNCTION_SET_VARIABLE
);
515 if (EFI_ERROR (Status
)) {
518 ASSERT (SmmVariableHeader
!= NULL
);
520 CopyGuid ((EFI_GUID
*) &SmmVariableHeader
->Guid
, VendorGuid
);
521 SmmVariableHeader
->DataSize
= DataSize
;
522 SmmVariableHeader
->NameSize
= VariableNameSize
;
523 SmmVariableHeader
->Attributes
= Attributes
;
524 CopyMem (SmmVariableHeader
->Name
, VariableName
, SmmVariableHeader
->NameSize
);
525 CopyMem ((UINT8
*) SmmVariableHeader
->Name
+ SmmVariableHeader
->NameSize
, Data
, DataSize
);
530 Status
= SendCommunicateBuffer (PayloadSize
);
533 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
539 This code returns information about the EFI variables.
541 @param[in] Attributes Attributes bitmask to specify the type of variables
542 on which to return information.
543 @param[out] MaximumVariableStorageSize Pointer to the maximum size of the storage space available
544 for the EFI variables associated with the attributes specified.
545 @param[out] RemainingVariableStorageSize Pointer to the remaining size of the storage space available
546 for EFI variables associated with the attributes specified.
547 @param[out] MaximumVariableSize Pointer to the maximum size of an individual EFI variables
548 associated with the attributes specified.
550 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.
551 @retval EFI_SUCCESS Query successfully.
552 @retval EFI_UNSUPPORTED The attribute is not supported on this platform.
557 RuntimeServiceQueryVariableInfo (
558 IN UINT32 Attributes
,
559 OUT UINT64
*MaximumVariableStorageSize
,
560 OUT UINT64
*RemainingVariableStorageSize
,
561 OUT UINT64
*MaximumVariableSize
566 SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO
*SmmQueryVariableInfo
;
568 SmmQueryVariableInfo
= NULL
;
570 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
|| Attributes
== 0) {
571 return EFI_INVALID_PARAMETER
;
574 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
577 // Init the communicate buffer. The buffer data size is:
578 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize;
580 PayloadSize
= sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO
);
581 Status
= InitCommunicateBuffer ((VOID
**)&SmmQueryVariableInfo
, PayloadSize
, SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO
);
582 if (EFI_ERROR (Status
)) {
585 ASSERT (SmmQueryVariableInfo
!= NULL
);
587 SmmQueryVariableInfo
->Attributes
= Attributes
;
592 Status
= SendCommunicateBuffer (PayloadSize
);
593 if (EFI_ERROR (Status
)) {
598 // Get data from SMM.
600 *MaximumVariableSize
= SmmQueryVariableInfo
->MaximumVariableSize
;
601 *MaximumVariableStorageSize
= SmmQueryVariableInfo
->MaximumVariableStorageSize
;
602 *RemainingVariableStorageSize
= SmmQueryVariableInfo
->RemainingVariableStorageSize
;
605 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
611 Exit Boot Services Event notification handler.
613 Notify SMM variable driver about the event.
615 @param[in] Event Event whose notification function is being invoked.
616 @param[in] Context Pointer to the notification function's context.
627 // Init the communicate buffer. The buffer data size is:
628 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
630 InitCommunicateBuffer (NULL
, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE
);
635 SendCommunicateBuffer (0);
640 On Ready To Boot Services Event notification handler.
642 Notify SMM variable driver about the event.
644 @param[in] Event Event whose notification function is being invoked
645 @param[in] Context Pointer to the notification function's context
656 // Init the communicate buffer. The buffer data size is:
657 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
659 InitCommunicateBuffer (NULL
, 0, SMM_VARIABLE_FUNCTION_READY_TO_BOOT
);
664 SendCommunicateBuffer (0);
669 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
671 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
672 It convers pointer to new virtual address.
674 @param[in] Event Event whose notification function is being invoked.
675 @param[in] Context Pointer to the notification function's context.
680 VariableAddressChangeEvent (
685 EfiConvertPointer (0x0, (VOID
**) &mVariableBuffer
);
686 EfiConvertPointer (0x0, (VOID
**) &mSmmCommunication
);
691 Initialize variable service and install Variable Architectural protocol.
693 @param[in] Event Event whose notification function is being invoked.
694 @param[in] Context Pointer to the notification function's context.
706 Status
= gBS
->LocateProtocol (&gEfiSmmVariableProtocolGuid
, NULL
, (VOID
**)&mSmmVariable
);
707 if (EFI_ERROR (Status
)) {
711 Status
= gBS
->LocateProtocol (&gEfiSmmCommunicationProtocolGuid
, NULL
, (VOID
**) &mSmmCommunication
);
712 ASSERT_EFI_ERROR (Status
);
715 // Allocate memory for variable communicate buffer.
717 mVariableBufferPayloadSize
= MAX (PcdGet32 (PcdMaxVariableSize
), PcdGet32 (PcdMaxHardwareErrorVariableSize
)) +
718 OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - sizeof (VARIABLE_HEADER
);
719 mVariableBufferSize
= SMM_COMMUNICATE_HEADER_SIZE
+ SMM_VARIABLE_COMMUNICATE_HEADER_SIZE
+ mVariableBufferPayloadSize
;
720 mVariableBuffer
= AllocateRuntimePool (mVariableBufferSize
);
721 ASSERT (mVariableBuffer
!= NULL
);
724 // Save the buffer physical address used for SMM conmunication.
726 mVariableBufferPhysical
= mVariableBuffer
;
728 gRT
->GetVariable
= RuntimeServiceGetVariable
;
729 gRT
->GetNextVariableName
= RuntimeServiceGetNextVariableName
;
730 gRT
->SetVariable
= RuntimeServiceSetVariable
;
731 gRT
->QueryVariableInfo
= RuntimeServiceQueryVariableInfo
;
734 // Install the Variable Architectural Protocol on a new handle.
736 Status
= gBS
->InstallProtocolInterface (
738 &gEfiVariableArchProtocolGuid
,
739 EFI_NATIVE_INTERFACE
,
742 ASSERT_EFI_ERROR (Status
);
747 SMM Non-Volatile variable write service is ready notify event handler.
749 @param[in] Event Event whose notification function is being invoked.
750 @param[in] Context Pointer to the notification function's context.
755 SmmVariableWriteReady (
764 // Check whether the protocol is installed or not.
766 Status
= gBS
->LocateProtocol (&gSmmVariableWriteGuid
, NULL
, (VOID
**) &ProtocolOps
);
767 if (EFI_ERROR (Status
)) {
771 Status
= gBS
->InstallProtocolInterface (
773 &gEfiVariableWriteArchProtocolGuid
,
774 EFI_NATIVE_INTERFACE
,
777 ASSERT_EFI_ERROR (Status
);
782 Variable Driver main entry point. The Variable driver places the 4 EFI
783 runtime services in the EFI System Table and installs arch protocols
784 for variable read and write services being available. It also registers
785 a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
787 @param[in] ImageHandle The firmware allocated handle for the EFI image.
788 @param[in] SystemTable A pointer to the EFI System Table.
790 @retval EFI_SUCCESS Variable service successfully initialized.
795 VariableSmmRuntimeInitialize (
796 IN EFI_HANDLE ImageHandle
,
797 IN EFI_SYSTEM_TABLE
*SystemTable
801 VOID
*SmmVariableRegistration
;
802 VOID
*SmmVariableWriteRegistration
;
803 EFI_EVENT OnReadyToBootEvent
;
804 EFI_EVENT ExitBootServiceEvent
;
806 EfiInitializeLock (&mVariableServicesLock
, TPL_NOTIFY
);
808 mVariableLock
.RequestToLock
= VariableLockRequestToLock
;
809 Status
= gBS
->InstallMultipleProtocolInterfaces (
811 &gEdkiiVariableLockProtocolGuid
,
815 ASSERT_EFI_ERROR (Status
);
818 // Smm variable service is ready
820 EfiCreateProtocolNotifyEvent (
821 &gEfiSmmVariableProtocolGuid
,
825 &SmmVariableRegistration
829 // Smm Non-Volatile variable write service is ready
831 EfiCreateProtocolNotifyEvent (
832 &gSmmVariableWriteGuid
,
834 SmmVariableWriteReady
,
836 &SmmVariableWriteRegistration
840 // Register the event to reclaim variable for OS usage.
842 EfiCreateEventReadyToBootEx (
850 // Register the event to inform SMM variable that it is at runtime.
857 &gEfiEventExitBootServicesGuid
,
858 &ExitBootServiceEvent
862 // Register the event to convert the pointer for runtime.
867 VariableAddressChangeEvent
,
869 &gEfiEventVirtualAddressChangeGuid
,
870 &mVirtualAddressChangeEvent