summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.c')
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.c207
1 files changed, 207 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.c
new file mode 100644
index 00000000..932361fe
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.c
@@ -0,0 +1,207 @@
+/** @file
+PiSmmCommunication SMM Driver.
+
+Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiSmm.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SmmMemLib.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/SmmCommunication.h>
+#include <Ppi/SmmCommunication.h>
+
+#include "PiSmmCommunicationPrivate.h"
+
+EFI_SMM_COMMUNICATION_CONTEXT mSmmCommunicationContext = {
+ SMM_COMMUNICATION_SIGNATURE
+};
+
+/**
+ Set SMM communication context.
+**/
+VOID
+SetCommunicationContext (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gSmst->SmmInstallConfigurationTable (
+ gSmst,
+ &gEfiPeiSmmCommunicationPpiGuid,
+ &mSmmCommunicationContext,
+ sizeof(mSmmCommunicationContext)
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Dispatch function for a Software SMI handler.
+
+ @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
+PiSmmCommunicationHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ UINTN CommSize;
+ EFI_STATUS Status;
+ EFI_SMM_COMMUNICATE_HEADER *CommunicateHeader;
+ EFI_PHYSICAL_ADDRESS *BufferPtrAddress;
+
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Enter\n"));
+
+ BufferPtrAddress = (EFI_PHYSICAL_ADDRESS *)(UINTN)mSmmCommunicationContext.BufferPtrAddress;
+ CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)(UINTN)*BufferPtrAddress;
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler CommunicateHeader - %x\n", CommunicateHeader));
+ if (CommunicateHeader == NULL) {
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler is NULL, needn't to call dispatch function\n"));
+ Status = EFI_SUCCESS;
+ } else {
+ if (!SmmIsBufferOutsideSmmValid ((UINTN)CommunicateHeader, OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data))) {
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler CommunicateHeader invalid - 0x%x\n", CommunicateHeader));
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ CommSize = (UINTN)CommunicateHeader->MessageLength;
+ if (!SmmIsBufferOutsideSmmValid ((UINTN)&CommunicateHeader->Data[0], CommSize)) {
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler CommunicateData invalid - 0x%x\n", &CommunicateHeader->Data[0]));
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ //
+ // Call dispatch function
+ //
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Data - %x\n", &CommunicateHeader->Data[0]));
+ Status = gSmst->SmiManage (
+ &CommunicateHeader->HeaderGuid,
+ NULL,
+ &CommunicateHeader->Data[0],
+ &CommSize
+ );
+ }
+
+Done:
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler %r\n", Status));
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Exit\n"));
+
+ return (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_INTERRUPT_PENDING;
+}
+
+/**
+ Allocate EfiACPIMemoryNVS below 4G memory address.
+
+ This function allocates EfiACPIMemoryNVS below 4G memory address.
+
+ @param Size Size of memory to allocate.
+
+ @return Allocated address for output.
+
+**/
+VOID*
+AllocateAcpiNvsMemoryBelow4G (
+ IN UINTN Size
+ )
+{
+ UINTN Pages;
+ EFI_PHYSICAL_ADDRESS Address;
+ EFI_STATUS Status;
+ VOID* Buffer;
+
+ Pages = EFI_SIZE_TO_PAGES (Size);
+ Address = 0xffffffff;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ Pages,
+ &Address
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Buffer = (VOID *) (UINTN) Address;
+ ZeroMem (Buffer, Size);
+
+ return Buffer;
+}
+
+/**
+ Entry Point for PI SMM communication SMM driver.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable A Pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS
+ @return Others Some error occurs.
+**/
+EFI_STATUS
+EFIAPI
+PiSmmCommunicationSmmEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMM_SW_DISPATCH2_PROTOCOL *SmmSwDispatch2;
+ EFI_SMM_SW_REGISTER_CONTEXT SmmSwDispatchContext;
+ EFI_HANDLE DispatchHandle;
+ EFI_PHYSICAL_ADDRESS *BufferPtrAddress;
+
+ //
+ // Register software SMI handler
+ //
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmSwDispatch2ProtocolGuid,
+ NULL,
+ (VOID **)&SmmSwDispatch2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ SmmSwDispatchContext.SwSmiInputValue = (UINTN)-1;
+ Status = SmmSwDispatch2->Register (
+ SmmSwDispatch2,
+ PiSmmCommunicationHandler,
+ &SmmSwDispatchContext,
+ &DispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((EFI_D_INFO, "SmmCommunication SwSmi: %x\n", (UINTN)SmmSwDispatchContext.SwSmiInputValue));
+
+ BufferPtrAddress = AllocateAcpiNvsMemoryBelow4G (sizeof(EFI_PHYSICAL_ADDRESS));
+ ASSERT (BufferPtrAddress != NULL);
+ DEBUG ((EFI_D_INFO, "SmmCommunication BufferPtrAddress: 0x%016lx, BufferPtr: 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)BufferPtrAddress, *BufferPtrAddress));
+
+ //
+ // Save context
+ //
+ mSmmCommunicationContext.SwSmiNumber = (UINT32)SmmSwDispatchContext.SwSmiInputValue;
+ mSmmCommunicationContext.BufferPtrAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)BufferPtrAddress;
+ SetCommunicationContext ();
+
+ return Status;
+}