2 Implement all four UEFI Runtime Variable services for the nonvolatile
3 and volatile storage space and install variable architecture protocol
4 based on SMM variable module.
6 Caution: This module requires additional review when modified.
7 This driver will have external input - variable data.
8 This external input must be validated carefully to avoid security issue like
9 buffer overflow, integer overflow.
11 RuntimeServiceGetVariable() and RuntimeServiceSetVariable() are external API
12 to receive data buffer. The size should be checked carefully.
14 InitCommunicateBuffer() is really function to check the variable data size.
16 Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
17 This program and the accompanying materials
18 are licensed and made available under the terms and conditions of the BSD License
19 which accompanies this distribution. The full text of the license may be found at
20 http://opensource.org/licenses/bsd-license.php
22 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
23 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
28 #include <Protocol/VariableWrite.h>
29 #include <Protocol/Variable.h>
30 #include <Protocol/SmmCommunication.h>
31 #include <Protocol/SmmVariable.h>
32 #include <Protocol/VariableLock.h>
34 #include <Library/UefiBootServicesTableLib.h>
35 #include <Library/UefiRuntimeServicesTableLib.h>
36 #include <Library/MemoryAllocationLib.h>
37 #include <Library/UefiDriverEntryPoint.h>
38 #include <Library/UefiRuntimeLib.h>
39 #include <Library/BaseMemoryLib.h>
40 #include <Library/DebugLib.h>
41 #include <Library/PcdLib.h>
42 #include <Library/UefiLib.h>
43 #include <Library/BaseLib.h>
45 #include <Guid/EventGroup.h>
46 #include <Guid/AuthenticatedVariableFormat.h>
47 #include <Guid/SmmVariableCommon.h>
49 EFI_HANDLE mHandle
= NULL
;
50 EFI_SMM_VARIABLE_PROTOCOL
*mSmmVariable
= NULL
;
51 EFI_EVENT mVirtualAddressChangeEvent
= NULL
;
52 EFI_SMM_COMMUNICATION_PROTOCOL
*mSmmCommunication
= NULL
;
53 UINT8
*mVariableBuffer
= NULL
;
54 UINT8
*mVariableBufferPhysical
= NULL
;
55 UINTN mVariableBufferSize
;
56 UINTN mVariableBufferPayloadSize
;
57 EFI_LOCK mVariableServicesLock
;
58 EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock
;
61 Acquires lock only at boot time. Simply returns at runtime.
63 This is a temperary function that will be removed when
64 EfiAcquireLock() in UefiLib can handle the call in UEFI
65 Runtimer driver in RT phase.
66 It calls EfiAcquireLock() at boot time, and simply returns
69 @param Lock A pointer to the lock to acquire.
73 AcquireLockOnlyAtBootTime (
77 if (!EfiAtRuntime ()) {
78 EfiAcquireLock (Lock
);
83 Releases lock only at boot time. Simply returns at runtime.
85 This is a temperary function which will be removed when
86 EfiReleaseLock() in UefiLib can handle the call in UEFI
87 Runtimer driver in RT phase.
88 It calls EfiReleaseLock() at boot time and simply returns
91 @param Lock A pointer to the lock to release.
95 ReleaseLockOnlyAtBootTime (
99 if (!EfiAtRuntime ()) {
100 EfiReleaseLock (Lock
);
105 Initialize the communicate buffer using DataSize and Function.
107 The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE +
110 Caution: This function may receive untrusted input.
111 The data size external input, so this function will validate it carefully to avoid buffer overflow.
113 @param[out] DataPtr Points to the data in the communicate buffer.
114 @param[in] DataSize The data size to send to SMM.
115 @param[in] Function The function number to initialize the communicate header.
117 @retval EFI_INVALID_PARAMETER The data size is too big.
118 @retval EFI_SUCCESS Find the specified variable.
122 InitCommunicateBuffer (
123 OUT VOID
**DataPtr OPTIONAL
,
128 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
129 SMM_VARIABLE_COMMUNICATE_HEADER
*SmmVariableFunctionHeader
;
132 if (DataSize
+ SMM_COMMUNICATE_HEADER_SIZE
+ SMM_VARIABLE_COMMUNICATE_HEADER_SIZE
> mVariableBufferSize
) {
133 return EFI_INVALID_PARAMETER
;
136 SmmCommunicateHeader
= (EFI_SMM_COMMUNICATE_HEADER
*) mVariableBuffer
;
137 CopyGuid (&SmmCommunicateHeader
->HeaderGuid
, &gEfiSmmVariableProtocolGuid
);
138 SmmCommunicateHeader
->MessageLength
= DataSize
+ SMM_VARIABLE_COMMUNICATE_HEADER_SIZE
;
140 SmmVariableFunctionHeader
= (SMM_VARIABLE_COMMUNICATE_HEADER
*) SmmCommunicateHeader
->Data
;
141 SmmVariableFunctionHeader
->Function
= Function
;
142 if (DataPtr
!= NULL
) {
143 *DataPtr
= SmmVariableFunctionHeader
->Data
;
151 Send the data in communicate buffer to SMM.
153 @param[in] DataSize This size of the function header and the data.
155 @retval EFI_SUCCESS Success is returned from the functin in SMM.
156 @retval Others Failure is returned from the function in SMM.
160 SendCommunicateBuffer (
166 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
167 SMM_VARIABLE_COMMUNICATE_HEADER
*SmmVariableFunctionHeader
;
169 CommSize
= DataSize
+ SMM_COMMUNICATE_HEADER_SIZE
+ SMM_VARIABLE_COMMUNICATE_HEADER_SIZE
;
170 Status
= mSmmCommunication
->Communicate (mSmmCommunication
, mVariableBufferPhysical
, &CommSize
);
171 ASSERT_EFI_ERROR (Status
);
173 SmmCommunicateHeader
= (EFI_SMM_COMMUNICATE_HEADER
*) mVariableBuffer
;
174 SmmVariableFunctionHeader
= (SMM_VARIABLE_COMMUNICATE_HEADER
*)SmmCommunicateHeader
->Data
;
175 return SmmVariableFunctionHeader
->ReturnStatus
;
179 Mark a variable that will become read-only after leaving the DXE phase of execution.
181 @param[in] This The VARIABLE_LOCK_PROTOCOL instance.
182 @param[in] VariableName A pointer to the variable name that will be made read-only subsequently.
183 @param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently.
185 @retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked
186 as pending to be read-only.
187 @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
188 Or VariableName is an empty string.
189 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
190 already been signaled.
191 @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request.
195 VariableLockRequestToLock (
196 IN CONST EDKII_VARIABLE_LOCK_PROTOCOL
*This
,
197 IN CHAR16
*VariableName
,
198 IN EFI_GUID
*VendorGuid
202 UINTN VariableNameSize
;
204 SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE
*VariableToLock
;
206 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
207 return EFI_INVALID_PARAMETER
;
210 VariableNameSize
= StrSize (VariableName
);
213 // If VariableName exceeds SMM payload limit. Return failure
215 if (VariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE
, Name
)) {
216 return EFI_INVALID_PARAMETER
;
219 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
222 // Init the communicate buffer. The buffer data size is:
223 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
225 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE
, Name
) + VariableNameSize
;
226 Status
= InitCommunicateBuffer ((VOID
**) &VariableToLock
, PayloadSize
, SMM_VARIABLE_FUNCTION_LOCK_VARIABLE
);
227 if (EFI_ERROR (Status
)) {
230 ASSERT (VariableToLock
!= NULL
);
232 CopyGuid (&VariableToLock
->Guid
, VendorGuid
);
233 VariableToLock
->NameSize
= VariableNameSize
;
234 CopyMem (VariableToLock
->Name
, VariableName
, VariableToLock
->NameSize
);
239 Status
= SendCommunicateBuffer (PayloadSize
);
242 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
247 This code finds variable in storage blocks (Volatile or Non-Volatile).
249 Caution: This function may receive untrusted input.
250 The data size is external input, so this function will validate it carefully to avoid buffer overflow.
252 @param[in] VariableName Name of Variable to be found.
253 @param[in] VendorGuid Variable vendor GUID.
254 @param[out] Attributes Attribute value of the variable found.
255 @param[in, out] DataSize Size of Data found. If size is less than the
256 data, this value contains the required size.
257 @param[out] Data Data pointer.
259 @retval EFI_INVALID_PARAMETER Invalid parameter.
260 @retval EFI_SUCCESS Find the specified variable.
261 @retval EFI_NOT_FOUND Not found.
262 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.
267 RuntimeServiceGetVariable (
268 IN CHAR16
*VariableName
,
269 IN EFI_GUID
*VendorGuid
,
270 OUT UINT32
*Attributes OPTIONAL
,
271 IN OUT UINTN
*DataSize
,
277 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
*SmmVariableHeader
;
279 UINTN VariableNameSize
;
281 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
282 return EFI_INVALID_PARAMETER
;
285 if ((*DataSize
!= 0) && (Data
== NULL
)) {
286 return EFI_INVALID_PARAMETER
;
289 TempDataSize
= *DataSize
;
290 VariableNameSize
= StrSize (VariableName
);
293 // If VariableName exceeds SMM payload limit. Return failure
295 if (VariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
)) {
296 return EFI_INVALID_PARAMETER
;
299 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
302 // Init the communicate buffer. The buffer data size is:
303 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
305 if (TempDataSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - VariableNameSize
) {
307 // If output data buffer exceed SMM payload limit. Trim output buffer to SMM payload size
309 TempDataSize
= mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - VariableNameSize
;
311 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) + VariableNameSize
+ TempDataSize
;
313 Status
= InitCommunicateBuffer ((VOID
**)&SmmVariableHeader
, PayloadSize
, SMM_VARIABLE_FUNCTION_GET_VARIABLE
);
314 if (EFI_ERROR (Status
)) {
317 ASSERT (SmmVariableHeader
!= NULL
);
319 CopyGuid (&SmmVariableHeader
->Guid
, VendorGuid
);
320 SmmVariableHeader
->DataSize
= TempDataSize
;
321 SmmVariableHeader
->NameSize
= VariableNameSize
;
322 if (Attributes
== NULL
) {
323 SmmVariableHeader
->Attributes
= 0;
325 SmmVariableHeader
->Attributes
= *Attributes
;
327 CopyMem (SmmVariableHeader
->Name
, VariableName
, SmmVariableHeader
->NameSize
);
332 Status
= SendCommunicateBuffer (PayloadSize
);
335 // Get data from SMM.
337 if (Status
== EFI_SUCCESS
|| Status
== EFI_BUFFER_TOO_SMALL
) {
339 // SMM CommBuffer DataSize can be a trimed value
340 // Only update DataSize when needed
342 *DataSize
= SmmVariableHeader
->DataSize
;
344 if (Attributes
!= NULL
) {
345 *Attributes
= SmmVariableHeader
->Attributes
;
348 if (EFI_ERROR (Status
)) {
352 CopyMem (Data
, (UINT8
*)SmmVariableHeader
->Name
+ SmmVariableHeader
->NameSize
, SmmVariableHeader
->DataSize
);
355 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
361 This code Finds the Next available variable.
363 @param[in, out] VariableNameSize Size of the variable name.
364 @param[in, out] VariableName Pointer to variable name.
365 @param[in, out] VendorGuid Variable Vendor Guid.
367 @retval EFI_INVALID_PARAMETER Invalid parameter.
368 @retval EFI_SUCCESS Find the specified variable.
369 @retval EFI_NOT_FOUND Not found.
370 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.
375 RuntimeServiceGetNextVariableName (
376 IN OUT UINTN
*VariableNameSize
,
377 IN OUT CHAR16
*VariableName
,
378 IN OUT EFI_GUID
*VendorGuid
383 SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
*SmmGetNextVariableName
;
384 UINTN OutVariableNameSize
;
385 UINTN InVariableNameSize
;
387 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
388 return EFI_INVALID_PARAMETER
;
391 OutVariableNameSize
= *VariableNameSize
;
392 InVariableNameSize
= StrSize (VariableName
);
395 // If input string exceeds SMM payload limit. Return failure
397 if (InVariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
)) {
398 return EFI_INVALID_PARAMETER
;
401 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
404 // Init the communicate buffer. The buffer data size is:
405 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
407 if (OutVariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
)) {
409 // If output buffer exceed SMM payload limit. Trim output buffer to SMM payload size
411 OutVariableNameSize
= mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
);
414 // Payload should be Guid + NameSize + MAX of Input & Output buffer
416 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
, Name
) + MAX (OutVariableNameSize
, InVariableNameSize
);
418 Status
= InitCommunicateBuffer ((VOID
**)&SmmGetNextVariableName
, PayloadSize
, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME
);
419 if (EFI_ERROR (Status
)) {
422 ASSERT (SmmGetNextVariableName
!= NULL
);
425 // SMM comm buffer->NameSize is buffer size for return string
427 SmmGetNextVariableName
->NameSize
= OutVariableNameSize
;
429 CopyGuid (&SmmGetNextVariableName
->Guid
, VendorGuid
);
433 CopyMem (SmmGetNextVariableName
->Name
, VariableName
, InVariableNameSize
);
434 if (OutVariableNameSize
> InVariableNameSize
) {
435 ZeroMem ((UINT8
*) SmmGetNextVariableName
->Name
+ InVariableNameSize
, OutVariableNameSize
- InVariableNameSize
);
441 Status
= SendCommunicateBuffer (PayloadSize
);
444 // Get data from SMM.
446 if (Status
== EFI_SUCCESS
|| Status
== EFI_BUFFER_TOO_SMALL
) {
448 // SMM CommBuffer NameSize can be a trimed value
449 // Only update VariableNameSize when needed
451 *VariableNameSize
= SmmGetNextVariableName
->NameSize
;
453 if (EFI_ERROR (Status
)) {
457 CopyGuid (VendorGuid
, &SmmGetNextVariableName
->Guid
);
458 CopyMem (VariableName
, SmmGetNextVariableName
->Name
, SmmGetNextVariableName
->NameSize
);
461 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
466 This code sets variable in storage blocks (Volatile or Non-Volatile).
468 Caution: This function may receive untrusted input.
469 The data size and data are external input, so this function will validate it carefully to avoid buffer overflow.
471 @param[in] VariableName Name of Variable to be found.
472 @param[in] VendorGuid Variable vendor GUID.
473 @param[in] Attributes Attribute value of the variable found
474 @param[in] DataSize Size of Data found. If size is less than the
475 data, this value contains the required size.
476 @param[in] Data Data pointer.
478 @retval EFI_INVALID_PARAMETER Invalid parameter.
479 @retval EFI_SUCCESS Set successfully.
480 @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.
481 @retval EFI_NOT_FOUND Not found.
482 @retval EFI_WRITE_PROTECTED Variable is read-only.
487 RuntimeServiceSetVariable (
488 IN CHAR16
*VariableName
,
489 IN EFI_GUID
*VendorGuid
,
490 IN UINT32 Attributes
,
497 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
*SmmVariableHeader
;
498 UINTN VariableNameSize
;
501 // Check input parameters.
503 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
504 return EFI_INVALID_PARAMETER
;
507 if (DataSize
!= 0 && Data
== NULL
) {
508 return EFI_INVALID_PARAMETER
;
511 VariableNameSize
= StrSize (VariableName
);
514 // If VariableName or DataSize exceeds SMM payload limit. Return failure
516 if ((VariableNameSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
)) ||
517 (DataSize
> mVariableBufferPayloadSize
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - VariableNameSize
)){
518 return EFI_INVALID_PARAMETER
;
521 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
524 // Init the communicate buffer. The buffer data size is:
525 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
527 PayloadSize
= OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) + VariableNameSize
+ DataSize
;
528 Status
= InitCommunicateBuffer ((VOID
**)&SmmVariableHeader
, PayloadSize
, SMM_VARIABLE_FUNCTION_SET_VARIABLE
);
529 if (EFI_ERROR (Status
)) {
532 ASSERT (SmmVariableHeader
!= NULL
);
534 CopyGuid ((EFI_GUID
*) &SmmVariableHeader
->Guid
, VendorGuid
);
535 SmmVariableHeader
->DataSize
= DataSize
;
536 SmmVariableHeader
->NameSize
= VariableNameSize
;
537 SmmVariableHeader
->Attributes
= Attributes
;
538 CopyMem (SmmVariableHeader
->Name
, VariableName
, SmmVariableHeader
->NameSize
);
539 CopyMem ((UINT8
*) SmmVariableHeader
->Name
+ SmmVariableHeader
->NameSize
, Data
, DataSize
);
544 Status
= SendCommunicateBuffer (PayloadSize
);
547 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
553 This code returns information about the EFI variables.
555 @param[in] Attributes Attributes bitmask to specify the type of variables
556 on which to return information.
557 @param[out] MaximumVariableStorageSize Pointer to the maximum size of the storage space available
558 for the EFI variables associated with the attributes specified.
559 @param[out] RemainingVariableStorageSize Pointer to the remaining size of the storage space available
560 for EFI variables associated with the attributes specified.
561 @param[out] MaximumVariableSize Pointer to the maximum size of an individual EFI variables
562 associated with the attributes specified.
564 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.
565 @retval EFI_SUCCESS Query successfully.
566 @retval EFI_UNSUPPORTED The attribute is not supported on this platform.
571 RuntimeServiceQueryVariableInfo (
572 IN UINT32 Attributes
,
573 OUT UINT64
*MaximumVariableStorageSize
,
574 OUT UINT64
*RemainingVariableStorageSize
,
575 OUT UINT64
*MaximumVariableSize
580 SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO
*SmmQueryVariableInfo
;
582 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
|| Attributes
== 0) {
583 return EFI_INVALID_PARAMETER
;
586 AcquireLockOnlyAtBootTime(&mVariableServicesLock
);
589 // Init the communicate buffer. The buffer data size is:
590 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize;
592 PayloadSize
= sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO
);
593 Status
= InitCommunicateBuffer ((VOID
**)&SmmQueryVariableInfo
, PayloadSize
, SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO
);
594 if (EFI_ERROR (Status
)) {
597 ASSERT (SmmQueryVariableInfo
!= NULL
);
599 SmmQueryVariableInfo
->Attributes
= Attributes
;
604 Status
= SendCommunicateBuffer (PayloadSize
);
605 if (EFI_ERROR (Status
)) {
610 // Get data from SMM.
612 *MaximumVariableSize
= SmmQueryVariableInfo
->MaximumVariableSize
;
613 *MaximumVariableStorageSize
= SmmQueryVariableInfo
->MaximumVariableStorageSize
;
614 *RemainingVariableStorageSize
= SmmQueryVariableInfo
->RemainingVariableStorageSize
;
617 ReleaseLockOnlyAtBootTime (&mVariableServicesLock
);
623 Exit Boot Services Event notification handler.
625 Notify SMM variable driver about the event.
627 @param[in] Event Event whose notification function is being invoked.
628 @param[in] Context Pointer to the notification function's context.
639 // Init the communicate buffer. The buffer data size is:
640 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
642 InitCommunicateBuffer (NULL
, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE
);
647 SendCommunicateBuffer (0);
652 On Ready To Boot Services Event notification handler.
654 Notify SMM variable driver about the event.
656 @param[in] Event Event whose notification function is being invoked
657 @param[in] Context Pointer to the notification function's context
668 // Init the communicate buffer. The buffer data size is:
669 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
671 InitCommunicateBuffer (NULL
, 0, SMM_VARIABLE_FUNCTION_READY_TO_BOOT
);
676 SendCommunicateBuffer (0);
681 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
683 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
684 It convers pointer to new virtual address.
686 @param[in] Event Event whose notification function is being invoked.
687 @param[in] Context Pointer to the notification function's context.
692 VariableAddressChangeEvent (
697 EfiConvertPointer (0x0, (VOID
**) &mVariableBuffer
);
698 EfiConvertPointer (0x0, (VOID
**) &mSmmCommunication
);
703 Initialize variable service and install Variable Architectural protocol.
705 @param[in] Event Event whose notification function is being invoked.
706 @param[in] Context Pointer to the notification function's context.
718 Status
= gBS
->LocateProtocol (&gEfiSmmVariableProtocolGuid
, NULL
, (VOID
**)&mSmmVariable
);
719 if (EFI_ERROR (Status
)) {
723 Status
= gBS
->LocateProtocol (&gEfiSmmCommunicationProtocolGuid
, NULL
, (VOID
**) &mSmmCommunication
);
724 ASSERT_EFI_ERROR (Status
);
727 // Allocate memory for variable communicate buffer.
729 mVariableBufferPayloadSize
= MAX (PcdGet32 (PcdMaxVariableSize
), PcdGet32 (PcdMaxHardwareErrorVariableSize
)) +
730 OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
, Name
) - sizeof (VARIABLE_HEADER
);
731 mVariableBufferSize
= SMM_COMMUNICATE_HEADER_SIZE
+ SMM_VARIABLE_COMMUNICATE_HEADER_SIZE
+ mVariableBufferPayloadSize
;
732 mVariableBuffer
= AllocateRuntimePool (mVariableBufferSize
);
733 ASSERT (mVariableBuffer
!= NULL
);
736 // Save the buffer physical address used for SMM conmunication.
738 mVariableBufferPhysical
= mVariableBuffer
;
740 gRT
->GetVariable
= RuntimeServiceGetVariable
;
741 gRT
->GetNextVariableName
= RuntimeServiceGetNextVariableName
;
742 gRT
->SetVariable
= RuntimeServiceSetVariable
;
743 gRT
->QueryVariableInfo
= RuntimeServiceQueryVariableInfo
;
746 // Install the Variable Architectural Protocol on a new handle.
748 Status
= gBS
->InstallProtocolInterface (
750 &gEfiVariableArchProtocolGuid
,
751 EFI_NATIVE_INTERFACE
,
754 ASSERT_EFI_ERROR (Status
);
759 SMM Non-Volatile variable write service is ready notify event handler.
761 @param[in] Event Event whose notification function is being invoked.
762 @param[in] Context Pointer to the notification function's context.
767 SmmVariableWriteReady (
776 // Check whether the protocol is installed or not.
778 Status
= gBS
->LocateProtocol (&gSmmVariableWriteGuid
, NULL
, (VOID
**) &ProtocolOps
);
779 if (EFI_ERROR (Status
)) {
783 Status
= gBS
->InstallProtocolInterface (
785 &gEfiVariableWriteArchProtocolGuid
,
786 EFI_NATIVE_INTERFACE
,
789 ASSERT_EFI_ERROR (Status
);
794 Variable Driver main entry point. The Variable driver places the 4 EFI
795 runtime services in the EFI System Table and installs arch protocols
796 for variable read and write services being available. It also registers
797 a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
799 @param[in] ImageHandle The firmware allocated handle for the EFI image.
800 @param[in] SystemTable A pointer to the EFI System Table.
802 @retval EFI_SUCCESS Variable service successfully initialized.
807 VariableSmmRuntimeInitialize (
808 IN EFI_HANDLE ImageHandle
,
809 IN EFI_SYSTEM_TABLE
*SystemTable
813 VOID
*SmmVariableRegistration
;
814 VOID
*SmmVariableWriteRegistration
;
815 EFI_EVENT OnReadyToBootEvent
;
816 EFI_EVENT ExitBootServiceEvent
;
818 EfiInitializeLock (&mVariableServicesLock
, TPL_NOTIFY
);
820 mVariableLock
.RequestToLock
= VariableLockRequestToLock
;
821 Status
= gBS
->InstallMultipleProtocolInterfaces (
823 &gEdkiiVariableLockProtocolGuid
,
827 ASSERT_EFI_ERROR (Status
);
830 // Smm variable service is ready
832 EfiCreateProtocolNotifyEvent (
833 &gEfiSmmVariableProtocolGuid
,
837 &SmmVariableRegistration
841 // Smm Non-Volatile variable write service is ready
843 EfiCreateProtocolNotifyEvent (
844 &gSmmVariableWriteGuid
,
846 SmmVariableWriteReady
,
848 &SmmVariableWriteRegistration
852 // Register the event to reclaim variable for OS usage.
854 EfiCreateEventReadyToBootEx (
862 // Register the event to inform SMM variable that it is at runtime.
869 &gEfiEventExitBootServicesGuid
,
870 &ExitBootServiceEvent
874 // Register the event to convert the pointer for runtime.
879 VariableAddressChangeEvent
,
881 &gEfiEventVirtualAddressChangeGuid
,
882 &mVirtualAddressChangeEvent