From ce928a58c93ca34ef8ba6f0f992c77a303942f8a Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Thu, 2 Jun 2016 10:26:23 +0800 Subject: BraswellPlatformPkg/IntelSiliconBasic: Add PiSmmCommunication Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- .../PiSmmCommunication/PiSmmCommunicationPei.c | 424 +++++++++++++++++++++ .../PiSmmCommunication/PiSmmCommunicationPei.inf | 67 ++++ .../PiSmmCommunication/PiSmmCommunicationPrivate.h | 31 ++ .../PiSmmCommunication/PiSmmCommunicationSmm.c | 288 ++++++++++++++ .../PiSmmCommunication/PiSmmCommunicationSmm.inf | 78 ++++ 5 files changed, 888 insertions(+) create mode 100644 BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationPei.c create mode 100644 BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationPei.inf create mode 100644 BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationPrivate.h create mode 100644 BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationSmm.c create mode 100644 BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationSmm.inf diff --git a/BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationPei.c b/BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationPei.c new file mode 100644 index 0000000000..d546181ca5 --- /dev/null +++ b/BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationPei.c @@ -0,0 +1,424 @@ +/** @file + PiSmmCommunication PEI Driver. + + Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.
+ + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + | AcpiTableAddress | + +----------------------------------+--- + | + +----------------------------------+<-- + | EFI_SMM_COMMUNICATION_ACPI_TABLE | + | SwSmiNumber | <- AcpiNvs + | BufferPtrAddress | + +----------------------------------+--- + | + +----------------------------------+<-- + | 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; + EFI_SMM_COMMUNICATION_ACPI_TABLE *SmmCommunicationAcpiTable; + + 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 AcpiTableAddress - %x\n", (UINTN)SmmCommunicationContext->AcpiTableAddress)); + + SmmCommunicationAcpiTable = (EFI_SMM_COMMUNICATION_ACPI_TABLE *)(UINTN)SmmCommunicationContext->AcpiTableAddress; + // + // No need to check if BufferPtrAddress is 0, because it is in PEI phase. + // + SmmCommunicationAcpiTable->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 BufferPtrAddress to 0 means this transaction is done. + // + SmmCommunicationAcpiTable->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/BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationPei.inf b/BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationPei.inf new file mode 100644 index 0000000000..fd1cb31264 --- /dev/null +++ b/BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationPei.inf @@ -0,0 +1,67 @@ +## @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 - 2015, Intel Corporation. All rights reserved.
+# +# 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 = 0x00010018 + BASE_NAME = PiSmmCommunicationPei + 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 + diff --git a/BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationPrivate.h b/BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationPrivate.h new file mode 100644 index 0000000000..1001aa2416 --- /dev/null +++ b/BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationPrivate.h @@ -0,0 +1,31 @@ +/** @file + PiSmmCommunication private data structure + + Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.
+ + 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 AcpiTableAddress; +} EFI_SMM_COMMUNICATION_CONTEXT; + +#pragma pack(pop) + +#endif diff --git a/BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationSmm.c b/BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationSmm.c new file mode 100644 index 0000000000..7d2091bb02 --- /dev/null +++ b/BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationSmm.c @@ -0,0 +1,288 @@ +/** @file + PiSmmCommunication SMM Driver. + + Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.
+ + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +} + +/** + Get SMM communication ACPI table address. + + @return SMM communication ACPI table address. +**/ +EFI_PHYSICAL_ADDRESS +GetSmmCommunicationAcpiTableAddress ( + VOID + ) +{ + EFI_ACPI_4_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; + EFI_ACPI_DESCRIPTION_HEADER *Rsdt; + EFI_ACPI_DESCRIPTION_HEADER *Xsdt; + UINTN Index; + UINT32 *TableAddress; + UINT64 *XTableAddress; + UINTN TableCount; + EFI_SMM_COMMUNICATION_ACPI_TABLE *SmmAcpi; + + Rsdp = NULL; + for (Index = 0; Index < gST->NumberOfTableEntries; Index++) { + if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi20TableGuid) || + CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi10TableGuid) || + CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpiTableGuid) ) { + // + // A match was found. + // + Rsdp = (EFI_ACPI_4_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) gST->ConfigurationTable[Index].VendorTable; + break; + } + } + + ASSERT (Rsdp != NULL); + if (Rsdp == NULL) { + return 0; + } + + Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress; + TableCount = (Rsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT32); + TableAddress = (UINT32 *)(Rsdt + 1); + for (Index = 0; Index < TableCount; Index++) { + SmmAcpi = (EFI_SMM_COMMUNICATION_ACPI_TABLE *)(UINTN)TableAddress[Index]; + if (SmmAcpi == NULL) { + continue; + } + if ((SmmAcpi->UefiAcpiDataTable.Header.Signature == EFI_ACPI_4_0_UEFI_ACPI_DATA_TABLE_SIGNATURE) && + (SmmAcpi->UefiAcpiDataTable.Header.Length == sizeof (EFI_SMM_COMMUNICATION_ACPI_TABLE)) && + CompareGuid (&(SmmAcpi->UefiAcpiDataTable.Identifier), &gEfiSmmCommunicationProtocolGuid) ) { + return (EFI_PHYSICAL_ADDRESS)(UINTN)SmmAcpi; + } + } + + if (Rsdp->Revision >= 2) { + Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->XsdtAddress; + TableCount = (Rsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64); + XTableAddress = (UINT64 *)(Xsdt + 1); + for (Index = 0; Index < TableCount; Index++) { + SmmAcpi = (EFI_SMM_COMMUNICATION_ACPI_TABLE *)(UINTN)XTableAddress[Index]; + if (SmmAcpi == NULL) { + continue; + } + if ((SmmAcpi->UefiAcpiDataTable.Header.Signature == EFI_ACPI_4_0_UEFI_ACPI_DATA_TABLE_SIGNATURE) && + (SmmAcpi->UefiAcpiDataTable.Header.Length == sizeof (EFI_SMM_COMMUNICATION_ACPI_TABLE)) && + CompareGuid (&(SmmAcpi->UefiAcpiDataTable.Identifier), &gEfiSmmCommunicationProtocolGuid) ) { + return (EFI_PHYSICAL_ADDRESS)(UINTN)SmmAcpi; + } + } + } + + ASSERT(FALSE); + return 0; +} + +/** + 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 + ) +{ + EFI_SMM_COMMUNICATION_ACPI_TABLE *SmmCommunicationAcpiTable; + UINTN CommSize; + EFI_STATUS Status; + EFI_SMM_COMMUNICATE_HEADER *CommunicateHeader; + + DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Enter\n")); + + SmmCommunicationAcpiTable = (EFI_SMM_COMMUNICATION_ACPI_TABLE *)(UINTN)mSmmCommunicationContext.AcpiTableAddress; + CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)(UINTN)SmmCommunicationAcpiTable->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 { + CommSize = (UINTN)CommunicateHeader->MessageLength; + + // + // Call dispatch function + // + DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Data - %x\n", &CommunicateHeader->Data[0])); + Status = gSmst->SmiManage ( + &CommunicateHeader->HeaderGuid, + NULL, + &CommunicateHeader->Data[0], + &CommSize + ); + } + DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler %r\n", Status)); + DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Exit\n")); + + return (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_INTERRUPT_PENDING; +} + +/** + 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; + + 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; + 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.AcpiTableAddress = GetSmmCommunicationAcpiTableAddress (); + DEBUG ((EFI_D_INFO, "SmmCommunicationAcpiTable: %x\n", mSmmCommunicationContext.AcpiTableAddress)); + SetCommunicationContext (); + + return Status; +} diff --git a/BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationSmm.inf b/BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationSmm.inf new file mode 100644 index 0000000000..22a61ee147 --- /dev/null +++ b/BraswellPlatformPkg/IntelSiliconBasic/PiSmmCommunication/PiSmmCommunicationSmm.inf @@ -0,0 +1,78 @@ +## @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.
+# +# 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 = 0x00010018 + BASE_NAME = PiSmmCommunicationSmm + 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 + 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 + -- cgit v1.2.3