public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v4 0/7] OvmfPkg: implement initrd shell command and mixed mode loader
@ 2020-03-03 14:01 Ard Biesheuvel
  2020-03-03 14:01 ` [PATCH v4 1/7] OvmfPkg: add definition of LINUX_EFI_INITRD_MEDIA_GUID Ard Biesheuvel
                   ` (7 more replies)
  0 siblings, 8 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2020-03-03 14:01 UTC (permalink / raw)
  To: devel; +Cc: Ard Biesheuvel, lersek, leif, Liming Gao

This series is part of my effort to define a generic EFI boot protocol for
Linux, i.e,. one that is the same across all different architectures that
are able to boot Linux from EFI, and naturally reused the firmware's
infrastructure for authenticated boot and measured boot.

Path #1 ... #4 implement the 'initrd' dynamic shell command, which takes a
file and exposes it via the LoadFile2 protocol installed on a vendor media
device path with guid LINUX_EFI_INITRD_MEDIA_GUID. This is a Linux specific,
but arch-agnostic way for the OS loader to load an initial ramdisk, while
leaving the firmware (or bootloader) in charge of where the file contents
are served from. This supersedes the currently existing solutions on Linux,
which are either limited to loading from the same volume that the OS loader
was loaded from, or load the initrd into memory first, and use architecture
specific data structures to pass on the information regarding base and size.

Patch #5 is an update to the integration of the PE/COFF emulator protocol,
to align it more closely with how LoadImage() and StartImage() behave today:
LoadImage() is not restricted to images that can execute natively on the
platform, but also permits loading of cross-type supported images. This means
that any judgement on whether an image can be *started* needs to be deferred
until StartImage(), which is why the invocation of the RegisterImage()
callback needs to be deferred as well.

Patch #6 implements the PE/COFF emulator protocol so it can start X64 images
that have been loaded on IA32 firmware. This is needed for Linux's so-called
'mixed mode', which is an elaborate scheme of on-the-fly translation of data
structures and thunking into 32-bit compat mode, allowing X64 Linux kernels
to be used on X64 capable hardware that shipped with IA32 firmware. This
needs support from the loader, and is currently implemented in GRUB (and
OVMF's command line kernel loader) using the EFI handover protocol, which
relies far too much on knowledge of kernel internal data structures, and
circumvents LoadImage and StartImage entirely.
(Note: mixed mode support is mainly targeted at cheap Atom tablets that
shipped with a [cheaper] 32-bit version of Windows, and so this particular
patch is unlikely to help that use case, but it is useful for validation.)

Patch #7 is new in v4, and modified the initrd Shell command so it aborts
immediately if the Linux initrd media GUID device path already has the
LoadFile2 protocol installed in the protocol database.

With these changes in place, we can boot x86 mixed-mode Linux straight from
the UEFI Shell

Shell>initrd fs0:\initrd.img
Shell>fs0:\bzImage root=/dev/vda2

Another benefit of this approach is that we can exit cleanly from the loader
(and back to the shell) using the Exit() boot service if any errors occur,
whereas the EFI handover protocol enters a deadloop upon any error that
occurs during execution of the EFI stub.

Changes since v3:
- pick up some acks
- update patch #6 to sanity check the contents of the .compat section so
  we don't overrun the end of the section looking for a compatible entrypoint
- add patch #7

Changes since v2:
- incorporate Laszlo's feedback, and add R-b's - I have incorporated all the
  feedback given, except for the structure of the shell command implementation:
  it is not my preferred style, but it is correct, and idiomatic for the shell
  commands I could find in the tree.

Changes from v1:
- Use a dynamic UEFI shell command, which is the recommended way of implementing
  new shell commands that are not covered by the UEFI shell specification. It
  also makes the command more easily usable on existing platforms, since the
  driver can be loaded as an ordinary driver.
- split initrd patch into 4, as requested by Laszlo
- add patch to tweak the LoadImage/StartImage behavior wrt the PE/COFF emulator
  protocol
- return EFI_UNSUPPORTED from PeCoffEmu::RegisterImage() if the image does not
  have the required .compat section

[0] https://edk2.groups.io/g/devel/topic/rfc_patch_1_1_ovmfpkg_add/71177416
[1] https://edk2.groups.io/g/devel/topic/patch_1_1_ovmfpkg_ia32_add/71272266

v2: https://edk2.groups.io/g/devel/topic/patch_v2_0_6_ovmfpkg/71530294
v3: https://edk2.groups.io/g/devel/message/54932

Cc: lersek@redhat.com
Cc: leif@nuviainc.com
Cc: Liming Gao <liming.gao@intel.com>

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2564

Ard Biesheuvel (7):
  OvmfPkg: add definition of LINUX_EFI_INITRD_MEDIA_GUID
  OvmfPkg: add 'initrd' shell command to expose Linux initrd via device
    path
  ArmVirtPkg: add the 'initrd' dynamic shell command
  OvmfPkg: add the 'initrd' dynamic shell command
  MdeModulePkg/DxeCore: defer PE/COFF emulator registration to
    StartImage
  OvmfPkg IA32: add support for loading X64 images
  OvmfPkg/LinuxInitrdDynamicShellCommand: bail if initrd already exists

 ArmVirtPkg/ArmVirt.dsc.inc                    |   4 +
 ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc          |   1 +
 ArmVirtPkg/ArmVirtXen.fdf                     |   1 +
 MdeModulePkg/Core/Dxe/Image/Image.c           |  24 +-
 .../CompatImageLoaderDxe.c                    | 143 ++++++
 .../CompatImageLoaderDxe.inf                  |  37 ++
 OvmfPkg/Include/Guid/LinuxEfiInitrdMedia.h    |  17 +
 .../LinuxInitrdDynamicShellCommand.c          | 460 ++++++++++++++++++
 .../LinuxInitrdDynamicShellCommand.inf        |  53 ++
 .../LinuxInitrdDynamicShellCommand.uni        |  52 ++
 OvmfPkg/OvmfPkg.dec                           |   1 +
 OvmfPkg/OvmfPkgIa32.dsc                       |   9 +
 OvmfPkg/OvmfPkgIa32.fdf                       |   5 +
 OvmfPkg/OvmfPkgIa32X64.dsc                    |   4 +
 OvmfPkg/OvmfPkgIa32X64.fdf                    |   1 +
 OvmfPkg/OvmfPkgX64.dsc                        |   4 +
 OvmfPkg/OvmfPkgX64.fdf                        |   1 +
 OvmfPkg/OvmfXen.dsc                           |   4 +
 OvmfPkg/OvmfXen.fdf                           |   1 +
 19 files changed, 811 insertions(+), 11 deletions(-)
 create mode 100644 OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
 create mode 100644 OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
 create mode 100644 OvmfPkg/Include/Guid/LinuxEfiInitrdMedia.h
 create mode 100644 OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c
 create mode 100644 OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
 create mode 100644 OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni

-- 
2.17.1


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

* [PATCH v4 1/7] OvmfPkg: add definition of LINUX_EFI_INITRD_MEDIA_GUID
  2020-03-03 14:01 [PATCH v4 0/7] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
@ 2020-03-03 14:01 ` Ard Biesheuvel
  2020-03-03 14:01 ` [PATCH v4 2/7] OvmfPkg: add 'initrd' shell command to expose Linux initrd via device path Ard Biesheuvel
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2020-03-03 14:01 UTC (permalink / raw)
  To: devel; +Cc: Ard Biesheuvel, lersek, leif, Liming Gao

Add LINUX_EFI_INITRD_MEDIA_GUID to our collection of GUID definitions,
it can be used in a media device path to specify a Linux style initrd
that can be loaded by the OS using the LoadFile2 protocol.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2564
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/Include/Guid/LinuxEfiInitrdMedia.h | 17 +++++++++++++++++
 OvmfPkg/OvmfPkg.dec                        |  1 +
 2 files changed, 18 insertions(+)

diff --git a/OvmfPkg/Include/Guid/LinuxEfiInitrdMedia.h b/OvmfPkg/Include/Guid/LinuxEfiInitrdMedia.h
new file mode 100644
index 000000000000..83fc3fc79aa6
--- /dev/null
+++ b/OvmfPkg/Include/Guid/LinuxEfiInitrdMedia.h
@@ -0,0 +1,17 @@
+/** @file
+  GUID definition for the Linux Initrd media device path
+
+  Copyright (c) 2020, Arm, Ltd. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef LINUX_EFI_INITRD_MEDIA_GUID_H__
+#define LINUX_EFI_INITRD_MEDIA_GUID_H__
+
+#define LINUX_EFI_INITRD_MEDIA_GUID \
+  {0x5568e427, 0x68fc, 0x4f3d, {0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68}}
+
+extern EFI_GUID gLinuxEfiInitrdMediaGuid;
+
+#endif
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 4c5b6511cb97..6849a79cd8b0 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -86,6 +86,7 @@ [Guids]
   gMicrosoftVendorGuid                = {0x77fa9abd, 0x0359, 0x4d32, {0xbd, 0x60, 0x28, 0xf4, 0xe7, 0x8f, 0x78, 0x4b}}
   gEfiLegacyBiosGuid                  = {0x2E3044AC, 0x879F, 0x490F, {0x97, 0x60, 0xBB, 0xDF, 0xAF, 0x69, 0x5F, 0x50}}
   gEfiLegacyDevOrderVariableGuid      = {0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52}}
+  gLinuxEfiInitrdMediaGuid            = {0x5568e427, 0x68fc, 0x4f3d, {0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68}}
 
 [Protocols]
   gVirtioDeviceProtocolGuid           = {0xfa920010, 0x6785, 0x4941, {0xb6, 0xec, 0x49, 0x8c, 0x57, 0x9f, 0x16, 0x0a}}
-- 
2.17.1


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

* [PATCH v4 2/7] OvmfPkg: add 'initrd' shell command to expose Linux initrd via device path
  2020-03-03 14:01 [PATCH v4 0/7] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
  2020-03-03 14:01 ` [PATCH v4 1/7] OvmfPkg: add definition of LINUX_EFI_INITRD_MEDIA_GUID Ard Biesheuvel
@ 2020-03-03 14:01 ` Ard Biesheuvel
  2020-03-03 14:01 ` [PATCH v4 3/7] ArmVirtPkg: add the 'initrd' dynamic shell command Ard Biesheuvel
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2020-03-03 14:01 UTC (permalink / raw)
  To: devel; +Cc: Ard Biesheuvel, lersek, leif, Liming Gao

Add a new 'initrd' command to the UEFI Shell that allows any file that is
accessible to the shell to be registered as the initrd that is returned
when Linux's EFI stub loader invokes the LoadFile2 protocol on its special
vendor media device path.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2564
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c   | 429 ++++++++++++++++++++
 OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf |  53 +++
 OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni |  49 +++
 3 files changed, 531 insertions(+)

diff --git a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c
new file mode 100644
index 000000000000..47ed26b50d3a
--- /dev/null
+++ b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c
@@ -0,0 +1,429 @@
+/** @file
+  Provides 'initrd' dynamic UEFI shell command to load a Linux initrd
+  via its GUIDed vendor media path
+
+  Copyright (c) 2020, Arm, Ltd. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi.h>
+
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ShellLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiHiiServicesLib.h>
+
+#include <Guid/LinuxEfiInitrdMedia.h>
+
+#include <Protocol/DevicePath.h>
+#include <Protocol/HiiPackageList.h>
+#include <Protocol/LoadFile2.h>
+#include <Protocol/ShellDynamicCommand.h>
+
+#pragma pack (1)
+typedef struct {
+  VENDOR_DEVICE_PATH          VenMediaNode;
+  EFI_DEVICE_PATH_PROTOCOL    EndNode;
+} SINGLE_NODE_VENDOR_MEDIA_DEVPATH;
+#pragma pack ()
+
+STATIC EFI_HII_HANDLE         mLinuxInitrdShellCommandHiiHandle;
+STATIC EFI_PHYSICAL_ADDRESS   mInitrdFileAddress;
+STATIC UINTN                  mInitrdFileSize;
+STATIC EFI_HANDLE             mInitrdLoadFile2Handle;
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+  {L"-u", TypeFlag},
+  {NULL, TypeMax}
+  };
+
+STATIC CONST SINGLE_NODE_VENDOR_MEDIA_DEVPATH mInitrdDevicePath = {
+  {
+    {
+      MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH) }
+    },
+    LINUX_EFI_INITRD_MEDIA_GUID
+  }, {
+    END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    { sizeof (EFI_DEVICE_PATH_PROTOCOL) }
+  }
+};
+
+STATIC
+EFI_STATUS
+EFIAPI
+InitrdLoadFile2 (
+  IN      EFI_LOAD_FILE2_PROTOCOL       *This,
+  IN      EFI_DEVICE_PATH_PROTOCOL      *FilePath,
+  IN      BOOLEAN                       BootPolicy,
+  IN  OUT UINTN                         *BufferSize,
+  OUT     VOID                          *Buffer     OPTIONAL
+  )
+{
+  if (BootPolicy) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (BufferSize == NULL || !IsDevicePathValid (FilePath, 0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (FilePath->Type != END_DEVICE_PATH_TYPE ||
+      FilePath->SubType != END_ENTIRE_DEVICE_PATH_SUBTYPE ||
+      mInitrdFileSize == 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  if (Buffer == NULL || *BufferSize < mInitrdFileSize) {
+    *BufferSize = mInitrdFileSize;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  ASSERT (mInitrdFileAddress != 0);
+
+  gBS->CopyMem (Buffer, (VOID *)(UINTN)mInitrdFileAddress, mInitrdFileSize);
+  *BufferSize = mInitrdFileSize;
+  return EFI_SUCCESS;
+}
+
+STATIC CONST EFI_LOAD_FILE2_PROTOCOL     mInitrdLoadFile2 = {
+  InitrdLoadFile2,
+};
+
+STATIC
+EFI_STATUS
+UninstallLoadFile2Protocol (
+  VOID
+  )
+{
+  EFI_STATUS    Status;
+
+  if (mInitrdLoadFile2Handle != NULL) {
+    Status = gBS->UninstallMultipleProtocolInterfaces (mInitrdLoadFile2Handle,
+                    &gEfiDevicePathProtocolGuid,    &mInitrdDevicePath,
+                    &gEfiLoadFile2ProtocolGuid,     &mInitrdLoadFile2,
+                    NULL);
+    if (!EFI_ERROR (Status)) {
+      mInitrdLoadFile2Handle = NULL;
+    }
+  }
+  return Status;
+}
+
+STATIC
+VOID
+FreeInitrdFile (
+  VOID
+  )
+{
+  if (mInitrdFileSize != 0) {
+    gBS->FreePages (mInitrdFileAddress, EFI_SIZE_TO_PAGES (mInitrdFileSize));
+    mInitrdFileSize = 0;
+  }
+}
+
+STATIC
+EFI_STATUS
+CacheInitrdFile (
+  IN  SHELL_FILE_HANDLE   FileHandle
+  )
+{
+  EFI_STATUS              Status;
+  UINT64                  FileSize;
+  UINTN                   ReadSize;
+
+  Status = gEfiShellProtocol->GetFileSize (FileHandle, &FileSize);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (FileSize == 0 || FileSize > MAX_UINTN) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = gBS->AllocatePages (AllocateAnyPages, EfiLoaderData,
+                  EFI_SIZE_TO_PAGES ((UINTN)FileSize), &mInitrdFileAddress);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ReadSize = (UINTN)FileSize;
+  Status = gEfiShellProtocol->ReadFile (FileHandle, &ReadSize,
+                                (VOID *)(UINTN)mInitrdFileAddress);
+  if (EFI_ERROR (Status) || ReadSize < FileSize) {
+    DEBUG ((DEBUG_WARN, "%a: failed to read initrd file - %r 0x%lx 0x%lx\n",
+      __FUNCTION__, Status, (UINT64)ReadSize, FileSize));
+    goto FreeMemory;
+  }
+
+  if (mInitrdLoadFile2Handle == NULL) {
+    Status = gBS->InstallMultipleProtocolInterfaces (&mInitrdLoadFile2Handle,
+                    &gEfiDevicePathProtocolGuid,  &mInitrdDevicePath,
+                    &gEfiLoadFile2ProtocolGuid,   &mInitrdLoadFile2,
+                    NULL);
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  mInitrdFileSize = FileSize;
+  return EFI_SUCCESS;
+
+FreeMemory:
+  gBS->FreePages (mInitrdFileAddress, EFI_SIZE_TO_PAGES ((UINTN)FileSize));
+  return Status;
+}
+
+/**
+  Function for 'initrd' command.
+
+  @param[in] ImageHandle  Handle to the Image (NULL if Internal).
+  @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
+**/
+STATIC
+SHELL_STATUS
+EFIAPI
+RunInitrd (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS            Status;
+  LIST_ENTRY            *Package;
+  CHAR16                *ProblemParam;
+  CONST CHAR16          *Param;
+  CHAR16                *Filename;
+  SHELL_STATUS          ShellStatus;
+  SHELL_FILE_HANDLE     FileHandle;
+
+  ProblemParam        = NULL;
+  ShellStatus         = SHELL_SUCCESS;
+
+  Status = ShellInitialize ();
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // parse the command line
+  //
+  Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM),
+        mLinuxInitrdShellCommandHiiHandle, L"initrd", ProblemParam);
+      FreePool (ProblemParam);
+      ShellStatus = SHELL_INVALID_PARAMETER;
+    } else {
+      ASSERT(FALSE);
+    }
+  } else {
+    if (ShellCommandLineGetCount (Package) > 2) {
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY),
+        mLinuxInitrdShellCommandHiiHandle, L"initrd");
+      ShellStatus = SHELL_INVALID_PARAMETER;
+    } else if (ShellCommandLineGetCount (Package) < 2) {
+      if (ShellCommandLineGetFlag (Package, L"-u")) {
+        FreeInitrdFile ();
+        UninstallLoadFile2Protocol ();
+      } else {
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW),
+          mLinuxInitrdShellCommandHiiHandle, L"initrd");
+        ShellStatus = SHELL_INVALID_PARAMETER;
+      }
+    } else {
+      Param = ShellCommandLineGetRawValue (Package, 1);
+      ASSERT (Param != NULL);
+
+      Filename = ShellFindFilePath (Param);
+      if (Filename == NULL) {
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FIND_FAIL),
+          mLinuxInitrdShellCommandHiiHandle, L"initrd", Param);
+        ShellStatus = SHELL_NOT_FOUND;
+      } else {
+        Status = ShellOpenFileByName (Filename, &FileHandle,
+                   EFI_FILE_MODE_READ, 0);
+        if (!EFI_ERROR (Status)) {
+          FreeInitrdFile ();
+          Status = CacheInitrdFile (FileHandle);
+          ShellCloseFile (&FileHandle);
+        }
+        if (EFI_ERROR (Status)) {
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL),
+            mLinuxInitrdShellCommandHiiHandle, L"initrd", Param);
+          ShellStatus = SHELL_NOT_FOUND;
+        }
+        FreePool (Filename);
+      }
+    }
+  }
+  return ShellStatus;
+}
+
+
+/**
+  This is the shell command handler function pointer callback type.  This
+  function handles the command when it is invoked in the shell.
+
+  @param[in] This                   The instance of the
+                                    EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
+  @param[in] SystemTable            The pointer to the system table.
+  @param[in] ShellParameters        The parameters associated with the command.
+  @param[in] Shell                  The instance of the shell protocol used in
+                                    the context of processing this command.
+
+  @return EFI_SUCCESS               the operation was successful
+  @return other                     the operation failed.
+**/
+SHELL_STATUS
+EFIAPI
+LinuxInitrdCommandHandler (
+  IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL    *This,
+  IN EFI_SYSTEM_TABLE                      *SystemTable,
+  IN EFI_SHELL_PARAMETERS_PROTOCOL         *ShellParameters,
+  IN EFI_SHELL_PROTOCOL                    *Shell
+  )
+{
+  gEfiShellParametersProtocol = ShellParameters;
+  gEfiShellProtocol           = Shell;
+
+  return RunInitrd (gImageHandle, SystemTable);
+}
+
+/**
+  This is the command help handler function pointer callback type.  This
+  function is responsible for displaying help information for the associated
+  command.
+
+  @param[in] This                   The instance of the
+                                    EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
+  @param[in] Language               The pointer to the language string to use.
+
+  @return string                    Pool allocated help string, must be freed
+                                    by caller
+**/
+STATIC
+CHAR16 *
+EFIAPI
+LinuxInitrdGetHelp (
+  IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL    *This,
+  IN CONST CHAR8                           *Language
+  )
+{
+  return HiiGetString (mLinuxInitrdShellCommandHiiHandle,
+           STRING_TOKEN (STR_GET_HELP_INITRD), Language);
+}
+
+STATIC EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mLinuxInitrdDynamicCommand = {
+  L"initrd",
+  LinuxInitrdCommandHandler,
+  LinuxInitrdGetHelp
+};
+
+/**
+  Retrieve HII package list from ImageHandle and publish to HII database.
+
+  @param ImageHandle            The image handle of the process.
+
+  @return HII handle.
+**/
+STATIC
+EFI_HII_HANDLE
+InitializeHiiPackage (
+  EFI_HANDLE                  ImageHandle
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+  EFI_HII_HANDLE              HiiHandle;
+
+  //
+  // Retrieve HII package list from ImageHandle
+  //
+  Status = gBS->OpenProtocol (ImageHandle, &gEfiHiiPackageListProtocolGuid,
+                  (VOID **)&PackageList, ImageHandle, NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  //
+  // Publish HII package list to HII Database.
+  //
+  Status = gHiiDatabase->NewPackageList (gHiiDatabase, PackageList, NULL,
+                           &HiiHandle);
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+  return HiiHandle;
+}
+
+/**
+  Entry point of Linux Initrd dynamic UEFI Shell command.
+
+  Produce the DynamicCommand protocol to handle "initrd" command.
+
+  @param ImageHandle            The image handle of the process.
+  @param SystemTable            The EFI System Table pointer.
+
+  @retval EFI_SUCCESS           Initrd command is executed successfully.
+  @retval EFI_ABORTED           HII package was failed to initialize.
+  @retval others                Other errors when executing Initrd command.
+**/
+EFI_STATUS
+EFIAPI
+LinuxInitrdDynamicShellCommandEntryPoint (
+  IN EFI_HANDLE               ImageHandle,
+  IN EFI_SYSTEM_TABLE         *SystemTable
+  )
+{
+  EFI_STATUS                  Status;
+
+  mLinuxInitrdShellCommandHiiHandle = InitializeHiiPackage (ImageHandle);
+  if (mLinuxInitrdShellCommandHiiHandle == NULL) {
+    return EFI_ABORTED;
+  }
+
+  Status = gBS->InstallProtocolInterface (&ImageHandle,
+                  &gEfiShellDynamicCommandProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &mLinuxInitrdDynamicCommand);
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
+/**
+  Unload the dynamic UEFI Shell command.
+
+  @param ImageHandle            The image handle of the process.
+
+  @retval EFI_SUCCESS           The image is unloaded.
+  @retval Others                Failed to unload the image.
+**/
+EFI_STATUS
+EFIAPI
+LinuxInitrdDynamicShellCommandUnload (
+  IN EFI_HANDLE               ImageHandle
+)
+{
+  EFI_STATUS                  Status;
+
+  FreeInitrdFile ();
+
+  Status = UninstallLoadFile2Protocol ();
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gBS->UninstallProtocolInterface (ImageHandle,
+                  &gEfiShellDynamicCommandProtocolGuid,
+                  &mLinuxInitrdDynamicCommand);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  HiiRemovePackages (mLinuxInitrdShellCommandHiiHandle);
+  return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
new file mode 100644
index 000000000000..6da6ef6d7818
--- /dev/null
+++ b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
@@ -0,0 +1,53 @@
+##  @file
+# Provides 'initrd' dynamic UEFI shell command to load a Linux initrd
+# via its GUIDed vendor media path
+#
+# Copyright (c) 2020, Arm, Ltd. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 1.27
+  BASE_NAME                      = LinuxInitrdDynamicShellCommand
+  FILE_GUID                      = 2f30da26-f51b-4b6f-85c4-31873c281bca
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = LinuxInitrdDynamicShellCommandEntryPoint
+  UNLOAD_IMAGE                   = LinuxInitrdDynamicShellCommandUnload
+  UEFI_HII_RESOURCE_SECTION      = TRUE
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64 ARM AARCH64 EBC
+#
+
+[Sources.common]
+  LinuxInitrdDynamicShellCommand.c
+  LinuxInitrdDynamicShellCommand.uni
+
+[Packages]
+  MdePkg/MdePkg.dec
+  ShellPkg/ShellPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+  DebugLib
+  DevicePathLib
+  HiiLib
+  MemoryAllocationLib
+  ShellLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiHiiServicesLib
+
+[Protocols]
+  gEfiDevicePathProtocolGuid                      ## SOMETIMES_PRODUCES
+  gEfiHiiPackageListProtocolGuid                  ## CONSUMES
+  gEfiLoadFile2ProtocolGuid                       ## SOMETIMES_PRODUCES
+  gEfiShellDynamicCommandProtocolGuid             ## PRODUCES
+
+[DEPEX]
+  TRUE
diff --git a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni
new file mode 100644
index 000000000000..a88fa6e3641b
--- /dev/null
+++ b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni
@@ -0,0 +1,49 @@
+// /**
+//
+// Copyright (c) 2020, Arm, Ltd. All rights reserved.<BR>
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// Module Name:
+//
+// LinuxInitrdDynamicShellCommand.uni
+//
+// Abstract:
+//
+// String definitions for 'initrd' UEFI Shell command
+//
+// **/
+
+/=#
+
+#langdef   en-US "english"
+
+#string STR_GEN_PROBLEM           #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n"
+#string STR_GEN_TOO_MANY          #language en-US "%H%s%N: Too many arguments.\r\n"
+#string STR_GEN_TOO_FEW           #language en-US "%H%s%N: Too few arguments.\r\n"
+#string STR_GEN_FIND_FAIL         #language en-US "%H%s%N: File not found - '%H%s%N'\r\n"
+#string STR_GEN_FILE_OPEN_FAIL    #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n"
+
+#string STR_GET_HELP_INITRD       #language en-US ""
+".TH initrd 0 "Registers or unregisters a file as Linux initrd."\r\n"
+".SH NAME\r\n"
+"Registers or unregisters a file as Linux initrd.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"initrd <FileName>\r\n"
+"initrd -u\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+"  FileName    - Specifies a file to register as initrd.\r\n"
+"  -u          - Unregisters any previously registered initrd files.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+"  1. Only a single file can be loaded as initrd at any given time. Using the\r\n"
+"     command twice with a <FileName> option will result in the first file to\r\n"
+"     be unloaded again, regardless of whether the second invocation succeeded\r\n"
+"     or not.\r\n"
+"  2. The initrd is not unloaded when the shell exits, and will remain active\r\n"
+"     until it is unloaded again by a different invocation of the shell.\r\n"
+"     Consumers of the LoadFile2 protocol on the LINUX_EFI_INITRD_MEDIA_GUID\r\n"
+"     device path that are started via means other than the shell will be able\r\n"
+"     to locate the protocol and invoke it.\r\n"
-- 
2.17.1


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

* [PATCH v4 3/7] ArmVirtPkg: add the 'initrd' dynamic shell command
  2020-03-03 14:01 [PATCH v4 0/7] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
  2020-03-03 14:01 ` [PATCH v4 1/7] OvmfPkg: add definition of LINUX_EFI_INITRD_MEDIA_GUID Ard Biesheuvel
  2020-03-03 14:01 ` [PATCH v4 2/7] OvmfPkg: add 'initrd' shell command to expose Linux initrd via device path Ard Biesheuvel
@ 2020-03-03 14:01 ` Ard Biesheuvel
  2020-03-03 14:01 ` [PATCH v4 4/7] OvmfPkg: " Ard Biesheuvel
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2020-03-03 14:01 UTC (permalink / raw)
  To: devel; +Cc: Ard Biesheuvel, lersek, leif, Liming Gao

Add the 'initrd' dynamic shell command to the build so we can load
Linux initrds straight from the shell using the new generic protocol,
which does not rely on initrd= being passed on the command line.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2564
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 ArmVirtPkg/ArmVirt.dsc.inc           | 4 ++++
 ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc | 1 +
 ArmVirtPkg/ArmVirtXen.fdf            | 1 +
 3 files changed, 6 insertions(+)

diff --git a/ArmVirtPkg/ArmVirt.dsc.inc b/ArmVirtPkg/ArmVirt.dsc.inc
index 10037c938eb8..42ecd5ce1d52 100644
--- a/ArmVirtPkg/ArmVirt.dsc.inc
+++ b/ArmVirtPkg/ArmVirt.dsc.inc
@@ -379,6 +379,10 @@ [Components.common]
     <PcdsFixedAtBuild>
       gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
   }
+  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
+    <PcdsFixedAtBuild>
+      gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+  }
   ShellPkg/Application/Shell/Shell.inf {
     <LibraryClasses>
       ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
diff --git a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
index 31f615a9d0f9..bfa380815f1a 100644
--- a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
+++ b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
@@ -103,6 +103,7 @@ [FV.FvMain]
   #
   INF ShellPkg/Application/Shell/Shell.inf
   INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
+  INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
 
   #
   # Bds
diff --git a/ArmVirtPkg/ArmVirtXen.fdf b/ArmVirtPkg/ArmVirtXen.fdf
index 38d4cc163524..6a97bceeacbc 100644
--- a/ArmVirtPkg/ArmVirtXen.fdf
+++ b/ArmVirtPkg/ArmVirtXen.fdf
@@ -182,6 +182,7 @@ [FV.FvMain]
   #
   INF ShellPkg/Application/Shell/Shell.inf
   INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
+  INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
 
   #
   # Bds
-- 
2.17.1


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

* [PATCH v4 4/7] OvmfPkg: add the 'initrd' dynamic shell command
  2020-03-03 14:01 [PATCH v4 0/7] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
                   ` (2 preceding siblings ...)
  2020-03-03 14:01 ` [PATCH v4 3/7] ArmVirtPkg: add the 'initrd' dynamic shell command Ard Biesheuvel
@ 2020-03-03 14:01 ` Ard Biesheuvel
  2020-03-03 14:01 ` [PATCH v4 5/7] MdeModulePkg/DxeCore: defer PE/COFF emulator registration to StartImage Ard Biesheuvel
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2020-03-03 14:01 UTC (permalink / raw)
  To: devel; +Cc: Ard Biesheuvel, lersek, leif, Liming Gao

Add the 'initrd' dynamic shell command to the build so we can load
Linux initrds straight from the shell using the new generic protocol,
which does not rely on initrd= being passed on the command line.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2564
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/OvmfPkgIa32.dsc    | 4 ++++
 OvmfPkg/OvmfPkgIa32.fdf    | 1 +
 OvmfPkg/OvmfPkgIa32X64.dsc | 4 ++++
 OvmfPkg/OvmfPkgIa32X64.fdf | 1 +
 OvmfPkg/OvmfPkgX64.dsc     | 4 ++++
 OvmfPkg/OvmfPkgX64.fdf     | 1 +
 OvmfPkg/OvmfXen.dsc        | 4 ++++
 OvmfPkg/OvmfXen.fdf        | 1 +
 8 files changed, 20 insertions(+)

diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 19728f20b34e..76e52a3de120 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -821,6 +821,10 @@ [Components]
       gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
   }
 !endif
+  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
+    <PcdsFixedAtBuild>
+      gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+  }
   ShellPkg/Application/Shell/Shell.inf {
     <LibraryClasses>
       ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
index 63607551ed75..6c342823d206 100644
--- a/OvmfPkg/OvmfPkgIa32.fdf
+++ b/OvmfPkg/OvmfPkgIa32.fdf
@@ -281,6 +281,7 @@ [FV.DXEFV]
 !if $(TOOL_CHAIN_TAG) != "XCODE5"
 INF  ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
 !endif
+INF  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
 INF  ShellPkg/Application/Shell/Shell.inf
 
 INF MdeModulePkg/Logo/LogoDxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 3c0c229e3a72..842b4a028913 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -834,6 +834,10 @@ [Components.X64]
       gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
   }
 !endif
+  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
+    <PcdsFixedAtBuild>
+      gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+  }
   ShellPkg/Application/Shell/Shell.inf {
     <LibraryClasses>
       ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
index 0488e5d95ffe..69c133ec08d5 100644
--- a/OvmfPkg/OvmfPkgIa32X64.fdf
+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
@@ -282,6 +282,7 @@ [FV.DXEFV]
 !if $(TOOL_CHAIN_TAG) != "XCODE5"
 INF  ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
 !endif
+INF  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
 INF  ShellPkg/Application/Shell/Shell.inf
 
 INF MdeModulePkg/Logo/LogoDxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index f6c1d8d228c6..0b1e45d1f15a 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -832,6 +832,10 @@ [Components]
       gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
   }
 !endif
+  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
+    <PcdsFixedAtBuild>
+      gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+  }
   ShellPkg/Application/Shell/Shell.inf {
     <LibraryClasses>
       ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index 0488e5d95ffe..69c133ec08d5 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -282,6 +282,7 @@ [FV.DXEFV]
 !if $(TOOL_CHAIN_TAG) != "XCODE5"
 INF  ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
 !endif
+INF  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
 INF  ShellPkg/Application/Shell/Shell.inf
 
 INF MdeModulePkg/Logo/LogoDxe.inf
diff --git a/OvmfPkg/OvmfXen.dsc b/OvmfPkg/OvmfXen.dsc
index 5751ff1f0352..d476694b18d5 100644
--- a/OvmfPkg/OvmfXen.dsc
+++ b/OvmfPkg/OvmfXen.dsc
@@ -692,6 +692,10 @@ [Components]
       gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
   }
 !endif
+  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
+    <PcdsFixedAtBuild>
+      gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+  }
   ShellPkg/Application/Shell/Shell.inf {
     <LibraryClasses>
       ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
diff --git a/OvmfPkg/OvmfXen.fdf b/OvmfPkg/OvmfXen.fdf
index 05138ffc5b4f..5ca8081c0265 100644
--- a/OvmfPkg/OvmfXen.fdf
+++ b/OvmfPkg/OvmfXen.fdf
@@ -364,6 +364,7 @@ [FV.DXEFV]
 !if $(TOOL_CHAIN_TAG) != "XCODE5"
 INF  ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
 !endif
+INF  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
 INF  ShellPkg/Application/Shell/Shell.inf
 
 INF MdeModulePkg/Logo/LogoDxe.inf
-- 
2.17.1


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

* [PATCH v4 5/7] MdeModulePkg/DxeCore: defer PE/COFF emulator registration to StartImage
  2020-03-03 14:01 [PATCH v4 0/7] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
                   ` (3 preceding siblings ...)
  2020-03-03 14:01 ` [PATCH v4 4/7] OvmfPkg: " Ard Biesheuvel
@ 2020-03-03 14:01 ` Ard Biesheuvel
  2020-03-03 14:01 ` [PATCH v4 6/7] OvmfPkg IA32: add support for loading X64 images Ard Biesheuvel
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2020-03-03 14:01 UTC (permalink / raw)
  To: devel; +Cc: Ard Biesheuvel, lersek, leif, Liming Gao

EDK2's implementation of the LoadImage() boot service permits non-native
binaries to be loaded (i.e., X64 images on IA32 firmware), but any
attempts to start such an image using StartImage() will return
EFI_UNSUPPORTED.

The integration of the PE/COFF emulator protocol into the DXE core
deviates slightly from this paradigm, given that its IsImageSupported
hook as well as its RegisterImage hook are invoked from LoadImage,
and by the time StartImage is called, no opportunity is given to the
provider of the PE/COFF emulator protocol to prevent an image from
being started if it only supports loading it.

To address this disparity, let's move the invocation of RegisterImage()
to the implementation of the StartImage() boot service, allowing the
emulator to permit LoadImage() but reject StartImage() on images that
turn out not to meet the requirements of the emulator as it is being
started.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2564
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Liming Gao <liming.gao@intel.com>
---
 MdeModulePkg/Core/Dxe/Image/Image.c | 24 +++++++++++---------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/MdeModulePkg/Core/Dxe/Image/Image.c b/MdeModulePkg/Core/Dxe/Image/Image.c
index 22a87ecf6d7c..d86da89ee704 100644
--- a/MdeModulePkg/Core/Dxe/Image/Image.c
+++ b/MdeModulePkg/Core/Dxe/Image/Image.c
@@ -756,17 +756,6 @@ CoreLoadPeImage (
   // Get the image entry point.
   //
   Image->EntryPoint   = (EFI_IMAGE_ENTRY_POINT)(UINTN)Image->ImageContext.EntryPoint;
-  if (Image->PeCoffEmu != NULL) {
-    Status = Image->PeCoffEmu->RegisterImage (Image->PeCoffEmu,
-                                 Image->ImageBasePage,
-                                 EFI_PAGES_TO_SIZE (Image->NumberOfPages),
-                                 &Image->EntryPoint);
-    if (EFI_ERROR (Status)) {
-      DEBUG ((DEBUG_LOAD | DEBUG_ERROR,
-        "CoreLoadPeImage: Failed to register foreign image with emulator.\n"));
-      goto Done;
-    }
-  }
 
   //
   // Fill in the image information for the Loaded Image Protocol
@@ -1603,6 +1592,19 @@ CoreStartImage (
     return EFI_UNSUPPORTED;
   }
 
+  if (Image->PeCoffEmu != NULL) {
+    Status = Image->PeCoffEmu->RegisterImage (Image->PeCoffEmu,
+                                 Image->ImageBasePage,
+                                 EFI_PAGES_TO_SIZE (Image->NumberOfPages),
+                                 &Image->EntryPoint);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_LOAD | DEBUG_ERROR,
+        "CoreLoadPeImage: Failed to register foreign image with emulator - %r\n",
+          Status));
+      return Status;
+    }
+  }
+
   PERF_START_IMAGE_BEGIN (Handle);
 
 
-- 
2.17.1


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

* [PATCH v4 6/7] OvmfPkg IA32: add support for loading X64 images
  2020-03-03 14:01 [PATCH v4 0/7] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
                   ` (4 preceding siblings ...)
  2020-03-03 14:01 ` [PATCH v4 5/7] MdeModulePkg/DxeCore: defer PE/COFF emulator registration to StartImage Ard Biesheuvel
@ 2020-03-03 14:01 ` Ard Biesheuvel
  2020-03-03 20:54   ` [edk2-devel] " Laszlo Ersek
  2020-03-03 14:01 ` [PATCH v4 7/7] OvmfPkg/LinuxInitrdDynamicShellCommand: bail if initrd already exists Ard Biesheuvel
  2020-03-04  9:29 ` [PATCH v4 0/7] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
  7 siblings, 1 reply; 14+ messages in thread
From: Ard Biesheuvel @ 2020-03-03 14:01 UTC (permalink / raw)
  To: devel; +Cc: Ard Biesheuvel, lersek, leif, Liming Gao

This is the UEFI counterpart to my Linux series 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 header 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 shell.

This feature is based on the EDK2 specific PE/COFF emulator protocol
that was introduced in commit 57df17fe26cd ("MdeModulePkg/DxeCore:
invoke the emulator protocol for foreign images", 2019-04-14).

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2564
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c   | 143 ++++++++++++++++++++
 OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf |  37 +++++
 OvmfPkg/OvmfPkgIa32.dsc                               |   5 +
 OvmfPkg/OvmfPkgIa32.fdf                               |   4 +
 4 files changed, 189 insertions(+)

diff --git a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
new file mode 100644
index 000000000000..ae47917f1589
--- /dev/null
+++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
@@ -0,0 +1,143 @@
+/** @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/DebugLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/UefiBootServicesTableLib.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
+  )
+{
+  return ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;
+}
+
+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;
+  VOID                                  *PeCompatEnd;
+
+  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)&Pe32->OptionalHeader +
+                                         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);
+      PeCompatEnd = (UINT8 *)PeCompat + Section->Misc.VirtualSize;
+
+      while (PeCompat->Type != 0 && (VOID *)PeCompat < PeCompatEnd) {
+        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);
+        ASSERT ((VOID *)PeCompat < PeCompatEnd);
+      }
+    }
+    Section++;
+  }
+  return NULL;
+}
+
+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
+  )
+{
+  EFI_IMAGE_ENTRY_POINT                           CompatEntryPoint;
+
+  CompatEntryPoint = GetCompatEntryPoint (ImageBase);
+  if (CompatEntryPoint == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  *EntryPoint = CompatEntryPoint;
+  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..74f06c64bfbf
--- /dev/null
+++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
@@ -0,0 +1,37 @@
+## @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
+  DebugLib
+  PeCoffLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+
+[Protocols]
+  gEdkiiPeCoffImageEmulatorProtocolGuid   ## PRODUCES
+
+[Depex]
+  TRUE
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 76e52a3de120..8d91903f8b4e 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -33,6 +33,7 @@ [Defines]
   DEFINE SOURCE_DEBUG_ENABLE     = FALSE
   DEFINE TPM2_ENABLE             = FALSE
   DEFINE TPM2_CONFIG_ENABLE      = FALSE
+  DEFINE LOAD_X64_ON_IA32_ENABLE = FALSE
 
   #
   # Network definition
@@ -932,3 +933,7 @@ [Components]
   SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf
 !endif
 !endif
+
+!if $(LOAD_X64_ON_IA32_ENABLE) == TRUE
+  OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
+!endif
diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
index 6c342823d206..f57de4a26f92 100644
--- a/OvmfPkg/OvmfPkgIa32.fdf
+++ b/OvmfPkg/OvmfPkgIa32.fdf
@@ -354,6 +354,10 @@ [FV.DXEFV]
 !endif
 !endif
 
+!if $(LOAD_X64_ON_IA32_ENABLE) == TRUE
+INF  OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
+!endif
+
 ################################################################################
 
 [FV.FVMAIN_COMPACT]
-- 
2.17.1


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

* [PATCH v4 7/7] OvmfPkg/LinuxInitrdDynamicShellCommand: bail if initrd already exists
  2020-03-03 14:01 [PATCH v4 0/7] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
                   ` (5 preceding siblings ...)
  2020-03-03 14:01 ` [PATCH v4 6/7] OvmfPkg IA32: add support for loading X64 images Ard Biesheuvel
@ 2020-03-03 14:01 ` Ard Biesheuvel
  2020-03-03 21:03   ` [edk2-devel] " Laszlo Ersek
  2020-03-04  9:29 ` [PATCH v4 0/7] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
  7 siblings, 1 reply; 14+ messages in thread
From: Ard Biesheuvel @ 2020-03-03 14:01 UTC (permalink / raw)
  To: devel; +Cc: Ard Biesheuvel, lersek, leif, Liming Gao

Before taking any actions, check if an instance of the LoadFile2 exists
already on the Linux initrd media GUID device path, and whether it was
provided by this command. If so, abort, since no duplicate instances of
the device path should exist.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2564
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c   | 31 ++++++++++++++++++++
 OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni |  3 ++
 2 files changed, 34 insertions(+)

diff --git a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c
index 47ed26b50d3a..ed8fbaa77069 100644
--- a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c
+++ b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c
@@ -53,6 +53,33 @@ STATIC CONST SINGLE_NODE_VENDOR_MEDIA_DEVPATH mInitrdDevicePath = {
   }
 };
 
+STATIC
+BOOLEAN
+IsOtherInitrdDevicePathAlreadyInstalled (
+  VOID
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_DEVICE_PATH_PROTOCOL    *DevicePath;
+  EFI_HANDLE                  Handle;
+
+  DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mInitrdDevicePath;
+  Status = gBS->LocateDevicePath (&gEfiLoadFile2ProtocolGuid, &DevicePath,
+                  &Handle);
+  if (EFI_ERROR (Status)) {
+    return FALSE;
+  }
+
+  //
+  // Check whether the existing instance is one that we installed during
+  // a previous invocation.
+  //
+  if (Handle == mInitrdLoadFile2Handle) {
+    return FALSE;
+  }
+  return TRUE;
+}
+
 STATIC
 EFI_STATUS
 EFIAPI
@@ -217,6 +244,10 @@ RunInitrd (
     } else {
       ASSERT(FALSE);
     }
+  } else if (IsOtherInitrdDevicePathAlreadyInstalled ()) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ALREADY_INSTALLED),
+      mLinuxInitrdShellCommandHiiHandle, L"initrd");
+    ShellStatus = SHELL_UNSUPPORTED;
   } else {
     if (ShellCommandLineGetCount (Package) > 2) {
       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY),
diff --git a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni
index a88fa6e3641b..4b6b1285fffd 100644
--- a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni
+++ b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni
@@ -18,6 +18,7 @@
 #langdef   en-US "english"
 
 #string STR_GEN_PROBLEM           #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n"
+#string STR_GEN_ALREADY_INSTALLED #language en-US "%H%s%N: Linux initrd already provided by platform\r\n"
 #string STR_GEN_TOO_MANY          #language en-US "%H%s%N: Too many arguments.\r\n"
 #string STR_GEN_TOO_FEW           #language en-US "%H%s%N: Too few arguments.\r\n"
 #string STR_GEN_FIND_FAIL         #language en-US "%H%s%N: File not found - '%H%s%N'\r\n"
@@ -47,3 +48,5 @@
 "     Consumers of the LoadFile2 protocol on the LINUX_EFI_INITRD_MEDIA_GUID\r\n"
 "     device path that are started via means other than the shell will be able\r\n"
 "     to locate the protocol and invoke it.\r\n"
+"  3. Exposing an initrd using this command is only supported if no initrd is\r\n"
+"     already being exposed by another driver on the platform.\r\n"
-- 
2.17.1


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

* Re: [edk2-devel] [PATCH v4 6/7] OvmfPkg IA32: add support for loading X64 images
  2020-03-03 14:01 ` [PATCH v4 6/7] OvmfPkg IA32: add support for loading X64 images Ard Biesheuvel
@ 2020-03-03 20:54   ` Laszlo Ersek
  2020-03-03 21:53     ` Ard Biesheuvel
  0 siblings, 1 reply; 14+ messages in thread
From: Laszlo Ersek @ 2020-03-03 20:54 UTC (permalink / raw)
  To: devel, ard.biesheuvel; +Cc: leif, Liming Gao

On 03/03/20 15:01, Ard Biesheuvel wrote:
> This is the UEFI counterpart to my Linux series 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 header 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 shell.
> 
> This feature is based on the EDK2 specific PE/COFF emulator protocol
> that was introduced in commit 57df17fe26cd ("MdeModulePkg/DxeCore:
> invoke the emulator protocol for foreign images", 2019-04-14).
> 
> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2564
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Acked-by: Laszlo Ersek <lersek@redhat.com>
> ---
>  OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c   | 143 ++++++++++++++++++++
>  OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf |  37 +++++
>  OvmfPkg/OvmfPkgIa32.dsc                               |   5 +
>  OvmfPkg/OvmfPkgIa32.fdf                               |   4 +
>  4 files changed, 189 insertions(+)
> 
> diff --git a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
> new file mode 100644
> index 000000000000..ae47917f1589
> --- /dev/null
> +++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
> @@ -0,0 +1,143 @@
> +/** @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/DebugLib.h>
> +#include <Library/PeCoffLib.h>
> +#include <Library/UefiBootServicesTableLib.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
> +  )
> +{
> +  return ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;
> +}
> +
> +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;
> +  VOID                                  *PeCompatEnd;
> +
> +  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)&Pe32->OptionalHeader +
> +                                         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);
> +      PeCompatEnd = (UINT8 *)PeCompat + Section->Misc.VirtualSize;
> +
> +      while (PeCompat->Type != 0 && (VOID *)PeCompat < PeCompatEnd) {
> +        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);
> +        ASSERT ((VOID *)PeCompat < PeCompatEnd);

The new pointer comparisons make me really uncomfortable. They look
doubly undefined:

(a) comparing (VOID*) against a pointer to a complete type. The C99
standard says:

------
6.5.8 Relational operators

Constraints

2 One of the following shall hold:
  - both operands have real type;
  - both operands are pointers to qualified or unqualified versions of
    compatible object types; or
  - both operands are pointers to qualified or unqualified versions of
    compatible incomplete types.
------

"void" is an incomplete type that cannot be completed (it is never an
"object type"), and PE_COMPAT_TYPE1 is a complete type (we know its
size). So none of the permitted cases apply.

(b) I don't want to quote all of paragraph 5, but the point is, the
comparisons invoke undefined behavior *at least* when we'd expect them
to evaluate to FALSE. (Basically: when PeCompat does not point to an
element in the array whose last element PeCompatEnd points one past.)


As one alternative, please introduce "PeCompatEnd" as UINTN, set it with:

  PeCompatEnd = (UINTN)(VOID *)PeCompat + Section->Misc.VirtualSize;

and replace the

  (VOID *)PeCompat < PeCompatEnd

comparisons with

  (UINTN)(VOID *)PeCompat < PeCompatEnd

I'm not requesting a repost just for this, you can keep the A-b.

Thanks
Laszlo



> +      }
> +    }
> +    Section++;
> +  }
> +  return NULL;
> +}
> +
> +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
> +  )
> +{
> +  EFI_IMAGE_ENTRY_POINT                           CompatEntryPoint;
> +
> +  CompatEntryPoint = GetCompatEntryPoint (ImageBase);
> +  if (CompatEntryPoint == NULL) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  *EntryPoint = CompatEntryPoint;
> +  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..74f06c64bfbf
> --- /dev/null
> +++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
> @@ -0,0 +1,37 @@
> +## @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
> +  DebugLib
> +  PeCoffLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +
> +[Protocols]
> +  gEdkiiPeCoffImageEmulatorProtocolGuid   ## PRODUCES
> +
> +[Depex]
> +  TRUE
> diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
> index 76e52a3de120..8d91903f8b4e 100644
> --- a/OvmfPkg/OvmfPkgIa32.dsc
> +++ b/OvmfPkg/OvmfPkgIa32.dsc
> @@ -33,6 +33,7 @@ [Defines]
>    DEFINE SOURCE_DEBUG_ENABLE     = FALSE
>    DEFINE TPM2_ENABLE             = FALSE
>    DEFINE TPM2_CONFIG_ENABLE      = FALSE
> +  DEFINE LOAD_X64_ON_IA32_ENABLE = FALSE
>  
>    #
>    # Network definition
> @@ -932,3 +933,7 @@ [Components]
>    SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf
>  !endif
>  !endif
> +
> +!if $(LOAD_X64_ON_IA32_ENABLE) == TRUE
> +  OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
> +!endif
> diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
> index 6c342823d206..f57de4a26f92 100644
> --- a/OvmfPkg/OvmfPkgIa32.fdf
> +++ b/OvmfPkg/OvmfPkgIa32.fdf
> @@ -354,6 +354,10 @@ [FV.DXEFV]
>  !endif
>  !endif
>  
> +!if $(LOAD_X64_ON_IA32_ENABLE) == TRUE
> +INF  OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
> +!endif
> +
>  ################################################################################
>  
>  [FV.FVMAIN_COMPACT]
> 


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

* Re: [edk2-devel] [PATCH v4 7/7] OvmfPkg/LinuxInitrdDynamicShellCommand: bail if initrd already exists
  2020-03-03 14:01 ` [PATCH v4 7/7] OvmfPkg/LinuxInitrdDynamicShellCommand: bail if initrd already exists Ard Biesheuvel
@ 2020-03-03 21:03   ` Laszlo Ersek
  2020-03-03 21:08     ` Laszlo Ersek
  0 siblings, 1 reply; 14+ messages in thread
From: Laszlo Ersek @ 2020-03-03 21:03 UTC (permalink / raw)
  To: devel, ard.biesheuvel; +Cc: leif, Liming Gao

On 03/03/20 15:01, Ard Biesheuvel wrote:
> Before taking any actions, check if an instance of the LoadFile2 exists
> already on the Linux initrd media GUID device path, and whether it was
> provided by this command. If so, abort, since no duplicate instances of
> the device path should exist.
> 
> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2564
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c   | 31 ++++++++++++++++++++
>  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni |  3 ++
>  2 files changed, 34 insertions(+)
> 
> diff --git a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c
> index 47ed26b50d3a..ed8fbaa77069 100644
> --- a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c
> +++ b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c
> @@ -53,6 +53,33 @@ STATIC CONST SINGLE_NODE_VENDOR_MEDIA_DEVPATH mInitrdDevicePath = {
>    }
>  };
>  
> +STATIC
> +BOOLEAN
> +IsOtherInitrdDevicePathAlreadyInstalled (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  EFI_DEVICE_PATH_PROTOCOL    *DevicePath;
> +  EFI_HANDLE                  Handle;
> +
> +  DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mInitrdDevicePath;
> +  Status = gBS->LocateDevicePath (&gEfiLoadFile2ProtocolGuid, &DevicePath,
> +                  &Handle);
> +  if (EFI_ERROR (Status)) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Check whether the existing instance is one that we installed during
> +  // a previous invocation.
> +  //
> +  if (Handle == mInitrdLoadFile2Handle) {
> +    return FALSE;
> +  }
> +  return TRUE;
> +}

Looks good, the function will return TRUE when mInitrdLoadFile2Handle is
NULL.

Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Thanks
Laszlo


> +
>  STATIC
>  EFI_STATUS
>  EFIAPI
> @@ -217,6 +244,10 @@ RunInitrd (
>      } else {
>        ASSERT(FALSE);
>      }
> +  } else if (IsOtherInitrdDevicePathAlreadyInstalled ()) {
> +    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ALREADY_INSTALLED),
> +      mLinuxInitrdShellCommandHiiHandle, L"initrd");
> +    ShellStatus = SHELL_UNSUPPORTED;
>    } else {
>      if (ShellCommandLineGetCount (Package) > 2) {
>        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY),
> diff --git a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni
> index a88fa6e3641b..4b6b1285fffd 100644
> --- a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni
> +++ b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni
> @@ -18,6 +18,7 @@
>  #langdef   en-US "english"
>  
>  #string STR_GEN_PROBLEM           #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n"
> +#string STR_GEN_ALREADY_INSTALLED #language en-US "%H%s%N: Linux initrd already provided by platform\r\n"
>  #string STR_GEN_TOO_MANY          #language en-US "%H%s%N: Too many arguments.\r\n"
>  #string STR_GEN_TOO_FEW           #language en-US "%H%s%N: Too few arguments.\r\n"
>  #string STR_GEN_FIND_FAIL         #language en-US "%H%s%N: File not found - '%H%s%N'\r\n"
> @@ -47,3 +48,5 @@
>  "     Consumers of the LoadFile2 protocol on the LINUX_EFI_INITRD_MEDIA_GUID\r\n"
>  "     device path that are started via means other than the shell will be able\r\n"
>  "     to locate the protocol and invoke it.\r\n"
> +"  3. Exposing an initrd using this command is only supported if no initrd is\r\n"
> +"     already being exposed by another driver on the platform.\r\n"
> 


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

* Re: [edk2-devel] [PATCH v4 7/7] OvmfPkg/LinuxInitrdDynamicShellCommand: bail if initrd already exists
  2020-03-03 21:03   ` [edk2-devel] " Laszlo Ersek
@ 2020-03-03 21:08     ` Laszlo Ersek
  2020-03-03 21:53       ` Ard Biesheuvel
  0 siblings, 1 reply; 14+ messages in thread
From: Laszlo Ersek @ 2020-03-03 21:08 UTC (permalink / raw)
  To: devel, ard.biesheuvel; +Cc: leif, Liming Gao

On 03/03/20 22:03, Laszlo Ersek wrote:
> On 03/03/20 15:01, Ard Biesheuvel wrote:
>> Before taking any actions, check if an instance of the LoadFile2 exists
>> already on the Linux initrd media GUID device path, and whether it was
>> provided by this command. If so, abort, since no duplicate instances of
>> the device path should exist.
>>
>> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2564
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>>  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c   | 31 ++++++++++++++++++++
>>  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni |  3 ++
>>  2 files changed, 34 insertions(+)
>>
>> diff --git a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c
>> index 47ed26b50d3a..ed8fbaa77069 100644
>> --- a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c
>> +++ b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c
>> @@ -53,6 +53,33 @@ STATIC CONST SINGLE_NODE_VENDOR_MEDIA_DEVPATH mInitrdDevicePath = {
>>    }
>>  };
>>  
>> +STATIC
>> +BOOLEAN
>> +IsOtherInitrdDevicePathAlreadyInstalled (
>> +  VOID
>> +  )
>> +{
>> +  EFI_STATUS                  Status;
>> +  EFI_DEVICE_PATH_PROTOCOL    *DevicePath;
>> +  EFI_HANDLE                  Handle;
>> +
>> +  DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mInitrdDevicePath;
>> +  Status = gBS->LocateDevicePath (&gEfiLoadFile2ProtocolGuid, &DevicePath,
>> +                  &Handle);
>> +  if (EFI_ERROR (Status)) {
>> +    return FALSE;
>> +  }
>> +
>> +  //
>> +  // Check whether the existing instance is one that we installed during
>> +  // a previous invocation.
>> +  //
>> +  if (Handle == mInitrdLoadFile2Handle) {
>> +    return FALSE;
>> +  }
>> +  return TRUE;
>> +}
> 
> Looks good, the function will return TRUE when mInitrdLoadFile2Handle is
> NULL.

To clarify, what I mean is that the controlling expression

  (Handle == mInitrdLoadFile2Handle)

assuming it is reached, will evaluate to 0, if mInitrdLoadFile2Handle is
NULL. That's because Handle cannot be NULL at that point. Hence the
function will return TRUE.

Thanks
Laszlo

> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> 
> Thanks
> Laszlo
> 
> 
>> +
>>  STATIC
>>  EFI_STATUS
>>  EFIAPI
>> @@ -217,6 +244,10 @@ RunInitrd (
>>      } else {
>>        ASSERT(FALSE);
>>      }
>> +  } else if (IsOtherInitrdDevicePathAlreadyInstalled ()) {
>> +    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ALREADY_INSTALLED),
>> +      mLinuxInitrdShellCommandHiiHandle, L"initrd");
>> +    ShellStatus = SHELL_UNSUPPORTED;
>>    } else {
>>      if (ShellCommandLineGetCount (Package) > 2) {
>>        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY),
>> diff --git a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni
>> index a88fa6e3641b..4b6b1285fffd 100644
>> --- a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni
>> +++ b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni
>> @@ -18,6 +18,7 @@
>>  #langdef   en-US "english"
>>  
>>  #string STR_GEN_PROBLEM           #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n"
>> +#string STR_GEN_ALREADY_INSTALLED #language en-US "%H%s%N: Linux initrd already provided by platform\r\n"
>>  #string STR_GEN_TOO_MANY          #language en-US "%H%s%N: Too many arguments.\r\n"
>>  #string STR_GEN_TOO_FEW           #language en-US "%H%s%N: Too few arguments.\r\n"
>>  #string STR_GEN_FIND_FAIL         #language en-US "%H%s%N: File not found - '%H%s%N'\r\n"
>> @@ -47,3 +48,5 @@
>>  "     Consumers of the LoadFile2 protocol on the LINUX_EFI_INITRD_MEDIA_GUID\r\n"
>>  "     device path that are started via means other than the shell will be able\r\n"
>>  "     to locate the protocol and invoke it.\r\n"
>> +"  3. Exposing an initrd using this command is only supported if no initrd is\r\n"
>> +"     already being exposed by another driver on the platform.\r\n"
>>
> 


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

* Re: [edk2-devel] [PATCH v4 7/7] OvmfPkg/LinuxInitrdDynamicShellCommand: bail if initrd already exists
  2020-03-03 21:08     ` Laszlo Ersek
@ 2020-03-03 21:53       ` Ard Biesheuvel
  0 siblings, 0 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2020-03-03 21:53 UTC (permalink / raw)
  To: edk2-devel-groups-io, Laszlo Ersek; +Cc: Leif Lindholm, Liming Gao

On Tue, 3 Mar 2020 at 22:08, Laszlo Ersek <lersek@redhat.com> wrote:
>
> On 03/03/20 22:03, Laszlo Ersek wrote:
> > On 03/03/20 15:01, Ard Biesheuvel wrote:
> >> Before taking any actions, check if an instance of the LoadFile2 exists
> >> already on the Linux initrd media GUID device path, and whether it was
> >> provided by this command. If so, abort, since no duplicate instances of
> >> the device path should exist.
> >>
> >> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2564
> >> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> >> ---
> >>  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c   | 31 ++++++++++++++++++++
> >>  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni |  3 ++
> >>  2 files changed, 34 insertions(+)
> >>
> >> diff --git a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c
> >> index 47ed26b50d3a..ed8fbaa77069 100644
> >> --- a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c
> >> +++ b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.c
> >> @@ -53,6 +53,33 @@ STATIC CONST SINGLE_NODE_VENDOR_MEDIA_DEVPATH mInitrdDevicePath = {
> >>    }
> >>  };
> >>
> >> +STATIC
> >> +BOOLEAN
> >> +IsOtherInitrdDevicePathAlreadyInstalled (
> >> +  VOID
> >> +  )
> >> +{
> >> +  EFI_STATUS                  Status;
> >> +  EFI_DEVICE_PATH_PROTOCOL    *DevicePath;
> >> +  EFI_HANDLE                  Handle;
> >> +
> >> +  DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mInitrdDevicePath;
> >> +  Status = gBS->LocateDevicePath (&gEfiLoadFile2ProtocolGuid, &DevicePath,
> >> +                  &Handle);
> >> +  if (EFI_ERROR (Status)) {
> >> +    return FALSE;
> >> +  }
> >> +
> >> +  //
> >> +  // Check whether the existing instance is one that we installed during
> >> +  // a previous invocation.
> >> +  //
> >> +  if (Handle == mInitrdLoadFile2Handle) {
> >> +    return FALSE;
> >> +  }
> >> +  return TRUE;
> >> +}
> >
> > Looks good, the function will return TRUE when mInitrdLoadFile2Handle is
> > NULL.
>
> To clarify, what I mean is that the controlling expression
>
>   (Handle == mInitrdLoadFile2Handle)
>
> assuming it is reached, will evaluate to 0, if mInitrdLoadFile2Handle is
> NULL. That's because Handle cannot be NULL at that point. Hence the
> function will return TRUE.
>

Indeed

> > Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> >

Thanks!

I will push this series (asl well as the TPM one for ArmVirtPkg)
tomorrow, once the stable tag is assigned.


> >
> >
> >> +
> >>  STATIC
> >>  EFI_STATUS
> >>  EFIAPI
> >> @@ -217,6 +244,10 @@ RunInitrd (
> >>      } else {
> >>        ASSERT(FALSE);
> >>      }
> >> +  } else if (IsOtherInitrdDevicePathAlreadyInstalled ()) {
> >> +    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ALREADY_INSTALLED),
> >> +      mLinuxInitrdShellCommandHiiHandle, L"initrd");
> >> +    ShellStatus = SHELL_UNSUPPORTED;
> >>    } else {
> >>      if (ShellCommandLineGetCount (Package) > 2) {
> >>        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY),
> >> diff --git a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni
> >> index a88fa6e3641b..4b6b1285fffd 100644
> >> --- a/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni
> >> +++ b/OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.uni
> >> @@ -18,6 +18,7 @@
> >>  #langdef   en-US "english"
> >>
> >>  #string STR_GEN_PROBLEM           #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n"
> >> +#string STR_GEN_ALREADY_INSTALLED #language en-US "%H%s%N: Linux initrd already provided by platform\r\n"
> >>  #string STR_GEN_TOO_MANY          #language en-US "%H%s%N: Too many arguments.\r\n"
> >>  #string STR_GEN_TOO_FEW           #language en-US "%H%s%N: Too few arguments.\r\n"
> >>  #string STR_GEN_FIND_FAIL         #language en-US "%H%s%N: File not found - '%H%s%N'\r\n"
> >> @@ -47,3 +48,5 @@
> >>  "     Consumers of the LoadFile2 protocol on the LINUX_EFI_INITRD_MEDIA_GUID\r\n"
> >>  "     device path that are started via means other than the shell will be able\r\n"
> >>  "     to locate the protocol and invoke it.\r\n"
> >> +"  3. Exposing an initrd using this command is only supported if no initrd is\r\n"
> >> +"     already being exposed by another driver on the platform.\r\n"
> >>
> >
>
>
> 
>

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

* Re: [edk2-devel] [PATCH v4 6/7] OvmfPkg IA32: add support for loading X64 images
  2020-03-03 20:54   ` [edk2-devel] " Laszlo Ersek
@ 2020-03-03 21:53     ` Ard Biesheuvel
  0 siblings, 0 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2020-03-03 21:53 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: edk2-devel-groups-io, Leif Lindholm, Liming Gao

On Tue, 3 Mar 2020 at 21:54, Laszlo Ersek <lersek@redhat.com> wrote:
>
> On 03/03/20 15:01, Ard Biesheuvel wrote:
> > This is the UEFI counterpart to my Linux series 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 header 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 shell.
> >
> > This feature is based on the EDK2 specific PE/COFF emulator protocol
> > that was introduced in commit 57df17fe26cd ("MdeModulePkg/DxeCore:
> > invoke the emulator protocol for foreign images", 2019-04-14).
> >
> > Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2564
> > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > Acked-by: Laszlo Ersek <lersek@redhat.com>
> > ---
> >  OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c   | 143 ++++++++++++++++++++
> >  OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf |  37 +++++
> >  OvmfPkg/OvmfPkgIa32.dsc                               |   5 +
> >  OvmfPkg/OvmfPkgIa32.fdf                               |   4 +
> >  4 files changed, 189 insertions(+)
> >
> > diff --git a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
> > new file mode 100644
> > index 000000000000..ae47917f1589
> > --- /dev/null
> > +++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
> > @@ -0,0 +1,143 @@
> > +/** @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/DebugLib.h>
> > +#include <Library/PeCoffLib.h>
> > +#include <Library/UefiBootServicesTableLib.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
> > +  )
> > +{
> > +  return ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;
> > +}
> > +
> > +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;
> > +  VOID                                  *PeCompatEnd;
> > +
> > +  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)&Pe32->OptionalHeader +
> > +                                         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);
> > +      PeCompatEnd = (UINT8 *)PeCompat + Section->Misc.VirtualSize;
> > +
> > +      while (PeCompat->Type != 0 && (VOID *)PeCompat < PeCompatEnd) {
> > +        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);
> > +        ASSERT ((VOID *)PeCompat < PeCompatEnd);
>
> The new pointer comparisons make me really uncomfortable. They look
> doubly undefined:
>
> (a) comparing (VOID*) against a pointer to a complete type. The C99
> standard says:
>
> ------
> 6.5.8 Relational operators
>
> Constraints
>
> 2 One of the following shall hold:
>   - both operands have real type;
>   - both operands are pointers to qualified or unqualified versions of
>     compatible object types; or
>   - both operands are pointers to qualified or unqualified versions of
>     compatible incomplete types.
> ------
>
> "void" is an incomplete type that cannot be completed (it is never an
> "object type"), and PE_COMPAT_TYPE1 is a complete type (we know its
> size). So none of the permitted cases apply.
>
> (b) I don't want to quote all of paragraph 5, but the point is, the
> comparisons invoke undefined behavior *at least* when we'd expect them
> to evaluate to FALSE. (Basically: when PeCompat does not point to an
> element in the array whose last element PeCompatEnd points one past.)
>
>
> As one alternative, please introduce "PeCompatEnd" as UINTN, set it with:
>
>   PeCompatEnd = (UINTN)(VOID *)PeCompat + Section->Misc.VirtualSize;
>
> and replace the
>
>   (VOID *)PeCompat < PeCompatEnd
>
> comparisons with
>
>   (UINTN)(VOID *)PeCompat < PeCompatEnd
>
> I'm not requesting a repost just for this, you can keep the A-b.
>

OK, thanks.

>
>
> > +      }
> > +    }
> > +    Section++;
> > +  }
> > +  return NULL;
> > +}
> > +
> > +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
> > +  )
> > +{
> > +  EFI_IMAGE_ENTRY_POINT                           CompatEntryPoint;
> > +
> > +  CompatEntryPoint = GetCompatEntryPoint (ImageBase);
> > +  if (CompatEntryPoint == NULL) {
> > +    return EFI_UNSUPPORTED;
> > +  }
> > +
> > +  *EntryPoint = CompatEntryPoint;
> > +  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..74f06c64bfbf
> > --- /dev/null
> > +++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
> > @@ -0,0 +1,37 @@
> > +## @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
> > +  DebugLib
> > +  PeCoffLib
> > +  UefiBootServicesTableLib
> > +  UefiDriverEntryPoint
> > +
> > +[Protocols]
> > +  gEdkiiPeCoffImageEmulatorProtocolGuid   ## PRODUCES
> > +
> > +[Depex]
> > +  TRUE
> > diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
> > index 76e52a3de120..8d91903f8b4e 100644
> > --- a/OvmfPkg/OvmfPkgIa32.dsc
> > +++ b/OvmfPkg/OvmfPkgIa32.dsc
> > @@ -33,6 +33,7 @@ [Defines]
> >    DEFINE SOURCE_DEBUG_ENABLE     = FALSE
> >    DEFINE TPM2_ENABLE             = FALSE
> >    DEFINE TPM2_CONFIG_ENABLE      = FALSE
> > +  DEFINE LOAD_X64_ON_IA32_ENABLE = FALSE
> >
> >    #
> >    # Network definition
> > @@ -932,3 +933,7 @@ [Components]
> >    SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf
> >  !endif
> >  !endif
> > +
> > +!if $(LOAD_X64_ON_IA32_ENABLE) == TRUE
> > +  OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
> > +!endif
> > diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
> > index 6c342823d206..f57de4a26f92 100644
> > --- a/OvmfPkg/OvmfPkgIa32.fdf
> > +++ b/OvmfPkg/OvmfPkgIa32.fdf
> > @@ -354,6 +354,10 @@ [FV.DXEFV]
> >  !endif
> >  !endif
> >
> > +!if $(LOAD_X64_ON_IA32_ENABLE) == TRUE
> > +INF  OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
> > +!endif
> > +
> >  ################################################################################
> >
> >  [FV.FVMAIN_COMPACT]
> >
>

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

* Re: [PATCH v4 0/7] OvmfPkg: implement initrd shell command and mixed mode loader
  2020-03-03 14:01 [PATCH v4 0/7] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
                   ` (6 preceding siblings ...)
  2020-03-03 14:01 ` [PATCH v4 7/7] OvmfPkg/LinuxInitrdDynamicShellCommand: bail if initrd already exists Ard Biesheuvel
@ 2020-03-04  9:29 ` Ard Biesheuvel
  7 siblings, 0 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2020-03-04  9:29 UTC (permalink / raw)
  To: edk2-devel-groups-io; +Cc: Laszlo Ersek, Leif Lindholm, Liming Gao

On Tue, 3 Mar 2020 at 15:01, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>
> This series is part of my effort to define a generic EFI boot protocol for
> Linux, i.e,. one that is the same across all different architectures that
> are able to boot Linux from EFI, and naturally reused the firmware's
> infrastructure for authenticated boot and measured boot.
>
> Path #1 ... #4 implement the 'initrd' dynamic shell command, which takes a
> file and exposes it via the LoadFile2 protocol installed on a vendor media
> device path with guid LINUX_EFI_INITRD_MEDIA_GUID. This is a Linux specific,
> but arch-agnostic way for the OS loader to load an initial ramdisk, while
> leaving the firmware (or bootloader) in charge of where the file contents
> are served from. This supersedes the currently existing solutions on Linux,
> which are either limited to loading from the same volume that the OS loader
> was loaded from, or load the initrd into memory first, and use architecture
> specific data structures to pass on the information regarding base and size.
>
> Patch #5 is an update to the integration of the PE/COFF emulator protocol,
> to align it more closely with how LoadImage() and StartImage() behave today:
> LoadImage() is not restricted to images that can execute natively on the
> platform, but also permits loading of cross-type supported images. This means
> that any judgement on whether an image can be *started* needs to be deferred
> until StartImage(), which is why the invocation of the RegisterImage()
> callback needs to be deferred as well.
>
> Patch #6 implements the PE/COFF emulator protocol so it can start X64 images
> that have been loaded on IA32 firmware. This is needed for Linux's so-called
> 'mixed mode', which is an elaborate scheme of on-the-fly translation of data
> structures and thunking into 32-bit compat mode, allowing X64 Linux kernels
> to be used on X64 capable hardware that shipped with IA32 firmware. This
> needs support from the loader, and is currently implemented in GRUB (and
> OVMF's command line kernel loader) using the EFI handover protocol, which
> relies far too much on knowledge of kernel internal data structures, and
> circumvents LoadImage and StartImage entirely.
> (Note: mixed mode support is mainly targeted at cheap Atom tablets that
> shipped with a [cheaper] 32-bit version of Windows, and so this particular
> patch is unlikely to help that use case, but it is useful for validation.)
>
> Patch #7 is new in v4, and modified the initrd Shell command so it aborts
> immediately if the Linux initrd media GUID device path already has the
> LoadFile2 protocol installed in the protocol database.
>
> With these changes in place, we can boot x86 mixed-mode Linux straight from
> the UEFI Shell
>
> Shell>initrd fs0:\initrd.img
> Shell>fs0:\bzImage root=/dev/vda2
>
> Another benefit of this approach is that we can exit cleanly from the loader
> (and back to the shell) using the Exit() boot service if any errors occur,
> whereas the EFI handover protocol enters a deadloop upon any error that
> occurs during execution of the EFI stub.
>
> Changes since v3:
> - pick up some acks
> - update patch #6 to sanity check the contents of the .compat section so
>   we don't overrun the end of the section looking for a compatible entrypoint
> - add patch #7
>
> Changes since v2:
> - incorporate Laszlo's feedback, and add R-b's - I have incorporated all the
>   feedback given, except for the structure of the shell command implementation:
>   it is not my preferred style, but it is correct, and idiomatic for the shell
>   commands I could find in the tree.
>
> Changes from v1:
> - Use a dynamic UEFI shell command, which is the recommended way of implementing
>   new shell commands that are not covered by the UEFI shell specification. It
>   also makes the command more easily usable on existing platforms, since the
>   driver can be loaded as an ordinary driver.
> - split initrd patch into 4, as requested by Laszlo
> - add patch to tweak the LoadImage/StartImage behavior wrt the PE/COFF emulator
>   protocol
> - return EFI_UNSUPPORTED from PeCoffEmu::RegisterImage() if the image does not
>   have the required .compat section
>
> [0] https://edk2.groups.io/g/devel/topic/rfc_patch_1_1_ovmfpkg_add/71177416
> [1] https://edk2.groups.io/g/devel/topic/patch_1_1_ovmfpkg_ia32_add/71272266
>
> v2: https://edk2.groups.io/g/devel/topic/patch_v2_0_6_ovmfpkg/71530294
> v3: https://edk2.groups.io/g/devel/message/54932
>
> Cc: lersek@redhat.com
> Cc: leif@nuviainc.com
> Cc: Liming Gao <liming.gao@intel.com>
>
> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2564
>
> Ard Biesheuvel (7):
>   OvmfPkg: add definition of LINUX_EFI_INITRD_MEDIA_GUID
>   OvmfPkg: add 'initrd' shell command to expose Linux initrd via device
>     path
>   ArmVirtPkg: add the 'initrd' dynamic shell command
>   OvmfPkg: add the 'initrd' dynamic shell command
>   MdeModulePkg/DxeCore: defer PE/COFF emulator registration to
>     StartImage
>   OvmfPkg IA32: add support for loading X64 images
>   OvmfPkg/LinuxInitrdDynamicShellCommand: bail if initrd already exists
>

Merged as 0980779a9ddc..ecb30848fdc9

(after incorporating Laszlo's final review comments)

Thanks all!

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

end of thread, other threads:[~2020-03-04  9:30 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-03-03 14:01 [PATCH v4 0/7] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
2020-03-03 14:01 ` [PATCH v4 1/7] OvmfPkg: add definition of LINUX_EFI_INITRD_MEDIA_GUID Ard Biesheuvel
2020-03-03 14:01 ` [PATCH v4 2/7] OvmfPkg: add 'initrd' shell command to expose Linux initrd via device path Ard Biesheuvel
2020-03-03 14:01 ` [PATCH v4 3/7] ArmVirtPkg: add the 'initrd' dynamic shell command Ard Biesheuvel
2020-03-03 14:01 ` [PATCH v4 4/7] OvmfPkg: " Ard Biesheuvel
2020-03-03 14:01 ` [PATCH v4 5/7] MdeModulePkg/DxeCore: defer PE/COFF emulator registration to StartImage Ard Biesheuvel
2020-03-03 14:01 ` [PATCH v4 6/7] OvmfPkg IA32: add support for loading X64 images Ard Biesheuvel
2020-03-03 20:54   ` [edk2-devel] " Laszlo Ersek
2020-03-03 21:53     ` Ard Biesheuvel
2020-03-03 14:01 ` [PATCH v4 7/7] OvmfPkg/LinuxInitrdDynamicShellCommand: bail if initrd already exists Ard Biesheuvel
2020-03-03 21:03   ` [edk2-devel] " Laszlo Ersek
2020-03-03 21:08     ` Laszlo Ersek
2020-03-03 21:53       ` Ard Biesheuvel
2020-03-04  9:29 ` [PATCH v4 0/7] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel

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