The comments in PiSmmCommunicationPei.c describe the whole memory
layout of the SMRAM regarding the SMM communication.
But SHA-1: 8b1d149390
PiSmmCommunicationSmm: Deprecate SMM Communication ACPI Table
removed the code that produces the ACPI Table.
This change updates the accordingly comments.
Signed-off-by: Ray Ni <ray.ni@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
		
	
		
			
				
	
	
		
			414 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			414 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| PiSmmCommunication PEI Driver.
 | |
| 
 | |
| Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #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               |---
 | |
|   +----------------------------------+   |
 | |
|                                          |
 | |
|   +----------------------------------+<--
 | |
|   | 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_SUCCESS
 | |
|   @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;
 | |
| }
 |