* [PATCH v3 1/6] OvmfPkg: add definition of LINUX_EFI_INITRD_MEDIA_GUID
2020-02-26 19:43 [PATCH v3 0/6] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
@ 2020-02-26 19:43 ` Ard Biesheuvel
2020-02-26 19:43 ` [PATCH v3 2/6] OvmfPkg: add 'initrd' shell command to expose Linux initrd via device path Ard Biesheuvel
` (5 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-26 19:43 UTC (permalink / raw)
To: devel
Cc: Ard Biesheuvel, lersek, leif, michael.d.kinney, jian.j.wang,
hao.a.wu, ray.ni, zhichao.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.
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] 16+ messages in thread
* [PATCH v3 2/6] OvmfPkg: add 'initrd' shell command to expose Linux initrd via device path
2020-02-26 19:43 [PATCH v3 0/6] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
2020-02-26 19:43 ` [PATCH v3 1/6] OvmfPkg: add definition of LINUX_EFI_INITRD_MEDIA_GUID Ard Biesheuvel
@ 2020-02-26 19:43 ` Ard Biesheuvel
2020-02-27 10:59 ` [edk2-devel] " Laszlo Ersek
2020-02-26 19:43 ` [PATCH v3 3/6] ArmVirtPkg: add the 'initrd' dynamic shell command Ard Biesheuvel
` (4 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-26 19:43 UTC (permalink / raw)
To: devel
Cc: Ard Biesheuvel, lersek, leif, michael.d.kinney, jian.j.wang,
hao.a.wu, ray.ni, zhichao.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.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
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..7ddeba0df624
--- /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;
+ CONST 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] 16+ messages in thread
* Re: [edk2-devel] [PATCH v3 2/6] OvmfPkg: add 'initrd' shell command to expose Linux initrd via device path
2020-02-26 19:43 ` [PATCH v3 2/6] OvmfPkg: add 'initrd' shell command to expose Linux initrd via device path Ard Biesheuvel
@ 2020-02-27 10:59 ` Laszlo Ersek
0 siblings, 0 replies; 16+ messages in thread
From: Laszlo Ersek @ 2020-02-27 10:59 UTC (permalink / raw)
To: devel, ard.biesheuvel
Cc: leif, michael.d.kinney, jian.j.wang, hao.a.wu, ray.ni,
zhichao.gao
On 02/26/20 20:43, Ard Biesheuvel wrote:
> 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.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> 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..7ddeba0df624
> --- /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
"BufferSize" is IN OUT, so if we wanted to align those annotations
nicely, we'd do
IN EFI_LOAD_FILE2_PROTOCOL *This,
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
IN BOOLEAN BootPolicy,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer OPTIONAL
But I'm fine with the current columns too.
One request below:
> + )
> +{
> + 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;
> + CONST 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);
(1) This FreePool() is in the wrong spot; FreePool() can't deal with
NULL (unlike free() in standard C) in general. Please move FreePool()
just one line higher up (and two spaces to the right); i.e., to the end
of the "else" branch of the (Filename == NULL) check.
With (1) addressed (no need to repost):
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Thanks!
Laszlo
> + }
> + }
> + 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"
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 3/6] ArmVirtPkg: add the 'initrd' dynamic shell command
2020-02-26 19:43 [PATCH v3 0/6] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
2020-02-26 19:43 ` [PATCH v3 1/6] OvmfPkg: add definition of LINUX_EFI_INITRD_MEDIA_GUID Ard Biesheuvel
2020-02-26 19:43 ` [PATCH v3 2/6] OvmfPkg: add 'initrd' shell command to expose Linux initrd via device path Ard Biesheuvel
@ 2020-02-26 19:43 ` Ard Biesheuvel
2020-02-26 19:43 ` [PATCH v3 4/6] OvmfPkg: " Ard Biesheuvel
` (3 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-26 19:43 UTC (permalink / raw)
To: devel
Cc: Ard Biesheuvel, lersek, leif, michael.d.kinney, jian.j.wang,
hao.a.wu, ray.ni, zhichao.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.
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] 16+ messages in thread
* [PATCH v3 4/6] OvmfPkg: add the 'initrd' dynamic shell command
2020-02-26 19:43 [PATCH v3 0/6] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
` (2 preceding siblings ...)
2020-02-26 19:43 ` [PATCH v3 3/6] ArmVirtPkg: add the 'initrd' dynamic shell command Ard Biesheuvel
@ 2020-02-26 19:43 ` Ard Biesheuvel
2020-02-27 11:06 ` [edk2-devel] " Laszlo Ersek
2020-02-26 19:43 ` [PATCH v3 5/6] MdeModulePkg/DxeCore: defer PE/COFF emulator registration to StartImage Ard Biesheuvel
` (2 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-26 19:43 UTC (permalink / raw)
To: devel
Cc: Ard Biesheuvel, lersek, leif, michael.d.kinney, jian.j.wang,
hao.a.wu, ray.ni, zhichao.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.
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..b6cd5da4f2b3 100644
--- a/OvmfPkg/OvmfPkgIa32.fdf
+++ b/OvmfPkg/OvmfPkgIa32.fdf
@@ -282,6 +282,7 @@ [FV.DXEFV]
INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
!endif
INF ShellPkg/Application/Shell/Shell.inf
+INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.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..6612018ad6a8 100644
--- a/OvmfPkg/OvmfXen.dsc
+++ b/OvmfPkg/OvmfXen.dsc
@@ -714,6 +714,10 @@ [Components]
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
}
+ OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
+ <PcdsFixedAtBuild>
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ }
OvmfPkg/PlatformDxe/Platform.inf
OvmfPkg/AmdSevDxe/AmdSevDxe.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] 16+ messages in thread
* Re: [edk2-devel] [PATCH v3 4/6] OvmfPkg: add the 'initrd' dynamic shell command
2020-02-26 19:43 ` [PATCH v3 4/6] OvmfPkg: " Ard Biesheuvel
@ 2020-02-27 11:06 ` Laszlo Ersek
2020-02-27 11:07 ` Ard Biesheuvel
0 siblings, 1 reply; 16+ messages in thread
From: Laszlo Ersek @ 2020-02-27 11:06 UTC (permalink / raw)
To: devel, ard.biesheuvel
Cc: leif, michael.d.kinney, jian.j.wang, hao.a.wu, ray.ni,
zhichao.gao
On 02/26/20 20:43, Ard Biesheuvel wrote:
> 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.
>
> 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(+)
The updates are not complete on this patch.
The order should be "tftp, initrd, shell" everywhere.
Therefore please fix the following two remaining warts (no need to repost).
(1) The order in "OvmfPkg/OvmfPkgIa32.fdf" is still wrong. (It is
currently "tftp, shell, initrd".)
(2) The order in "OvmfPkg/OvmfXen.dsc" remains wrong ("tftp, shell,
initrd").
No need to repost; with (1) and (2) fixed, you can keep the R-b.
Thanks!
Laszlo
>
> 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..b6cd5da4f2b3 100644
> --- a/OvmfPkg/OvmfPkgIa32.fdf
> +++ b/OvmfPkg/OvmfPkgIa32.fdf
> @@ -282,6 +282,7 @@ [FV.DXEFV]
> INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
> !endif
> INF ShellPkg/Application/Shell/Shell.inf
> +INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.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..6612018ad6a8 100644
> --- a/OvmfPkg/OvmfXen.dsc
> +++ b/OvmfPkg/OvmfXen.dsc
> @@ -714,6 +714,10 @@ [Components]
> gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
> gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
> }
> + OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
> + <PcdsFixedAtBuild>
> + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
> + }
>
> OvmfPkg/PlatformDxe/Platform.inf
> OvmfPkg/AmdSevDxe/AmdSevDxe.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
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [edk2-devel] [PATCH v3 4/6] OvmfPkg: add the 'initrd' dynamic shell command
2020-02-27 11:06 ` [edk2-devel] " Laszlo Ersek
@ 2020-02-27 11:07 ` Ard Biesheuvel
0 siblings, 0 replies; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-27 11:07 UTC (permalink / raw)
To: Laszlo Ersek
Cc: edk2-devel-groups-io, Leif Lindholm, Kinney, Michael D,
Jian J Wang, Wu, Hao A, Ni, Ray, Zhichao Gao
On Thu, 27 Feb 2020 at 12:07, Laszlo Ersek <lersek@redhat.com> wrote:
>
> On 02/26/20 20:43, Ard Biesheuvel wrote:
> > 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.
> >
> > 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(+)
>
> The updates are not complete on this patch.
>
> The order should be "tftp, initrd, shell" everywhere.
>
> Therefore please fix the following two remaining warts (no need to repost).
>
> (1) The order in "OvmfPkg/OvmfPkgIa32.fdf" is still wrong. (It is
> currently "tftp, shell, initrd".)
>
> (2) The order in "OvmfPkg/OvmfXen.dsc" remains wrong ("tftp, shell,
> initrd").
>
> No need to repost; with (1) and (2) fixed, you can keep the R-b.
>
Oops. Apologies for missing that.
> >
> > 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..b6cd5da4f2b3 100644
> > --- a/OvmfPkg/OvmfPkgIa32.fdf
> > +++ b/OvmfPkg/OvmfPkgIa32.fdf
> > @@ -282,6 +282,7 @@ [FV.DXEFV]
> > INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
> > !endif
> > INF ShellPkg/Application/Shell/Shell.inf
> > +INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.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..6612018ad6a8 100644
> > --- a/OvmfPkg/OvmfXen.dsc
> > +++ b/OvmfPkg/OvmfXen.dsc
> > @@ -714,6 +714,10 @@ [Components]
> > gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
> > gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
> > }
> > + OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
> > + <PcdsFixedAtBuild>
> > + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
> > + }
> >
> > OvmfPkg/PlatformDxe/Platform.inf
> > OvmfPkg/AmdSevDxe/AmdSevDxe.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
> >
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 5/6] MdeModulePkg/DxeCore: defer PE/COFF emulator registration to StartImage
2020-02-26 19:43 [PATCH v3 0/6] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
` (3 preceding siblings ...)
2020-02-26 19:43 ` [PATCH v3 4/6] OvmfPkg: " Ard Biesheuvel
@ 2020-02-26 19:43 ` Ard Biesheuvel
2020-02-27 17:10 ` Ard Biesheuvel
2020-02-26 19:43 ` [PATCH v3 6/6] OvmfPkg IA32: add support for loading X64 images Ard Biesheuvel
2020-02-27 19:40 ` [PATCH v3 0/6] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
6 siblings, 1 reply; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-26 19:43 UTC (permalink / raw)
To: devel
Cc: Ard Biesheuvel, lersek, leif, michael.d.kinney, jian.j.wang,
hao.a.wu, ray.ni, zhichao.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.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
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] 16+ messages in thread
* Re: [PATCH v3 5/6] MdeModulePkg/DxeCore: defer PE/COFF emulator registration to StartImage
2020-02-26 19:43 ` [PATCH v3 5/6] MdeModulePkg/DxeCore: defer PE/COFF emulator registration to StartImage Ard Biesheuvel
@ 2020-02-27 17:10 ` Ard Biesheuvel
2020-02-28 12:02 ` [edk2-devel] " Liming Gao
0 siblings, 1 reply; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-27 17:10 UTC (permalink / raw)
To: edk2-devel-groups-io, Wu, Hao A, Jian J Wang, Zhichao Gao,
Ni, Ray
Cc: Laszlo Ersek, Leif Lindholm, Kinney, Michael D
On Wed, 26 Feb 2020 at 20:43, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>
> 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.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
@MdeModulePkg maintainers: do you have any comments on this patch?
> ---
> 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 [flat|nested] 16+ messages in thread
* Re: [edk2-devel] [PATCH v3 5/6] MdeModulePkg/DxeCore: defer PE/COFF emulator registration to StartImage
2020-02-27 17:10 ` Ard Biesheuvel
@ 2020-02-28 12:02 ` Liming Gao
0 siblings, 0 replies; 16+ messages in thread
From: Liming Gao @ 2020-02-28 12:02 UTC (permalink / raw)
To: devel@edk2.groups.io, ard.biesheuvel@linaro.org, Wu, Hao A,
Wang, Jian J, Gao, Zhichao, Ni, Ray
Cc: Laszlo Ersek, Leif Lindholm, Kinney, Michael D
Ard:
I think this change is OK. Ack-by: Liming Gao <liming.gao@intel.com>
Thanks
Liming
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Ard Biesheuvel
> Sent: Friday, February 28, 2020 1:11 AM
> To: edk2-devel-groups-io <devel@edk2.groups.io>; Wu, Hao A <hao.a.wu@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Gao,
> Zhichao <zhichao.gao@intel.com>; Ni, Ray <ray.ni@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>; Leif Lindholm <leif@nuviainc.com>; Kinney, Michael D <michael.d.kinney@intel.com>
> Subject: Re: [edk2-devel] [PATCH v3 5/6] MdeModulePkg/DxeCore: defer PE/COFF emulator registration to StartImage
>
> On Wed, 26 Feb 2020 at 20:43, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> >
> > 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.
> >
> > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>
> @MdeModulePkg maintainers: do you have any comments on this patch?
>
>
> > ---
> > 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 [flat|nested] 16+ messages in thread
* [PATCH v3 6/6] OvmfPkg IA32: add support for loading X64 images
2020-02-26 19:43 [PATCH v3 0/6] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
` (4 preceding siblings ...)
2020-02-26 19:43 ` [PATCH v3 5/6] MdeModulePkg/DxeCore: defer PE/COFF emulator registration to StartImage Ard Biesheuvel
@ 2020-02-26 19:43 ` Ard Biesheuvel
2020-02-26 20:32 ` [edk2-devel] " Brian J. Johnson
2020-02-27 19:40 ` [PATCH v3 0/6] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
6 siblings, 1 reply; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-26 19:43 UTC (permalink / raw)
To: devel
Cc: Ard Biesheuvel, lersek, leif, michael.d.kinney, jian.j.wang,
hao.a.wu, ray.ni, zhichao.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).
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Laszlo Ersek <lersek@redhat.com>
---
OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c | 139 ++++++++++++++++++++
OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf | 36 +++++
OvmfPkg/OvmfPkgIa32.dsc | 5 +
OvmfPkg/OvmfPkgIa32.fdf | 4 +
4 files changed, 184 insertions(+)
diff --git a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
new file mode 100644
index 000000000000..6dc07f467752
--- /dev/null
+++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
@@ -0,0 +1,139 @@
+/** @file
+ * PE/COFF emulator protocol implementation to start Linux kernel
+ * images from non-native firmware
+ *
+ * Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ *
+ */
+
+#include <PiDxe.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <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;
+
+ 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);
+
+ while (PeCompat->Type != 0) {
+ if (PeCompat->Type == 1 &&
+ PeCompat->Size >= sizeof (PE_COMPAT_TYPE1) &&
+ EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCompat->MachineType)) {
+
+ return (EFI_IMAGE_ENTRY_POINT)((UINTN)ImageBase + PeCompat->EntryPoint);
+ }
+ PeCompat = (PE_COMPAT_TYPE1 *)((UINTN)PeCompat + PeCompat->Size);
+ }
+ }
+ Section++;
+ }
+ return NULL;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+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..82369384fbe6
--- /dev/null
+++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
@@ -0,0 +1,36 @@
+## @file
+# PE/COFF emulator protocol implementation to start Linux kernel
+# images from non-native firmware
+#
+# Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.27
+ BASE_NAME = CompatImageLoaderDxe
+ FILE_GUID = 1019f54a-2560-41b2-87b0-6750b98f3eff
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = CompatImageLoaderDxeEntryPoint
+
+[Sources]
+ CompatImageLoaderDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ PeCoffLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Protocols]
+ gEdkiiPeCoffImageEmulatorProtocolGuid ## PRODUCES
+
+[Depex]
+ TRUE
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 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 b6cd5da4f2b3..ff8d80859fb9 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] 16+ messages in thread
* Re: [edk2-devel] [PATCH v3 6/6] OvmfPkg IA32: add support for loading X64 images
2020-02-26 19:43 ` [PATCH v3 6/6] OvmfPkg IA32: add support for loading X64 images Ard Biesheuvel
@ 2020-02-26 20:32 ` Brian J. Johnson
2020-02-26 21:40 ` Ard Biesheuvel
0 siblings, 1 reply; 16+ messages in thread
From: Brian J. Johnson @ 2020-02-26 20:32 UTC (permalink / raw)
To: devel, ard.biesheuvel
Cc: lersek, leif, michael.d.kinney, jian.j.wang, hao.a.wu, ray.ni,
zhichao.gao
On 2/26/20 1:43 PM, 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).
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Acked-by: Laszlo Ersek <lersek@redhat.com>
> ---
> OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c | 139 ++++++++++++++++++++
> OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf | 36 +++++
> OvmfPkg/OvmfPkgIa32.dsc | 5 +
> OvmfPkg/OvmfPkgIa32.fdf | 4 +
> 4 files changed, 184 insertions(+)
>
> diff --git a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
> new file mode 100644
> index 000000000000..6dc07f467752
> --- /dev/null
> +++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
> @@ -0,0 +1,139 @@
> +/** @file
> + * PE/COFF emulator protocol implementation to start Linux kernel
> + * images from non-native firmware
> + *
> + * Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
> + *
> + * SPDX-License-Identifier: BSD-2-Clause-Patent
> + *
> + */
> +
> +#include <PiDxe.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/PeCoffLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <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;
> +
> + 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);
> +
> + while (PeCompat->Type != 0) {
> + if (PeCompat->Type == 1 &&
> + PeCompat->Size >= sizeof (PE_COMPAT_TYPE1) &&
> + EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCompat->MachineType)) {
> +
> + return (EFI_IMAGE_ENTRY_POINT)((UINTN)ImageBase + PeCompat->EntryPoint);
> + }
> + PeCompat = (PE_COMPAT_TYPE1 *)((UINTN)PeCompat + PeCompat->Size);
> + }
Ard,
Cool patch series!
I'm not an official reviewer, but I'd feel better about this patch if
you added a condition to exit the "while (PeCompat->Type != 0)" loop if
PeCompat ever gets pointed outside of the section. Otherwise a
malformed or corrupted .compat section could send you off dereferencing
anything at all.
Similarly, it wouldn't hurt to sanity check the header fields, such as
e_lfanew, OptionalHeader, SizeOfOptionalHeader, and NumberOfSections (or
at least verify that all pointers you calculate from them point within
the overall image. Or has that already been done by the PeCoff loader
by the time this code is called?
Thanks,
Brian J. Johnson
> + }
> + 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..82369384fbe6
> --- /dev/null
> +++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
> @@ -0,0 +1,36 @@
> +## @file
> +# PE/COFF emulator protocol implementation to start Linux kernel
> +# images from non-native firmware
> +#
> +# Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> + INF_VERSION = 1.27
> + BASE_NAME = CompatImageLoaderDxe
> + FILE_GUID = 1019f54a-2560-41b2-87b0-6750b98f3eff
> + MODULE_TYPE = DXE_DRIVER
> + VERSION_STRING = 1.0
> + ENTRY_POINT = CompatImageLoaderDxeEntryPoint
> +
> +[Sources]
> + CompatImageLoaderDxe.c
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> + BaseMemoryLib
> + PeCoffLib
> + UefiBootServicesTableLib
> + UefiDriverEntryPoint
> +
> +[Protocols]
> + gEdkiiPeCoffImageEmulatorProtocolGuid ## PRODUCES
> +
> +[Depex]
> + TRUE
> diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
> index 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 b6cd5da4f2b3..ff8d80859fb9 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]
>
--
Brian
--------------------------------------------------------------------
"I don't believe personal letters sent bulk rate."
-- me
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [edk2-devel] [PATCH v3 6/6] OvmfPkg IA32: add support for loading X64 images
2020-02-26 20:32 ` [edk2-devel] " Brian J. Johnson
@ 2020-02-26 21:40 ` Ard Biesheuvel
2020-02-27 11:10 ` Laszlo Ersek
0 siblings, 1 reply; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-26 21:40 UTC (permalink / raw)
To: Brian J. Johnson
Cc: edk2-devel-groups-io, Laszlo Ersek, Leif Lindholm,
Kinney, Michael D, Jian J Wang, Wu, Hao A, Ni, Ray, Zhichao Gao
On Wed, 26 Feb 2020 at 21:32, Brian J. Johnson <brian.johnson@hpe.com> wrote:
>
> On 2/26/20 1:43 PM, 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).
> >
> > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > Acked-by: Laszlo Ersek <lersek@redhat.com>
> > ---
> > OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c | 139 ++++++++++++++++++++
> > OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf | 36 +++++
> > OvmfPkg/OvmfPkgIa32.dsc | 5 +
> > OvmfPkg/OvmfPkgIa32.fdf | 4 +
> > 4 files changed, 184 insertions(+)
> >
> > diff --git a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
> > new file mode 100644
> > index 000000000000..6dc07f467752
> > --- /dev/null
> > +++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
> > @@ -0,0 +1,139 @@
> > +/** @file
> > + * PE/COFF emulator protocol implementation to start Linux kernel
> > + * images from non-native firmware
> > + *
> > + * Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
> > + *
> > + * SPDX-License-Identifier: BSD-2-Clause-Patent
> > + *
> > + */
> > +
> > +#include <PiDxe.h>
> > +
> > +#include <Library/BaseMemoryLib.h>
> > +#include <Library/PeCoffLib.h>
> > +#include <Library/UefiBootServicesTableLib.h>
> > +
> > +#include <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;
> > +
> > + 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);
> > +
> > + while (PeCompat->Type != 0) {
> > + if (PeCompat->Type == 1 &&
> > + PeCompat->Size >= sizeof (PE_COMPAT_TYPE1) &&
> > + EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCompat->MachineType)) {
> > +
> > + return (EFI_IMAGE_ENTRY_POINT)((UINTN)ImageBase + PeCompat->EntryPoint);
> > + }
> > + PeCompat = (PE_COMPAT_TYPE1 *)((UINTN)PeCompat + PeCompat->Size);
> > + }
>
> Ard,
>
> Cool patch series!
>
Thanks!
> I'm not an official reviewer, but I'd feel better about this patch if
> you added a condition to exit the "while (PeCompat->Type != 0)" loop if
> PeCompat ever gets pointed outside of the section. Otherwise a
> malformed or corrupted .compat section could send you off dereferencing
> anything at all.
>
Good point, I'll look into that.
> Similarly, it wouldn't hurt to sanity check the header fields, such as
> e_lfanew, OptionalHeader, SizeOfOptionalHeader, and NumberOfSections (or
> at least verify that all pointers you calculate from them point within
> the overall image. Or has that already been done by the PeCoff loader
> by the time this code is called?
>
At this point, we should be able to rely on the LoadImage() boot
service to have sanity checked the headers, since we also have to rely
on the section having been copied into memory at the correct address.
> > + }
> > + 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..82369384fbe6
> > --- /dev/null
> > +++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
> > @@ -0,0 +1,36 @@
> > +## @file
> > +# PE/COFF emulator protocol implementation to start Linux kernel
> > +# images from non-native firmware
> > +#
> > +# Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
> > +#
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +
> > +[Defines]
> > + INF_VERSION = 1.27
> > + BASE_NAME = CompatImageLoaderDxe
> > + FILE_GUID = 1019f54a-2560-41b2-87b0-6750b98f3eff
> > + MODULE_TYPE = DXE_DRIVER
> > + VERSION_STRING = 1.0
> > + ENTRY_POINT = CompatImageLoaderDxeEntryPoint
> > +
> > +[Sources]
> > + CompatImageLoaderDxe.c
> > +
> > +[Packages]
> > + MdePkg/MdePkg.dec
> > + MdeModulePkg/MdeModulePkg.dec
> > +
> > +[LibraryClasses]
> > + BaseMemoryLib
> > + PeCoffLib
> > + UefiBootServicesTableLib
> > + UefiDriverEntryPoint
> > +
> > +[Protocols]
> > + gEdkiiPeCoffImageEmulatorProtocolGuid ## PRODUCES
> > +
> > +[Depex]
> > + TRUE
> > diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
> > index 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 b6cd5da4f2b3..ff8d80859fb9 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]
> >
>
>
> --
>
> Brian
>
> --------------------------------------------------------------------
>
> "I don't believe personal letters sent bulk rate."
> -- me
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [edk2-devel] [PATCH v3 6/6] OvmfPkg IA32: add support for loading X64 images
2020-02-26 21:40 ` Ard Biesheuvel
@ 2020-02-27 11:10 ` Laszlo Ersek
0 siblings, 0 replies; 16+ messages in thread
From: Laszlo Ersek @ 2020-02-27 11:10 UTC (permalink / raw)
To: Ard Biesheuvel, Brian J. Johnson
Cc: edk2-devel-groups-io, Leif Lindholm, Kinney, Michael D,
Jian J Wang, Wu, Hao A, Ni, Ray, Zhichao Gao
On 02/26/20 22:40, Ard Biesheuvel wrote:
> On Wed, 26 Feb 2020 at 21:32, Brian J. Johnson <brian.johnson@hpe.com> wrote:
>>
>> I'm not an official reviewer, but I'd feel better about this patch if
>> you added a condition to exit the "while (PeCompat->Type != 0)" loop if
>> PeCompat ever gets pointed outside of the section. Otherwise a
>> malformed or corrupted .compat section could send you off dereferencing
>> anything at all.
>>
>
> Good point, I'll look into that.
You can keep my Acked-by if this is going to be the only change for this
patch, in v4.
Thanks
Laszlo
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 0/6] OvmfPkg: implement initrd shell command and mixed mode loader
2020-02-26 19:43 [PATCH v3 0/6] OvmfPkg: implement initrd shell command and mixed mode loader Ard Biesheuvel
` (5 preceding siblings ...)
2020-02-26 19:43 ` [PATCH v3 6/6] OvmfPkg IA32: add support for loading X64 images Ard Biesheuvel
@ 2020-02-27 19:40 ` Ard Biesheuvel
6 siblings, 0 replies; 16+ messages in thread
From: Ard Biesheuvel @ 2020-02-27 19:40 UTC (permalink / raw)
To: edk2-devel-groups-io
Cc: Laszlo Ersek, Leif Lindholm, Kinney, Michael D, Jian J Wang,
Wu, Hao A, Ni, Ray, Zhichao Gao
On Wed, 26 Feb 2020 at 20:43, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>
> This is tagged as a v2 since it is a followup to a couple of patches [0][1]
> that have already been sent to the list.
>
> 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.
>
Logged as https://bugzilla.tianocore.org/show_bug.cgi?id=2564
^ permalink raw reply [flat|nested] 16+ messages in thread