]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c
Add security package to repository.
[mirror_edk2.git] / SecurityPkg / VariableAuthenticated / RuntimeDxe / VariableSmmRuntimeDxe.c
1 /** @file
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.
5
6 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
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/AuthenticatedVariableFormat.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