UefiCpuPkg: Add SMM Communication PPI and Handler Modules

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
This commit is contained in:
Michael Kinney 2015-10-19 19:09:33 +00:00 committed by mdkinney
parent 28a7ddf031
commit b3dc26ed7e
10 changed files with 881 additions and 0 deletions

View File

@ -0,0 +1,425 @@
/** @file
PiSmmCommunication PEI Driver.
Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <PiPei.h>
#include <PiDxe.h>
#include <PiSmm.h>
#include <Library/PeiServicesTablePointerLib.h>
#include <Library/PeiServicesLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/HobLib.h>
#include <Library/DebugLib.h>
#include <Protocol/SmmCommunication.h>
#include <Ppi/SmmCommunication.h>
#include <Ppi/SmmAccess.h>
#include <Ppi/SmmControl.h>
#include <Guid/AcpiS3Context.h>
#include "PiSmmCommunicationPrivate.h"
/**
the whole picture is below:
+----------------------------------+
| ACPI_VARIABLE_HOB |
| SmramDescriptor | <- DRAM
| CpuStart |---
+----------------------------------+ |
|
+----------------------------------+<--
| SMM_S3_RESUME_STATE |
| Signature | <- SMRAM
| Smst |---
+----------------------------------+ |
|
+----------------------------------+<--
| EFI_SMM_SYSTEM_TABLE2 |
| NumberOfTableEntries | <- SMRAM
| SmmConfigurationTable |---
+----------------------------------+ |
|
+----------------------------------+<--
| EFI_SMM_COMMUNICATION_CONTEXT |
| SwSmiNumber | <- SMRAM
| BufferPtrAddress |----------------
+----------------------------------+ |
|
+----------------------------------+ |
| EFI_SMM_COMMUNICATION_ACPI_TABLE | |
| SwSmiNumber | <- AcpiTable |
| BufferPtrAddress |--- |
+----------------------------------+ | |
| |
+----------------------------------+<---------------
| Communication Buffer Pointer | <- AcpiNvs
+----------------------------------+---
|
+----------------------------------+<--
| EFI_SMM_COMMUNICATE_HEADER |
| HeaderGuid | <- DRAM
| MessageLength |
+----------------------------------+
**/
#if defined (MDE_CPU_IA32)
typedef struct {
EFI_TABLE_HEADER Hdr;
UINT64 SmmFirmwareVendor;
UINT64 SmmFirmwareRevision;
UINT64 SmmInstallConfigurationTable;
UINT64 SmmIoMemRead;
UINT64 SmmIoMemWrite;
UINT64 SmmIoIoRead;
UINT64 SmmIoIoWrite;
UINT64 SmmAllocatePool;
UINT64 SmmFreePool;
UINT64 SmmAllocatePages;
UINT64 SmmFreePages;
UINT64 SmmStartupThisAp;
UINT64 CurrentlyExecutingCpu;
UINT64 NumberOfCpus;
UINT64 CpuSaveStateSize;
UINT64 CpuSaveState;
UINT64 NumberOfTableEntries;
UINT64 SmmConfigurationTable;
} EFI_SMM_SYSTEM_TABLE2_64;
typedef struct {
EFI_GUID VendorGuid;
UINT64 VendorTable;
} EFI_CONFIGURATION_TABLE64;
#endif
#if defined (MDE_CPU_X64)
typedef EFI_SMM_SYSTEM_TABLE2 EFI_SMM_SYSTEM_TABLE2_64;
typedef EFI_CONFIGURATION_TABLE EFI_CONFIGURATION_TABLE64;
#endif
/**
Communicates with a registered handler.
This function provides a service to send and receive messages from a registered UEFI service.
@param[in] This The EFI_PEI_SMM_COMMUNICATION_PPI instance.
@param[in, out] CommBuffer A pointer to the buffer to convey into SMRAM.
@param[in, out] CommSize The size of the data buffer being passed in.On exit, the size of data
being returned. Zero if the handler does not wish to reply with any data.
@retval EFI_SUCCESS The message was successfully posted.
@retval EFI_INVALID_PARAMETER The CommBuffer was NULL.
@retval EFI_NOT_STARTED The service is NOT started.
**/
EFI_STATUS
EFIAPI
Communicate (
IN CONST EFI_PEI_SMM_COMMUNICATION_PPI *This,
IN OUT VOID *CommBuffer,
IN OUT UINTN *CommSize
);
EFI_PEI_SMM_COMMUNICATION_PPI mSmmCommunicationPpi = { Communicate };
EFI_PEI_PPI_DESCRIPTOR mPpiList = {
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiPeiSmmCommunicationPpiGuid,
&mSmmCommunicationPpi
};
/**
Get SMM communication context.
@return SMM communication context.
**/
EFI_SMM_COMMUNICATION_CONTEXT *
GetCommunicationContext (
VOID
)
{
EFI_HOB_GUID_TYPE *GuidHob;
EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext;
GuidHob = GetFirstGuidHob (&gEfiPeiSmmCommunicationPpiGuid);
ASSERT (GuidHob != NULL);
SmmCommunicationContext = (EFI_SMM_COMMUNICATION_CONTEXT *)GET_GUID_HOB_DATA (GuidHob);
return SmmCommunicationContext;
}
/**
Set SMM communication context.
@param SmmCommunicationContext SMM communication context.
**/
VOID
SetCommunicationContext (
IN EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext
)
{
EFI_PEI_HOB_POINTERS Hob;
UINTN BufferSize;
BufferSize = sizeof (*SmmCommunicationContext);
Hob.Raw = BuildGuidHob (
&gEfiPeiSmmCommunicationPpiGuid,
BufferSize
);
ASSERT (Hob.Raw);
CopyMem ((VOID *)Hob.Raw, SmmCommunicationContext, sizeof(*SmmCommunicationContext));
}
/**
Get VendorTable by VendorGuid in Smst.
@param Signature Signature of SMM_S3_RESUME_STATE
@param Smst SMM system table
@param VendorGuid vendor guid
@return vendor table.
**/
VOID *
InternalSmstGetVendorTableByGuid (
IN UINT64 Signature,
IN EFI_SMM_SYSTEM_TABLE2 *Smst,
IN EFI_GUID *VendorGuid
)
{
EFI_CONFIGURATION_TABLE *SmmConfigurationTable;
UINTN NumberOfTableEntries;
UINTN Index;
EFI_SMM_SYSTEM_TABLE2_64 *Smst64;
EFI_CONFIGURATION_TABLE64 *SmmConfigurationTable64;
if ((sizeof(UINTN) == sizeof(UINT32)) && (Signature == SMM_S3_RESUME_SMM_64)) {
//
// 32 PEI + 64 DXE
//
Smst64 = (EFI_SMM_SYSTEM_TABLE2_64 *)Smst;
DEBUG ((EFI_D_INFO, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst64->SmmConfigurationTable));
DEBUG ((EFI_D_INFO, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst64->NumberOfTableEntries));
SmmConfigurationTable64 = (EFI_CONFIGURATION_TABLE64 *)(UINTN)Smst64->SmmConfigurationTable;
NumberOfTableEntries = (UINTN)Smst64->NumberOfTableEntries;
for (Index = 0; Index < NumberOfTableEntries; Index++) {
if (CompareGuid (&SmmConfigurationTable64[Index].VendorGuid, VendorGuid)) {
return (VOID *)(UINTN)SmmConfigurationTable64[Index].VendorTable;
}
}
return NULL;
} else {
DEBUG ((EFI_D_INFO, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst->SmmConfigurationTable));
DEBUG ((EFI_D_INFO, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst->NumberOfTableEntries));
SmmConfigurationTable = Smst->SmmConfigurationTable;
NumberOfTableEntries = Smst->NumberOfTableEntries;
for (Index = 0; Index < NumberOfTableEntries; Index++) {
if (CompareGuid (&SmmConfigurationTable[Index].VendorGuid, VendorGuid)) {
return (VOID *)SmmConfigurationTable[Index].VendorTable;
}
}
return NULL;
}
}
/**
Init SMM communication context.
**/
VOID
InitCommunicationContext (
VOID
)
{
EFI_SMRAM_DESCRIPTOR *SmramDescriptor;
SMM_S3_RESUME_STATE *SmmS3ResumeState;
VOID *GuidHob;
EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext;
GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);
ASSERT (GuidHob != NULL);
SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);
SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;
DEBUG ((EFI_D_INFO, "InitCommunicationContext - SmmS3ResumeState: %x\n", SmmS3ResumeState));
DEBUG ((EFI_D_INFO, "InitCommunicationContext - Smst: %x\n", SmmS3ResumeState->Smst));
SmmCommunicationContext = (EFI_SMM_COMMUNICATION_CONTEXT *)InternalSmstGetVendorTableByGuid (
SmmS3ResumeState->Signature,
(EFI_SMM_SYSTEM_TABLE2 *)(UINTN)SmmS3ResumeState->Smst,
&gEfiPeiSmmCommunicationPpiGuid
);
ASSERT (SmmCommunicationContext != NULL);
SetCommunicationContext (SmmCommunicationContext);
return ;
}
/**
Communicates with a registered handler.
This function provides a service to send and receive messages from a registered UEFI service.
@param[in] This The EFI_PEI_SMM_COMMUNICATION_PPI instance.
@param[in, out] CommBuffer A pointer to the buffer to convey into SMRAM.
@param[in, out] CommSize The size of the data buffer being passed in.On exit, the size of data
being returned. Zero if the handler does not wish to reply with any data.
@retval EFI_SUCCESS The message was successfully posted.
@retval EFI_INVALID_PARAMETER The CommBuffer was NULL.
@retval EFI_NOT_STARTED The service is NOT started.
**/
EFI_STATUS
EFIAPI
Communicate (
IN CONST EFI_PEI_SMM_COMMUNICATION_PPI *This,
IN OUT VOID *CommBuffer,
IN OUT UINTN *CommSize
)
{
EFI_STATUS Status;
PEI_SMM_CONTROL_PPI *SmmControl;
PEI_SMM_ACCESS_PPI *SmmAccess;
UINT8 SmiCommand;
UINTN Size;
EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext;
DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei Communicate Enter\n"));
if (CommBuffer == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Get needed resource
//
Status = PeiServicesLocatePpi (
&gPeiSmmControlPpiGuid,
0,
NULL,
(VOID **)&SmmControl
);
if (EFI_ERROR (Status)) {
return EFI_NOT_STARTED;
}
Status = PeiServicesLocatePpi (
&gPeiSmmAccessPpiGuid,
0,
NULL,
(VOID **)&SmmAccess
);
if (EFI_ERROR (Status)) {
return EFI_NOT_STARTED;
}
//
// Check SMRAM locked, it should be done after SMRAM lock.
//
if (!SmmAccess->LockState) {
DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei LockState - %x\n", (UINTN)SmmAccess->LockState));
return EFI_NOT_STARTED;
}
SmmCommunicationContext = GetCommunicationContext ();
DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei BufferPtrAddress - 0x%016lx, BufferPtr: 0x%016lx\n", SmmCommunicationContext->BufferPtrAddress, *(EFI_PHYSICAL_ADDRESS *)(UINTN)SmmCommunicationContext->BufferPtrAddress));
//
// No need to check if BufferPtr is 0, because it is in PEI phase.
//
*(EFI_PHYSICAL_ADDRESS *)(UINTN)SmmCommunicationContext->BufferPtrAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer;
DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei CommBuffer - %x\n", (UINTN)CommBuffer));
//
// Send command
//
SmiCommand = (UINT8)SmmCommunicationContext->SwSmiNumber;
Size = sizeof(SmiCommand);
Status = SmmControl->Trigger (
(EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),
SmmControl,
(INT8 *)&SmiCommand,
&Size,
FALSE,
0
);
ASSERT_EFI_ERROR (Status);
//
// Setting BufferPtr to 0 means this transaction is done.
//
*(EFI_PHYSICAL_ADDRESS *)(UINTN)SmmCommunicationContext->BufferPtrAddress = 0;
DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei Communicate Exit\n"));
return EFI_SUCCESS;
}
/**
Entry Point for PI SMM communication PEIM.
@param FileHandle Handle of the file being invoked.
@param PeiServices Pointer to PEI Services table.
@retval EFI_SUCEESS
@return Others Some error occurs.
**/
EFI_STATUS
EFIAPI
PiSmmCommunicationPeiEntryPoint (
IN EFI_PEI_FILE_HANDLE FileHandle,
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
EFI_STATUS Status;
PEI_SMM_ACCESS_PPI *SmmAccess;
EFI_BOOT_MODE BootMode;
UINTN Index;
BootMode = GetBootModeHob ();
if (BootMode != BOOT_ON_S3_RESUME) {
return EFI_UNSUPPORTED;
}
Status = PeiServicesLocatePpi (
&gPeiSmmAccessPpiGuid,
0,
NULL,
(VOID **)&SmmAccess
);
if (EFI_ERROR (Status)) {
return EFI_NOT_STARTED;
}
//
// Check SMRAM locked, it should be done before SMRAM lock.
//
if (SmmAccess->LockState) {
DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei LockState - %x\n", (UINTN)SmmAccess->LockState));
return EFI_ACCESS_DENIED;
}
//
// Open all SMRAM
//
for (Index = 0; !EFI_ERROR (Status); Index++) {
Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
}
InitCommunicationContext ();
PeiServicesInstallPpi (&mPpiList);
return RETURN_SUCCESS;
}

View File

@ -0,0 +1,70 @@
## @file
# PI SMM Communication PEIM which produces PEI SMM Communication PPI.
#
# This PEIM retrieves the SMM communication context and produces PEI SMM
# Communication PPIin the S3 boot mode.
#
# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PiSmmCommunicationPei
MODULE_UNI_FILE = PiSmmCommunicationPei.uni
FILE_GUID = 1C8B7F78-1699-40e6-AF33-9B995D16B043
MODULE_TYPE = PEIM
VERSION_STRING = 1.0
ENTRY_POINT = PiSmmCommunicationPeiEntryPoint
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
PiSmmCommunicationPei.c
PiSmmCommunicationPrivate.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
PeimEntryPoint
PeiServicesTablePointerLib
PeiServicesLib
BaseLib
BaseMemoryLib
HobLib
DebugLib
[Guids]
gEfiAcpiVariableGuid ## CONSUMES ## HOB
[Ppis]
## PRODUCES
## UNDEFINED # HOB # SMM Configuration Table
gEfiPeiSmmCommunicationPpiGuid
gPeiSmmAccessPpiGuid ## CONSUMES
gPeiSmmControlPpiGuid ## CONSUMES
# [BootMode]
# S3_RESUME ## CONSUMES
[Depex]
gPeiSmmAccessPpiGuid AND
gPeiSmmControlPpiGuid AND
gEfiPeiMasterBootModePpiGuid
[UserExtensions.TianoCore."ExtraFiles"]
PiSmmCommunicationPeiExtra.uni

View File

@ -0,0 +1,30 @@
/** @file
PiSmmCommunication private data structure
Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _SMM_COMMUNICATION_PRIVATE_H_
#define _SMM_COMMUNICATION_PRIVATE_H_
#pragma pack(push, 1)
#define SMM_COMMUNICATION_SIGNATURE SIGNATURE_32 ('S','M','M','C')
typedef struct {
UINT32 Signature;
UINT32 SwSmiNumber;
EFI_PHYSICAL_ADDRESS BufferPtrAddress;
} EFI_SMM_COMMUNICATION_CONTEXT;
#pragma pack(pop)
#endif

View File

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

View File

@ -0,0 +1,82 @@
## @file
# PI SMM Communication SMM driver that installs the SMM Communication ACPI Table.
#
# This SMM driver installs the SMM Communication ACPI Table defined in the UEFI spec
# which provides a mechanism that can be used in the OS present environment by
# non-firmware agents for inter-mode communication with SMM agents. It also saves
# SMM communication context for use by SMM Communication PEIM in the S3 boot mode.
#
# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PiSmmCommunicationSmm
MODULE_UNI_FILE = PiSmmCommunicationSmm.uni
FILE_GUID = E21F35A8-42FF-4050-82D6-93F7CDFA7073
MODULE_TYPE = DXE_SMM_DRIVER
VERSION_STRING = 1.0
PI_SPECIFICATION_VERSION = 0x0001000A
ENTRY_POINT = PiSmmCommunicationSmmEntryPoint
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
PiSmmCommunicationSmm.c
PiSmmCommunicationPrivate.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
UefiDriverEntryPoint
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
SmmServicesTableLib
BaseLib
BaseMemoryLib
HobLib
DebugLib
SmmMemLib
PcdLib
[Guids]
gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ## SystemTable
gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ## SystemTable
gEfiAcpiTableGuid ## SOMETIMES_CONSUMES ## SystemTable
[Ppis]
gEfiPeiSmmCommunicationPpiGuid ## UNDEFINED # SMM Configuration Table
[Protocols]
gEfiSmmSwDispatch2ProtocolGuid ## CONSUMES
gEfiSmmCommunicationProtocolGuid ## UNDEFINED # SMM Communication ACPI Table GUID
gEfiAcpiTableProtocolGuid ## CONSUMES
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## CONSUMES
[Depex]
gEfiSmmSwDispatch2ProtocolGuid AND
gEfiAcpiTableProtocolGuid
[UserExtensions.TianoCore."ExtraFiles"]
PiSmmCommunicationSmmExtra.uni

View File

@ -53,6 +53,8 @@
ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
[LibraryClasses.common.PEIM]
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
@ -72,6 +74,7 @@
[LibraryClasses.common.DXE_SMM_DRIVER]
SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
#
# Drivers/Libraries within this package
@ -93,5 +96,7 @@
UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf
UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.inf
UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf