--- /dev/null
+/** @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
--- /dev/null
+## @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
--- /dev/null
+/** @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
--- /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
--- /dev/null
+## @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
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
[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
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