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