summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.c425
-rw-r--r--UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf70
-rw-r--r--UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.unibin0 -> 2066 bytes
-rw-r--r--UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPeiExtra.unibin0 -> 1370 bytes
-rw-r--r--UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPrivate.h30
-rw-r--r--UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.c269
-rw-r--r--UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.inf82
-rw-r--r--UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.unibin0 -> 3004 bytes
-rw-r--r--UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmmExtra.unibin0 -> 1392 bytes
-rw-r--r--UefiCpuPkg/UefiCpuPkg.dsc5
10 files changed, 881 insertions, 0 deletions
diff --git a/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.c b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.c
new file mode 100644
index 0000000000..aaeaa06729
--- /dev/null
+++ b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.c
@@ -0,0 +1,425 @@
+/** @file
+PiSmmCommunication PEI Driver.
+
+Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+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
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+#include <PiDxe.h>
+#include <PiSmm.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Protocol/SmmCommunication.h>
+#include <Ppi/SmmCommunication.h>
+#include <Ppi/SmmAccess.h>
+#include <Ppi/SmmControl.h>
+#include <Guid/AcpiS3Context.h>
+
+#include "PiSmmCommunicationPrivate.h"
+
+/**
+ the whole picture is below:
+
+ +----------------------------------+
+ | ACPI_VARIABLE_HOB |
+ | SmramDescriptor | <- DRAM
+ | CpuStart |---
+ +----------------------------------+ |
+ |
+ +----------------------------------+<--
+ | SMM_S3_RESUME_STATE |
+ | Signature | <- SMRAM
+ | Smst |---
+ +----------------------------------+ |
+ |
+ +----------------------------------+<--
+ | EFI_SMM_SYSTEM_TABLE2 |
+ | NumberOfTableEntries | <- SMRAM
+ | SmmConfigurationTable |---
+ +----------------------------------+ |
+ |
+ +----------------------------------+<--
+ | EFI_SMM_COMMUNICATION_CONTEXT |
+ | SwSmiNumber | <- SMRAM
+ | BufferPtrAddress |----------------
+ +----------------------------------+ |
+ |
+ +----------------------------------+ |
+ | EFI_SMM_COMMUNICATION_ACPI_TABLE | |
+ | SwSmiNumber | <- AcpiTable |
+ | BufferPtrAddress |--- |
+ +----------------------------------+ | |
+ | |
+ +----------------------------------+<---------------
+ | Communication Buffer Pointer | <- AcpiNvs
+ +----------------------------------+---
+ |
+ +----------------------------------+<--
+ | EFI_SMM_COMMUNICATE_HEADER |
+ | HeaderGuid | <- DRAM
+ | MessageLength |
+ +----------------------------------+
+
+**/
+
+#if defined (MDE_CPU_IA32)
+typedef struct {
+ EFI_TABLE_HEADER Hdr;
+ UINT64 SmmFirmwareVendor;
+ UINT64 SmmFirmwareRevision;
+ UINT64 SmmInstallConfigurationTable;
+ UINT64 SmmIoMemRead;
+ UINT64 SmmIoMemWrite;
+ UINT64 SmmIoIoRead;
+ UINT64 SmmIoIoWrite;
+ UINT64 SmmAllocatePool;
+ UINT64 SmmFreePool;
+ UINT64 SmmAllocatePages;
+ UINT64 SmmFreePages;
+ UINT64 SmmStartupThisAp;
+ UINT64 CurrentlyExecutingCpu;
+ UINT64 NumberOfCpus;
+ UINT64 CpuSaveStateSize;
+ UINT64 CpuSaveState;
+ UINT64 NumberOfTableEntries;
+ UINT64 SmmConfigurationTable;
+} EFI_SMM_SYSTEM_TABLE2_64;
+
+typedef struct {
+ EFI_GUID VendorGuid;
+ UINT64 VendorTable;
+} EFI_CONFIGURATION_TABLE64;
+#endif
+
+#if defined (MDE_CPU_X64)
+typedef EFI_SMM_SYSTEM_TABLE2 EFI_SMM_SYSTEM_TABLE2_64;
+typedef EFI_CONFIGURATION_TABLE EFI_CONFIGURATION_TABLE64;
+#endif
+
+/**
+ Communicates with a registered handler.
+
+ This function provides a service to send and receive messages from a registered UEFI service.
+
+ @param[in] This The EFI_PEI_SMM_COMMUNICATION_PPI instance.
+ @param[in, out] CommBuffer A pointer to the buffer to convey into SMRAM.
+ @param[in, out] CommSize The size of the data buffer being passed in.On exit, the size of data
+ being returned. Zero if the handler does not wish to reply with any data.
+
+ @retval EFI_SUCCESS The message was successfully posted.
+ @retval EFI_INVALID_PARAMETER The CommBuffer was NULL.
+ @retval EFI_NOT_STARTED The service is NOT started.
+**/
+EFI_STATUS
+EFIAPI
+Communicate (
+ IN CONST EFI_PEI_SMM_COMMUNICATION_PPI *This,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommSize
+ );
+
+EFI_PEI_SMM_COMMUNICATION_PPI mSmmCommunicationPpi = { Communicate };
+
+EFI_PEI_PPI_DESCRIPTOR mPpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiSmmCommunicationPpiGuid,
+ &mSmmCommunicationPpi
+};
+
+/**
+ Get SMM communication context.
+
+ @return SMM communication context.
+**/
+EFI_SMM_COMMUNICATION_CONTEXT *
+GetCommunicationContext (
+ VOID
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+ EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext;
+
+ GuidHob = GetFirstGuidHob (&gEfiPeiSmmCommunicationPpiGuid);
+ ASSERT (GuidHob != NULL);
+
+ SmmCommunicationContext = (EFI_SMM_COMMUNICATION_CONTEXT *)GET_GUID_HOB_DATA (GuidHob);
+
+ return SmmCommunicationContext;
+}
+
+/**
+ Set SMM communication context.
+
+ @param SmmCommunicationContext SMM communication context.
+**/
+VOID
+SetCommunicationContext (
+ IN EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ UINTN BufferSize;
+
+ BufferSize = sizeof (*SmmCommunicationContext);
+ Hob.Raw = BuildGuidHob (
+ &gEfiPeiSmmCommunicationPpiGuid,
+ BufferSize
+ );
+ ASSERT (Hob.Raw);
+
+ CopyMem ((VOID *)Hob.Raw, SmmCommunicationContext, sizeof(*SmmCommunicationContext));
+}
+
+/**
+ Get VendorTable by VendorGuid in Smst.
+
+ @param Signature Signature of SMM_S3_RESUME_STATE
+ @param Smst SMM system table
+ @param VendorGuid vendor guid
+
+ @return vendor table.
+**/
+VOID *
+InternalSmstGetVendorTableByGuid (
+ IN UINT64 Signature,
+ IN EFI_SMM_SYSTEM_TABLE2 *Smst,
+ IN EFI_GUID *VendorGuid
+ )
+{
+ EFI_CONFIGURATION_TABLE *SmmConfigurationTable;
+ UINTN NumberOfTableEntries;
+ UINTN Index;
+ EFI_SMM_SYSTEM_TABLE2_64 *Smst64;
+ EFI_CONFIGURATION_TABLE64 *SmmConfigurationTable64;
+
+ if ((sizeof(UINTN) == sizeof(UINT32)) && (Signature == SMM_S3_RESUME_SMM_64)) {
+ //
+ // 32 PEI + 64 DXE
+ //
+ Smst64 = (EFI_SMM_SYSTEM_TABLE2_64 *)Smst;
+ DEBUG ((EFI_D_INFO, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst64->SmmConfigurationTable));
+ DEBUG ((EFI_D_INFO, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst64->NumberOfTableEntries));
+ SmmConfigurationTable64 = (EFI_CONFIGURATION_TABLE64 *)(UINTN)Smst64->SmmConfigurationTable;
+ NumberOfTableEntries = (UINTN)Smst64->NumberOfTableEntries;
+ for (Index = 0; Index < NumberOfTableEntries; Index++) {
+ if (CompareGuid (&SmmConfigurationTable64[Index].VendorGuid, VendorGuid)) {
+ return (VOID *)(UINTN)SmmConfigurationTable64[Index].VendorTable;
+ }
+ }
+ return NULL;
+ } else {
+ DEBUG ((EFI_D_INFO, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst->SmmConfigurationTable));
+ DEBUG ((EFI_D_INFO, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst->NumberOfTableEntries));
+ SmmConfigurationTable = Smst->SmmConfigurationTable;
+ NumberOfTableEntries = Smst->NumberOfTableEntries;
+ for (Index = 0; Index < NumberOfTableEntries; Index++) {
+ if (CompareGuid (&SmmConfigurationTable[Index].VendorGuid, VendorGuid)) {
+ return (VOID *)SmmConfigurationTable[Index].VendorTable;
+ }
+ }
+ return NULL;
+ }
+}
+
+/**
+ Init SMM communication context.
+**/
+VOID
+InitCommunicationContext (
+ VOID
+ )
+{
+ EFI_SMRAM_DESCRIPTOR *SmramDescriptor;
+ SMM_S3_RESUME_STATE *SmmS3ResumeState;
+ VOID *GuidHob;
+ EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext;
+
+ GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);
+ ASSERT (GuidHob != NULL);
+ SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);
+ SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;
+
+ DEBUG ((EFI_D_INFO, "InitCommunicationContext - SmmS3ResumeState: %x\n", SmmS3ResumeState));
+ DEBUG ((EFI_D_INFO, "InitCommunicationContext - Smst: %x\n", SmmS3ResumeState->Smst));
+
+ SmmCommunicationContext = (EFI_SMM_COMMUNICATION_CONTEXT *)InternalSmstGetVendorTableByGuid (
+ SmmS3ResumeState->Signature,
+ (EFI_SMM_SYSTEM_TABLE2 *)(UINTN)SmmS3ResumeState->Smst,
+ &gEfiPeiSmmCommunicationPpiGuid
+ );
+ ASSERT (SmmCommunicationContext != NULL);
+
+ SetCommunicationContext (SmmCommunicationContext);
+
+ return ;
+}
+
+/**
+ Communicates with a registered handler.
+
+ This function provides a service to send and receive messages from a registered UEFI service.
+
+ @param[in] This The EFI_PEI_SMM_COMMUNICATION_PPI instance.
+ @param[in, out] CommBuffer A pointer to the buffer to convey into SMRAM.
+ @param[in, out] CommSize The size of the data buffer being passed in.On exit, the size of data
+ being returned. Zero if the handler does not wish to reply with any data.
+
+ @retval EFI_SUCCESS The message was successfully posted.
+ @retval EFI_INVALID_PARAMETER The CommBuffer was NULL.
+ @retval EFI_NOT_STARTED The service is NOT started.
+**/
+EFI_STATUS
+EFIAPI
+Communicate (
+ IN CONST EFI_PEI_SMM_COMMUNICATION_PPI *This,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommSize
+ )
+{
+ EFI_STATUS Status;
+ PEI_SMM_CONTROL_PPI *SmmControl;
+ PEI_SMM_ACCESS_PPI *SmmAccess;
+ UINT8 SmiCommand;
+ UINTN Size;
+ EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext;
+
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei Communicate Enter\n"));
+
+ if (CommBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get needed resource
+ //
+ Status = PeiServicesLocatePpi (
+ &gPeiSmmControlPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&SmmControl
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_STARTED;
+ }
+
+ Status = PeiServicesLocatePpi (
+ &gPeiSmmAccessPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&SmmAccess
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_STARTED;
+ }
+
+ //
+ // Check SMRAM locked, it should be done after SMRAM lock.
+ //
+ if (!SmmAccess->LockState) {
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei LockState - %x\n", (UINTN)SmmAccess->LockState));
+ return EFI_NOT_STARTED;
+ }
+
+ SmmCommunicationContext = GetCommunicationContext ();
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei BufferPtrAddress - 0x%016lx, BufferPtr: 0x%016lx\n", SmmCommunicationContext->BufferPtrAddress, *(EFI_PHYSICAL_ADDRESS *)(UINTN)SmmCommunicationContext->BufferPtrAddress));
+
+ //
+ // No need to check if BufferPtr is 0, because it is in PEI phase.
+ //
+ *(EFI_PHYSICAL_ADDRESS *)(UINTN)SmmCommunicationContext->BufferPtrAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer;
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei CommBuffer - %x\n", (UINTN)CommBuffer));
+
+ //
+ // Send command
+ //
+ SmiCommand = (UINT8)SmmCommunicationContext->SwSmiNumber;
+ Size = sizeof(SmiCommand);
+ Status = SmmControl->Trigger (
+ (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),
+ SmmControl,
+ (INT8 *)&SmiCommand,
+ &Size,
+ FALSE,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Setting BufferPtr to 0 means this transaction is done.
+ //
+ *(EFI_PHYSICAL_ADDRESS *)(UINTN)SmmCommunicationContext->BufferPtrAddress = 0;
+
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei Communicate Exit\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Entry Point for PI SMM communication PEIM.
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Pointer to PEI Services table.
+
+ @retval EFI_SUCEESS
+ @return Others Some error occurs.
+**/
+EFI_STATUS
+EFIAPI
+PiSmmCommunicationPeiEntryPoint (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ PEI_SMM_ACCESS_PPI *SmmAccess;
+ EFI_BOOT_MODE BootMode;
+ UINTN Index;
+
+ BootMode = GetBootModeHob ();
+ if (BootMode != BOOT_ON_S3_RESUME) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PeiServicesLocatePpi (
+ &gPeiSmmAccessPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&SmmAccess
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_STARTED;
+ }
+
+ //
+ // Check SMRAM locked, it should be done before SMRAM lock.
+ //
+ if (SmmAccess->LockState) {
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei LockState - %x\n", (UINTN)SmmAccess->LockState));
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Open all SMRAM
+ //
+ for (Index = 0; !EFI_ERROR (Status); Index++) {
+ Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
+ }
+
+ InitCommunicationContext ();
+
+ PeiServicesInstallPpi (&mPpiList);
+
+ return RETURN_SUCCESS;
+}
diff --git a/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf
new file mode 100644
index 0000000000..5cb596c564
--- /dev/null
+++ b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf
@@ -0,0 +1,70 @@
+## @file
+# PI SMM Communication PEIM which produces PEI SMM Communication PPI.
+#
+# This PEIM retrieves the SMM communication context and produces PEI SMM
+# Communication PPIin the S3 boot mode.
+#
+# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# 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
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PiSmmCommunicationPei
+ MODULE_UNI_FILE = PiSmmCommunicationPei.uni
+ FILE_GUID = 1C8B7F78-1699-40e6-AF33-9B995D16B043
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PiSmmCommunicationPeiEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ PiSmmCommunicationPei.c
+ PiSmmCommunicationPrivate.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ PeiServicesTablePointerLib
+ PeiServicesLib
+ BaseLib
+ BaseMemoryLib
+ HobLib
+ DebugLib
+
+[Guids]
+ gEfiAcpiVariableGuid ## CONSUMES ## HOB
+
+[Ppis]
+ ## PRODUCES
+ ## UNDEFINED # HOB # SMM Configuration Table
+ gEfiPeiSmmCommunicationPpiGuid
+ gPeiSmmAccessPpiGuid ## CONSUMES
+ gPeiSmmControlPpiGuid ## CONSUMES
+
+# [BootMode]
+# S3_RESUME ## CONSUMES
+
+[Depex]
+ gPeiSmmAccessPpiGuid AND
+ gPeiSmmControlPpiGuid AND
+ gEfiPeiMasterBootModePpiGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ PiSmmCommunicationPeiExtra.uni
diff --git a/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.uni b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.uni
new file mode 100644
index 0000000000..08af34e11b
--- /dev/null
+++ b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.uni
Binary files differ
diff --git a/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPeiExtra.uni b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPeiExtra.uni
new file mode 100644
index 0000000000..ee10182a68
--- /dev/null
+++ b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPeiExtra.uni
Binary files differ
diff --git a/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPrivate.h b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPrivate.h
new file mode 100644
index 0000000000..3dd5ac6e38
--- /dev/null
+++ b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPrivate.h
@@ -0,0 +1,30 @@
+/** @file
+PiSmmCommunication private data structure
+
+Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+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
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SMM_COMMUNICATION_PRIVATE_H_
+#define _SMM_COMMUNICATION_PRIVATE_H_
+
+#pragma pack(push, 1)
+
+#define SMM_COMMUNICATION_SIGNATURE SIGNATURE_32 ('S','M','M','C')
+
+typedef struct {
+ UINT32 Signature;
+ UINT32 SwSmiNumber;
+ EFI_PHYSICAL_ADDRESS BufferPtrAddress;
+} EFI_SMM_COMMUNICATION_CONTEXT;
+
+#pragma pack(pop)
+
+#endif
diff --git a/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.c b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.c
new file mode 100644
index 0000000000..077eacce88
--- /dev/null
+++ b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.c
@@ -0,0 +1,269 @@
+/** @file
+PiSmmCommunication SMM Driver.
+
+Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+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
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#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/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SmmMemLib.h>
+#include <Library/PcdLib.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/SmmReadyToLock.h>
+#include <Protocol/SmmCommunication.h>
+#include <Protocol/AcpiTable.h>
+#include <Ppi/SmmCommunication.h>
+#include <Guid/Acpi.h>
+
+#include "PiSmmCommunicationPrivate.h"
+
+EFI_SMM_COMMUNICATION_CONTEXT mSmmCommunicationContext = {
+ SMM_COMMUNICATION_SIGNATURE
+};
+
+EFI_SMM_COMMUNICATION_ACPI_TABLE mSmmCommunicationAcpiTable = {
+ {
+ {
+ EFI_ACPI_4_0_UEFI_ACPI_DATA_TABLE_SIGNATURE,
+ sizeof (EFI_SMM_COMMUNICATION_ACPI_TABLE),
+ 0x1, // Revision
+ 0x0, // Checksum
+ {0x0}, // OemId[6]
+ 0x0, // OemTableId
+ 0x0, // OemRevision
+ 0x0, // CreatorId
+ 0x0 // CreatorRevision
+ },
+ {0x0}, // Identifier
+ OFFSET_OF (EFI_SMM_COMMUNICATION_ACPI_TABLE, SwSmiNumber) // DataOffset
+ },
+ 0x0, // SwSmiNumber
+ 0x0 // BufferPtrAddress
+};
+
+/**
+ 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_SUCEESS
+ @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_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
+ UINTN TableKey;
+ UINT64 OemTableId;
+ EFI_PHYSICAL_ADDRESS *BufferPtrAddress;
+
+ CopyMem (
+ mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.OemId,
+ PcdGetPtr (PcdAcpiDefaultOemId),
+ sizeof (mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.OemId)
+ );
+ OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
+ CopyMem (&mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.OemTableId, &OemTableId, sizeof (UINT64));
+ mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);
+ mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
+ mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
+
+ //
+ // 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));
+
+ //
+ // Set ACPI table
+ //
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ mSmmCommunicationAcpiTable.SwSmiNumber = (UINT32)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));
+ mSmmCommunicationAcpiTable.BufferPtrAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)BufferPtrAddress;
+ CopyMem (&mSmmCommunicationAcpiTable.UefiAcpiDataTable.Identifier, &gEfiSmmCommunicationProtocolGuid, sizeof(gEfiSmmCommunicationProtocolGuid));
+
+ Status = AcpiTableProtocol->InstallAcpiTable (
+ AcpiTableProtocol,
+ &mSmmCommunicationAcpiTable,
+ sizeof(mSmmCommunicationAcpiTable),
+ &TableKey
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Save context
+ //
+ mSmmCommunicationContext.SwSmiNumber = (UINT32)SmmSwDispatchContext.SwSmiInputValue;
+ mSmmCommunicationContext.BufferPtrAddress = mSmmCommunicationAcpiTable.BufferPtrAddress;
+ SetCommunicationContext ();
+
+ return Status;
+}
diff --git a/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.inf b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.inf
new file mode 100644
index 0000000000..9b03837cf3
--- /dev/null
+++ b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.inf
@@ -0,0 +1,82 @@
+## @file
+# PI SMM Communication SMM driver that installs the SMM Communication ACPI Table.
+#
+# This SMM driver installs the SMM Communication ACPI Table defined in the UEFI spec
+# which provides a mechanism that can be used in the OS present environment by
+# non-firmware agents for inter-mode communication with SMM agents. It also saves
+# SMM communication context for use by SMM Communication PEIM in the S3 boot mode.
+#
+# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# 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
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PiSmmCommunicationSmm
+ MODULE_UNI_FILE = PiSmmCommunicationSmm.uni
+ FILE_GUID = E21F35A8-42FF-4050-82D6-93F7CDFA7073
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = PiSmmCommunicationSmmEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ PiSmmCommunicationSmm.c
+ PiSmmCommunicationPrivate.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ SmmServicesTableLib
+ BaseLib
+ BaseMemoryLib
+ HobLib
+ DebugLib
+ SmmMemLib
+ PcdLib
+
+[Guids]
+ gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ## SystemTable
+ gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ## SystemTable
+ gEfiAcpiTableGuid ## SOMETIMES_CONSUMES ## SystemTable
+
+[Ppis]
+ gEfiPeiSmmCommunicationPpiGuid ## UNDEFINED # SMM Configuration Table
+
+[Protocols]
+ gEfiSmmSwDispatch2ProtocolGuid ## CONSUMES
+ gEfiSmmCommunicationProtocolGuid ## UNDEFINED # SMM Communication ACPI Table GUID
+ gEfiAcpiTableProtocolGuid ## CONSUMES
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## CONSUMES
+
+[Depex]
+ gEfiSmmSwDispatch2ProtocolGuid AND
+ gEfiAcpiTableProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ PiSmmCommunicationSmmExtra.uni
diff --git a/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.uni b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.uni
new file mode 100644
index 0000000000..0ce635815c
--- /dev/null
+++ b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.uni
Binary files differ
diff --git a/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmmExtra.uni b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmmExtra.uni
new file mode 100644
index 0000000000..60a7d627da
--- /dev/null
+++ b/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmmExtra.uni
Binary files differ
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index 5fcff1510d..a4117a2e85 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -53,6 +53,8 @@
ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+ SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
+
[LibraryClasses.common.PEIM]
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
@@ -72,6 +74,7 @@
[LibraryClasses.common.DXE_SMM_DRIVER]
SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
#
# Drivers/Libraries within this package
@@ -93,5 +96,7 @@
UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
+ UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf
+ UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.inf
UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf