public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Marcello Sylvester Bauer" <marcello.bauer@9elements.com>
To: devel@edk2.groups.io
Cc: Patrick Rudolph <patrick.rudolph@9elements.com>,
	Christian Walter <christian.walter@9elements.com>,
	Maurice Ma <maurice.ma@intel.com>,
	Nate DeSimone <nathaniel.l.desimone@intel.com>,
	Star Zeng <star.zeng@intel.com>
Subject: [PATCH v2 2/2] UefiPayloadPkg: Scan for Option ROMs
Date: Tue, 15 Sep 2020 14:26:16 +0200	[thread overview]
Message-ID: <20200915122616.17196-3-marcello.bauer@9elements.com> (raw)
In-Reply-To: <20200915122616.17196-1-marcello.bauer@9elements.com>

From: Patrick Rudolph <patrick.rudolph@9elements.com>

Install the gPciPlatformProtocol to scan for Option ROMs.

For every device we probe the Option ROM and provide a pointer
to the activated BAR if found.

It's safe to assume that all ROM bars have been enumerated,
reserved in the bridge resources and are disabled by default.

Enabling them and leaving them enabled will do no harm.

Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Signed-off-by: Marcello Sylvester Bauer <marcello.bauer@9elements.com>
Cc: Patrick Rudolph <patrick.rudolph@9elements.com>
Cc: Christian Walter <christian.walter@9elements.com>
Cc: Maurice Ma <maurice.ma@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
---
 UefiPayloadPkg/UefiPayloadPkgIa32.dsc            |   1 +
 UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc         |   1 +
 UefiPayloadPkg/UefiPayloadPkg.fdf                |   1 +
 UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf |  46 +++
 UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.h   |  19 +
 UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.c   | 426 ++++++++++++++++++++
 6 files changed, 494 insertions(+)

diff --git a/UefiPayloadPkg/UefiPayloadPkgIa32.dsc b/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
index 12d7ffe81416..9f42d2cd6b74 100644
--- a/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
@@ -513,6 +513,7 @@ [Components.IA32]
   MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
 !endif
   UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf
+  UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf
 
   #------------------------------
   #  Build the shell
diff --git a/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc b/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
index 9bae1daa09bb..59fc1b79457b 100644
--- a/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
@@ -514,6 +514,7 @@ [Components.X64]
   MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
 !endif
   UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf
+  UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf
 
   #------------------------------
   #  Build the shell
diff --git a/UefiPayloadPkg/UefiPayloadPkg.fdf b/UefiPayloadPkg/UefiPayloadPkg.fdf
index 570a8ee7fdc1..9b188724221d 100644
--- a/UefiPayloadPkg/UefiPayloadPkg.fdf
+++ b/UefiPayloadPkg/UefiPayloadPkg.fdf
@@ -151,6 +151,7 @@ [FV.DXEFV]
 INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
 !endif
 INF UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf
+INF UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf
 
 #
 # SCSI/ATA/IDE/DISK Support
diff --git a/UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf b/UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf
new file mode 100644
index 000000000000..96cedad5afc3
--- /dev/null
+++ b/UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf
@@ -0,0 +1,46 @@
+## @file
+# This driver produces gEfiPciPlatform protocol to load PCI Option ROMs
+#
+# Copyright (c) 2020, 9elements Agency GmbH
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PciPlatformDxe
+  FILE_GUID                      = 86D58F7B-6E7C-401F-BDD4-E32E6D582AAD
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = InstallPciPlatformProtocol
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources.common]
+  PciPlatformDxe.h
+  PciPlatformDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  DxeServicesTableLib
+  DebugLib
+  MemoryAllocationLib
+  BaseMemoryLib
+  DevicePathLib
+  UefiLib
+  HobLib
+
+[Protocols]
+  gEfiPciPlatformProtocolGuid                   ## PRODUCES
+  gEfiPciIoProtocolGuid                         ## COMSUMES
diff --git a/UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.h b/UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.h
new file mode 100644
index 000000000000..c40518c703f8
--- /dev/null
+++ b/UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.h
@@ -0,0 +1,19 @@
+/** @file
+  Header file for a PCI platform driver.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+#ifndef _PCI_PLATFORM_DXE_H_
+#define _PCI_PLATFORM_DXE_H_
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Pci22.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/PciPlatform.h>
+
+#endif
diff --git a/UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.c b/UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.c
new file mode 100644
index 000000000000..65a1ba967314
--- /dev/null
+++ b/UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.c
@@ -0,0 +1,426 @@
+/** @file
+  This driver will probe for the Option Rom and provide a pointer to
+  the activated BAR if found.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+
+#include "PciPlatformDxe.h"
+#include <Bus/Pci/PciBusDxe/PciBus.h>
+#include <Bus/Pci/PciBusDxe/PciOptionRomSupport.h>
+
+//
+// The driver should only start on one graphics controller.
+// So a global flag is used to remember that the driver is already started.
+//
+EFI_HANDLE      mDriverHandle = NULL;
+
+/**
+  The notification from the PCI bus enumerator to the platform that it is
+  about to enter a certain phase during the enumeration process.
+
+  @param[in] This           The pointer to the EFI_PCI_PLATFORM_PROTOCOL instance.
+  @param[in] HostBridge     The handle of the host bridge controller.
+  @param[in] Phase          The phase of the PCI bus enumeration.
+  @param[in] ExecPhase      Defines the execution phase of the PCI chipset driver.
+
+  @retval EFI_SUCCESS   The function completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PciPlatformNotify(
+  IN EFI_PCI_PLATFORM_PROTOCOL                      *This,
+  IN EFI_HANDLE                                     HostBridge,
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE  Phase,
+  IN EFI_PCI_EXECUTION_PHASE                        ExecPhase
+  )
+{
+  return EFI_SUCCESS;
+}
+
+
+/**
+  The notification from the PCI bus enumerator to the platform for each PCI
+  controller at several predefined points during PCI controller initialization.
+
+  @param[in] This           The pointer to the EFI_PCI_PLATFORM_PROTOCOL instance.
+  @param[in] HostBridge     The associated PCI host bridge handle.
+  @param[in] RootBridge     The associated PCI root bridge handle.
+  @param[in] PciAddress     The address of the PCI device on the PCI bus.
+  @param[in] Phase          The phase of the PCI controller enumeration.
+  @param[in] ExecPhase      Defines the execution phase of the PCI chipset driver.
+
+  @retval EFI_SUCCESS   The function completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PciPlatformPrepController(
+  IN EFI_PCI_PLATFORM_PROTOCOL                     *This,
+  IN EFI_HANDLE                                    HostBridge,
+  IN EFI_HANDLE                                    RootBridge,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS   PciAddress,
+  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE  Phase,
+  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  Gets the PCI device's option ROM.
+
+  @param[in]  This        The pointer to the EFI_PCI_PLATFORM_PROTOCOL instance.
+  @param[in]  PciHandle   The handle of the PCI device.
+  @param[out] RomImage    If the call succeeds, the pointer to the pointer to the option ROM image.
+                          Otherwise, this field is undefined. The memory for RomImage is allocated
+                          by EFI_PCI_PLATFORM_PROTOCOL.GetPciRom() using the EFI Boot Service AllocatePool().
+                          It is the caller's responsibility to free the memory using the EFI Boot Service
+                          FreePool(), when the caller is done with the option ROM.
+  @param[out] RomSize     If the call succeeds, a pointer to the size of the option ROM size. Otherwise,
+                          this field is undefined.
+
+  @retval EFI_SUCCESS            The option ROM was available for this device and loaded into memory.
+  @retval EFI_NOT_FOUND          No option ROM was available for this device.
+  @retval EFI_OUT_OF_RESOURCES   No memory was available to load the option ROM.
+  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the option ROM.
+
+**/
+EFI_STATUS
+EFIAPI
+PciGetPciRom (
+  IN  CONST EFI_PCI_PLATFORM_PROTOCOL  *This,
+  IN        EFI_HANDLE                 PciHandle,
+  OUT       VOID                       **RomImage,
+  OUT       UINTN                      *RomSize
+  )
+{
+  EFI_STATUS                           Status;
+  IN EFI_PCI_IO_PROTOCOL               *PciIo;
+  UINTN                                PciSegment;
+  UINTN                                PciBus;
+  UINTN                                PciDevice;
+  UINTN                                PciFunction;
+  UINTN                                RomBarIndex;
+  UINT32                               Buffer;
+  UINT32                               AllOnes;
+  PCI_IO_DEVICE                        *PciIoDevice;
+  UINT8                                Indicator;
+  UINT16                               OffsetPcir;
+  UINT32                               RomBarOffset;
+  UINT32                               RomBar;
+  BOOLEAN                              FirstCheck;
+  PCI_EXPANSION_ROM_HEADER             *RomHeader;
+  PCI_DATA_STRUCTURE                   *RomPcir;
+  UINT64                               RomImageSize;
+  UINT32                               LegacyImageLength;
+  UINT8                                *RomInMemory;
+  UINT8                                CodeType;
+
+  if (!RomImage || !RomSize) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *RomImage = NULL;
+  *RomSize = 0;
+
+  Status = gBS->HandleProtocol (
+                  PciHandle,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &PciIo
+                  );
+  if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_INFO, "%a: Failed to open gEfiPciIoProtocolGuid\n", __FUNCTION__));
+
+    return EFI_UNSUPPORTED;
+  }
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
+
+  //
+  // Get the location of the PCI device
+  //
+  PciIo->GetLocation (
+           PciIo,
+           &PciSegment,
+           &PciBus,
+           &PciDevice,
+           &PciFunction
+           );
+
+  DEBUG ((DEBUG_INFO, "%a: Searching Option ROM on device:\n", __FUNCTION__));
+  DEBUG ((DEBUG_INFO, " PciSegment         - %02x\n", PciSegment));
+  DEBUG ((DEBUG_INFO, " PciBus             - %02x\n", PciBus));
+  DEBUG ((DEBUG_INFO, " PciDevice          - %02x\n", PciDevice));
+  DEBUG ((DEBUG_INFO, " PciFunction        - %02x\n", PciFunction));
+
+  //
+  // Offset is 0x30 if is not ppb
+  //
+  RomBarIndex = PCI_EXPANSION_ROM_BASE;
+
+  if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
+    //
+    // If is ppb, 0x38
+    //
+    RomBarIndex = PCI_BRIDGE_ROMBAR;
+  }
+
+  //
+  // Backup BAR
+  //
+  Status = PciIo->Pci.Read (
+                          PciIo,
+                          EfiPciWidthUint32,
+                          RomBarIndex,
+                          1,
+                          &Buffer
+                          );
+  if (EFI_ERROR (Status)) {
+    goto CloseAndReturn;
+    return Status;
+  }
+
+  //
+  // The bit0 is 0 to prevent the enabling of the Rom address decoder
+  //
+  AllOnes = 0xfffffffe;
+
+  Status = PciIo->Pci.Write (
+                            PciIo,
+                            EfiPciWidthUint32,
+                            RomBarIndex,
+                            1,
+                            &AllOnes
+                            );
+  if (EFI_ERROR (Status)) {
+    goto CloseAndReturn;
+  }
+
+  //
+  // Read back
+  //
+  Status = PciIo->Pci.Read(
+                          PciIo,
+                          EfiPciWidthUint32,
+                          RomBarIndex,
+                          1,
+                          &AllOnes
+                          );
+  if (EFI_ERROR (Status)) {
+    goto CloseAndReturn;
+  }
+
+  //
+  // Bits [1, 10] are reserved
+  //
+  AllOnes &= 0xFFFFF800;
+  if ((AllOnes == 0) || (AllOnes == 0xFFFFF800)) {
+    DEBUG ((DEBUG_INFO, "%a: No Option ROM found\n", __FUNCTION__));
+    return EFI_NOT_FOUND;
+  }
+
+  *RomSize = (~AllOnes) + 1;
+
+  DEBUG ((DEBUG_INFO, "%a: Option ROM with size %d\n", __FUNCTION__, *RomSize));
+
+  //
+  // Restore BAR and enable it
+  //
+  Buffer |= 1;
+  Status = PciIo->Pci.Write (
+                            PciIo,
+                            EfiPciWidthUint32,
+                            RomBarIndex,
+                            1,
+                            &Buffer
+                            );
+  if (EFI_ERROR (Status)) {
+    goto CloseAndReturn;
+  }
+
+  //
+  // Allocate memory for Rom header and PCIR
+  //
+  RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER));
+  if (RomHeader == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto CloseAndReturn;
+  }
+
+  RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));
+  if (RomPcir == NULL) {
+    FreePool (RomHeader);
+    Status = EFI_OUT_OF_RESOURCES;
+    goto CloseAndReturn;
+  }
+
+  // FIXME: Use gEfiPciRootBridgeIoProtocolGuid
+  RomBar = (UINT32) Buffer &~1;
+
+  RomBarOffset  = RomBar;
+  FirstCheck    = TRUE;
+  LegacyImageLength = 0;
+  RomImageSize = 0;
+
+  do {
+    // FIXME: Use gEfiPciRootBridgeIoProtocolGuid
+    CopyMem(RomHeader, (VOID *)(UINTN)RomBarOffset, sizeof (PCI_EXPANSION_ROM_HEADER));
+
+    DEBUG ((DEBUG_INFO, "%a: RomHeader->Signature %x\n", __FUNCTION__, RomHeader->Signature));
+
+    if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
+
+      RomBarOffset = RomBarOffset + 512;
+      if (FirstCheck) {
+        break;
+      } else {
+        RomImageSize = RomImageSize + 512;
+        continue;
+      }
+    }
+
+    FirstCheck  = FALSE;
+    OffsetPcir  = RomHeader->PcirOffset;
+    //
+    // If the pointer to the PCI Data Structure is invalid, no further images can be located.
+    // The PCI Data Structure must be DWORD aligned.
+    //
+    if (OffsetPcir == 0 ||
+        (OffsetPcir & 3) != 0 ||
+        RomImageSize + OffsetPcir + sizeof (PCI_DATA_STRUCTURE) > *RomSize) {
+      break;
+    }
+    // FIXME: Use gEfiPciRootBridgeIoProtocolGuid
+    CopyMem(RomPcir, (VOID *)(UINTN)RomBarOffset + OffsetPcir, sizeof (PCI_DATA_STRUCTURE));
+
+    DEBUG ((DEBUG_INFO, "%a: RomPcir->Signature %x\n", __FUNCTION__, RomPcir->Signature));
+
+    //
+    // If a valid signature is not present in the PCI Data Structure, no further images can be located.
+    //
+    if (RomPcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
+      break;
+    }
+    if (RomImageSize + RomPcir->ImageLength * 512 > *RomSize) {
+      break;
+    }
+    if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {
+      CodeType = PCI_CODE_TYPE_PCAT_IMAGE;
+      LegacyImageLength = ((UINT32)((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512) * 512;
+    }
+    Indicator     = RomPcir->Indicator;
+    RomImageSize  = RomImageSize + RomPcir->ImageLength * 512;
+    RomBarOffset  = RomBarOffset + RomPcir->ImageLength * 512;
+  } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < *RomSize));
+
+  //
+  // Some Legacy Cards do not report the correct ImageLength so used the maximum
+  // of the legacy length and the PCIR Image Length
+  //
+  if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {
+    RomImageSize = MAX (RomImageSize, LegacyImageLength);
+  }
+
+  if (RomImageSize > 0) {
+    // FIXME: Use gEfiPciRootBridgeIoProtocolGuid
+    RomInMemory = (VOID *)(UINTN)RomBar;
+  }
+
+  //
+  // Free allocated memory
+  //
+  FreePool (RomHeader);
+  FreePool (RomPcir);
+
+  if (RomImageSize > 0) {
+    *RomImage = RomInMemory;
+    *RomSize = RomImageSize;
+    DEBUG ((DEBUG_INFO, "%a: Found Option ROM at %p, length 0x%x\n", __FUNCTION__,
+        RomInMemory, RomImageSize));
+
+    Status = EFI_SUCCESS;
+  } else {
+    Status = EFI_NOT_FOUND;
+  }
+
+CloseAndReturn:
+  //
+  // Close the I/O Abstraction(s) used to perform the supported test
+  //
+  gBS->CloseProtocol (
+        PciHandle,
+        &gEfiPciIoProtocolGuid,
+        PciIo,
+        PciHandle
+        );
+
+  return Status;
+}
+
+/**
+  Retrieves the platform policy regarding enumeration.
+
+  The GetPlatformPolicy() function retrieves the platform policy regarding PCI
+  enumeration. The PCI bus driver and the PCI Host Bridge Resource Allocation Protocol
+  driver can call this member function to retrieve the policy.
+
+  @param[in]  This        The pointer to the EFI_PCI_PLATFORM_PROTOCOL instance.
+  @param[out] PciPolicy   The platform policy with respect to VGA and ISA aliasing.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   PciPolicy is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+PciGetPlatformPolicy (
+  IN  CONST EFI_PCI_PLATFORM_PROTOCOL  *This,
+  OUT       EFI_PCI_PLATFORM_POLICY    *PciPolicy
+  )
+{
+  if (PciPolicy == NULL)
+    return EFI_INVALID_PARAMETER;
+
+  *PciPolicy = 0;
+
+  return EFI_SUCCESS;
+}
+
+EFI_PCI_PLATFORM_PROTOCOL                     mPciPlatformProtocol = {
+  PciPlatformNotify,
+  PciPlatformPrepController,
+  PciGetPlatformPolicy,
+  PciGetPciRom,
+};
+
+/**
+  The Entry Point for Option ROM driver.
+
+  It installs DriverBinding.
+
+  @retval EFI_SUCCESS       The entry point is executed successfully.
+  @retval other             Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InstallPciPlatformProtocol (
+  IN EFI_HANDLE                        ImageHandle,
+  IN EFI_SYSTEM_TABLE                  *SystemTable
+  )
+{
+  EFI_STATUS                           Status;
+
+  Status = gBS->InstallProtocolInterface (
+                  &mDriverHandle,
+                  &gEfiPciPlatformProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &mPciPlatformProtocol
+                  );
+
+  return Status;
+}
-- 
2.28.0


  parent reply	other threads:[~2020-09-15 12:26 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-15 12:26 [PATCH v2 0/2] Add support for scanning Option ROMs Marcello Sylvester Bauer
2020-09-15 12:26 ` [PATCH v2 1/2] MdeModulePkg: Fix OptionROM scanning Marcello Sylvester Bauer
2020-09-15 12:34   ` [edk2-devel] " Laszlo Ersek
2020-09-15 12:26 ` Marcello Sylvester Bauer [this message]
2020-09-16  8:28 ` [edk2-devel] [PATCH v2 0/2] Add support for scanning Option ROMs Ni, Ray
2020-09-21 13:25   ` Marcello Sylvester Bauer
2020-09-22 23:58     ` Michael D Kinney
2020-11-10 15:01       ` Marcello Sylvester Bauer
2024-10-09  9:11         ` Dmitry Ponamorev
     [not found] ` <16353648FD0ACD96.16285@groups.io>
2020-09-17  1:41   ` Ni, Ray

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=20200915122616.17196-3-marcello.bauer@9elements.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