mirror of https://github.com/acidanthera/audk.git
MdePkg-SmmMemLib: Enhance SmmIsBufferOutsideSmmValid() check for fixed comm buffer.
This patch adds more check in SmmIsBufferOutsideSmmValid(), to make sure that SMM communication buffer is only EfiReservedMemoryType/EfiRuntimeServicesCode/ EfiRuntimeServicesData/EfiACPIMemoryNVS. So that the communication buffer will not touch any OS memory. The assumption is that a platform reports valid SMM communication buffer at EndOfDxe, because EndOfDxe is last hook point that SMM code can call-out to get memory map information. A platform MUST finish SMM communication buffer allocation before EndOfDxe. If a DXE or OS driver need do communication after EndOfDxe, it can either allocate SMM communication buffer before EndOfDxe and save it, or consume EDKII_PI_SMM_COMMUNICATION_REGION_TABLE table to get general fixed comm buffer. This is designed to meet Microsoft WSMT table definition on FIXED_COMM_BUFFERS requirement. Cc: Liming Gao <liming.gao@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao <jiewen.yao@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
parent
009264f5cf
commit
91f51fcc84
|
@ -6,7 +6,7 @@
|
||||||
all SMRAM range via SMM_ACCESS2_PROTOCOL, including the range for firmware (like SMM Core
|
all SMRAM range via SMM_ACCESS2_PROTOCOL, including the range for firmware (like SMM Core
|
||||||
and SMM driver) and/or specific dedicated hardware.
|
and SMM driver) and/or specific dedicated hardware.
|
||||||
|
|
||||||
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
@ -28,6 +28,11 @@
|
||||||
#include <Library/SmmServicesTableLib.h>
|
#include <Library/SmmServicesTableLib.h>
|
||||||
#include <Library/HobLib.h>
|
#include <Library/HobLib.h>
|
||||||
#include <Protocol/SmmAccess2.h>
|
#include <Protocol/SmmAccess2.h>
|
||||||
|
#include <Protocol/SmmReadyToLock.h>
|
||||||
|
#include <Protocol/SmmEndOfDxe.h>
|
||||||
|
|
||||||
|
#define NEXT_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
|
||||||
|
((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) + (Size)))
|
||||||
|
|
||||||
EFI_SMRAM_DESCRIPTOR *mSmmMemLibInternalSmramRanges;
|
EFI_SMRAM_DESCRIPTOR *mSmmMemLibInternalSmramRanges;
|
||||||
UINTN mSmmMemLibInternalSmramCount;
|
UINTN mSmmMemLibInternalSmramCount;
|
||||||
|
@ -37,6 +42,15 @@ UINTN mSmmMemLibInternalSmramCount;
|
||||||
//
|
//
|
||||||
EFI_PHYSICAL_ADDRESS mSmmMemLibInternalMaximumSupportAddress = 0;
|
EFI_PHYSICAL_ADDRESS mSmmMemLibInternalMaximumSupportAddress = 0;
|
||||||
|
|
||||||
|
UINTN mMemoryMapEntryCount;
|
||||||
|
EFI_MEMORY_DESCRIPTOR *mMemoryMap;
|
||||||
|
UINTN mDescriptorSize;
|
||||||
|
|
||||||
|
VOID *mRegistrationEndOfDxe;
|
||||||
|
VOID *mRegistrationReadyToLock;
|
||||||
|
|
||||||
|
BOOLEAN mSmmReadyToLock = FALSE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Calculate and save the maximum support address.
|
Calculate and save the maximum support address.
|
||||||
|
|
||||||
|
@ -137,6 +151,34 @@ SmmIsBufferOutsideSmmValid (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check override for Valid Communication Region
|
||||||
|
//
|
||||||
|
if (mSmmReadyToLock) {
|
||||||
|
EFI_MEMORY_DESCRIPTOR *MemoryMap;
|
||||||
|
BOOLEAN InValidCommunicationRegion;
|
||||||
|
|
||||||
|
InValidCommunicationRegion = FALSE;
|
||||||
|
MemoryMap = mMemoryMap;
|
||||||
|
for (Index = 0; Index < mMemoryMapEntryCount; Index++) {
|
||||||
|
if ((Buffer >= MemoryMap->PhysicalStart) &&
|
||||||
|
(Buffer + Length <= MemoryMap->PhysicalStart + LShiftU64 (MemoryMap->NumberOfPages, EFI_PAGE_SHIFT))) {
|
||||||
|
InValidCommunicationRegion = TRUE;
|
||||||
|
}
|
||||||
|
MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, mDescriptorSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!InValidCommunicationRegion) {
|
||||||
|
DEBUG ((
|
||||||
|
EFI_D_ERROR,
|
||||||
|
"SmmIsBufferOutsideSmmValid: Not in ValidCommunicationRegion: Buffer (0x%lx) - Length (0x%lx), ",
|
||||||
|
Buffer,
|
||||||
|
Length
|
||||||
|
));
|
||||||
|
ASSERT (FALSE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,6 +318,128 @@ SmmSetMem (
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Notification for SMM EndOfDxe protocol.
|
||||||
|
|
||||||
|
@param[in] Protocol Points to the protocol's unique identifier.
|
||||||
|
@param[in] Interface Points to the interface instance.
|
||||||
|
@param[in] Handle The handle on which the interface was installed.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Notification runs successfully.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmLibInternalEndOfDxeNotify (
|
||||||
|
IN CONST EFI_GUID *Protocol,
|
||||||
|
IN VOID *Interface,
|
||||||
|
IN EFI_HANDLE Handle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN MapKey;
|
||||||
|
UINTN MemoryMapSize;
|
||||||
|
EFI_MEMORY_DESCRIPTOR *MemoryMap;
|
||||||
|
EFI_MEMORY_DESCRIPTOR *MemoryMapStart;
|
||||||
|
EFI_MEMORY_DESCRIPTOR *SmmMemoryMapStart;
|
||||||
|
UINTN MemoryMapEntryCount;
|
||||||
|
UINTN DescriptorSize;
|
||||||
|
UINT32 DescriptorVersion;
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
MemoryMapSize = 0;
|
||||||
|
MemoryMap = NULL;
|
||||||
|
Status = gBS->GetMemoryMap (
|
||||||
|
&MemoryMapSize,
|
||||||
|
MemoryMap,
|
||||||
|
&MapKey,
|
||||||
|
&DescriptorSize,
|
||||||
|
&DescriptorVersion
|
||||||
|
);
|
||||||
|
ASSERT (Status == EFI_BUFFER_TOO_SMALL);
|
||||||
|
|
||||||
|
do {
|
||||||
|
Status = gBS->AllocatePool (EfiBootServicesData, MemoryMapSize, (VOID **)&MemoryMap);
|
||||||
|
ASSERT (MemoryMap != NULL);
|
||||||
|
|
||||||
|
Status = gBS->GetMemoryMap (
|
||||||
|
&MemoryMapSize,
|
||||||
|
MemoryMap,
|
||||||
|
&MapKey,
|
||||||
|
&DescriptorSize,
|
||||||
|
&DescriptorVersion
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
gBS->FreePool (MemoryMap);
|
||||||
|
}
|
||||||
|
} while (Status == EFI_BUFFER_TOO_SMALL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get Count
|
||||||
|
//
|
||||||
|
mDescriptorSize = DescriptorSize;
|
||||||
|
MemoryMapEntryCount = MemoryMapSize/DescriptorSize;
|
||||||
|
MemoryMapStart = MemoryMap;
|
||||||
|
mMemoryMapEntryCount = 0;
|
||||||
|
for (Index = 0; Index < MemoryMapEntryCount; Index++) {
|
||||||
|
switch (MemoryMap->Type) {
|
||||||
|
case EfiReservedMemoryType:
|
||||||
|
case EfiRuntimeServicesCode:
|
||||||
|
case EfiRuntimeServicesData:
|
||||||
|
case EfiACPIMemoryNVS:
|
||||||
|
mMemoryMapEntryCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);
|
||||||
|
}
|
||||||
|
MemoryMap = MemoryMapStart;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get Data
|
||||||
|
//
|
||||||
|
mMemoryMap = AllocatePool (mMemoryMapEntryCount*DescriptorSize);
|
||||||
|
ASSERT (mMemoryMap != NULL);
|
||||||
|
SmmMemoryMapStart = mMemoryMap;
|
||||||
|
for (Index = 0; Index < MemoryMapEntryCount; Index++) {
|
||||||
|
switch (MemoryMap->Type) {
|
||||||
|
case EfiReservedMemoryType:
|
||||||
|
case EfiRuntimeServicesCode:
|
||||||
|
case EfiRuntimeServicesData:
|
||||||
|
case EfiACPIMemoryNVS:
|
||||||
|
CopyMem (mMemoryMap, MemoryMap, DescriptorSize);
|
||||||
|
mMemoryMap = NEXT_MEMORY_DESCRIPTOR(mMemoryMap, DescriptorSize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);
|
||||||
|
}
|
||||||
|
mMemoryMap = SmmMemoryMapStart;
|
||||||
|
MemoryMap = MemoryMapStart;
|
||||||
|
|
||||||
|
gBS->FreePool (MemoryMap);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Notification for SMM ReadyToLock protocol.
|
||||||
|
|
||||||
|
@param[in] Protocol Points to the protocol's unique identifier.
|
||||||
|
@param[in] Interface Points to the interface instance.
|
||||||
|
@param[in] Handle The handle on which the interface was installed.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Notification runs successfully.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmLibInternalReadyToLockNotify (
|
||||||
|
IN CONST EFI_GUID *Protocol,
|
||||||
|
IN VOID *Interface,
|
||||||
|
IN EFI_HANDLE Handle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
mSmmReadyToLock = TRUE;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
The constructor function initializes the Smm Mem library
|
The constructor function initializes the Smm Mem library
|
||||||
|
|
||||||
|
@ -319,6 +483,18 @@ SmmMemLibConstructor (
|
||||||
//
|
//
|
||||||
SmmMemLibInternalCalculateMaximumSupportAddress ();
|
SmmMemLibInternalCalculateMaximumSupportAddress ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Register EndOfDxe to get UEFI memory map
|
||||||
|
//
|
||||||
|
Status = gSmst->SmmRegisterProtocolNotify (&gEfiSmmEndOfDxeProtocolGuid, SmmLibInternalEndOfDxeNotify, &mRegistrationEndOfDxe);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Register ready to lock so that we can know when to check valid SMRAM region
|
||||||
|
//
|
||||||
|
Status = gSmst->SmmRegisterProtocolNotify (&gEfiSmmReadyToLockProtocolGuid, SmmLibInternalReadyToLockNotify, &mRegistrationReadyToLock);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,5 +515,7 @@ SmmMemLibDestructor (
|
||||||
{
|
{
|
||||||
FreePool (mSmmMemLibInternalSmramRanges);
|
FreePool (mSmmMemLibInternalSmramRanges);
|
||||||
|
|
||||||
|
gSmst->SmmRegisterProtocolNotify (&gEfiSmmEndOfDxeProtocolGuid, NULL, &mRegistrationEndOfDxe);
|
||||||
|
gSmst->SmmRegisterProtocolNotify (&gEfiSmmReadyToLockProtocolGuid, NULL, &mRegistrationReadyToLock);
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
# all SMRAM range via SMM_ACCESS2_PROTOCOL, including the range for firmware (like SMM Core
|
# all SMRAM range via SMM_ACCESS2_PROTOCOL, including the range for firmware (like SMM Core
|
||||||
# and SMM driver) and/or specific dedicated hardware.
|
# and SMM driver) and/or specific dedicated hardware.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
|
# Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
|
||||||
# This program and the accompanying materials
|
# This program and the accompanying materials
|
||||||
# are licensed and made available under the terms and conditions of the BSD License
|
# are licensed and made available under the terms and conditions of the BSD License
|
||||||
# which accompanies this distribution. The full text of the license may be found at
|
# which accompanies this distribution. The full text of the license may be found at
|
||||||
|
@ -49,7 +49,9 @@
|
||||||
MemoryAllocationLib
|
MemoryAllocationLib
|
||||||
|
|
||||||
[Protocols]
|
[Protocols]
|
||||||
gEfiSmmAccess2ProtocolGuid ## CONSUMES
|
gEfiSmmAccess2ProtocolGuid ## CONSUMES
|
||||||
|
gEfiSmmReadyToLockProtocolGuid ## CONSUMES
|
||||||
|
gEfiSmmEndOfDxeProtocolGuid ## CONSUMES
|
||||||
|
|
||||||
[Depex]
|
[Depex]
|
||||||
gEfiSmmAccess2ProtocolGuid
|
gEfiSmmAccess2ProtocolGuid
|
||||||
|
|
Loading…
Reference in New Issue