public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "gaoliming" <gaoliming@byosoft.com.cn>
To: <devel@edk2.groups.io>, <bobm@nvidia.com>
Cc: "'Jian J Wang'" <jian.j.wang@intel.com>,
	"'Guomin Jiang'" <guomin.jiang@intel.com>
Subject: 回复: [edk2-devel] [PATCH] MdeModulePkg/DxeCapsuleLibFmp: Add runtime SetImage support
Date: Tue, 2 Nov 2021 09:16:45 +0800	[thread overview]
Message-ID: <002c01d7cf87$4db94100$e92bc300$@byosoft.com.cn> (raw)
In-Reply-To: <DM6PR12MB47793440EE34928A5B995F27AA879@DM6PR12MB4779.namprd12.prod.outlook.com>

Bob:
  Thanks for your detail. PcdRuntimeFmpCapsuleImageTypeIdGuid is edk2 implementation solution. Have you the proposal on how to update UEFI spec to support runtime FMP protocol?

Thanks
Liming
> -----邮件原件-----
> 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Bob Morgan
> via groups.io
> 发送时间: 2021年10月30日 1:59
> 收件人: gaoliming <gaoliming@byosoft.com.cn>; devel@edk2.groups.io
> 抄送: 'Jian J Wang' <jian.j.wang@intel.com>; 'Guomin Jiang'
> <guomin.jiang@intel.com>
> 主题: Re: [edk2-devel] [PATCH] MdeModulePkg/DxeCapsuleLibFmp: Add
> runtime SetImage support
> 
> Hi Liming,  See inline below.
> 
> > -----Original Message-----
> > From: gaoliming <gaoliming@byosoft.com.cn>
> > Sent: Thursday, October 28, 2021 7:57 PM
> > To: devel@edk2.groups.io; Bob Morgan <bobm@nvidia.com>
> > Cc: 'Jian J Wang' <jian.j.wang@intel.com>; 'Guomin Jiang'
> > <guomin.jiang@intel.com>
> > Subject: 回复: [edk2-devel] [PATCH] MdeModulePkg/DxeCapsuleLibFmp:
> > Add runtime SetImage support
> >
> > External email: Use caution opening links or attachments
> >
> >
> > Bob:
> >   I think this patch needs to work together with the changes of
> > FmpDevicePkg: Add support for runtime FmpDxe driver.
> 
> Yes, this patch adds support to process FMP capsules at runtime if the
> capsule’s UpdateImageTypeId is supported by a runtime-capable FmpDxe
> driver (e.g. using the FmpDevicePkg  patch you mentioned).  The
> PcdSupportProcessCapsuleAtRuntime PCD must be TRUE and the capsule’s
> CAPSULE_FLAGS_PERSIST_ACROSS_RESET flag must be FALSE.
> >
> >   Capsule is runtime service. If it consumes FMP to do update, FMP service
> > can support runtime. But, how does Capsule know whether FMP protocol
> > supports runtime or not?
> 
> Right, this patch requires an implementation to list the FMP ImageTypeId
> GUIDs supported by any runtime-capable FmpDxe drivers in the new
> PcdRuntimeFmpCapsuleImageTypeIdGuid array PCD.  This PCD is used by
> the new  InitializeRuntimeFmpArrays() function during
> DxeRuntimeCapsuleLib initialization to find the FMP instances that support
> those ImageTypeIds and save their
> EFI_FIRMWARE_MANAGEMENT_PROTOCOL protocol structure pointers for
> runtime use during capsule processing.
> 
> When ProcessFmpCapsuleImage() executes its step ‘2. Route payload to right
> FMP instance’, it detects runtime execution and uses the saved
> runtime-capable FMP protocol structure pointer if its ImageTypeId matches
> that of the capsule being processed.
> 
> I hope that helps.  Please let me know if additional clarification is needed.
> 
> Thanks,
> -bob
> >
> > Thanks
> > Liming
> > > -----邮件原件-----
> > > 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Bob
> Morgan
> > via
> > > groups.io
> > > 发送时间: 2021年10月20日 4:11
> > > 收件人: devel@edk2.groups.io
> > > 抄送: Bob Morgan <bobm@nvidia.com>; Jian J Wang
> > <jian.j.wang@intel.com>;
> > > Liming Gao <gaoliming@byosoft.com.cn>; Guomin Jiang
> > > <guomin.jiang@intel.com>
> > > 主题: [edk2-devel] [PATCH] MdeModulePkg/DxeCapsuleLibFmp: Add
> > runtime
> > > SetImage support
> > >
> > > Adds optional support for processing FMP capusle images after
> > > ExitBootServices() if the ImageTypeIdGuid is mentioned in the new
> > > PcdRuntimeFmpCapsuleImageTypeIdGuid list.
> > >
> > > Cc: Jian J Wang <jian.j.wang@intel.com>
> > > Cc: Liming Gao <gaoliming@byosoft.com.cn>
> > > Cc: Guomin Jiang <guomin.jiang@intel.com>
> > > Signed-off-by: Bob Morgan <bobm@nvidia.com>
> > > ---
> > >  .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.c  |  81 +++++++++---
> > >  .../DxeCapsuleLibFmp/DxeCapsuleRuntime.c      | 119
> > > ++++++++++++++++++
> > >  .../DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf |   4 +
> > >  MdeModulePkg/MdeModulePkg.dec                 |   7 +-
> > >  4 files changed, 192 insertions(+), 19 deletions(-)
> > >
> > > diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> > > b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> > > index 90942135d7..0000f91c6a 100644
> > > --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> > > +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> > > @@ -10,6 +10,7 @@
> > >    ValidateFmpCapsule(), and DisplayCapsuleImage() receives untrusted
> > > input and
> > >    performs basic validation.
> > >
> > > +  Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.<BR>
> > >    Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
> > >    SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > > @@ -41,6 +42,11 @@
> > >  #include <Protocol/FirmwareManagementProgress.h>
> > >  #include <Protocol/DevicePath.h>
> > >
> > > +BOOLEAN (EFIAPI *mLibAtRuntimeFunction) (VOID)
> =
> > > NULL;
> > > +EFI_FIRMWARE_MANAGEMENT_PROTOCOL    *mRuntimeFmp
> > > = NULL;
> > > +VOID
> **mRuntimeFmpProtocolArray
> > > = NULL;
> > > +EFI_GUID                            *mRuntimeFmpGuidArray
> > > = NULL;
> > > +
> > >  EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable                  =
> NULL;
> > >  BOOLEAN                   mIsVirtualAddrConverted      =
> FALSE;
> > >
> > > @@ -551,6 +557,11 @@ DumpAllFmpInfo (
> > >    UINT32
> PackageVersion;
> > >    CHAR16
> > > *PackageVersionName;
> > >
> > > +  // Dump not supported at runtime.
> > > +  if ((mLibAtRuntimeFunction != NULL) && mLibAtRuntimeFunction ()) {
> > > +    return;
> > > +  }
> > > +
> > >    Status = gBS->LocateHandleBuffer (
> > >                    ByProtocol,
> > >                    &gEfiFirmwareManagementProtocolGuid,
> > > @@ -906,25 +917,35 @@ SetFmpImageData (
> > >    CHAR16
> *AbortReason;
> > >    EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS
> > > ProgressCallback;
> > >
> > > -  Status = gBS->HandleProtocol(
> > > -                  Handle,
> > > -                  &gEfiFirmwareManagementProtocolGuid,
> > > -                  (VOID **)&Fmp
> > > -                  );
> > > -  if (EFI_ERROR(Status)) {
> > > -    return Status;
> > > -  }
> > > +  // If not using optional runtime support, get FMP protocol for
> > > + given
> > > Handle.
> > > +  // Otherwise, use the one saved by ProcessFmpCapsuleImage().
> > > +  if ((mLibAtRuntimeFunction == NULL) || !mLibAtRuntimeFunction ()) {
> > > +    Status = gBS->HandleProtocol(
> > > +                    Handle,
> > > +                    &gEfiFirmwareManagementProtocolGuid,
> > > +                    (VOID **)&Fmp
> > > +                    );
> > > +    if (EFI_ERROR(Status)) {
> > > +      return Status;
> > > +    }
> > >
> > > -  //
> > > -  // Lookup Firmware Management Progress Protocol before SetImage()
> > > is called
> > > -  // This is an optional protocol that may not be present on Handle.
> > > -  //
> > > -  Status = gBS->HandleProtocol (
> > > -                  Handle,
> > > -
> &gEdkiiFirmwareManagementProgressProtocolGuid,
> > > -                  (VOID **)&mFmpProgress
> > > -                  );
> > > -  if (EFI_ERROR (Status)) {
> > > +    //
> > > +    // Lookup Firmware Management Progress Protocol before
> SetImage()
> > > is called
> > > +    // This is an optional protocol that may not be present on Handle.
> > > +    //
> > > +    Status = gBS->HandleProtocol (
> > > +                    Handle,
> > > +
> > > &gEdkiiFirmwareManagementProgressProtocolGuid,
> > > +                    (VOID **)&mFmpProgress
> > > +                    );
> > > +    if (EFI_ERROR (Status)) {
> > > +      mFmpProgress = NULL;
> > > +    }
> > > +  } else {
> > > +    if (mRuntimeFmp == NULL) {
> > > +      return EFI_UNSUPPORTED;
> > > +    }
> > > +    Fmp = mRuntimeFmp;
> > >      mFmpProgress = NULL;
> > >    }
> > >
> > > @@ -1259,6 +1280,30 @@ ProcessFmpCapsuleImage (
> > >        UpdateHardwareInstance =
> > > ImageHeader->UpdateHardwareInstance;
> > >      }
> > >
> > > +    // Optional runtime FMP SetImage processing sequence
> > > +    if ((mLibAtRuntimeFunction != NULL) && mLibAtRuntimeFunction ()
> &&
> > > +        (mRuntimeFmpProtocolArray != NULL)) {
> > > +      mRuntimeFmp = NULL;
> > > +      Index2 = 0;
> > > +      while (mRuntimeFmpProtocolArray[Index2] != NULL) {
> > > +        if (CompareGuid (&ImageHeader->UpdateImageTypeId,
> > > +                         &mRuntimeFmpGuidArray[Index2])) {
> > > +          mRuntimeFmp =
> (EFI_FIRMWARE_MANAGEMENT_PROTOCOL
> > > *)
> > > +            mRuntimeFmpProtocolArray[Index2];
> > > +          break;
> > > +        }
> > > +        Index2++;
> > > +      }
> > > +
> > > +      Status = SetFmpImageData (NULL,
> > > +                                ImageHeader,
> > > +                                Index -
> > > FmpCapsuleHeader->EmbeddedDriverCount);
> > > +      if (EFI_ERROR (Status)) {
> > > +        return Status;
> > > +      }
> > > +      continue;
> > > +    }
> > > +
> > >      Status = GetFmpHandleBufferByType (
> > >                 &ImageHeader->UpdateImageTypeId,
> > >                 UpdateHardwareInstance, diff --git
> > > a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
> > > b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
> > > index f94044a409..6feb6dab79 100644
> > > --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
> > > +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
> > > @@ -1,6 +1,7 @@
> > >  /** @file
> > >    Capsule library runtime support.
> > >
> > > +  Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.<BR>
> > >    Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
> > >    SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > > @@ -19,7 +20,11 @@
> > >  #include <Library/UefiBootServicesTableLib.h>
> > >  #include <Library/UefiRuntimeServicesTableLib.h>
> > >  #include <Library/MemoryAllocationLib.h>
> > > +#include <Library/UefiRuntimeLib.h>
> > >
> > > +extern BOOLEAN                   (EFIAPI
> *mLibAtRuntimeFunction)
> > > (VOID);
> > > +extern VOID                      **mRuntimeFmpProtocolArray;
> > > +extern EFI_GUID                  *mRuntimeFmpGuidArray;
> > >  extern EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable;
> > >  extern BOOLEAN                   mIsVirtualAddrConverted;
> > >  EFI_EVENT
> > > mDxeRuntimeCapsuleLibVirtualAddressChangeEvent  = NULL; @@ -40,9
> > > +45,121 @@ DxeCapsuleLibVirtualAddressChangeEvent (
> > >    )
> > >  {
> > >    gRT->ConvertPointer (EFI_OPTIONAL_PTR, (VOID **)&mEsrtTable);
> > > +
> > > +  if (mRuntimeFmpProtocolArray != NULL) {
> > > +    VOID **FmpArrayEntry;
> > > +
> > > +    FmpArrayEntry = mRuntimeFmpProtocolArray;
> > > +    while (*FmpArrayEntry != NULL) {
> > > +      EfiConvertPointer (0x0, (VOID **) FmpArrayEntry);
> > > +      FmpArrayEntry++;
> > > +    }
> > > +    EfiConvertPointer (0x0, (VOID **)
> &mRuntimeFmpProtocolArray);  }
> > > + if (mRuntimeFmpGuidArray != NULL) {
> > > +    EfiConvertPointer (0x0, (VOID **) &mRuntimeFmpGuidArray);  }
> if
> > > + (mLibAtRuntimeFunction != NULL ) {
> > > +    EfiConvertPointer (0x0, (VOID **) &mLibAtRuntimeFunction);  }
> > > +
> > >    mIsVirtualAddrConverted = TRUE;
> > >  }
> > >
> > > +/**
> > > +  Initialize optional runtime FMP arrays to support FMP SetImage
> > > processing
> > > +  after ExitBootServices() is called.
> > > +
> > > +  The ImageTypeIdGuids of runtime-capable FMP protocol drivers are
> > > extracted
> > > +  from the PcdRuntimeFmpCapsuleImageTypeIdGuid list and their
> > > + protocol  structure pointers are saved in the
> > > + mRuntimeFmpProtocolArray for use
> > > during
> > > +  UpdateCapsule() processing. UpdateHardwareInstance is not
> supported.
> > > +
> > > +**/
> > > +STATIC
> > > +VOID
> > > +EFIAPI
> > > +InitializeRuntimeFmpArrays (
> > > +  VOID
> > > +  )
> > > +{
> > > +  EFI_GUID      *Guid;
> > > +  UINTN         NumHandles;
> > > +  EFI_HANDLE    *HandleBuffer;
> > > +  EFI_STATUS    Status;
> > > +  UINTN         Count;
> > > +  UINTN         Index;
> > > +  UINTN         FmpArrayIndex;
> > > +
> > > +  EFI_STATUS
> > > +    GetFmpHandleBufferByType (
> > > +      IN     EFI_GUID
> *UpdateImageTypeId,
> > > +      IN     UINT64
> > > UpdateHardwareInstance,
> > > +      OUT    UINTN                        *NoHandles,
> > > OPTIONAL
> > > +      OUT    EFI_HANDLE                   **HandleBuf,
> > > OPTIONAL
> > > +      OUT    BOOLEAN
> **ResetRequiredBuf
> > > OPTIONAL
> > > +      );
> > > +
> > > +  Count = PcdGetSize (PcdRuntimeFmpCapsuleImageTypeIdGuid) /
> sizeof
> > > (GUID);
> > > +  if (Count == 0) {
> > > +    return;
> > > +  }
> > > +
> > > +  // mRuntimeFmpProtocolArray is a NULL-terminated list of FMP
> > > + protocol
> > > pointers
> > > +  mRuntimeFmpProtocolArray = (VOID **)
> > > +    AllocateRuntimeZeroPool ((Count + 1) * sizeof (VOID *));  if
> > > + (mRuntimeFmpProtocolArray == NULL) {
> > > +    DEBUG ((DEBUG_ERROR, "Error allocating
> > > mRuntimeFmpProtocolArray\n"));
> > > +    return;
> > > +  }
> > > +  mRuntimeFmpGuidArray = (EFI_GUID *)
> > > +    AllocateRuntimeZeroPool (Count * sizeof (EFI_GUID));  if
> > > + (mRuntimeFmpGuidArray == NULL) {
> > > +    DEBUG ((DEBUG_ERROR, "Error allocating
> mRuntimeFmpGuidArray"));
> > > +    FreePool (mRuntimeFmpProtocolArray);
> > > +    return;
> > > +  }
> > > +
> > > +  // For each runtime ImageTypeIdGuid in the PCD, save its GUID and
> > > + FMP
> > > protocol
> > > +  FmpArrayIndex = 0;
> > > +  Guid  = PcdGetPtr (PcdRuntimeFmpCapsuleImageTypeIdGuid);
> > > +  for (Index = 0; Index < Count; Index++, Guid++) {
> > > +    mRuntimeFmpGuidArray[FmpArrayIndex] = *Guid;
> > > +    HandleBuffer = NULL;
> > > +    Status = GetFmpHandleBufferByType (Guid,
> > > +                                       0,
> > > +                                       &NumHandles,
> > > +                                       &HandleBuffer,
> > > +                                       NULL);
> > > +    if (EFI_ERROR (Status)) {
> > > +      DEBUG ((DEBUG_ERROR,
> > > +              "Error finding FMP handle for runtime
> > > ImageTypeIdGuid=%g: %r\n",
> > > +              Guid, Status));
> > > +      continue;
> > > +    }
> > > +
> > > +    if (NumHandles > 1) {
> > > +      DEBUG ((DEBUG_ERROR,
> > > +              "FMP runtime ImageTypeIdGuid=%g returned %u
> handles,
> > > only 1 supported\n",
> > > +              Guid, NumHandles));
> > > +    }
> > > +    Status = gBS->HandleProtocol (HandleBuffer[0],
> > > +
> > > &gEfiFirmwareManagementProtocolGuid,
> > > +
> > > &mRuntimeFmpProtocolArray[FmpArrayIndex]);
> > > +    FreePool (HandleBuffer);
> > > +    if (EFI_ERROR(Status)) {
> > > +      DEBUG ((DEBUG_ERROR,
> > > +              "Error getting FMP protocol for runtime
> > > ImageTypeIdGuid=%g: %r\n",
> > > +              Guid, Status));
> > > +      continue;
> > > +    }
> > > +
> > > +    FmpArrayIndex++;
> > > +  }
> > > +
> > > +  mLibAtRuntimeFunction = EfiAtRuntime; }
> > > +
> > >  /**
> > >    Notify function for event group
> EFI_EVENT_GROUP_READY_TO_BOOT.
> > >
> > > @@ -93,6 +210,8 @@ DxeCapsuleLibReadyToBootEventNotify (
> > >      //
> > >      mEsrtTable->FwResourceCountMax =
> mEsrtTable->FwResourceCount;
> > >    }
> > > +
> > > +  InitializeRuntimeFmpArrays ();
> > >  }
> > >
> > >  /**
> > > diff --git
> > > a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> > > b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> > > index bf56f4623f..7b3f5e04f8 100644
> > > ---
> > a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> > > +++
> > b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> > > @@ -49,6 +49,7 @@
> > >    PrintLib
> > >    HobLib
> > >    BmpSupportLib
> > > +  PcdLib
> > >
> > >
> > >  [Protocols]
> > > @@ -70,5 +71,8 @@
> > >    gEfiEventVirtualAddressChangeGuid       ## CONSUMES ## Event
> > >    gEdkiiCapsuleOnDiskNameGuid             ##
> > > SOMETIMES_CONSUMES ## GUID
> > >
> > > +[Pcd]
> > > +
> > >
> > gEfiMdeModulePkgTokenSpaceGuid.PcdRuntimeFmpCapsuleImageTypeIdG
> > ui
> > > d
> > > +
> > >  [Depex]
> > >    gEfiVariableWriteArchProtocolGuid
> > > diff --git a/MdeModulePkg/MdeModulePkg.dec
> > > b/MdeModulePkg/MdeModulePkg.dec index 133e04ee86..869aa892f7
> > 100644
> > > --- a/MdeModulePkg/MdeModulePkg.dec
> > > +++ b/MdeModulePkg/MdeModulePkg.dec
> > > @@ -3,7 +3,7 @@
> > >  # It also provides the definitions(including PPIs/PROTOCOLs/GUIDs and
> > > library classes)  # and libraries instances, which are used for those
> > > modules.
> > >  #
> > > -# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
> > > +# Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights
> > > +reserved.<BR>
> > >  # Copyright (c) 2007 - 2021, Intel Corporation. All rights
> > > reserved.<BR>  # Copyright (c) 2016, Linaro Ltd. All rights
> > > reserved.<BR>  # (C) Copyright 2016 - 2019 Hewlett Packard Enterprise
> > > Development LP<BR> @@ -2020,6 +2020,11 @@
> > >    # @Prompt Capsule On Disk Temp Relocation file name in PEI phase
> > >
> > >
> > gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName|L"Cod.tmp
> > "|
> > > VOID*|0x30001048
> > >
> > > +  ## This PCD holds a list of GUIDs for the ImageTypeId to indicate
> > > + the  #  FMP is runtime capable.
> > > +  # @Prompt A list of runtime-capable FMP ImageTypeId GUIDs
> > > +
> > >
> > gEfiMdeModulePkgTokenSpaceGuid.PcdRuntimeFmpCapsuleImageTypeIdG
> > ui
> > > d|{0x0}|VOID*|0x30001049
> > > +
> > >    ## This PCD hold a list GUIDs for the ImageTypeId to indicate the
> > >    #  FMP capsule is a system FMP.
> > >    # @Prompt A list of system FMP ImageTypeId GUIDs
> > > --
> > > 2.17.1
> > >
> > >
> > >
> > >
> > >
> >
> >
> 
> 
> 
> 
> 




  reply	other threads:[~2021-11-02  1:16 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-19 20:10 [PATCH] MdeModulePkg/DxeCapsuleLibFmp: Add runtime SetImage support Bob Morgan
2021-10-29  1:57 ` 回复: [edk2-devel] " gaoliming
2021-10-29 17:58   ` Bob Morgan
2021-11-02  1:16     ` gaoliming [this message]
2021-11-04 22:53       ` Bob Morgan
2021-11-05  5:45         ` 回复: " gaoliming
2021-11-09 23:05           ` Bob Morgan

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='002c01d7cf87$4db94100$e92bc300$@byosoft.com.cn' \
    --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