From: "Ard Biesheuvel" <ard.biesheuvel@linaro.org>
To: devel@edk2.groups.io
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>,
lersek@redhat.com, leif@nuviainc.com,
Liming Gao <liming.gao@intel.com>
Subject: [PATCH v4 2/7] OvmfPkg: add 'initrd' shell command to expose Linux initrd via device path
Date: Tue, 3 Mar 2020 15:01:12 +0100 [thread overview]
Message-ID: <20200303140117.7288-3-ard.biesheuvel@linaro.org> (raw)
In-Reply-To: <20200303140117.7288-1-ard.biesheuvel@linaro.org>
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
next prev parent reply other threads:[~2020-03-03 14:01 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200303140117.7288-3-ard.biesheuvel@linaro.org \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox