public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Chang, Abner via groups.io" <abner.chang=amd.com@groups.io>
To: "Attar, AbdulLateef (Abdul Lateef)" <AbdulLateef.Attar@amd.com>,
	"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Attar, AbdulLateef (Abdul Lateef)" <AbdulLateef.Attar@amd.com>,
	"Grimes, Paul" <Paul.Grimes@amd.com>
Subject: Re: [edk2-devel] [edk2-platforms 3/3] AmdPlatformPkg: Adds SPI smm core platform hook
Date: Wed, 29 May 2024 08:57:07 +0000	[thread overview]
Message-ID: <LV8PR12MB9452AEBF1DE7E6DCF074AB6AEAF22@LV8PR12MB9452.namprd12.prod.outlook.com> (raw)
In-Reply-To: <34726328bd35e35c1c8ac4953d98bc71099a7f10.1716905162.git.AbdulLateef.Attar@amd.com>

[AMD Official Use Only - AMD Internal Distribution Only]

Reviewed-by: Abner Chang <abner.chang@amd.com>

> -----Original Message-----
> From: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>
> Sent: Tuesday, May 28, 2024 10:08 PM
> To: devel@edk2.groups.io
> Cc: Attar, AbdulLateef (Abdul Lateef) <AbdulLateef.Attar@amd.com>; Chang,
> Abner <Abner.Chang@amd.com>; Grimes, Paul <Paul.Grimes@amd.com>
> Subject: [edk2-platforms 3/3] AmdPlatformPkg: Adds SPI smm core platform
> hook
>
> Register a smm core platform hook handler for SPI device,
> using AMD SmmCorePlatformHookLib library.
>
> This platform hook saves the SPI host controller state.
>
> Cc: Abner Chang <abner.chang@amd.com>
> Cc: Paul Grimes <paul.grimes@amd.com>
> Signed-off-by: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>
> ---
>  .../AMD/AmdPlatformPkg/AmdPlatformPkg.dec     |   3 +
>  .../AMD/AmdPlatformPkg/AmdPlatformPkg.dsc     |   2 +
>  .../Include/Protocol/AmdSpiSmmHcState.h       | 107 +++++++++++++
>  .../SmmCoreAmdSpiHcHookLib.c                  | 145 ++++++++++++++++++
>  .../SmmCoreAmdSpiHcHookLib.h                  |  20 +++
>  .../SmmCoreAmdSpiHcHookLib.inf                |  41 +++++
>  .../SmmCoreAmdSpiHcHookLib.uni                |  11 ++
>  7 files changed, 329 insertions(+)
>  create mode 100644
> Platform/AMD/AmdPlatformPkg/Include/Protocol/AmdSpiSmmHcState.h
>  create mode 100644
> Platform/AMD/AmdPlatformPkg/Library/SmmCoreAmdSpiHcHookLib/SmmC
> oreAmdSpiHcHookLib.c
>  create mode 100644
> Platform/AMD/AmdPlatformPkg/Library/SmmCoreAmdSpiHcHookLib/SmmC
> oreAmdSpiHcHookLib.h
>  create mode 100644
> Platform/AMD/AmdPlatformPkg/Library/SmmCoreAmdSpiHcHookLib/SmmC
> oreAmdSpiHcHookLib.inf
>  create mode 100644
> Platform/AMD/AmdPlatformPkg/Library/SmmCoreAmdSpiHcHookLib/SmmC
> oreAmdSpiHcHookLib.uni
>
> diff --git a/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dec
> b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dec
> index 3020e628a3..907c5b9b74 100644
> --- a/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dec
> +++ b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dec
> @@ -29,6 +29,9 @@
>  [Guids]
>    gAmdPlatformPkgTokenSpaceGuid   = { 0x663DE733, 0x70E0, 0x4D37,
> { 0xBB, 0x30, 0x7D, 0x9E, 0xAF, 0x9B, 0xDA, 0xE9 }}
>
> +[Protocols]
> +  gAmdSpiHcStateProtocolGuid      = { 0x189566ab, 0x245, 0x43ae, {0x9d,
> 0x1, 0xd2, 0x21, 0x1c, 0xb9, 0x1a, 0xda }}
> +
>  [PcdsDynamic]
>    ## Event GUID to trigger logo displaying
>    #  Default set to
> gMinPlatformPkgTokenSpaceGuid.gBdsEventAfterConsoleReadyBeforeBootO
> ptionGuid
> diff --git a/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc
> b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc
> index 482e6f2f30..012270074d 100644
> --- a/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc
> +++ b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc
> @@ -64,6 +64,7 @@
>
>  [LibraryClasses.common.SMM_CORE]
>
> SmmCorePlatformHookLib|AmdPlatformPkg/Library/SmmCorePlatformHook
> Lib/SmmCorePlatformHookLib.inf
> +
> SmmCoreAmdSpiHcHookLib|AmdPlatformPkg/Library/SmmCoreAmdSpiHcH
> ookLib/SmmCoreAmdSpiHcHookLib.inf
>
>  [Components]
>
> AmdPlatformPkg/Library/BaseAlwaysFalseDepexLib/BaseAlwaysFalseDepexLi
> b.inf
> @@ -79,3 +80,4 @@
>
>  [Components.common.SMM_CORE]
>
> AmdPlatformPkg/Library/SmmCorePlatformHookLib/SmmCorePlatformHook
> Lib.inf
> +
> AmdPlatformPkg/Library/SmmCoreAmdSpiHcHookLib/SmmCoreAmdSpiHcH
> ookLib.inf
> diff --git
> a/Platform/AMD/AmdPlatformPkg/Include/Protocol/AmdSpiSmmHcState.h
> b/Platform/AMD/AmdPlatformPkg/Include/Protocol/AmdSpiSmmHcState.h
> new file mode 100644
> index 0000000000..0e2bccb3ef
> --- /dev/null
> +++
> b/Platform/AMD/AmdPlatformPkg/Include/Protocol/AmdSpiSmmHcState.h
> @@ -0,0 +1,107 @@
> +/** @file
> +  Header file of AMD SMM SPI host controller state protocol
> +
> +  Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef AMD_SMM_SPI_HC_STATE_PROTOCOL_H_
> +#define AMD_SMM_SPI_HC_STATE_PROTOCOL_H_
> +
> +typedef struct _SMM_EFI_SPI_HC_STATE_PROTOCOL
> SMM_EFI_SPI_HC_STATE_PROTOCOL;
> +
> +/**
> +  Save/Restore the state of the SPI Host Controller
> +
> +  Use a chipset specific method to save the state of the SPI Host controller so
> +  it can be used without disturbing other transactions.
> +
> +  @param[in] This           Pointer to an SMM_EFI_SPI_HC_STATE_PROTOCOL
> structure.
> +
> +  @retval EFI_SUCCESS            The State was saved successfully
> +  @retval DEVICE_ERROR           SPI Executes command failed
> +
> +**/
> +typedef EFI_STATUS
> +(EFIAPI *SMM_SPI_HC_STATE)(
> +  IN CONST SMM_EFI_SPI_HC_STATE_PROTOCOL  *This
> +  );
> +
> +/**
> +  Lock/Unlock the SPI host controller register
> +
> +  Use a chipset specific method to lock or unlock SPI host controller register.
> +
> +  @param[in] This           Pointer to an SMM_EFI_SPI_HC_STATE_PROTOCOL
> structure.
> +
> +  @retval EFI_SUCCESS      The clock was set up successfully
> +  @retval DEVICE_ERROR     SPI Executes command failed
> +
> +
> +**/
> +typedef EFI_STATUS
> +(EFIAPI *SMM_SPI_HC_LOCK_UNLOCK)(
> +  IN CONST SMM_EFI_SPI_HC_STATE_PROTOCOL  *This
> +  );
> +
> +/**
> +  Block/Unblock SPI opcode
> +
> +  Use a chipset specific method to block and unclock specific SPI opcode.
> +
> +  @param[in] This           Pointer to an SMM_EFI_SPI_HC_STATE_PROTOCOL
> structure.
> +
> +  @retval EFI_SUCCESS      The clock was set up successfully
> +  @retval DEVICE_ERROR     SPI Executes command failed
> +
> +**/
> +typedef EFI_STATUS
> +(EFIAPI *SMM_SPI_HC_BLOCK_UNBLOCK_OPCODE)(
> +  IN CONST SMM_EFI_SPI_HC_STATE_PROTOCOL  *This,
> +  IN UINT8 Opcode
> +  );
> +
> +/**
> +  Block/Unblock any SPI opcodes
> +
> +  Use a chipset specific method to block and unclock all SPI opcodes.
> +
> +  @param[in] This           Pointer to an SMM_EFI_SPI_HC_STATE_PROTOCOL
> structure.
> +
> +  @retval EFI_SUCCESS      The clock was set up successfully
> +  @retval DEVICE_ERROR     SPI Executes command failed
> +
> +**/
> +typedef EFI_STATUS
> +(EFIAPI *SMM_SPI_HC_BLOCK_UNBLOCK_ALL_OPCODES)(
> +  IN CONST SMM_EFI_SPI_HC_STATE_PROTOCOL  *This
> +  );
> +
> +///
> +/// Manage and control the SPI host controller state.
> +///
> +struct _SMM_EFI_SPI_HC_STATE_PROTOCOL {
> +  ///
> +  /// Save and Restore SPI host controller state.
> +  ///
> +  SMM_SPI_HC_STATE                        SaveState;
> +  SMM_SPI_HC_STATE                        RestoreState;
> +
> +  ///
> +  /// Lock and Unlock SPI host controller registers
> +  ///
> +  SMM_SPI_HC_LOCK_UNLOCK                  Lock;
> +  SMM_SPI_HC_LOCK_UNLOCK                  Unlock;
> +
> +  ///
> +  /// Block and Unblock SPI Opcode
> +  ///
> +  SMM_SPI_HC_BLOCK_UNBLOCK_OPCODE         BlockOpcode;
> +  SMM_SPI_HC_BLOCK_UNBLOCK_OPCODE         UnblockOpcode;
> +  SMM_SPI_HC_BLOCK_UNBLOCK_ALL_OPCODES    UnblockAllOpcodes;
> +};
> +
> +extern EFI_GUID  gAmdSpiHcStateProtocolGuid;
> +
> +#endif // AMD_SMM_SPI_HC_STATE_PROTOCOL_H__
> diff --git
> a/Platform/AMD/AmdPlatformPkg/Library/SmmCoreAmdSpiHcHookLib/Smm
> CoreAmdSpiHcHookLib.c
> b/Platform/AMD/AmdPlatformPkg/Library/SmmCoreAmdSpiHcHookLib/Sm
> mCoreAmdSpiHcHookLib.c
> new file mode 100644
> index 0000000000..4284f13a5e
> --- /dev/null
> +++
> b/Platform/AMD/AmdPlatformPkg/Library/SmmCoreAmdSpiHcHookLib/Sm
> mCoreAmdSpiHcHookLib.c
> @@ -0,0 +1,145 @@
> +/** @file
> +  SMM core hook for AMD SPI Host Controller State
> +
> +  Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +#include <PiSmm.h>
> +#include <Library/SmmServicesTableLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Protocol/AmdSpiSmmHcState.h>
> +
> +#include <Library/AmdSmmCorePlatformHookLib.h>
> +#include "SmmCoreAmdSpiHcHookLib.h"
> +
> +VOID  *mSmmCorePlatformHookHcStateRegistration = NULL;
> +
> +SMM_CORE_HOOK_AMD_SPI_HC_STATE_CONTEXT
> mSmmCorePlatformHookContext;
> +
> +/**
> +  Performs platform specific tasks before invoking registered SMI handlers.
> +
> +  This function performs platform specific tasks before invoking registered
> SMI handlers.
> +
> +  @retval EFI_SUCCESS       The platform hook completes successfully.
> +  @retval Other values      The platform hook cannot complete due to some
> error.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SmmCoreSpiHcHookBeforeSmmDispatch (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                     Status;
> +  SMM_EFI_SPI_HC_STATE_PROTOCOL  *SpiHcState;
> +
> +  Status     = EFI_SUCCESS;
> +  SpiHcState = mSmmCorePlatformHookContext.SmmSpiHcStateInterface;
> +  if (SpiHcState != NULL) {
> +    Status = SpiHcState->SaveState (SpiHcState);
> +    // Open up SPI HC for SMM, Restore state will automatically return back to
> +    // state on SMM entry
> +    Status = SpiHcState->Unlock (SpiHcState);
> +    Status = SpiHcState->UnblockAllOpcodes (SpiHcState);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Performs platform specific tasks after invoking registered SMI handlers.
> +
> +  This function performs platform specific tasks after invoking registered SMI
> handlers.
> +
> +  @retval EFI_SUCCESS       The platform hook completes successfully.
> +  @retval Other values      The platform hook cannot complete due to some
> error.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SmmCoreSpiHcHookAfterSmmDispatch (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                     Status;
> +  SMM_EFI_SPI_HC_STATE_PROTOCOL  *SpiHcState;
> +
> +  Status     = EFI_SUCCESS;
> +  SpiHcState = mSmmCorePlatformHookContext.SmmSpiHcStateInterface;
> +  if (SpiHcState != NULL) {
> +    Status = SpiHcState->RestoreState (SpiHcState);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Notification for SMM ReadyToLock protocol.
> +
> +  @param[in] Protocol   Points to the protocol's unique identifier.
> +  @param[in] Interface  Points to the interface instance.
> +  @param[in] Handle     The handle on which the interface was installed.
> +
> +  @retval EFI_SUCCESS   Notification runs successfully.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SmmCorePlatformHookHcStateNotify (
> +  IN CONST EFI_GUID  *Protocol,
> +  IN VOID            *Interface,
> +  IN EFI_HANDLE      Handle
> +  )
> +{
> +  mSmmCorePlatformHookContext.SmmSpiHcStateInterface = Interface;
> +  mSmmCorePlatformHookContext.SmmSpiHcStateHandle    = Handle;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Constructor for SmmLockBox library.
> +  This is used to set SmmLockBox context, which will be used in PEI phase in
> S3 boot path later.
> +
> +  @param[in] ImageHandle  Image handle of this driver.
> +  @param[in] SystemTable  A Pointer to the EFI System Table.
> +
> +  @retval EFI_SUCCESS
> +  @return Others          Some error occurs.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SmmCoreAmdSpiHcHookConstructor (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  SetMem (
> +    &mSmmCorePlatformHookContext,
> +    sizeof (mSmmCorePlatformHookContext),
> +    0
> +    );
> +  //
> +  // Register gAmdSpiHcStateProtocolGuid notification.
> +  //
> +  Status = gSmst->SmmRegisterProtocolNotify (
> +                    &gAmdSpiHcStateProtocolGuid,
> +                    SmmCorePlatformHookHcStateNotify,
> +                    &mSmmCorePlatformHookHcStateRegistration
> +                    );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Register AMD SMM Dispatcher hook instance.
> +  //
> +  Status = RegisterSmmDispatcherHook (
> +             SmmCoreSpiHcHookBeforeSmmDispatch,
> +             SmmCoreSpiHcHookAfterSmmDispatch,
> +             0
> +             );
> +  return Status;
> +}
> diff --git
> a/Platform/AMD/AmdPlatformPkg/Library/SmmCoreAmdSpiHcHookLib/Smm
> CoreAmdSpiHcHookLib.h
> b/Platform/AMD/AmdPlatformPkg/Library/SmmCoreAmdSpiHcHookLib/Sm
> mCoreAmdSpiHcHookLib.h
> new file mode 100644
> index 0000000000..8a5dfe623c
> --- /dev/null
> +++
> b/Platform/AMD/AmdPlatformPkg/Library/SmmCoreAmdSpiHcHookLib/Sm
> mCoreAmdSpiHcHookLib.h
> @@ -0,0 +1,20 @@
> +/** @file
> +  Header file of SMM core platform hook for AMD SPI Host Controller state
> library
> +
> +  Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef SMM_CORE_AMD_SPI_HC_HOOK_LIB_H_
> +#define SMM_CORE_AMD_SPI_HC_HOOK_LIB_H_
> +
> +///
> +/// Structure of AMD SPI HC State record
> +///
> +typedef struct {
> +  VOID          *SmmSpiHcStateInterface; ///< AMD SMM SPI HC State Protocol
> Interface
> +  EFI_HANDLE    SmmSpiHcStateHandle;     ///< Handle of MD SMM SPI HC
> State Protocol handle
> +} SMM_CORE_HOOK_AMD_SPI_HC_STATE_CONTEXT;
> +
> +#endif // SMM_CORE_AMD_SPI_HC_HOOK_LIB_H_
> diff --git
> a/Platform/AMD/AmdPlatformPkg/Library/SmmCoreAmdSpiHcHookLib/Smm
> CoreAmdSpiHcHookLib.inf
> b/Platform/AMD/AmdPlatformPkg/Library/SmmCoreAmdSpiHcHookLib/Sm
> mCoreAmdSpiHcHookLib.inf
> new file mode 100644
> index 0000000000..9855aa8543
> --- /dev/null
> +++
> b/Platform/AMD/AmdPlatformPkg/Library/SmmCoreAmdSpiHcHookLib/Sm
> mCoreAmdSpiHcHookLib.inf
> @@ -0,0 +1,41 @@
> +## @file
> +#  INF of SMM Core AMD SPI Host Contoller State hook library.
> +#
> +#  Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +##
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = SmmCoreAmdSpiHcHookLib
> +  MODULE_UNI_FILE                = SmmCoreAmdSpiHcHookLib.uni
> +  FILE_GUID                      = 65D0E2A5-C8C6-4DEE-8FD0-5A006A49E9B7
> +  MODULE_TYPE                    = SMM_CORE
> +  VERSION_STRING                 = 1.0
> +  PI_SPECIFICATION_VERSION       = 0x0001000A
> +  LIBRARY_CLASS                  = SmmCoreAmdSpiHcHookLib|SMM_CORE
> +  CONSTRUCTOR                    = SmmCoreAmdSpiHcHookConstructor
> +
> +#
> +# The following information is for reference only and not required by the build
> tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  SmmCoreAmdSpiHcHookLib.c
> +  SmmCoreAmdSpiHcHookLib.h
> +
> +[Packages]
> +  AmdPlatformPkg/AmdPlatformPkg.dec
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  SmmServicesTableLib
> +  BaseLib
> +  DebugLib
> +  BaseMemoryLib
> +
> +[Protocols]
> +  gAmdSpiHcStateProtocolGuid
> diff --git
> a/Platform/AMD/AmdPlatformPkg/Library/SmmCoreAmdSpiHcHookLib/Smm
> CoreAmdSpiHcHookLib.uni
> b/Platform/AMD/AmdPlatformPkg/Library/SmmCoreAmdSpiHcHookLib/Sm
> mCoreAmdSpiHcHookLib.uni
> new file mode 100644
> index 0000000000..0a73c4acb4
> --- /dev/null
> +++
> b/Platform/AMD/AmdPlatformPkg/Library/SmmCoreAmdSpiHcHookLib/Sm
> mCoreAmdSpiHcHookLib.uni
> @@ -0,0 +1,11 @@
> +## @file
> +#  UNI file of SMM Core AMD SPI Host Controller State hook library module
> +#
> +#  Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +##
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "SMM Core AMD
> SPI HC State Hook Library instance"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "SMM Core AMD
> SPI Host Controller Hook Library instance"
> --
> 2.34.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#119334): https://edk2.groups.io/g/devel/message/119334
Mute This Topic: https://groups.io/mt/106349079/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



      reply	other threads:[~2024-05-29  8:57 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-28 14:07 [edk2-devel] [edk2-platforms 0/3] AmdPlatformPkg: SmbiosDxe and SPI supporting libraries Abdul Lateef Attar via groups.io
2024-05-28 14:07 ` [edk2-devel] [edk2-platforms 1/3] AmdPlatformPkg: Removes unused gBoardBdsBootFromDevicePathProtocolGuid Abdul Lateef Attar via groups.io
2024-05-29  8:56   ` Chang, Abner via groups.io
2024-05-28 14:07 ` [edk2-devel] [edk2-platforms 2/3] AmdPlatformPkg: Implements SmmCorePlatformHookLib library Abdul Lateef Attar via groups.io
2024-05-29  8:57   ` Chang, Abner via groups.io
2024-05-28 14:07 ` [edk2-devel] [edk2-platforms 3/3] AmdPlatformPkg: Adds SPI smm core platform hook Abdul Lateef Attar via groups.io
2024-05-29  8:57   ` Chang, Abner via groups.io [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=LV8PR12MB9452AEBF1DE7E6DCF074AB6AEAF22@LV8PR12MB9452.namprd12.prod.outlook.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox