--- /dev/null
+/** @file\r
+PiSmmCommunication SMM Driver.\r
+\r
+Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiSmm.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/SmmServicesTableLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/SmmMemLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Protocol/SmmSwDispatch2.h>\r
+#include <Protocol/SmmReadyToLock.h>\r
+#include <Protocol/SmmCommunication.h>\r
+#include <Protocol/AcpiTable.h>\r
+#include <Ppi/SmmCommunication.h>\r
+#include <Guid/Acpi.h>\r
+\r
+#include "PiSmmCommunicationPrivate.h"\r
+\r
+EFI_SMM_COMMUNICATION_CONTEXT mSmmCommunicationContext = {\r
+ SMM_COMMUNICATION_SIGNATURE\r
+};\r
+\r
+EFI_SMM_COMMUNICATION_ACPI_TABLE mSmmCommunicationAcpiTable = {\r
+ {\r
+ {\r
+ EFI_ACPI_4_0_UEFI_ACPI_DATA_TABLE_SIGNATURE,\r
+ sizeof (EFI_SMM_COMMUNICATION_ACPI_TABLE),\r
+ 0x1, // Revision\r
+ 0x0, // Checksum\r
+ {0x0}, // OemId[6]\r
+ 0x0, // OemTableId\r
+ 0x0, // OemRevision\r
+ 0x0, // CreatorId\r
+ 0x0 // CreatorRevision\r
+ },\r
+ {0x0}, // Identifier\r
+ OFFSET_OF (EFI_SMM_COMMUNICATION_ACPI_TABLE, SwSmiNumber) // DataOffset\r
+ },\r
+ 0x0, // SwSmiNumber\r
+ 0x0 // BufferPtrAddress\r
+};\r
+\r
+/**\r
+ Set SMM communication context.\r
+**/\r
+VOID\r
+SetCommunicationContext (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = gSmst->SmmInstallConfigurationTable (\r
+ gSmst,\r
+ &gEfiPeiSmmCommunicationPpiGuid,\r
+ &mSmmCommunicationContext,\r
+ sizeof(mSmmCommunicationContext)\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+ Dispatch function for a Software SMI handler.\r
+\r
+ @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
+ @param Context Points to an optional handler context which was specified when the\r
+ handler was registered.\r
+ @param CommBuffer A pointer to a collection of data in memory that will\r
+ be conveyed from a non-SMM environment into an SMM environment.\r
+ @param CommBufferSize The size of the CommBuffer.\r
+\r
+ @retval EFI_SUCCESS Command is handled successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PiSmmCommunicationHandler (\r
+ IN EFI_HANDLE DispatchHandle,\r
+ IN CONST VOID *Context OPTIONAL,\r
+ IN OUT VOID *CommBuffer OPTIONAL,\r
+ IN OUT UINTN *CommBufferSize OPTIONAL\r
+ )\r
+{\r
+ UINTN CommSize;\r
+ EFI_STATUS Status;\r
+ EFI_SMM_COMMUNICATE_HEADER *CommunicateHeader;\r
+ EFI_PHYSICAL_ADDRESS *BufferPtrAddress;\r
+\r
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Enter\n"));\r
+\r
+ BufferPtrAddress = (EFI_PHYSICAL_ADDRESS *)(UINTN)mSmmCommunicationContext.BufferPtrAddress;\r
+ CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)(UINTN)*BufferPtrAddress;\r
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler CommunicateHeader - %x\n", CommunicateHeader));\r
+ if (CommunicateHeader == NULL) {\r
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler is NULL, needn't to call dispatch function\n"));\r
+ Status = EFI_SUCCESS;\r
+ } else {\r
+ if (!SmmIsBufferOutsideSmmValid ((UINTN)CommunicateHeader, OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data))) {\r
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler CommunicateHeader invalid - 0x%x\n", CommunicateHeader));\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ CommSize = (UINTN)CommunicateHeader->MessageLength;\r
+ if (!SmmIsBufferOutsideSmmValid ((UINTN)&CommunicateHeader->Data[0], CommSize)) {\r
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler CommunicateData invalid - 0x%x\n", &CommunicateHeader->Data[0]));\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Call dispatch function\r
+ //\r
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Data - %x\n", &CommunicateHeader->Data[0]));\r
+ Status = gSmst->SmiManage (\r
+ &CommunicateHeader->HeaderGuid,\r
+ NULL,\r
+ &CommunicateHeader->Data[0],\r
+ &CommSize\r
+ );\r
+ }\r
+\r
+Done:\r
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler %r\n", Status));\r
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Exit\n"));\r
+\r
+ return (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_INTERRUPT_PENDING;\r
+}\r
+\r
+/**\r
+ Allocate EfiACPIMemoryNVS below 4G memory address.\r
+\r
+ This function allocates EfiACPIMemoryNVS below 4G memory address.\r
+\r
+ @param Size Size of memory to allocate.\r
+\r
+ @return Allocated address for output.\r
+\r
+**/\r
+VOID*\r
+AllocateAcpiNvsMemoryBelow4G (\r
+ IN UINTN Size\r
+ )\r
+{\r
+ UINTN Pages;\r
+ EFI_PHYSICAL_ADDRESS Address;\r
+ EFI_STATUS Status;\r
+ VOID* Buffer;\r
+\r
+ Pages = EFI_SIZE_TO_PAGES (Size);\r
+ Address = 0xffffffff;\r
+\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiACPIMemoryNVS,\r
+ Pages,\r
+ &Address\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Buffer = (VOID *) (UINTN) Address;\r
+ ZeroMem (Buffer, Size);\r
+\r
+ return Buffer;\r
+}\r
+\r
+/**\r
+ Entry Point for PI SMM communication SMM driver.\r
+\r
+ @param[in] ImageHandle Image handle of this driver.\r
+ @param[in] SystemTable A Pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCEESS\r
+ @return Others Some error occurs.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PiSmmCommunicationSmmEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SMM_SW_DISPATCH2_PROTOCOL *SmmSwDispatch2;\r
+ EFI_SMM_SW_REGISTER_CONTEXT SmmSwDispatchContext;\r
+ EFI_HANDLE DispatchHandle;\r
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;\r
+ UINTN TableKey;\r
+ UINT64 OemTableId;\r
+ EFI_PHYSICAL_ADDRESS *BufferPtrAddress;\r
+\r
+ CopyMem (\r
+ mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.OemId,\r
+ PcdGetPtr (PcdAcpiDefaultOemId),\r
+ sizeof (mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.OemId)\r
+ );\r
+ OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
+ CopyMem (&mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
+ mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
+ mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
+ mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
+\r
+ //\r
+ // Register software SMI handler\r
+ //\r
+ Status = gSmst->SmmLocateProtocol (\r
+ &gEfiSmmSwDispatch2ProtocolGuid,\r
+ NULL,\r
+ (VOID **)&SmmSwDispatch2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ SmmSwDispatchContext.SwSmiInputValue = (UINTN)-1;\r
+ Status = SmmSwDispatch2->Register (\r
+ SmmSwDispatch2,\r
+ PiSmmCommunicationHandler,\r
+ &SmmSwDispatchContext,\r
+ &DispatchHandle\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ DEBUG ((EFI_D_INFO, "SmmCommunication SwSmi: %x\n", (UINTN)SmmSwDispatchContext.SwSmiInputValue));\r
+\r
+ //\r
+ // Set ACPI table\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ mSmmCommunicationAcpiTable.SwSmiNumber = (UINT32)SmmSwDispatchContext.SwSmiInputValue;\r
+ BufferPtrAddress = AllocateAcpiNvsMemoryBelow4G (sizeof(EFI_PHYSICAL_ADDRESS));\r
+ ASSERT (BufferPtrAddress != NULL);\r
+ DEBUG ((EFI_D_INFO, "SmmCommunication BufferPtrAddress: 0x%016lx, BufferPtr: 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)BufferPtrAddress, *BufferPtrAddress));\r
+ mSmmCommunicationAcpiTable.BufferPtrAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)BufferPtrAddress;\r
+ CopyMem (&mSmmCommunicationAcpiTable.UefiAcpiDataTable.Identifier, &gEfiSmmCommunicationProtocolGuid, sizeof(gEfiSmmCommunicationProtocolGuid));\r
+\r
+ Status = AcpiTableProtocol->InstallAcpiTable (\r
+ AcpiTableProtocol,\r
+ &mSmmCommunicationAcpiTable,\r
+ sizeof(mSmmCommunicationAcpiTable),\r
+ &TableKey\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Save context\r
+ //\r
+ mSmmCommunicationContext.SwSmiNumber = (UINT32)SmmSwDispatchContext.SwSmiInputValue;\r
+ mSmmCommunicationContext.BufferPtrAddress = mSmmCommunicationAcpiTable.BufferPtrAddress;\r
+ SetCommunicationContext ();\r
+\r
+ return Status;\r
+}\r