2 Instance of SMM memory check library.
4 SMM memory check library library implementation. This library consumes SMM_ACCESS2_PROTOCOL
5 to get SMRAM information. In order to use this library instance, the platform should produce
6 all SMRAM range via SMM_ACCESS2_PROTOCOL, including the range for firmware (like SMM Core
7 and SMM driver) and/or specific dedicated hardware.
9 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
10 This program and the accompanying materials
11 are licensed and made available under the terms and conditions of the BSD License
12 which accompanies this distribution. The full text of the license may be found at
13 http://opensource.org/licenses/bsd-license.php
15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
16 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
23 #include <Library/BaseLib.h>
24 #include <Library/BaseMemoryLib.h>
25 #include <Library/DebugLib.h>
26 #include <Library/MemoryAllocationLib.h>
27 #include <Library/UefiBootServicesTableLib.h>
28 #include <Library/DxeServicesTableLib.h>
29 #include <Library/SmmServicesTableLib.h>
30 #include <Library/UefiLib.h>
31 #include <Library/HobLib.h>
32 #include <Protocol/SmmAccess2.h>
33 #include <Protocol/SmmReadyToLock.h>
34 #include <Protocol/SmmEndOfDxe.h>
35 #include <Guid/MemoryAttributesTable.h>
38 // attributes for reserved memory before it is promoted to system memory
40 #define EFI_MEMORY_PRESENT 0x0100000000000000ULL
41 #define EFI_MEMORY_INITIALIZED 0x0200000000000000ULL
42 #define EFI_MEMORY_TESTED 0x0400000000000000ULL
44 EFI_SMRAM_DESCRIPTOR
*mSmmMemLibInternalSmramRanges
;
45 UINTN mSmmMemLibInternalSmramCount
;
48 // Maximum support address used to check input buffer
50 EFI_PHYSICAL_ADDRESS mSmmMemLibInternalMaximumSupportAddress
= 0;
52 UINTN mMemoryMapEntryCount
;
53 EFI_MEMORY_DESCRIPTOR
*mMemoryMap
;
54 UINTN mDescriptorSize
;
56 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*mSmmMemLibGcdMemSpace
= NULL
;
57 UINTN mSmmMemLibGcdMemNumberOfDesc
= 0;
59 EFI_MEMORY_ATTRIBUTES_TABLE
*mSmmMemLibMemoryAttributesTable
= NULL
;
61 VOID
*mRegistrationEndOfDxe
;
62 VOID
*mRegistrationReadyToLock
;
64 BOOLEAN mSmmMemLibSmmReadyToLock
= FALSE
;
67 Calculate and save the maximum support address.
71 SmmMemLibInternalCalculateMaximumSupportAddress (
77 UINT8 PhysicalAddressBits
;
80 // Get physical address bits supported.
82 Hob
= GetFirstHob (EFI_HOB_TYPE_CPU
);
84 PhysicalAddressBits
= ((EFI_HOB_CPU
*) Hob
)->SizeOfMemorySpace
;
86 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
87 if (RegEax
>= 0x80000008) {
88 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
89 PhysicalAddressBits
= (UINT8
) RegEax
;
91 PhysicalAddressBits
= 36;
95 // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.
97 ASSERT (PhysicalAddressBits
<= 52);
98 if (PhysicalAddressBits
> 48) {
99 PhysicalAddressBits
= 48;
103 // Save the maximum support address in one global variable
105 mSmmMemLibInternalMaximumSupportAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)(LShiftU64 (1, PhysicalAddressBits
) - 1);
106 DEBUG ((EFI_D_INFO
, "mSmmMemLibInternalMaximumSupportAddress = 0x%lx\n", mSmmMemLibInternalMaximumSupportAddress
));
110 This function check if the buffer is valid per processor architecture and not overlap with SMRAM.
112 @param Buffer The buffer start address to be checked.
113 @param Length The buffer length to be checked.
115 @retval TRUE This buffer is valid per processor architecture and not overlap with SMRAM.
116 @retval FALSE This buffer is not valid per processor architecture or overlap with SMRAM.
120 SmmIsBufferOutsideSmmValid (
121 IN EFI_PHYSICAL_ADDRESS Buffer
,
129 // NOTE: (B:0->L:4G) is invalid for IA32, but (B:1->L:4G-1)/(B:4G-1->L:1) is valid.
131 if ((Length
> mSmmMemLibInternalMaximumSupportAddress
) ||
132 (Buffer
> mSmmMemLibInternalMaximumSupportAddress
) ||
133 ((Length
!= 0) && (Buffer
> (mSmmMemLibInternalMaximumSupportAddress
- (Length
- 1)))) ) {
139 "SmmIsBufferOutsideSmmValid: Overflow: Buffer (0x%lx) - Length (0x%lx), MaximumSupportAddress (0x%lx)\n",
142 mSmmMemLibInternalMaximumSupportAddress
147 for (Index
= 0; Index
< mSmmMemLibInternalSmramCount
; Index
++) {
148 if (((Buffer
>= mSmmMemLibInternalSmramRanges
[Index
].CpuStart
) && (Buffer
< mSmmMemLibInternalSmramRanges
[Index
].CpuStart
+ mSmmMemLibInternalSmramRanges
[Index
].PhysicalSize
)) ||
149 ((mSmmMemLibInternalSmramRanges
[Index
].CpuStart
>= Buffer
) && (mSmmMemLibInternalSmramRanges
[Index
].CpuStart
< Buffer
+ Length
))) {
152 "SmmIsBufferOutsideSmmValid: Overlap: Buffer (0x%lx) - Length (0x%lx), ",
158 "CpuStart (0x%lx) - PhysicalSize (0x%lx)\n",
159 mSmmMemLibInternalSmramRanges
[Index
].CpuStart
,
160 mSmmMemLibInternalSmramRanges
[Index
].PhysicalSize
167 // Check override for Valid Communication Region
169 if (mSmmMemLibSmmReadyToLock
) {
170 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
171 BOOLEAN InValidCommunicationRegion
;
173 InValidCommunicationRegion
= FALSE
;
174 MemoryMap
= mMemoryMap
;
175 for (Index
= 0; Index
< mMemoryMapEntryCount
; Index
++) {
176 if ((Buffer
>= MemoryMap
->PhysicalStart
) &&
177 (Buffer
+ Length
<= MemoryMap
->PhysicalStart
+ LShiftU64 (MemoryMap
->NumberOfPages
, EFI_PAGE_SHIFT
))) {
178 InValidCommunicationRegion
= TRUE
;
180 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, mDescriptorSize
);
183 if (!InValidCommunicationRegion
) {
186 "SmmIsBufferOutsideSmmValid: Not in ValidCommunicationRegion: Buffer (0x%lx) - Length (0x%lx)\n",
194 // Check untested memory as invalid communication buffer.
196 for (Index
= 0; Index
< mSmmMemLibGcdMemNumberOfDesc
; Index
++) {
197 if (((Buffer
>= mSmmMemLibGcdMemSpace
[Index
].BaseAddress
) && (Buffer
< mSmmMemLibGcdMemSpace
[Index
].BaseAddress
+ mSmmMemLibGcdMemSpace
[Index
].Length
)) ||
198 ((mSmmMemLibGcdMemSpace
[Index
].BaseAddress
>= Buffer
) && (mSmmMemLibGcdMemSpace
[Index
].BaseAddress
< Buffer
+ Length
))) {
201 "SmmIsBufferOutsideSmmValid: In Untested Memory Region: Buffer (0x%lx) - Length (0x%lx)\n",
210 // Check UEFI runtime memory with EFI_MEMORY_RO as invalid communication buffer.
212 if (mSmmMemLibMemoryAttributesTable
!= NULL
) {
213 EFI_MEMORY_DESCRIPTOR
*Entry
;
215 Entry
= (EFI_MEMORY_DESCRIPTOR
*)(mSmmMemLibMemoryAttributesTable
+ 1);
216 for (Index
= 0; Index
< mSmmMemLibMemoryAttributesTable
->NumberOfEntries
; Index
++) {
217 if (Entry
->Type
== EfiRuntimeServicesCode
|| Entry
->Type
== EfiRuntimeServicesData
) {
218 if ((Entry
->Attribute
& EFI_MEMORY_RO
) != 0) {
219 if (((Buffer
>= Entry
->PhysicalStart
) && (Buffer
< Entry
->PhysicalStart
+ LShiftU64 (Entry
->NumberOfPages
, EFI_PAGE_SHIFT
))) ||
220 ((Entry
->PhysicalStart
>= Buffer
) && (Entry
->PhysicalStart
< Buffer
+ Length
))) {
223 "SmmIsBufferOutsideSmmValid: In RuntimeCode Region: Buffer (0x%lx) - Length (0x%lx)\n",
231 Entry
= NEXT_MEMORY_DESCRIPTOR (Entry
, mSmmMemLibMemoryAttributesTable
->DescriptorSize
);
239 Copies a source buffer (non-SMRAM) to a destination buffer (SMRAM).
241 This function copies a source buffer (non-SMRAM) to a destination buffer (SMRAM).
242 It checks if source buffer is valid per processor architecture and not overlap with SMRAM.
243 If the check passes, it copies memory and returns EFI_SUCCESS.
244 If the check fails, it return EFI_SECURITY_VIOLATION.
245 The implementation must be reentrant.
247 @param DestinationBuffer The pointer to the destination buffer of the memory copy.
248 @param SourceBuffer The pointer to the source buffer of the memory copy.
249 @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer.
251 @retval EFI_SECURITY_VIOLATION The SourceBuffer is invalid per processor architecture or overlap with SMRAM.
252 @retval EFI_SUCCESS Memory is copied.
258 OUT VOID
*DestinationBuffer
,
259 IN CONST VOID
*SourceBuffer
,
263 if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS
)(UINTN
)SourceBuffer
, Length
)) {
264 DEBUG ((EFI_D_ERROR
, "SmmCopyMemToSmram: Security Violation: Source (0x%x), Length (0x%x)\n", SourceBuffer
, Length
));
265 return EFI_SECURITY_VIOLATION
;
267 CopyMem (DestinationBuffer
, SourceBuffer
, Length
);
272 Copies a source buffer (SMRAM) to a destination buffer (NON-SMRAM).
274 This function copies a source buffer (non-SMRAM) to a destination buffer (SMRAM).
275 It checks if destination buffer is valid per processor architecture and not overlap with SMRAM.
276 If the check passes, it copies memory and returns EFI_SUCCESS.
277 If the check fails, it returns EFI_SECURITY_VIOLATION.
278 The implementation must be reentrant.
280 @param DestinationBuffer The pointer to the destination buffer of the memory copy.
281 @param SourceBuffer The pointer to the source buffer of the memory copy.
282 @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer.
284 @retval EFI_SECURITY_VIOLATION The DesinationBuffer is invalid per processor architecture or overlap with SMRAM.
285 @retval EFI_SUCCESS Memory is copied.
290 SmmCopyMemFromSmram (
291 OUT VOID
*DestinationBuffer
,
292 IN CONST VOID
*SourceBuffer
,
296 if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS
)(UINTN
)DestinationBuffer
, Length
)) {
297 DEBUG ((EFI_D_ERROR
, "SmmCopyMemFromSmram: Security Violation: Destination (0x%x), Length (0x%x)\n", DestinationBuffer
, Length
));
298 return EFI_SECURITY_VIOLATION
;
300 CopyMem (DestinationBuffer
, SourceBuffer
, Length
);
305 Copies a source buffer (NON-SMRAM) to a destination buffer (NON-SMRAM).
307 This function copies a source buffer (non-SMRAM) to a destination buffer (SMRAM).
308 It checks if source buffer and destination buffer are valid per processor architecture and not overlap with SMRAM.
309 If the check passes, it copies memory and returns EFI_SUCCESS.
310 If the check fails, it returns EFI_SECURITY_VIOLATION.
311 The implementation must be reentrant, and it must handle the case where source buffer overlaps destination buffer.
313 @param DestinationBuffer The pointer to the destination buffer of the memory copy.
314 @param SourceBuffer The pointer to the source buffer of the memory copy.
315 @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer.
317 @retval EFI_SECURITY_VIOLATION The DesinationBuffer is invalid per processor architecture or overlap with SMRAM.
318 @retval EFI_SECURITY_VIOLATION The SourceBuffer is invalid per processor architecture or overlap with SMRAM.
319 @retval EFI_SUCCESS Memory is copied.
325 OUT VOID
*DestinationBuffer
,
326 IN CONST VOID
*SourceBuffer
,
330 if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS
)(UINTN
)DestinationBuffer
, Length
)) {
331 DEBUG ((EFI_D_ERROR
, "SmmCopyMem: Security Violation: Destination (0x%x), Length (0x%x)\n", DestinationBuffer
, Length
));
332 return EFI_SECURITY_VIOLATION
;
334 if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS
)(UINTN
)SourceBuffer
, Length
)) {
335 DEBUG ((EFI_D_ERROR
, "SmmCopyMem: Security Violation: Source (0x%x), Length (0x%x)\n", SourceBuffer
, Length
));
336 return EFI_SECURITY_VIOLATION
;
338 CopyMem (DestinationBuffer
, SourceBuffer
, Length
);
343 Fills a target buffer (NON-SMRAM) with a byte value.
345 This function fills a target buffer (non-SMRAM) with a byte value.
346 It checks if target buffer is valid per processor architecture and not overlap with SMRAM.
347 If the check passes, it fills memory and returns EFI_SUCCESS.
348 If the check fails, it returns EFI_SECURITY_VIOLATION.
350 @param Buffer The memory to set.
351 @param Length The number of bytes to set.
352 @param Value The value with which to fill Length bytes of Buffer.
354 @retval EFI_SECURITY_VIOLATION The Buffer is invalid per processor architecture or overlap with SMRAM.
355 @retval EFI_SUCCESS Memory is set.
366 if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS
)(UINTN
)Buffer
, Length
)) {
367 DEBUG ((EFI_D_ERROR
, "SmmSetMem: Security Violation: Source (0x%x), Length (0x%x)\n", Buffer
, Length
));
368 return EFI_SECURITY_VIOLATION
;
370 SetMem (Buffer
, Length
, Value
);
376 Only record untested memory as invalid communication buffer.
379 SmmMemLibInternalGetGcdMemoryMap (
383 UINTN NumberOfDescriptors
;
384 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemSpaceMap
;
388 Status
= gDS
->GetMemorySpaceMap (&NumberOfDescriptors
, &MemSpaceMap
);
389 if (EFI_ERROR (Status
)) {
393 mSmmMemLibGcdMemNumberOfDesc
= 0;
394 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
395 if (MemSpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeReserved
&&
396 (MemSpaceMap
[Index
].Capabilities
& (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
| EFI_MEMORY_TESTED
)) ==
397 (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
)
399 mSmmMemLibGcdMemNumberOfDesc
++;
403 mSmmMemLibGcdMemSpace
= AllocateZeroPool (mSmmMemLibGcdMemNumberOfDesc
* sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
404 ASSERT (mSmmMemLibGcdMemSpace
!= NULL
);
405 if (mSmmMemLibGcdMemSpace
== NULL
) {
406 mSmmMemLibGcdMemNumberOfDesc
= 0;
407 gBS
->FreePool (MemSpaceMap
);
411 mSmmMemLibGcdMemNumberOfDesc
= 0;
412 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
413 if (MemSpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeReserved
&&
414 (MemSpaceMap
[Index
].Capabilities
& (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
| EFI_MEMORY_TESTED
)) ==
415 (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
)
418 &mSmmMemLibGcdMemSpace
[mSmmMemLibGcdMemNumberOfDesc
],
420 sizeof(EFI_GCD_MEMORY_SPACE_DESCRIPTOR
)
422 mSmmMemLibGcdMemNumberOfDesc
++;
426 gBS
->FreePool (MemSpaceMap
);
430 Get UEFI MemoryAttributesTable.
433 SmmMemLibInternalGetUefiMemoryAttributesTable (
438 EFI_MEMORY_ATTRIBUTES_TABLE
*MemoryAttributesTable
;
439 UINTN MemoryAttributesTableSize
;
441 Status
= EfiGetSystemConfigurationTable (&gEfiMemoryAttributesTableGuid
, (VOID
**)&MemoryAttributesTable
);
442 if (!EFI_ERROR (Status
) && (MemoryAttributesTable
!= NULL
)) {
443 MemoryAttributesTableSize
= sizeof(EFI_MEMORY_ATTRIBUTES_TABLE
) + MemoryAttributesTable
->DescriptorSize
* MemoryAttributesTable
->NumberOfEntries
;
444 mSmmMemLibMemoryAttributesTable
= AllocateCopyPool (MemoryAttributesTableSize
, MemoryAttributesTable
);
445 ASSERT (mSmmMemLibMemoryAttributesTable
!= NULL
);
450 Notification for SMM EndOfDxe protocol.
452 @param[in] Protocol Points to the protocol's unique identifier.
453 @param[in] Interface Points to the interface instance.
454 @param[in] Handle The handle on which the interface was installed.
456 @retval EFI_SUCCESS Notification runs successfully.
460 SmmLibInternalEndOfDxeNotify (
461 IN CONST EFI_GUID
*Protocol
,
469 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
470 EFI_MEMORY_DESCRIPTOR
*MemoryMapStart
;
471 EFI_MEMORY_DESCRIPTOR
*SmmMemoryMapStart
;
472 UINTN MemoryMapEntryCount
;
473 UINTN DescriptorSize
;
474 UINT32 DescriptorVersion
;
479 Status
= gBS
->GetMemoryMap (
486 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
489 Status
= gBS
->AllocatePool (EfiBootServicesData
, MemoryMapSize
, (VOID
**)&MemoryMap
);
490 ASSERT (MemoryMap
!= NULL
);
492 Status
= gBS
->GetMemoryMap (
499 if (EFI_ERROR (Status
)) {
500 gBS
->FreePool (MemoryMap
);
502 } while (Status
== EFI_BUFFER_TOO_SMALL
);
507 mDescriptorSize
= DescriptorSize
;
508 MemoryMapEntryCount
= MemoryMapSize
/DescriptorSize
;
509 MemoryMapStart
= MemoryMap
;
510 mMemoryMapEntryCount
= 0;
511 for (Index
= 0; Index
< MemoryMapEntryCount
; Index
++) {
512 switch (MemoryMap
->Type
) {
513 case EfiReservedMemoryType
:
514 case EfiRuntimeServicesCode
:
515 case EfiRuntimeServicesData
:
516 case EfiACPIMemoryNVS
:
517 mMemoryMapEntryCount
++;
520 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, DescriptorSize
);
522 MemoryMap
= MemoryMapStart
;
527 mMemoryMap
= AllocatePool (mMemoryMapEntryCount
*DescriptorSize
);
528 ASSERT (mMemoryMap
!= NULL
);
529 SmmMemoryMapStart
= mMemoryMap
;
530 for (Index
= 0; Index
< MemoryMapEntryCount
; Index
++) {
531 switch (MemoryMap
->Type
) {
532 case EfiReservedMemoryType
:
533 case EfiRuntimeServicesCode
:
534 case EfiRuntimeServicesData
:
535 case EfiACPIMemoryNVS
:
536 CopyMem (mMemoryMap
, MemoryMap
, DescriptorSize
);
537 mMemoryMap
= NEXT_MEMORY_DESCRIPTOR(mMemoryMap
, DescriptorSize
);
540 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, DescriptorSize
);
542 mMemoryMap
= SmmMemoryMapStart
;
543 MemoryMap
= MemoryMapStart
;
545 gBS
->FreePool (MemoryMap
);
548 // Get additional information from GCD memory map.
550 SmmMemLibInternalGetGcdMemoryMap ();
553 // Get UEFI memory attributes table.
555 SmmMemLibInternalGetUefiMemoryAttributesTable ();
561 Notification for SMM ReadyToLock protocol.
563 @param[in] Protocol Points to the protocol's unique identifier.
564 @param[in] Interface Points to the interface instance.
565 @param[in] Handle The handle on which the interface was installed.
567 @retval EFI_SUCCESS Notification runs successfully.
571 SmmLibInternalReadyToLockNotify (
572 IN CONST EFI_GUID
*Protocol
,
577 mSmmMemLibSmmReadyToLock
= TRUE
;
581 The constructor function initializes the Smm Mem library
583 @param ImageHandle The firmware allocated handle for the EFI image.
584 @param SystemTable A pointer to the EFI System Table.
586 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
591 SmmMemLibConstructor (
592 IN EFI_HANDLE ImageHandle
,
593 IN EFI_SYSTEM_TABLE
*SystemTable
597 EFI_SMM_ACCESS2_PROTOCOL
*SmmAccess
;
601 // Get SMRAM information
603 Status
= gBS
->LocateProtocol (&gEfiSmmAccess2ProtocolGuid
, NULL
, (VOID
**)&SmmAccess
);
604 ASSERT_EFI_ERROR (Status
);
607 Status
= SmmAccess
->GetCapabilities (SmmAccess
, &Size
, NULL
);
608 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
610 mSmmMemLibInternalSmramRanges
= AllocatePool (Size
);
611 ASSERT (mSmmMemLibInternalSmramRanges
!= NULL
);
613 Status
= SmmAccess
->GetCapabilities (SmmAccess
, &Size
, mSmmMemLibInternalSmramRanges
);
614 ASSERT_EFI_ERROR (Status
);
616 mSmmMemLibInternalSmramCount
= Size
/ sizeof (EFI_SMRAM_DESCRIPTOR
);
619 // Calculate and save maximum support address
621 SmmMemLibInternalCalculateMaximumSupportAddress ();
624 // Register EndOfDxe to get UEFI memory map
626 Status
= gSmst
->SmmRegisterProtocolNotify (&gEfiSmmEndOfDxeProtocolGuid
, SmmLibInternalEndOfDxeNotify
, &mRegistrationEndOfDxe
);
627 ASSERT_EFI_ERROR (Status
);
630 // Register ready to lock so that we can know when to check valid SMRAM region
632 Status
= gSmst
->SmmRegisterProtocolNotify (&gEfiSmmReadyToLockProtocolGuid
, SmmLibInternalReadyToLockNotify
, &mRegistrationReadyToLock
);
633 ASSERT_EFI_ERROR (Status
);
639 The destructor function frees resource used in the Smm Mem library
641 @param[in] ImageHandle The firmware allocated handle for the EFI image.
642 @param[in] SystemTable A pointer to the EFI System Table.
644 @retval EFI_SUCCESS The deconstructor always returns EFI_SUCCESS.
648 SmmMemLibDestructor (
649 IN EFI_HANDLE ImageHandle
,
650 IN EFI_SYSTEM_TABLE
*SystemTable
653 FreePool (mSmmMemLibInternalSmramRanges
);
655 gSmst
->SmmRegisterProtocolNotify (&gEfiSmmEndOfDxeProtocolGuid
, NULL
, &mRegistrationEndOfDxe
);
656 gSmst
->SmmRegisterProtocolNotify (&gEfiSmmReadyToLockProtocolGuid
, NULL
, &mRegistrationReadyToLock
);