public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH 1/1] OvmfPkg IA32: add support for loading X64 Linux images
@ 2020-02-14 11:41 ard.biesheuvel
  2020-02-14 14:45 ` Laszlo Ersek
  0 siblings, 1 reply; 4+ messages in thread
From: ard.biesheuvel @ 2020-02-14 11:41 UTC (permalink / raw)
  To: devel
  Cc: Ard Biesheuvel, lersek, leif, pjones, mjg59, agraf, daniel.kiper,
	nivedita

This is the UEFI counterpart to my Linux series [0] which generalizes
mixed mode support into a feature that requires very little internal
knowledge about the architecture specifics of booting Linux on the
part of the bootloader or firmware.

Instead, we add a .compat PE/COFF section containing an array of
PE_COMPAT nodes containing <machine type, entrypoint> tuples that
describe alternate entrypoints into the image for different native
machine types, e.g., IA-32 in a 64-bit image so it can be booted
from IA-32 firmware.

This patch implements the PE/COFF emulator protocol to take this new
section into account, so that such images can simply be loaded via
LoadImage/StartImage, e.g., straight from the UEFI shell.

[0] https://lore.kernel.org/linux-arm-kernel/20200213145928.7047-1-ardb@kernel.org/

Cc: lersek@redhat.com
Cc: leif@nuviainc.com
Cc: pjones@redhat.com
Cc: mjg59@google.com
Cc: agraf@csgraf.de
Cc: daniel.kiper@oracle.com
Cc: nivedita@alum.mit.edu
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
---
 OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c   | 151 ++++++++++++++++++++
 OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf |  36 +++++
 OvmfPkg/OvmfPkgIa32.dsc                               |   2 +
 OvmfPkg/OvmfPkgIa32.fdf                               |   2 +
 4 files changed, 191 insertions(+)

diff --git a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
new file mode 100644
index 000000000000..a9c960c64be9
--- /dev/null
+++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
@@ -0,0 +1,151 @@
+/** @file
+ *  PE/COFF emulator protocol implementation to start Linux kernel
+ *  images from non-native firmware
+ *
+ *  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+ *
+ *  SPDX-License-Identifier: BSD-2-Clause-Patent
+ *
+ */
+
+#include <PiDxe.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+
+#include <Protocol/PeCoffImageEmulator.h>
+
+#pragma pack(1)
+typedef struct {
+  UINT8   Type;
+  UINT8   Size;
+  UINT16  MachineType;
+  UINT32  EntryPoint;
+} PE_COMPAT_TYPE1;
+#pragma pack()
+
+STATIC
+BOOLEAN
+EFIAPI
+IsImageSupported (
+  IN  EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL    *This,
+  IN  UINT16                                  ImageType,
+  IN  EFI_DEVICE_PATH_PROTOCOL                *DevicePath   OPTIONAL
+  )
+{
+  if (ImageType != EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION &&
+      ImageType != EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) {
+    return FALSE;
+  }
+  return TRUE;
+}
+
+STATIC
+EFI_IMAGE_ENTRY_POINT
+EFIAPI
+GetCompatEntryPoint (
+  IN  EFI_PHYSICAL_ADDRESS             ImageBase
+  )
+{
+  EFI_IMAGE_DOS_HEADER                 *DosHdr;
+  UINTN                                 PeCoffHeaderOffset;
+  EFI_IMAGE_NT_HEADERS32                *Pe32;
+  EFI_IMAGE_SECTION_HEADER              *Section;
+  UINTN                                 NumberOfSections;
+  PE_COMPAT_TYPE1                       *PeCompat;
+
+  DosHdr = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageBase;
+  if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+    return NULL;
+  }
+
+  PeCoffHeaderOffset = DosHdr->e_lfanew;
+  Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageBase + PeCoffHeaderOffset);
+
+  Section = (EFI_IMAGE_SECTION_HEADER *)((UINTN)ImageBase + PeCoffHeaderOffset +
+                                         sizeof(UINT32) +
+                                         sizeof(EFI_IMAGE_FILE_HEADER) +
+                                         Pe32->FileHeader.SizeOfOptionalHeader);
+  NumberOfSections = (UINTN)Pe32->FileHeader.NumberOfSections;
+
+  while (NumberOfSections--) {
+    if (!CompareMem (Section->Name, ".compat", sizeof (Section->Name))) {
+      //
+      // Dereference the section contents to find the mixed mode entry point
+      //
+      PeCompat = (PE_COMPAT_TYPE1 *)((UINTN)ImageBase + Section->VirtualAddress);
+
+      while (PeCompat->Type != 0) {
+        if (PeCompat->Type == 1 &&
+            PeCompat->Size >= sizeof (PE_COMPAT_TYPE1) &&
+            EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCompat->MachineType)) {
+
+          return (EFI_IMAGE_ENTRY_POINT)((UINTN)ImageBase + PeCompat->EntryPoint);
+        }
+        PeCompat = (PE_COMPAT_TYPE1 *)((UINTN)PeCompat + PeCompat->Size);
+      }
+    }
+    Section++;
+  }
+  return NULL;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+Unsupported (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+RegisterImage (
+  IN      EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL    *This,
+  IN      EFI_PHYSICAL_ADDRESS                    ImageBase,
+  IN      UINT64                                  ImageSize,
+  IN  OUT EFI_IMAGE_ENTRY_POINT                   *EntryPoint
+  )
+{
+  *EntryPoint = GetCompatEntryPoint (ImageBase) ?: &Unsupported;
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+UnregisterImage (
+  IN  EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL    *This,
+  IN  EFI_PHYSICAL_ADDRESS                    ImageBase
+  )
+{
+  return EFI_SUCCESS;
+}
+
+STATIC EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL mCompatLoaderPeCoffEmuProtocol = {
+  IsImageSupported,
+  RegisterImage,
+  UnregisterImage,
+  EDKII_PECOFF_IMAGE_EMULATOR_VERSION,
+  EFI_IMAGE_MACHINE_X64
+};
+
+EFI_STATUS
+EFIAPI
+CompatImageLoaderDxeEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  return gBS->InstallProtocolInterface (&ImageHandle,
+                &gEdkiiPeCoffImageEmulatorProtocolGuid,
+                EFI_NATIVE_INTERFACE,
+                &mCompatLoaderPeCoffEmuProtocol);
+}
diff --git a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
new file mode 100644
index 000000000000..82369384fbe6
--- /dev/null
+++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
@@ -0,0 +1,36 @@
+## @file
+#  PE/COFF emulator protocol implementation to start Linux kernel
+#  images from non-native firmware
+#
+#  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 1.27
+  BASE_NAME                      = CompatImageLoaderDxe
+  FILE_GUID                      = 1019f54a-2560-41b2-87b0-6750b98f3eff
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = CompatImageLoaderDxeEntryPoint
+
+[Sources]
+  CompatImageLoaderDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  PeCoffLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+
+[Protocols]
+  gEdkiiPeCoffImageEmulatorProtocolGuid   ## PRODUCES
+
+[Depex]
+  TRUE
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 3ffaa9b3388f..66522a4bc555 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -916,3 +916,5 @@ [Components]
       NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf
   }
 !endif
+
+  OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
index 586bbff08585..3411e4ca676e 100644
--- a/OvmfPkg/OvmfPkgIa32.fdf
+++ b/OvmfPkg/OvmfPkgIa32.fdf
@@ -350,6 +350,8 @@ [FV.DXEFV]
 !endif
 !endif
 
+INF OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
+
 ################################################################################
 
 [FV.FVMAIN_COMPACT]
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/1] OvmfPkg IA32: add support for loading X64 Linux images
  2020-02-14 11:41 [PATCH 1/1] OvmfPkg IA32: add support for loading X64 Linux images ard.biesheuvel
@ 2020-02-14 14:45 ` Laszlo Ersek
  2020-02-14 15:05   ` [edk2-devel] " Ard Biesheuvel
  0 siblings, 1 reply; 4+ messages in thread
From: Laszlo Ersek @ 2020-02-14 14:45 UTC (permalink / raw)
  To: Ard Biesheuvel, devel; +Cc: leif, pjones, mjg59, agraf, daniel.kiper, nivedita

On 02/14/20 12:41, Ard Biesheuvel wrote:
> This is the UEFI counterpart to my Linux series [0] which generalizes
> mixed mode support into a feature that requires very little internal
> knowledge about the architecture specifics of booting Linux on the
> part of the bootloader or firmware.
> 
> Instead, we add a .compat PE/COFF section containing an array of
> PE_COMPAT nodes containing <machine type, entrypoint> tuples that
> describe alternate entrypoints into the image for different native
> machine types, e.g., IA-32 in a 64-bit image so it can be booted
> from IA-32 firmware.
> 
> This patch implements the PE/COFF emulator protocol to take this new
> section into account, so that such images can simply be loaded via
> LoadImage/StartImage, e.g., straight from the UEFI shell.

(1) Please mention that this driver / protocol implementation ties in
with the larger PE/COFF emulator feature that is based on e.g. your
commit 57df17fe26cd ("MdeModulePkg/DxeCore: invoke the emulator protocol
for foreign images", 2019-04-14).

(2) I think we're now in the soft feature freeze, so I believe this
patch will have to wait until the next dev cycle opens up. I hope that's
OK with you.

> 
> [0] https://lore.kernel.org/linux-arm-kernel/20200213145928.7047-1-ardb@kernel.org/
> 
> Cc: lersek@redhat.com
> Cc: leif@nuviainc.com
> Cc: pjones@redhat.com
> Cc: mjg59@google.com
> Cc: agraf@csgraf.de
> Cc: daniel.kiper@oracle.com
> Cc: nivedita@alum.mit.edu
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
> ---
>  OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c   | 151 ++++++++++++++++++++
>  OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf |  36 +++++
>  OvmfPkg/OvmfPkgIa32.dsc                               |   2 +
>  OvmfPkg/OvmfPkgIa32.fdf                               |   2 +
>  4 files changed, 191 insertions(+)
> 
> diff --git a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
> new file mode 100644
> index 000000000000..a9c960c64be9
> --- /dev/null
> +++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
> @@ -0,0 +1,151 @@
> +/** @file
> + *  PE/COFF emulator protocol implementation to start Linux kernel
> + *  images from non-native firmware
> + *
> + *  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
> + *
> + *  SPDX-License-Identifier: BSD-2-Clause-Patent
> + *
> + */
> +
> +#include <PiDxe.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/PeCoffLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiDriverEntryPoint.h>
> +
> +#include <Protocol/PeCoffImageEmulator.h>
> +
> +#pragma pack(1)
> +typedef struct {
> +  UINT8   Type;
> +  UINT8   Size;
> +  UINT16  MachineType;
> +  UINT32  EntryPoint;
> +} PE_COMPAT_TYPE1;
> +#pragma pack()
> +
> +STATIC
> +BOOLEAN
> +EFIAPI
> +IsImageSupported (
> +  IN  EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL    *This,
> +  IN  UINT16                                  ImageType,
> +  IN  EFI_DEVICE_PATH_PROTOCOL                *DevicePath   OPTIONAL
> +  )
> +{
> +  if (ImageType != EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION &&
> +      ImageType != EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) {
> +    return FALSE;
> +  }
> +  return TRUE;
> +}
> +
> +STATIC
> +EFI_IMAGE_ENTRY_POINT
> +EFIAPI
> +GetCompatEntryPoint (
> +  IN  EFI_PHYSICAL_ADDRESS             ImageBase
> +  )
> +{
> +  EFI_IMAGE_DOS_HEADER                 *DosHdr;
> +  UINTN                                 PeCoffHeaderOffset;
> +  EFI_IMAGE_NT_HEADERS32                *Pe32;
> +  EFI_IMAGE_SECTION_HEADER              *Section;
> +  UINTN                                 NumberOfSections;
> +  PE_COMPAT_TYPE1                       *PeCompat;
> +
> +  DosHdr = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageBase;
> +  if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
> +    return NULL;
> +  }
> +
> +  PeCoffHeaderOffset = DosHdr->e_lfanew;
> +  Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageBase + PeCoffHeaderOffset);
> +
> +  Section = (EFI_IMAGE_SECTION_HEADER *)((UINTN)ImageBase + PeCoffHeaderOffset +
> +                                         sizeof(UINT32) +
> +                                         sizeof(EFI_IMAGE_FILE_HEADER) +
> +                                         Pe32->FileHeader.SizeOfOptionalHeader);
> +  NumberOfSections = (UINTN)Pe32->FileHeader.NumberOfSections;
> +
> +  while (NumberOfSections--) {
> +    if (!CompareMem (Section->Name, ".compat", sizeof (Section->Name))) {
> +      //
> +      // Dereference the section contents to find the mixed mode entry point
> +      //
> +      PeCompat = (PE_COMPAT_TYPE1 *)((UINTN)ImageBase + Section->VirtualAddress);
> +
> +      while (PeCompat->Type != 0) {
> +        if (PeCompat->Type == 1 &&
> +            PeCompat->Size >= sizeof (PE_COMPAT_TYPE1) &&
> +            EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCompat->MachineType)) {
> +
> +          return (EFI_IMAGE_ENTRY_POINT)((UINTN)ImageBase + PeCompat->EntryPoint);
> +        }
> +        PeCompat = (PE_COMPAT_TYPE1 *)((UINTN)PeCompat + PeCompat->Size);
> +      }
> +    }
> +    Section++;
> +  }
> +  return NULL;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +Unsupported (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +RegisterImage (
> +  IN      EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL    *This,
> +  IN      EFI_PHYSICAL_ADDRESS                    ImageBase,
> +  IN      UINT64                                  ImageSize,
> +  IN  OUT EFI_IMAGE_ENTRY_POINT                   *EntryPoint
> +  )
> +{
> +  *EntryPoint = GetCompatEntryPoint (ImageBase) ?: &Unsupported;

(3) Operator "?:" is a GNU-ism, please replace it.

> +
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +UnregisterImage (
> +  IN  EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL    *This,
> +  IN  EFI_PHYSICAL_ADDRESS                    ImageBase
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL mCompatLoaderPeCoffEmuProtocol = {
> +  IsImageSupported,
> +  RegisterImage,
> +  UnregisterImage,
> +  EDKII_PECOFF_IMAGE_EMULATOR_VERSION,
> +  EFI_IMAGE_MACHINE_X64
> +};
> +
> +EFI_STATUS
> +EFIAPI
> +CompatImageLoaderDxeEntryPoint (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  return gBS->InstallProtocolInterface (&ImageHandle,
> +                &gEdkiiPeCoffImageEmulatorProtocolGuid,
> +                EFI_NATIVE_INTERFACE,
> +                &mCompatLoaderPeCoffEmuProtocol);
> +}
> diff --git a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
> new file mode 100644
> index 000000000000..82369384fbe6
> --- /dev/null
> +++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
> @@ -0,0 +1,36 @@
> +## @file
> +#  PE/COFF emulator protocol implementation to start Linux kernel
> +#  images from non-native firmware
> +#
> +#  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 1.27
> +  BASE_NAME                      = CompatImageLoaderDxe
> +  FILE_GUID                      = 1019f54a-2560-41b2-87b0-6750b98f3eff
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = CompatImageLoaderDxeEntryPoint
> +
> +[Sources]
> +  CompatImageLoaderDxe.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  BaseMemoryLib
> +  PeCoffLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +
> +[Protocols]
> +  gEdkiiPeCoffImageEmulatorProtocolGuid   ## PRODUCES
> +
> +[Depex]
> +  TRUE
> diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
> index 3ffaa9b3388f..66522a4bc555 100644
> --- a/OvmfPkg/OvmfPkgIa32.dsc
> +++ b/OvmfPkg/OvmfPkgIa32.dsc
> @@ -916,3 +916,5 @@ [Components]
>        NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf
>    }
>  !endif
> +
> +  OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
> diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
> index 586bbff08585..3411e4ca676e 100644
> --- a/OvmfPkg/OvmfPkgIa32.fdf
> +++ b/OvmfPkg/OvmfPkgIa32.fdf
> @@ -350,6 +350,8 @@ [FV.DXEFV]
>  !endif
>  !endif
>  
> +INF OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
> +
>  ################################################################################
>  
>  [FV.FVMAIN_COMPACT]
> 

(4) Please introduce a new build flag (such as -D
LOAD_X64_ON_IA32_ENABLE) for gating this feature. It's fine if the
default value of the flag is TRUE, I'd just like a possibility to
exclude this driver from the firmware without out-of-tree patches.

(5) Can you please explain how EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL
relates to Secure Boot and/or Trusted Boot?

(5a) Is the ".compat" section included in the image hashing?

(5b) Does the DXE core subject such non-native images to verification /
measurement at all? (Sorry I didn't follow your original work on
EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL.)

Thanks!
Laszlo


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [edk2-devel] [PATCH 1/1] OvmfPkg IA32: add support for loading X64 Linux images
  2020-02-14 14:45 ` Laszlo Ersek
@ 2020-02-14 15:05   ` Ard Biesheuvel
  2020-02-14 21:43     ` Laszlo Ersek
  0 siblings, 1 reply; 4+ messages in thread
From: Ard Biesheuvel @ 2020-02-14 15:05 UTC (permalink / raw)
  To: edk2-devel-groups-io, Laszlo Ersek
  Cc: Leif Lindholm, Peter Jones, Matthew Garrett, Alexander Graf,
	Daniel Kiper, Arvind Sankar

On Fri, 14 Feb 2020 at 15:45, Laszlo Ersek <lersek@redhat.com> wrote:
>
> On 02/14/20 12:41, Ard Biesheuvel wrote:
> > This is the UEFI counterpart to my Linux series [0] which generalizes
> > mixed mode support into a feature that requires very little internal
> > knowledge about the architecture specifics of booting Linux on the
> > part of the bootloader or firmware.
> >
> > Instead, we add a .compat PE/COFF section containing an array of
> > PE_COMPAT nodes containing <machine type, entrypoint> tuples that
> > describe alternate entrypoints into the image for different native
> > machine types, e.g., IA-32 in a 64-bit image so it can be booted
> > from IA-32 firmware.
> >
> > This patch implements the PE/COFF emulator protocol to take this new
> > section into account, so that such images can simply be loaded via
> > LoadImage/StartImage, e.g., straight from the UEFI shell.
>
> (1) Please mention that this driver / protocol implementation ties in
> with the larger PE/COFF emulator feature that is based on e.g. your
> commit 57df17fe26cd ("MdeModulePkg/DxeCore: invoke the emulator protocol
> for foreign images", 2019-04-14).
>

OK

> (2) I think we're now in the soft feature freeze, so I believe this
> patch will have to wait until the next dev cycle opens up. I hope that's
> OK with you.
>

Sure, that is fine. I just want the different pieces of the puzzle to
be public on a mailing list somewhere so people can see what the
opposite end looks like (seen from the Linux side :-))

> >
> > [0] https://lore.kernel.org/linux-arm-kernel/20200213145928.7047-1-ardb@kernel.org/
> >
> > Cc: lersek@redhat.com
> > Cc: leif@nuviainc.com
> > Cc: pjones@redhat.com
> > Cc: mjg59@google.com
> > Cc: agraf@csgraf.de
> > Cc: daniel.kiper@oracle.com
> > Cc: nivedita@alum.mit.edu
> > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
> > ---
> >  OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c   | 151 ++++++++++++++++++++
> >  OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf |  36 +++++
> >  OvmfPkg/OvmfPkgIa32.dsc                               |   2 +
> >  OvmfPkg/OvmfPkgIa32.fdf                               |   2 +
> >  4 files changed, 191 insertions(+)
> >
> > diff --git a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
> > new file mode 100644
> > index 000000000000..a9c960c64be9
> > --- /dev/null
> > +++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
> > @@ -0,0 +1,151 @@
> > +/** @file
> > + *  PE/COFF emulator protocol implementation to start Linux kernel
> > + *  images from non-native firmware
> > + *
> > + *  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
> > + *
> > + *  SPDX-License-Identifier: BSD-2-Clause-Patent
> > + *
> > + */
> > +
> > +#include <PiDxe.h>
> > +
> > +#include <Library/BaseMemoryLib.h>
> > +#include <Library/PeCoffLib.h>
> > +#include <Library/UefiBootServicesTableLib.h>
> > +#include <Library/UefiDriverEntryPoint.h>
> > +
> > +#include <Protocol/PeCoffImageEmulator.h>
> > +
> > +#pragma pack(1)
> > +typedef struct {
> > +  UINT8   Type;
> > +  UINT8   Size;
> > +  UINT16  MachineType;
> > +  UINT32  EntryPoint;
> > +} PE_COMPAT_TYPE1;
> > +#pragma pack()
> > +
> > +STATIC
> > +BOOLEAN
> > +EFIAPI
> > +IsImageSupported (
> > +  IN  EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL    *This,
> > +  IN  UINT16                                  ImageType,
> > +  IN  EFI_DEVICE_PATH_PROTOCOL                *DevicePath   OPTIONAL
> > +  )
> > +{
> > +  if (ImageType != EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION &&
> > +      ImageType != EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) {
> > +    return FALSE;
> > +  }
> > +  return TRUE;
> > +}
> > +
> > +STATIC
> > +EFI_IMAGE_ENTRY_POINT
> > +EFIAPI
> > +GetCompatEntryPoint (
> > +  IN  EFI_PHYSICAL_ADDRESS             ImageBase
> > +  )
> > +{
> > +  EFI_IMAGE_DOS_HEADER                 *DosHdr;
> > +  UINTN                                 PeCoffHeaderOffset;
> > +  EFI_IMAGE_NT_HEADERS32                *Pe32;
> > +  EFI_IMAGE_SECTION_HEADER              *Section;
> > +  UINTN                                 NumberOfSections;
> > +  PE_COMPAT_TYPE1                       *PeCompat;
> > +
> > +  DosHdr = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageBase;
> > +  if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
> > +    return NULL;
> > +  }
> > +
> > +  PeCoffHeaderOffset = DosHdr->e_lfanew;
> > +  Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageBase + PeCoffHeaderOffset);
> > +
> > +  Section = (EFI_IMAGE_SECTION_HEADER *)((UINTN)ImageBase + PeCoffHeaderOffset +
> > +                                         sizeof(UINT32) +
> > +                                         sizeof(EFI_IMAGE_FILE_HEADER) +
> > +                                         Pe32->FileHeader.SizeOfOptionalHeader);
> > +  NumberOfSections = (UINTN)Pe32->FileHeader.NumberOfSections;
> > +
> > +  while (NumberOfSections--) {
> > +    if (!CompareMem (Section->Name, ".compat", sizeof (Section->Name))) {
> > +      //
> > +      // Dereference the section contents to find the mixed mode entry point
> > +      //
> > +      PeCompat = (PE_COMPAT_TYPE1 *)((UINTN)ImageBase + Section->VirtualAddress);
> > +
> > +      while (PeCompat->Type != 0) {
> > +        if (PeCompat->Type == 1 &&
> > +            PeCompat->Size >= sizeof (PE_COMPAT_TYPE1) &&
> > +            EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCompat->MachineType)) {
> > +
> > +          return (EFI_IMAGE_ENTRY_POINT)((UINTN)ImageBase + PeCompat->EntryPoint);
> > +        }
> > +        PeCompat = (PE_COMPAT_TYPE1 *)((UINTN)PeCompat + PeCompat->Size);
> > +      }
> > +    }
> > +    Section++;
> > +  }
> > +  return NULL;
> > +}
> > +
> > +STATIC
> > +EFI_STATUS
> > +EFIAPI
> > +Unsupported (
> > +  IN EFI_HANDLE        ImageHandle,
> > +  IN EFI_SYSTEM_TABLE  *SystemTable
> > +  )
> > +{
> > +  return EFI_UNSUPPORTED;
> > +}
> > +
> > +STATIC
> > +EFI_STATUS
> > +EFIAPI
> > +RegisterImage (
> > +  IN      EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL    *This,
> > +  IN      EFI_PHYSICAL_ADDRESS                    ImageBase,
> > +  IN      UINT64                                  ImageSize,
> > +  IN  OUT EFI_IMAGE_ENTRY_POINT                   *EntryPoint
> > +  )
> > +{
> > +  *EntryPoint = GetCompatEntryPoint (ImageBase) ?: &Unsupported;
>
> (3) Operator "?:" is a GNU-ism, please replace it.
>

OK

> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +STATIC
> > +EFI_STATUS
> > +EFIAPI
> > +UnregisterImage (
> > +  IN  EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL    *This,
> > +  IN  EFI_PHYSICAL_ADDRESS                    ImageBase
> > +  )
> > +{
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +STATIC EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL mCompatLoaderPeCoffEmuProtocol = {
> > +  IsImageSupported,
> > +  RegisterImage,
> > +  UnregisterImage,
> > +  EDKII_PECOFF_IMAGE_EMULATOR_VERSION,
> > +  EFI_IMAGE_MACHINE_X64
> > +};
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +CompatImageLoaderDxeEntryPoint (
> > +  IN EFI_HANDLE        ImageHandle,
> > +  IN EFI_SYSTEM_TABLE  *SystemTable
> > +  )
> > +{
> > +  return gBS->InstallProtocolInterface (&ImageHandle,
> > +                &gEdkiiPeCoffImageEmulatorProtocolGuid,
> > +                EFI_NATIVE_INTERFACE,
> > +                &mCompatLoaderPeCoffEmuProtocol);
> > +}
> > diff --git a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
> > new file mode 100644
> > index 000000000000..82369384fbe6
> > --- /dev/null
> > +++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
> > @@ -0,0 +1,36 @@
> > +## @file
> > +#  PE/COFF emulator protocol implementation to start Linux kernel
> > +#  images from non-native firmware
> > +#
> > +#  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
> > +#
> > +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +
> > +[Defines]
> > +  INF_VERSION                    = 1.27
> > +  BASE_NAME                      = CompatImageLoaderDxe
> > +  FILE_GUID                      = 1019f54a-2560-41b2-87b0-6750b98f3eff
> > +  MODULE_TYPE                    = DXE_DRIVER
> > +  VERSION_STRING                 = 1.0
> > +  ENTRY_POINT                    = CompatImageLoaderDxeEntryPoint
> > +
> > +[Sources]
> > +  CompatImageLoaderDxe.c
> > +
> > +[Packages]
> > +  MdePkg/MdePkg.dec
> > +  MdeModulePkg/MdeModulePkg.dec
> > +
> > +[LibraryClasses]
> > +  BaseMemoryLib
> > +  PeCoffLib
> > +  UefiBootServicesTableLib
> > +  UefiDriverEntryPoint
> > +
> > +[Protocols]
> > +  gEdkiiPeCoffImageEmulatorProtocolGuid   ## PRODUCES
> > +
> > +[Depex]
> > +  TRUE
> > diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
> > index 3ffaa9b3388f..66522a4bc555 100644
> > --- a/OvmfPkg/OvmfPkgIa32.dsc
> > +++ b/OvmfPkg/OvmfPkgIa32.dsc
> > @@ -916,3 +916,5 @@ [Components]
> >        NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf
> >    }
> >  !endif
> > +
> > +  OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
> > diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
> > index 586bbff08585..3411e4ca676e 100644
> > --- a/OvmfPkg/OvmfPkgIa32.fdf
> > +++ b/OvmfPkg/OvmfPkgIa32.fdf
> > @@ -350,6 +350,8 @@ [FV.DXEFV]
> >  !endif
> >  !endif
> >
> > +INF OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
> > +
> >  ################################################################################
> >
> >  [FV.FVMAIN_COMPACT]
> >
>
> (4) Please introduce a new build flag (such as -D
> LOAD_X64_ON_IA32_ENABLE) for gating this feature. It's fine if the
> default value of the flag is TRUE, I'd just like a possibility to
> exclude this driver from the firmware without out-of-tree patches.
>

OK

> (5) Can you please explain how EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL
> relates to Secure Boot and/or Trusted Boot?
>
> (5a) Is the ".compat" section included in the image hashing?
>

Yes.

> (5b) Does the DXE core subject such non-native images to verification /
> measurement at all? (Sorry I didn't follow your original work on
> EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL.)
>

Yes. They are treated entirely like ordinary images, with all the
policy checks regarding authentication and measurement.

This is actually the whole point of this exercise: there is a whole
stack of secure boot and measured boot related patches trying to make
its way upstream that are based on circumventing LoadImage and
StartImage, open coding authentication checks using a protocol exposed
by shim, and taking its own measurements of the kernel as well.

I fully understand how this came about, but I strongly believe that we
should not extrapolate this to other architectures. What I would like
to see instead is shim hooking the LoadImage and StartImage boot
services (which it already does btw, but not for exposing its
augmented functionality to the caller), so that other components can
be agnostic about whether shim is being used or not.

There are currently two reasons why we cannot use LoadImage/StartImage:
- initrd loading (hence the other set of changes that I proposed)
- mixed mode support

With those two out of the way, we should be able to converge on a
generic EFI booting protocol for Linux that is identical across
architectures, with the only Linux specific pieces being this .compat
section handling and the LoadFile2 protocol for initrd.

Note that mixed mode on actual existing hardware still requires
special handling, given that their firmware predates this PE/COFF emu
protocol, but this handling may be something we could fold into shim,
given the amount of PE/COFF parsing it does already, which makes it
trivial to just jump to the IA32 entry point in the X64 binary in its
implementation of StartImage()

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [edk2-devel] [PATCH 1/1] OvmfPkg IA32: add support for loading X64 Linux images
  2020-02-14 15:05   ` [edk2-devel] " Ard Biesheuvel
@ 2020-02-14 21:43     ` Laszlo Ersek
  0 siblings, 0 replies; 4+ messages in thread
From: Laszlo Ersek @ 2020-02-14 21:43 UTC (permalink / raw)
  To: Ard Biesheuvel, edk2-devel-groups-io
  Cc: Leif Lindholm, Peter Jones, Matthew Garrett, Alexander Graf,
	Daniel Kiper, Arvind Sankar

On 02/14/20 16:05, Ard Biesheuvel wrote:
> On Fri, 14 Feb 2020 at 15:45, Laszlo Ersek <lersek@redhat.com> wrote:

>> (5) Can you please explain how EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL
>> relates to Secure Boot and/or Trusted Boot?
>>
>> (5a) Is the ".compat" section included in the image hashing?
>>
> 
> Yes.
> 
>> (5b) Does the DXE core subject such non-native images to verification /
>> measurement at all? (Sorry I didn't follow your original work on
>> EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL.)
>>
> 
> Yes. They are treated entirely like ordinary images, with all the
> policy checks regarding authentication and measurement.

[...]

Thank you!
Laszlo


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-02-14 21:43 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-02-14 11:41 [PATCH 1/1] OvmfPkg IA32: add support for loading X64 Linux images ard.biesheuvel
2020-02-14 14:45 ` Laszlo Ersek
2020-02-14 15:05   ` [edk2-devel] " Ard Biesheuvel
2020-02-14 21:43     ` Laszlo Ersek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox