UefiCpuPkg: Add SMM Communication PPI and Handler Modules
authorMichael Kinney <michael.d.kinney@intel.com>
Mon, 19 Oct 2015 19:09:33 +0000 (19:09 +0000)
committermdkinney <mdkinney@Edk2>
Mon, 19 Oct 2015 19:09:33 +0000 (19:09 +0000)
Add modules that produce the SMM Communications PPI and
install a SW SMI handler for SMM Communication requests

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Michael Kinney <michael.d.kinney@intel.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18634 6f19259b-4bc3-4df7-8a09-765794883524

UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.c [new file with mode: 0644]
UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf [new file with mode: 0644]
UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.uni [new file with mode: 0644]
UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPeiExtra.uni [new file with mode: 0644]
UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPrivate.h [new file with mode: 0644]
UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.c [new file with mode: 0644]
UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.inf [new file with mode: 0644]
UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.uni [new file with mode: 0644]
UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmmExtra.uni [new file with mode: 0644]
UefiCpuPkg/UefiCpuPkg.dsc

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