summaryrefslogtreecommitdiff
path: root/Platform/Intel/MinPlatformPkg/Test/Library/TestPointCheckLib/SmmTestPointCheckLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'Platform/Intel/MinPlatformPkg/Test/Library/TestPointCheckLib/SmmTestPointCheckLib.c')
-rw-r--r--Platform/Intel/MinPlatformPkg/Test/Library/TestPointCheckLib/SmmTestPointCheckLib.c191
1 files changed, 189 insertions, 2 deletions
diff --git a/Platform/Intel/MinPlatformPkg/Test/Library/TestPointCheckLib/SmmTestPointCheckLib.c b/Platform/Intel/MinPlatformPkg/Test/Library/TestPointCheckLib/SmmTestPointCheckLib.c
index cbc21307ce..3225f139e6 100644
--- a/Platform/Intel/MinPlatformPkg/Test/Library/TestPointCheckLib/SmmTestPointCheckLib.c
+++ b/Platform/Intel/MinPlatformPkg/Test/Library/TestPointCheckLib/SmmTestPointCheckLib.c
@@ -16,6 +16,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/TestPointLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/SmmMemLib.h>
+#include <Library/SmmServicesTableLib.h>
+
+#include "TestPointInternal.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID mTestPointSmmCommunciationGuid = TEST_POINT_SMM_COMMUNICATION_GUID;
EFI_STATUS
TestPointCheckSmrr (
@@ -39,7 +46,9 @@ TestPointCheckSmmPaging (
EFI_STATUS
TestPointCheckSmmCommunicationBuffer (
- VOID
+ IN EFI_MEMORY_DESCRIPTOR *UefiMemoryMap,
+ IN UINTN UefiMemoryMapSize,
+ IN UINTN UefiDescriptorSize
);
VOID
@@ -206,7 +215,7 @@ TestPointSmmReadyToBootSmmPageProtection (
if (mUefiMemoryMap != NULL) {
Result = TRUE;
- Status = TestPointCheckSmmCommunicationBuffer ();
+ Status = TestPointCheckSmmCommunicationBuffer (mUefiMemoryMap, mUefiMemoryMapSize, mUefiDescriptorSize);
if (EFI_ERROR(Status)) {
Result = FALSE;
}
@@ -223,6 +232,163 @@ TestPointSmmReadyToBootSmmPageProtection (
return EFI_SUCCESS;
}
+/**
+ Dispatch function for a Software SMI handler.
+
+ Caution: This function may receive untrusted input.
+ Communicate buffer and buffer size are external input, so this function will do basic validation.
+
+ @param CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-SMM environment into an SMM environment.
+ @param CommBufferSize The size of the CommBuffer.
+
+ @retval EFI_SUCCESS Command is handled successfully.
+**/
+EFI_STATUS
+TestPointSmmReadyToBootSmmPageProtectionHandler (
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Result;
+ TEST_POINT_SMM_COMMUNICATION_UEFI_GCD_MAP_INFO *CommData;
+ UINTN TempCommBufferSize;
+
+ if ((mFeatureImplemented[5] & TEST_POINT_BYTE5_SMM_READY_TO_BOOT_SMM_PAGE_LEVEL_PROTECTION) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ DEBUG ((DEBUG_INFO, "======== TestPointSmmReadyToBootSmmPageProtectionHandler - Enter\n"));
+
+ TempCommBufferSize = *CommBufferSize;
+
+ if (TempCommBufferSize < sizeof(TEST_POINT_SMM_COMMUNICATION_UEFI_GCD_MAP_INFO)) {
+ DEBUG((DEBUG_ERROR, "TestPointSmmReadyToBootSmmPageProtectionHandler: SMM communication buffer size invalid!\n"));
+ return EFI_SUCCESS;
+ }
+
+ if (!SmmIsBufferOutsideSmmValid((UINTN)CommBuffer, TempCommBufferSize)) {
+ DEBUG((DEBUG_ERROR, "TestPointSmmReadyToBootSmmPageProtectionHandler: SMM communication buffer in SMRAM or overflow!\n"));
+ return EFI_SUCCESS;
+ }
+ DEBUG ((DEBUG_INFO, "TempCommBufferSize - 0x%x\n", TempCommBufferSize));
+ CommData = AllocateCopyPool (TempCommBufferSize, CommBuffer);
+ if (CommData == NULL) {
+ DEBUG((DEBUG_ERROR, "TestPointSmmReadyToBootSmmPageProtectionHandler: SMM communication buffer size too big!\n"));
+ return EFI_SUCCESS;
+ }
+ if (CommData->UefiMemoryMapOffset != sizeof(TEST_POINT_SMM_COMMUNICATION_UEFI_GCD_MAP_INFO)) {
+ DEBUG((DEBUG_ERROR, "TestPointSmmReadyToBootSmmPageProtectionHandler: UefiMemoryMapOffset invalid!\n"));
+ goto Done;
+ }
+ if (CommData->UefiMemoryMapSize > TempCommBufferSize - CommData->UefiMemoryMapOffset) {
+ DEBUG((DEBUG_ERROR, "TestPointSmmReadyToBootSmmPageProtectionHandler: UefiMemoryMapSize invalid!\n"));
+ goto Done;
+ }
+ if (CommData->GcdMemoryMapOffset != CommData->UefiMemoryMapOffset + CommData->UefiMemoryMapSize) {
+ DEBUG((DEBUG_ERROR, "TestPointSmmReadyToBootSmmPageProtectionHandler: GcdMemoryMapOffset invalid!\n"));
+ goto Done;
+ }
+ if (CommData->GcdMemoryMapSize > TempCommBufferSize - CommData->GcdMemoryMapOffset) {
+ DEBUG((DEBUG_ERROR, "TestPointSmmReadyToBootSmmPageProtectionHandler: GcdMemoryMapSize invalid!\n"));
+ goto Done;
+ }
+ if (CommData->GcdIoMapOffset != CommData->GcdMemoryMapOffset + CommData->GcdMemoryMapSize) {
+ DEBUG((DEBUG_ERROR, "TestPointSmmReadyToBootSmmPageProtectionHandler: GcdIoMapOffset invalid!\n"));
+ goto Done;
+ }
+ if (CommData->GcdIoMapSize != TempCommBufferSize - CommData->GcdIoMapOffset) {
+ DEBUG((DEBUG_ERROR, "TestPointSmmReadyToBootSmmPageProtectionHandler: GcdIoMapSize invalid!\n"));
+ goto Done;
+ }
+
+ if (CommData->UefiMemoryMapSize != 0) {
+ Result = TRUE;
+
+ Status = TestPointCheckSmmCommunicationBuffer (
+ (EFI_MEMORY_DESCRIPTOR *)((UINTN)CommData + CommData->UefiMemoryMapOffset),
+ (UINTN)CommData->UefiMemoryMapSize,
+ mUefiDescriptorSize
+ );
+ if (EFI_ERROR(Status)) {
+ Result = FALSE;
+ }
+ if (Result) {
+ TestPointLibSetFeaturesVerified (
+ PLATFORM_TEST_POINT_ROLE_PLATFORM_IBV,
+ NULL,
+ 5,
+ TEST_POINT_BYTE5_SMM_READY_TO_LOCK_SECURE_SMM_COMMUNICATION_BUFFER
+ );
+ } else {
+ TestPointLibClearFeaturesVerified (
+ PLATFORM_TEST_POINT_ROLE_PLATFORM_IBV,
+ NULL,
+ 5,
+ TEST_POINT_BYTE5_SMM_READY_TO_LOCK_SECURE_SMM_COMMUNICATION_BUFFER
+ );
+ }
+ }
+Done:
+ FreePool (CommData);
+
+ DEBUG ((DEBUG_INFO, "======== TestPointSmmReadyToBootSmmPageProtectionHandler - Exit\n"));
+ return EFI_SUCCESS;
+}
+
+/**
+ Dispatch function for a Software SMI handler.
+
+ Caution: This function may receive untrusted input.
+ Communicate buffer and buffer size are external input, so this function will do basic validation.
+
+ @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
+ @param Context Points to an optional handler context which was specified when the
+ handler was registered.
+ @param CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-SMM environment into an SMM environment.
+ @param CommBufferSize The size of the CommBuffer.
+
+ @retval EFI_SUCCESS Command is handled successfully.
+**/
+EFI_STATUS
+EFIAPI
+TestPointSmmHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ TEST_POINT_SMM_COMMUNICATION_HEADER CommData;
+ UINTN TempCommBufferSize;
+
+ //
+ // If input is invalid, stop processing this SMI
+ //
+ if (CommBuffer == NULL || CommBufferSize == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ TempCommBufferSize = *CommBufferSize;
+
+ if (TempCommBufferSize < sizeof(TEST_POINT_SMM_COMMUNICATION_HEADER)) {
+ DEBUG((DEBUG_ERROR, "TestPointSmmHandler: SMM communication buffer size invalid!\n"));
+ return EFI_SUCCESS;
+ }
+ CopyMem (&CommData, CommBuffer, sizeof(CommData));
+ if (CommData.Version != TEST_POINT_SMM_COMMUNICATION_VERSION) {
+ DEBUG((DEBUG_ERROR, "TestPointSmmHandler: SMM communication Version invalid!\n"));
+ return EFI_SUCCESS;
+ }
+ switch (CommData.FuncId) {
+ case TEST_POINT_SMM_COMMUNICATION_FUNC_ID_UEFI_GCD_MAP_INFO:
+ return TestPointSmmReadyToBootSmmPageProtectionHandler (CommBuffer, CommBufferSize);
+ }
+ return EFI_SUCCESS;
+}
+
EFI_STATUS
EFIAPI
TestPointSmmExitBootServices (
@@ -236,6 +402,25 @@ TestPointSmmExitBootServices (
}
/**
+ Register SMM Test Point handler.
+**/
+VOID
+RegisterSmmTestPointHandler (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DispatchHandle;
+
+ Status = gSmst->SmiHandlerRegister (
+ TestPointSmmHandler,
+ &mTestPointSmmCommunciationGuid,
+ &DispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
Initialize feature data
**/
VOID
@@ -270,5 +455,7 @@ SmmTestPointCheckLibConstructor (
{
InitData (PLATFORM_TEST_POINT_ROLE_PLATFORM_IBV);
+ RegisterSmmTestPointHandler ();
+
return EFI_SUCCESS;
}