On Mon, 26 Jun 2023 at 22:00, Kun Qin <kuqi...@gmail.com> wrote:
>
> From: Kun Qin <ku...@microsoft.com>
>
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4464
>
> This change introduced the MM communicate support in PEI phase for ARM
> based platforms. Similar to the DXE counterpart, `PcdMmBufferBase` is
> used as communicate buffer and SMC will be invoked to communicate to
> TrustZone when MMI is requested.
>
> Cc: Leif Lindholm <quic_llind...@quicinc.com>
> Cc: Ard Biesheuvel <ardb+tianoc...@kernel.org>
> Cc: Sami Mujawar <sami.muja...@arm.com>
>
> Co-authored-by: Ronny Hansen <hansen.ro...@microsoft.com>
> Co-authored-by: Shriram Masanamuthu Chinnathurai <shrira...@microsoft.com>
> Co-authored-by: Preshit Harlikar <pharli...@microsoft.com>
> Signed-off-by: Kun Qin <ku...@microsoft.com>
> ---
>
> Notes:
>     v2:
>     - Adjustment to CommSize checks [Sami]
>     - Added more debug prints for error returns.
>
>  ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c   | 212 
> ++++++++++++++++++++
>  ArmPkg/ArmPkg.dsc                                        |   2 +
>  ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h   |  76 +++++++
>  ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf |  41 ++++
>  4 files changed, 331 insertions(+)
>
> diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c 
> b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c
> new file mode 100644
> index 000000000000..8661f0c8ee49
> --- /dev/null
> +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c
> @@ -0,0 +1,212 @@
> +/** @file -- MmCommunicationPei.c
> +  Provides an interface to send MM request in PEI
> +
> +  Copyright (c) 2016-2021, Arm Limited. All rights reserved.<BR>
> +  Copyright (c) Microsoft Corporation.
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "MmCommunicationPei.h"
> +
> +//
> +// Module globals
> +//

STATIC CONST

> +EFI_PEI_MM_COMMUNICATION_PPI  mPeiMmCommunication = {
> +  MmCommunicationPeim
> +};
> +

STATIC CONST

> +EFI_PEI_PPI_DESCRIPTOR  mPeiMmCommunicationPpi = {
> +  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> +  &gEfiPeiMmCommunicationPpiGuid,
> +  &mPeiMmCommunication
> +};
> +
> +/**
> +  Entry point of PEI MM Communication driver
> +
> +  @param  FileHandle   Handle of the file being invoked.
> +                       Type EFI_PEI_FILE_HANDLE is defined in 
> FfsFindNextFile().
> +  @param  PeiServices  General purpose services available to every PEIM.
> +
> +  @retval EFI_SUCCESS  If the interface could be successfully installed
> +  @retval Others       Returned from PeiServicesInstallPpi()
> +**/
> +EFI_STATUS
> +EFIAPI
> +MmCommunicationPeiInitialize (
> +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
> +  IN CONST EFI_PEI_SERVICES     **PeiServices
> +  )
> +{
> +  return PeiServicesInstallPpi (&mPeiMmCommunicationPpi);
> +}
> +
> +/**
> +  MmCommunicationPeim
> +  Communicates with a registered handler.
> +  This function provides a service to send and receive messages from a 
> registered UEFI service during PEI.
> +
> +  @param[in]      This            The EFI_PEI_MM_COMMUNICATION_PPI instance.
> +  @param[in, out] CommBuffer      Pointer to the data buffer
> +  @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   CommBuffer or CommSize was NULL, or 
> *CommSize does not
> +                                  match MessageLength + sizeof 
> (EFI_MM_COMMUNICATE_HEADER).
> +  @retval EFI_BAD_BUFFER_SIZE     The buffer is too large for the MM 
> implementation.
> +                                  If this error is returned, the 
> MessageLength field
> +                                  in the CommBuffer header or the integer 
> pointed by
> +                                  CommSize, are updated to reflect the 
> maximum payload
> +                                  size the implementation can accommodate.
> +  @retval EFI_ACCESS_DENIED       The CommunicateBuffer parameter or 
> CommSize parameter,
> +                                  if not omitted, are in address range that 
> cannot be
> +                                  accessed by the MM environment.
> +**/

This can be STATIC as well - no need to declare it in the header file
either (but you may need to reorder this file to avoid the need for a
forward declaration)


> +EFI_STATUS
> +EFIAPI
> +MmCommunicationPeim (
> +  IN CONST EFI_PEI_MM_COMMUNICATION_PPI  *This,
> +  IN OUT VOID                            *CommBuffer,
> +  IN OUT UINTN                           *CommSize
> +  )
> +{
> +  EFI_MM_COMMUNICATE_HEADER  *CommunicateHeader;
> +  EFI_MM_COMMUNICATE_HEADER  *TempCommHeader;
> +  ARM_SMC_ARGS               CommunicateSmcArgs;
> +  EFI_STATUS                 Status;
> +  UINTN                      BufferSize;
> +
> +  ZeroMem (&CommunicateSmcArgs, sizeof (ARM_SMC_ARGS));
> +
> +  // Check that our static buffer is looking good.
> +  // We are using PcdMmBufferBase to transfer variable data.
> +  // We are not using the full size of the buffer since there is a cost
> +  // of copying data between Normal and Secure World.
> +  ASSERT (PcdGet64 (PcdMmBufferSize) > 0 && PcdGet64 (PcdMmBufferBase) != 0);
> +

Please split these up into two separate ASSERT()s

> +  //
> +  // Check parameters
> +  //
> +  if ((CommBuffer == NULL) || (CommSize == NULL)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "%a One or more incoming pointers are NULL %p and %p!\n",
> +      __func__,
> +      CommBuffer,
> +      CommSize
> +      ));

Please drop the DEBUG() and use an ASSERT() for each parameter.
(Asserts are self documenting)

> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // If the length of the CommBuffer is 0 then return the expected length.
> +  // This case can be used by the consumer of this driver to find out the
> +  // max size that can be used for allocating CommBuffer.
> +  if ((*CommSize == 0) || (*CommSize > (UINTN)PcdGet64 (PcdMmBufferSize))) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "%a Invalid CommSize value 0x%llx!\n",
> +      __func__,
> +      *CommSize
> +      ));
> +    *CommSize = (UINTN)PcdGet64 (PcdMmBufferSize);
> +    return EFI_BAD_BUFFER_SIZE;
> +  }
> +
> +  // Given CommBuffer is not NULL here, we use it to test the legitimacy of 
> CommSize.
> +  TempCommHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)CommBuffer;
> +
> +  // CommBuffer is a mandatory parameter. Hence, Rely on
> +  // MessageLength + Header to ascertain the
> +  // total size of the communication payload rather than
> +  // rely on optional CommSize parameter
> +  BufferSize = TempCommHeader->MessageLength +
> +               sizeof (TempCommHeader->HeaderGuid) +
> +               sizeof (TempCommHeader->MessageLength);
> +
> +  //
> +  // If CommSize is supplied it must match MessageLength + sizeof 
> (EFI_MM_COMMUNICATE_HEADER);
> +  //
> +  if (*CommSize != BufferSize) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "%a Unexpected CommSize value, has: 0x%llx vs. expected: 0x%llx!\n",
> +      __func__,
> +      *CommSize,
> +      BufferSize
> +      ));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // Now we know that the size is something we can handle, copy it over to 
> the designated comm buffer.
> +  CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)(PcdGet64 
> (PcdMmBufferBase));
> +
> +  CopyMem ((VOID *)CommunicateHeader, CommBuffer, *CommSize);

No need for a (VOID*) cast

> +
> +  // SMC Function ID
> +  CommunicateSmcArgs.Arg0 = ARM_SMC_ID_MM_COMMUNICATE_AARCH64;
> +
> +  // Cookie
> +  CommunicateSmcArgs.Arg1 = 0;
> +
> +  // comm_buffer_address (64-bit physical address)
> +  CommunicateSmcArgs.Arg2 = (UINTN)CommunicateHeader;
> +
> +  // comm_size_address (not used, indicated by setting to zero)
> +  CommunicateSmcArgs.Arg3 = 0;
> +
> +  // Call the Standalone MM environment.
> +  ArmCallSmc (&CommunicateSmcArgs);
> +
> +  switch (CommunicateSmcArgs.Arg0) {
> +    case ARM_SMC_MM_RET_SUCCESS:
> +      // On successful return, the size of data being returned is inferred 
> from
> +      // MessageLength + Header.
> +      BufferSize = CommunicateHeader->MessageLength +
> +                   sizeof (CommunicateHeader->HeaderGuid) +
> +                   sizeof (CommunicateHeader->MessageLength);
> +      if (BufferSize > (UINTN)PcdGet64 (PcdMmBufferSize)) {
> +        // Something bad has happened, we should have landed in 
> ARM_SMC_MM_RET_NO_MEMORY
> +        DEBUG ((
> +          DEBUG_ERROR,
> +          "%a Returned buffer exceeds communication buffer limit. Has: 
> 0x%llx vs. max: 0x%llx!\n",
> +          __func__,
> +          BufferSize,
> +          (UINTN)PcdGet64 (PcdMmBufferSize)
> +          ));
> +        Status = EFI_BAD_BUFFER_SIZE;
> +        break;
> +      }
> +
> +      CopyMem (CommBuffer, (VOID *)CommunicateHeader, BufferSize);

No need for the (VOID *) cast

> +      if (CommSize != NULL) {

Can CommSize be NULL?

> +        *CommSize = BufferSize;
> +      }
> +
> +      Status = EFI_SUCCESS;
> +      break;
> +
> +    case ARM_SMC_MM_RET_INVALID_PARAMS:
> +      Status = EFI_INVALID_PARAMETER;
> +      break;
> +
> +    case ARM_SMC_MM_RET_DENIED:
> +      Status = EFI_ACCESS_DENIED;
> +      break;
> +
> +    case ARM_SMC_MM_RET_NO_MEMORY:
> +      // Unexpected error since the CommSize was checked for zero length
> +      // prior to issuing the SMC
> +      Status = EFI_OUT_OF_RESOURCES;
> +      ASSERT (0);
> +      break;
> +
> +    default:
> +      Status = EFI_ACCESS_DENIED;
> +      ASSERT (0);
> +      break;
> +  }
> +
> +  return Status;
> +}
> diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc
> index 6b938ce8b671..4939b3d59b7f 100644
> --- a/ArmPkg/ArmPkg.dsc
> +++ b/ArmPkg/ArmPkg.dsc
> @@ -162,6 +162,8 @@ [Components.common]
>    ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf
>    ArmPkg/Universal/Smbios/OemMiscLibNull/OemMiscLibNull.inf
>
> +  ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
> +
>  [Components.AARCH64]
>    ArmPkg/Drivers/ArmPsciMpServicesDxe/ArmPsciMpServicesDxe.inf
>    ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
> diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h 
> b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h
> new file mode 100644
> index 000000000000..a99baa2496a9
> --- /dev/null
> +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h

I don't think we need this header file at all.

> @@ -0,0 +1,76 @@
> +/** @file -- MmCommunicationPei.h
> +  Provides an interface to send MM request in PEI
> +
> +  Copyright (c) Microsoft Corporation.
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef MM_COMMUNICATION_PEI_H_
> +#define MM_COMMUNICATION_PEI_H_
> +
> +#include <PiPei.h>
> +
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/ArmSmcLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PeimEntryPoint.h>
> +#include <Library/PeiServicesLib.h>
> +#include <Library/HobLib.h>
> +
> +#include <Protocol/MmCommunication.h>
> +
> +#include <IndustryStandard/ArmStdSmc.h>
> +
> +#include <Ppi/MmCommunication.h>
> +
> +/**
> +  Entry point of PEI MM Communication driver
> +
> +  @param  FileHandle   Handle of the file being invoked.
> +                       Type EFI_PEI_FILE_HANDLE is defined in 
> FfsFindNextFile().
> +  @param  PeiServices  General purpose services available to every PEIM.
> +
> +  @retval EFI_SUCCESS  If the interface could be successfully installed
> +  @retval Others       Returned from PeiServicesInstallPpi()
> +**/
> +EFI_STATUS
> +EFIAPI
> +MmCommunicationPeiInitialize (
> +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
> +  IN CONST EFI_PEI_SERVICES     **PeiServices
> +  );
> +
> +/**
> +  MmCommunicationPeim
> +  Communicates with a registered handler.
> +  This function provides a service to send and receive messages from a 
> registered UEFI service during PEI.
> +
> +  @param[in]      This            The EFI_PEI_MM_COMMUNICATION_PPI instance.
> +  @param[in, out] CommBuffer      Pointer to the data buffer
> +  @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   CommBuffer was NULL or *CommSize does not 
> match
> +                                  MessageLength + sizeof 
> (EFI_MM_COMMUNICATE_HEADER).
> +  @retval EFI_BAD_BUFFER_SIZE     The buffer is too large for the MM 
> implementation.
> +                                  If this error is returned, the 
> MessageLength field
> +                                  in the CommBuffer header or the integer 
> pointed by
> +                                  CommSize, are updated to reflect the 
> maximum payload
> +                                  size the implementation can accommodate.
> +  @retval EFI_ACCESS_DENIED       The CommunicateBuffer parameter or 
> CommSize parameter,
> +                                  if not omitted, are in address range that 
> cannot be
> +                                  accessed by the MM environment.
> +**/
> +EFI_STATUS
> +EFIAPI
> +MmCommunicationPeim (
> +  IN CONST EFI_PEI_MM_COMMUNICATION_PPI  *This,
> +  IN OUT VOID                            *CommBuffer,
> +  IN OUT UINTN                           *CommSize
> +  );
> +
> +#endif /* MM_COMMUNICATION_PEI_H_ */
> diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf 
> b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
> new file mode 100644
> index 000000000000..7a0adbd9bd2f
> --- /dev/null
> +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
> @@ -0,0 +1,41 @@
> +## @file -- MmCommunicationPei.inf
> +#  PEI MM Communicate driver
> +#
> +#  Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
> +#  Copyright (c) Microsoft Corporation.
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001B
> +  BASE_NAME                      = MmCommunicationPei
> +  FILE_GUID                      = 58FFB346-1B75-42C7-AD69-37C652423C1A
> +  MODULE_TYPE                    = PEIM
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = MmCommunicationPeiInitialize
> +
> +[Sources]
> +  MmCommunicationPei.c
> +  MmCommunicationPei.h
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  ArmPkg/ArmPkg.dec
> +
> +[LibraryClasses]
> +  DebugLib
> +  ArmSmcLib
> +  PeimEntryPoint
> +  PeiServicesLib
> +  HobLib
> +
> +[Pcd]
> +  gArmTokenSpaceGuid.PcdMmBufferBase
> +  gArmTokenSpaceGuid.PcdMmBufferSize
> +
> +[Ppis]
> +  gEfiPeiMmCommunicationPpiGuid     ## PRODUCES
> +
> +[Depex]
> +  TRUE
> --
> 2.41.0.windows.1
>


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#106429): https://edk2.groups.io/g/devel/message/106429
Mute This Topic: https://groups.io/mt/99796183/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to