]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
Fix the issue that RuntimeServiceQueryVariableInfo() in VariableSmmRuntimeDxe always...
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / VariableSmmRuntimeDxe.c
1 /** @file
2
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.
6
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
12
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.
15
16 **/
17 #include <PiDxe.h>
18 #include <Protocol/VariableWrite.h>
19 #include <Protocol/Variable.h>
20 #include <Protocol/SmmCommunication.h>
21 #include <Protocol/SmmVariable.h>
22
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>
33
34 #include <Guid/EventGroup.h>
35 #include <Guid/VariableFormat.h>
36 #include <Guid/SmmVariableCommon.h>
37
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 EFI_LOCK mVariableServicesLock;
46
47 /**
48 Acquires lock only at boot time. Simply returns at runtime.
49
50 This is a temperary function that will be removed when
51 EfiAcquireLock() in UefiLib can handle the call in UEFI
52 Runtimer driver in RT phase.
53 It calls EfiAcquireLock() at boot time, and simply returns
54 at runtime.
55
56 @param Lock A pointer to the lock to acquire.
57
58 **/
59 VOID
60 AcquireLockOnlyAtBootTime (
61 IN EFI_LOCK *Lock
62 )
63 {
64 if (!EfiAtRuntime ()) {
65 EfiAcquireLock (Lock);
66 }
67 }
68
69 /**
70 Releases lock only at boot time. Simply returns at runtime.
71
72 This is a temperary function which will be removed when
73 EfiReleaseLock() in UefiLib can handle the call in UEFI
74 Runtimer driver in RT phase.
75 It calls EfiReleaseLock() at boot time and simply returns
76 at runtime.
77
78 @param Lock A pointer to the lock to release.
79
80 **/
81 VOID
82 ReleaseLockOnlyAtBootTime (
83 IN EFI_LOCK *Lock
84 )
85 {
86 if (!EfiAtRuntime ()) {
87 EfiReleaseLock (Lock);
88 }
89 }
90
91 /**
92 Initialize the communicate buffer using DataSize and Function.
93
94 The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE +
95 DataSize.
96
97 @param[out] DataPtr Points to the data in the communicate buffer.
98 @param[in] DataSize The data size to send to SMM.
99 @param[in] Function The function number to initialize the communicate header.
100
101 @retval EFI_INVALID_PARAMETER The data size is too big.
102 @retval EFI_SUCCESS Find the specified variable.
103
104 **/
105 EFI_STATUS
106 InitCommunicateBuffer (
107 OUT VOID **DataPtr OPTIONAL,
108 IN UINTN DataSize,
109 IN UINTN Function
110 )
111 {
112 EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
113 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
114
115
116 if (DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE > mVariableBufferSize) {
117 return EFI_INVALID_PARAMETER;
118 }
119
120 SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) mVariableBuffer;
121 CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
122 SmmCommunicateHeader->MessageLength = DataSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
123
124 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) SmmCommunicateHeader->Data;
125 SmmVariableFunctionHeader->Function = Function;
126 if (DataPtr != NULL) {
127 *DataPtr = SmmVariableFunctionHeader->Data;
128 }
129
130 return EFI_SUCCESS;
131 }
132
133
134 /**
135 Send the data in communicate buffer to SMM.
136
137 @param[in] DataSize This size of the function header and the data.
138
139 @retval EFI_SUCCESS Success is returned from the functin in SMM.
140 @retval Others Failure is returned from the function in SMM.
141
142 **/
143 EFI_STATUS
144 SendCommunicateBuffer (
145 IN UINTN DataSize
146 )
147 {
148 EFI_STATUS Status;
149 UINTN CommSize;
150 EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
151 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
152
153 CommSize = DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
154 Status = mSmmCommunication->Communicate (mSmmCommunication, mVariableBufferPhysical, &CommSize);
155 ASSERT_EFI_ERROR (Status);
156
157 SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) mVariableBuffer;
158 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
159 return SmmVariableFunctionHeader->ReturnStatus;
160 }
161
162
163 /**
164 This code finds variable in storage blocks (Volatile or Non-Volatile).
165
166 @param[in] VariableName Name of Variable to be found.
167 @param[in] VendorGuid Variable vendor GUID.
168 @param[out] Attributes Attribute value of the variable found.
169 @param[in, out] DataSize Size of Data found. If size is less than the
170 data, this value contains the required size.
171 @param[out] Data Data pointer.
172
173 @retval EFI_INVALID_PARAMETER Invalid parameter.
174 @retval EFI_SUCCESS Find the specified variable.
175 @retval EFI_NOT_FOUND Not found.
176 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.
177
178 **/
179 EFI_STATUS
180 EFIAPI
181 RuntimeServiceGetVariable (
182 IN CHAR16 *VariableName,
183 IN EFI_GUID *VendorGuid,
184 OUT UINT32 *Attributes OPTIONAL,
185 IN OUT UINTN *DataSize,
186 OUT VOID *Data
187 )
188 {
189 EFI_STATUS Status;
190 UINTN PayloadSize;
191 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;
192
193 if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {
194 return EFI_INVALID_PARAMETER;
195 }
196
197 if ((*DataSize != 0) && (Data == NULL)) {
198 return EFI_INVALID_PARAMETER;
199 }
200
201 AcquireLockOnlyAtBootTime(&mVariableServicesLock);
202
203 //
204 // Init the communicate buffer. The buffer data size is:
205 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
206 //
207 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName) + *DataSize;
208 Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);
209 if (EFI_ERROR (Status)) {
210 goto Done;
211 }
212 ASSERT (SmmVariableHeader != NULL);
213
214 CopyGuid (&SmmVariableHeader->Guid, VendorGuid);
215 SmmVariableHeader->DataSize = *DataSize;
216 SmmVariableHeader->NameSize = StrSize (VariableName);
217 if (Attributes == NULL) {
218 SmmVariableHeader->Attributes = 0;
219 } else {
220 SmmVariableHeader->Attributes = *Attributes;
221 }
222 CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);
223
224 //
225 // Send data to SMM.
226 //
227 Status = SendCommunicateBuffer (PayloadSize);
228
229 //
230 // Get data from SMM.
231 //
232 *DataSize = SmmVariableHeader->DataSize;
233 if (Attributes != NULL) {
234 *Attributes = SmmVariableHeader->Attributes;
235 }
236
237 if (EFI_ERROR (Status)) {
238 goto Done;
239 }
240
241 CopyMem (Data, (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize, SmmVariableHeader->DataSize);
242
243 Done:
244 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
245 return Status;
246 }
247
248
249 /**
250 This code Finds the Next available variable.
251
252 @param[in, out] VariableNameSize Size of the variable name.
253 @param[in, out] VariableName Pointer to variable name.
254 @param[in, out] VendorGuid Variable Vendor Guid.
255
256 @retval EFI_INVALID_PARAMETER Invalid parameter.
257 @retval EFI_SUCCESS Find the specified variable.
258 @retval EFI_NOT_FOUND Not found.
259 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.
260
261 **/
262 EFI_STATUS
263 EFIAPI
264 RuntimeServiceGetNextVariableName (
265 IN OUT UINTN *VariableNameSize,
266 IN OUT CHAR16 *VariableName,
267 IN OUT EFI_GUID *VendorGuid
268 )
269 {
270 EFI_STATUS Status;
271 UINTN PayloadSize;
272 SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *SmmGetNextVariableName;
273
274 if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {
275 return EFI_INVALID_PARAMETER;
276 }
277
278 AcquireLockOnlyAtBootTime(&mVariableServicesLock);
279
280 //
281 // Init the communicate buffer. The buffer data size is:
282 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
283 //
284 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + *VariableNameSize;
285 Status = InitCommunicateBuffer ((VOID **)&SmmGetNextVariableName, PayloadSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);
286 if (EFI_ERROR (Status)) {
287 goto Done;
288 }
289 ASSERT (SmmGetNextVariableName != NULL);
290
291 SmmGetNextVariableName->NameSize = *VariableNameSize;
292 CopyGuid (&SmmGetNextVariableName->Guid, VendorGuid);
293 CopyMem (SmmGetNextVariableName->Name, VariableName, *VariableNameSize);
294
295 //
296 // Send data to SMM
297 //
298 Status = SendCommunicateBuffer (PayloadSize);
299
300 //
301 // Get data from SMM.
302 //
303 *VariableNameSize = SmmGetNextVariableName->NameSize;
304 if (EFI_ERROR (Status)) {
305 goto Done;
306 }
307
308 CopyGuid (VendorGuid, &SmmGetNextVariableName->Guid);
309 CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize);
310
311 Done:
312 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
313 return Status;
314 }
315
316 /**
317 This code sets variable in storage blocks (Volatile or Non-Volatile).
318
319 @param[in] VariableName Name of Variable to be found.
320 @param[in] VendorGuid Variable vendor GUID.
321 @param[in] Attributes Attribute value of the variable found
322 @param[in] DataSize Size of Data found. If size is less than the
323 data, this value contains the required size.
324 @param[in] Data Data pointer.
325
326 @retval EFI_INVALID_PARAMETER Invalid parameter.
327 @retval EFI_SUCCESS Set successfully.
328 @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.
329 @retval EFI_NOT_FOUND Not found.
330 @retval EFI_WRITE_PROTECTED Variable is read-only.
331
332 **/
333 EFI_STATUS
334 EFIAPI
335 RuntimeServiceSetVariable (
336 IN CHAR16 *VariableName,
337 IN EFI_GUID *VendorGuid,
338 IN UINT32 Attributes,
339 IN UINTN DataSize,
340 IN VOID *Data
341 )
342 {
343 EFI_STATUS Status;
344 UINTN PayloadSize;
345 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;
346
347 //
348 // Check input parameters.
349 //
350 if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
351 return EFI_INVALID_PARAMETER;
352 }
353
354 if (DataSize != 0 && Data == NULL) {
355 return EFI_INVALID_PARAMETER;
356 }
357
358 AcquireLockOnlyAtBootTime(&mVariableServicesLock);
359
360 //
361 // Init the communicate buffer. The buffer data size is:
362 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
363 //
364 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName) + DataSize;
365 Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_SET_VARIABLE);
366 if (EFI_ERROR (Status)) {
367 goto Done;
368 }
369 ASSERT (SmmVariableHeader != NULL);
370
371 CopyGuid ((EFI_GUID *) &SmmVariableHeader->Guid, VendorGuid);
372 SmmVariableHeader->DataSize = DataSize;
373 SmmVariableHeader->NameSize = StrSize (VariableName);
374 SmmVariableHeader->Attributes = Attributes;
375 CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);
376 CopyMem ((UINT8 *) SmmVariableHeader->Name + SmmVariableHeader->NameSize, Data, DataSize);
377
378 //
379 // Send data to SMM.
380 //
381 Status = SendCommunicateBuffer (PayloadSize);
382
383 Done:
384 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
385 return Status;
386 }
387
388
389 /**
390 This code returns information about the EFI variables.
391
392 @param[in] Attributes Attributes bitmask to specify the type of variables
393 on which to return information.
394 @param[out] MaximumVariableStorageSize Pointer to the maximum size of the storage space available
395 for the EFI variables associated with the attributes specified.
396 @param[out] RemainingVariableStorageSize Pointer to the remaining size of the storage space available
397 for EFI variables associated with the attributes specified.
398 @param[out] MaximumVariableSize Pointer to the maximum size of an individual EFI variables
399 associated with the attributes specified.
400
401 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.
402 @retval EFI_SUCCESS Query successfully.
403 @retval EFI_UNSUPPORTED The attribute is not supported on this platform.
404
405 **/
406 EFI_STATUS
407 EFIAPI
408 RuntimeServiceQueryVariableInfo (
409 IN UINT32 Attributes,
410 OUT UINT64 *MaximumVariableStorageSize,
411 OUT UINT64 *RemainingVariableStorageSize,
412 OUT UINT64 *MaximumVariableSize
413 )
414 {
415 EFI_STATUS Status;
416 UINTN PayloadSize;
417 SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *SmmQueryVariableInfo;
418
419 if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {
420 return EFI_INVALID_PARAMETER;
421 }
422
423 AcquireLockOnlyAtBootTime(&mVariableServicesLock);
424
425 //
426 // Init the communicate buffer. The buffer data size is:
427 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize;
428 //
429 PayloadSize = sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO);
430 Status = InitCommunicateBuffer ((VOID **)&SmmQueryVariableInfo, PayloadSize, SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO);
431 if (EFI_ERROR (Status)) {
432 goto Done;
433 }
434 ASSERT (SmmQueryVariableInfo != NULL);
435
436 SmmQueryVariableInfo->Attributes = Attributes;
437
438 //
439 // Send data to SMM.
440 //
441 Status = SendCommunicateBuffer (PayloadSize);
442 if (EFI_ERROR (Status)) {
443 goto Done;
444 }
445
446 //
447 // Get data from SMM.
448 //
449 *MaximumVariableSize = SmmQueryVariableInfo->MaximumVariableSize;
450 *MaximumVariableStorageSize = SmmQueryVariableInfo->MaximumVariableStorageSize;
451 *RemainingVariableStorageSize = SmmQueryVariableInfo->RemainingVariableStorageSize;
452
453 Done:
454 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
455 return Status;
456 }
457
458
459 /**
460 Exit Boot Services Event notification handler.
461
462 Notify SMM variable driver about the event.
463
464 @param[in] Event Event whose notification function is being invoked.
465 @param[in] Context Pointer to the notification function's context.
466
467 **/
468 VOID
469 EFIAPI
470 OnExitBootServices (
471 IN EFI_EVENT Event,
472 IN VOID *Context
473 )
474 {
475 //
476 // Init the communicate buffer. The buffer data size is:
477 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
478 //
479 InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE);
480
481 //
482 // Send data to SMM.
483 //
484 SendCommunicateBuffer (0);
485 }
486
487
488 /**
489 On Ready To Boot Services Event notification handler.
490
491 Notify SMM variable driver about the event.
492
493 @param[in] Event Event whose notification function is being invoked
494 @param[in] Context Pointer to the notification function's context
495
496 **/
497 VOID
498 EFIAPI
499 OnReadyToBoot (
500 IN EFI_EVENT Event,
501 IN VOID *Context
502 )
503 {
504 //
505 // Init the communicate buffer. The buffer data size is:
506 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
507 //
508 InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_READY_TO_BOOT);
509
510 //
511 // Send data to SMM.
512 //
513 SendCommunicateBuffer (0);
514 }
515
516
517 /**
518 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
519
520 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
521 It convers pointer to new virtual address.
522
523 @param[in] Event Event whose notification function is being invoked.
524 @param[in] Context Pointer to the notification function's context.
525
526 **/
527 VOID
528 EFIAPI
529 VariableAddressChangeEvent (
530 IN EFI_EVENT Event,
531 IN VOID *Context
532 )
533 {
534 EfiConvertPointer (0x0, (VOID **) &mVariableBuffer);
535 EfiConvertPointer (0x0, (VOID **) &mSmmCommunication);
536 }
537
538
539 /**
540 Initialize variable service and install Variable Architectural protocol.
541
542 @param[in] Event Event whose notification function is being invoked.
543 @param[in] Context Pointer to the notification function's context.
544
545 **/
546 VOID
547 EFIAPI
548 SmmVariableReady (
549 IN EFI_EVENT Event,
550 IN VOID *Context
551 )
552 {
553 EFI_STATUS Status;
554
555 Status = gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **)&mSmmVariable);
556 if (EFI_ERROR (Status)) {
557 return;
558 }
559
560 Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &mSmmCommunication);
561 ASSERT_EFI_ERROR (Status);
562
563 //
564 // Allocate memory for variable store.
565 //
566 mVariableBufferSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
567 mVariableBufferSize += MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));
568 mVariableBuffer = AllocateRuntimePool (mVariableBufferSize);
569 ASSERT (mVariableBuffer != NULL);
570
571 //
572 // Save the buffer physical address used for SMM conmunication.
573 //
574 mVariableBufferPhysical = mVariableBuffer;
575
576 gRT->GetVariable = RuntimeServiceGetVariable;
577 gRT->GetNextVariableName = RuntimeServiceGetNextVariableName;
578 gRT->SetVariable = RuntimeServiceSetVariable;
579 gRT->QueryVariableInfo = RuntimeServiceQueryVariableInfo;
580
581 //
582 // Install the Variable Architectural Protocol on a new handle.
583 //
584 Status = gBS->InstallProtocolInterface (
585 &mHandle,
586 &gEfiVariableArchProtocolGuid,
587 EFI_NATIVE_INTERFACE,
588 NULL
589 );
590 ASSERT_EFI_ERROR (Status);
591 }
592
593
594 /**
595 SMM Non-Volatile variable write service is ready notify event handler.
596
597 @param[in] Event Event whose notification function is being invoked.
598 @param[in] Context Pointer to the notification function's context.
599
600 **/
601 VOID
602 EFIAPI
603 SmmVariableWriteReady (
604 IN EFI_EVENT Event,
605 IN VOID *Context
606 )
607 {
608 EFI_STATUS Status;
609 VOID *ProtocolOps;
610
611 //
612 // Check whether the protocol is installed or not.
613 //
614 Status = gBS->LocateProtocol (&gSmmVariableWriteGuid, NULL, (VOID **) &ProtocolOps);
615 if (EFI_ERROR (Status)) {
616 return;
617 }
618
619 Status = gBS->InstallProtocolInterface (
620 &mHandle,
621 &gEfiVariableWriteArchProtocolGuid,
622 EFI_NATIVE_INTERFACE,
623 NULL
624 );
625 ASSERT_EFI_ERROR (Status);
626 }
627
628
629 /**
630 Variable Driver main entry point. The Variable driver places the 4 EFI
631 runtime services in the EFI System Table and installs arch protocols
632 for variable read and write services being available. It also registers
633 a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
634
635 @param[in] ImageHandle The firmware allocated handle for the EFI image.
636 @param[in] SystemTable A pointer to the EFI System Table.
637
638 @retval EFI_SUCCESS Variable service successfully initialized.
639
640 **/
641 EFI_STATUS
642 EFIAPI
643 VariableSmmRuntimeInitialize (
644 IN EFI_HANDLE ImageHandle,
645 IN EFI_SYSTEM_TABLE *SystemTable
646 )
647 {
648 VOID *SmmVariableRegistration;
649 VOID *SmmVariableWriteRegistration;
650 EFI_EVENT OnReadyToBootEvent;
651 EFI_EVENT ExitBootServiceEvent;
652
653 EfiInitializeLock (&mVariableServicesLock, TPL_NOTIFY);
654
655 //
656 // Smm variable service is ready
657 //
658 EfiCreateProtocolNotifyEvent (
659 &gEfiSmmVariableProtocolGuid,
660 TPL_CALLBACK,
661 SmmVariableReady,
662 NULL,
663 &SmmVariableRegistration
664 );
665
666 //
667 // Smm Non-Volatile variable write service is ready
668 //
669 EfiCreateProtocolNotifyEvent (
670 &gSmmVariableWriteGuid,
671 TPL_CALLBACK,
672 SmmVariableWriteReady,
673 NULL,
674 &SmmVariableWriteRegistration
675 );
676
677 //
678 // Register the event to reclaim variable for OS usage.
679 //
680 EfiCreateEventReadyToBootEx (
681 TPL_NOTIFY,
682 OnReadyToBoot,
683 NULL,
684 &OnReadyToBootEvent
685 );
686
687 //
688 // Register the event to inform SMM variable that it is at runtime.
689 //
690 gBS->CreateEventEx (
691 EVT_NOTIFY_SIGNAL,
692 TPL_NOTIFY,
693 OnExitBootServices,
694 NULL,
695 &gEfiEventExitBootServicesGuid,
696 &ExitBootServiceEvent
697 );
698
699 //
700 // Register the event to convert the pointer for runtime.
701 //
702 gBS->CreateEventEx (
703 EVT_NOTIFY_SIGNAL,
704 TPL_NOTIFY,
705 VariableAddressChangeEvent,
706 NULL,
707 &gEfiEventVirtualAddressChangeGuid,
708 &mVirtualAddressChangeEvent
709 );
710
711 return EFI_SUCCESS;
712 }
713