From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-1.mimecast.com (us-smtp-1.mimecast.com [207.211.31.120]) by mx.groups.io with SMTP id smtpd.web12.10186.1583401903130899854 for ; Thu, 05 Mar 2020 01:51:43 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=LtnJR7RM; spf=pass (domain: redhat.com, ip: 207.211.31.120, mailfrom: lersek@redhat.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1583401902; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lhxL7tfmDHR9RK0F1zCpm4JXRzw9alvUBzdFiO2BFBo=; b=LtnJR7RMZq1I/LX1LnaDseIbXkuFa4g1+3PZUHS36Uexk/hL279Rxl12aMS+qkNMRyAQEJ YP4VL+QP83sVgc2eZlAJS5mjxbP9mk0XJbo7mYB3gJY6NbTCLwdV27hmt3WDjr8AbTq8/7 nR7ZvefPYxYNmxQ6OAlCL73NdCwRbdg= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-97-T14gCLbKPBWvLPXAIudD9A-1; Thu, 05 Mar 2020 04:51:40 -0500 X-MC-Unique: T14gCLbKPBWvLPXAIudD9A-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 3EBD418FF661; Thu, 5 Mar 2020 09:51:39 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-117-216.ams2.redhat.com [10.36.117.216]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3D45673884; Thu, 5 Mar 2020 09:51:38 +0000 (UTC) Subject: Re: [edk2-devel] [PATCH v2 04/14] OvmfPkg: provide a generic implementation of QemuLoadImageLib To: devel@edk2.groups.io, ard.biesheuvel@linaro.org References: <20200304095233.21046-1-ard.biesheuvel@linaro.org> <20200304095233.21046-5-ard.biesheuvel@linaro.org> From: "Laszlo Ersek" Message-ID: <1da5be78-4fe4-a672-9f57-d029a99cc606@redhat.com> Date: Thu, 5 Mar 2020 10:51:37 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 In-Reply-To: <20200304095233.21046-5-ard.biesheuvel@linaro.org> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On 03/04/20 10:52, Ard Biesheuvel wrote: > Implement QemuLoadImageLib, and make it load the image provided by the > QEMU_EFI_LOADER_FS_MEDIA_GUID/kernel device path that we implemented > in a preceding patch in a separate DXE driver, using only the standard > LoadImage and StartImage boot services. >=20 > Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2566 > Signed-off-by: Ard Biesheuvel > --- > OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.c | 27= 8 ++++++++++++++++++++ > OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf | 3= 8 +++ > 2 files changed, 316 insertions(+) Reviewed-by: Laszlo Ersek Thanks, Laszlo > diff --git a/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImage= Lib.c b/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.c > new file mode 100644 > index 000000000000..f5edb43cc0b9 > --- /dev/null > +++ b/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.c > @@ -0,0 +1,278 @@ > +/** @file > + Generic implementation of QemuLoadImageLib library class interface. > + > + Copyright (c) 2020, ARM Ltd. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#pragma pack (1) > +typedef struct { > + EFI_DEVICE_PATH_PROTOCOL FilePathHeader; > + CHAR16 FilePath[ARRAY_SIZE (L"kernel")]; > +} KERNEL_FILE_DEVPATH; > + > +typedef struct { > + VENDOR_DEVICE_PATH VenMediaNode; > + KERNEL_FILE_DEVPATH FileNode; > + EFI_DEVICE_PATH_PROTOCOL EndNode; > +} KERNEL_VENMEDIA_FILE_DEVPATH; > +#pragma pack () > + > +STATIC CONST KERNEL_VENMEDIA_FILE_DEVPATH mKernelDevicePath =3D { > + { > + { > + MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, > + { sizeof (VENDOR_DEVICE_PATH) } > + }, > + QEMU_KERNEL_LOADER_FS_MEDIA_GUID > + }, { > + { > + MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, > + { sizeof (KERNEL_FILE_DEVPATH) } > + }, > + L"kernel", > + }, { > + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, > + { sizeof (EFI_DEVICE_PATH_PROTOCOL) } > + } > +}; > + > +/** > + Download the kernel, the initial ramdisk, and the kernel command line = from > + QEMU's fw_cfg. The kernel will be instructed via its command line to l= oad > + the initrd from the same Simple FileSystem where the kernel was loaded= from. > + > + @param[out] ImageHandle The image handle that was allocated for > + loading the image > + @param[out] LoadedImage The loaded image protocol that was insta= lled > + on ImageHandle by the LoadImage boot ser= vice. > + > + @retval EFI_SUCCESS The image was loaded successfully. > + @retval EFI_NOT_FOUND Kernel image was not found. > + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. > + @retval EFI_PROTOCOL_ERROR Unterminated kernel command line. > + @retval EFI_ACCESS_DENIED The underlying LoadImage boot service ca= ll > + returned EFI_SECURITY_VIOLATION, and the= image > + was unloaded again. > + > + @return Error codes from any of the underlying > + functions. > +**/ > +EFI_STATUS > +EFIAPI > +QemuLoadKernelImage ( > + OUT EFI_HANDLE *ImageHandle > + ) > +{ > + EFI_STATUS Status; > + EFI_HANDLE KernelImageHandle; > + EFI_LOADED_IMAGE_PROTOCOL *KernelLoadedImage; > + UINTN CommandLineSize; > + CHAR8 *CommandLine; > + UINTN InitrdSize; > + > + // > + // Load the image. This should call back into the QEMU EFI loader file= system. > + // > + Status =3D gBS->LoadImage ( > + FALSE, // BootPolicy: exact match r= equired > + gImageHandle, // ParentImageHandle > + (EFI_DEVICE_PATH_PROTOCOL *)&mKernelDevicePath, > + NULL, // SourceBuffer > + 0, // SourceSize > + &KernelImageHandle > + ); > + switch (Status) { > + case EFI_SUCCESS: > + break; > + > + case EFI_SECURITY_VIOLATION: > + // > + // In this case, the image was loaded but failed to authenticate. > + // > + Status =3D EFI_ACCESS_DENIED; > + goto UnloadImage; > + > + default: > + DEBUG ((DEBUG_ERROR, "%a: LoadImage(): %r\n", __FUNCTION__, Status))= ; > + return Status; > + } > + > + // > + // Construct the kernel command line. > + // > + Status =3D gBS->OpenProtocol ( > + KernelImageHandle, > + &gEfiLoadedImageProtocolGuid, > + (VOID **)&KernelLoadedImage, > + gImageHandle, // AgentHandle > + NULL, // ControllerHandle > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + ASSERT_EFI_ERROR (Status); > + > + QemuFwCfgSelectItem (QemuFwCfgItemCommandLineSize); > + CommandLineSize =3D (UINTN)QemuFwCfgRead32 (); > + > + if (CommandLineSize =3D=3D 0) { > + KernelLoadedImage->LoadOptionsSize =3D 0; > + } else { > + CommandLine =3D AllocatePool (CommandLineSize); > + if (CommandLine =3D=3D NULL) { > + Status =3D EFI_OUT_OF_RESOURCES; > + goto UnloadImage; > + } > + > + QemuFwCfgSelectItem (QemuFwCfgItemCommandLineData); > + QemuFwCfgReadBytes (CommandLineSize, CommandLine); > + > + // > + // Verify NUL-termination of the command line. > + // > + if (CommandLine[CommandLineSize - 1] !=3D '\0') { > + DEBUG ((DEBUG_ERROR, "%a: kernel command line is not NUL-terminate= d\n", > + __FUNCTION__)); > + Status =3D EFI_PROTOCOL_ERROR; > + goto FreeCommandLine; > + } > + > + // > + // Drop the terminating NUL, convert to UTF-16. > + // > + KernelLoadedImage->LoadOptionsSize =3D (CommandLineSize - 1) * 2; > + } > + > + QemuFwCfgSelectItem (QemuFwCfgItemInitrdSize); > + InitrdSize =3D (UINTN)QemuFwCfgRead32 (); > + > + if (InitrdSize > 0) { > + // > + // Append ' initrd=3Dinitrd' in UTF-16. > + // > + KernelLoadedImage->LoadOptionsSize +=3D sizeof (L" initrd=3Dinitrd")= - 2; > + } > + > + if (KernelLoadedImage->LoadOptionsSize =3D=3D 0) { > + KernelLoadedImage->LoadOptions =3D NULL; > + } else { > + // > + // NUL-terminate in UTF-16. > + // > + KernelLoadedImage->LoadOptionsSize +=3D 2; > + > + KernelLoadedImage->LoadOptions =3D AllocatePool ( > + KernelLoadedImage->LoadOptionsSiz= e); > + if (KernelLoadedImage->LoadOptions =3D=3D NULL) { > + KernelLoadedImage->LoadOptionsSize =3D 0; > + Status =3D EFI_OUT_OF_RESOURCES; > + goto FreeCommandLine; > + } > + > + UnicodeSPrintAsciiFormat ( > + KernelLoadedImage->LoadOptions, > + KernelLoadedImage->LoadOptionsSize, > + "%a%a", > + (CommandLineSize =3D=3D 0) ? "" : CommandLine, > + (InitrdSize =3D=3D 0) ? "" : " initrd=3Dinitrd" > + ); > + DEBUG ((DEBUG_INFO, "%a: command line: \"%s\"\n", __FUNCTION__, > + (CHAR16 *)KernelLoadedImage->LoadOptions)); > + } > + > + *ImageHandle =3D KernelImageHandle; > + return EFI_SUCCESS; > + > +FreeCommandLine: > + if (CommandLineSize > 0) { > + FreePool (CommandLine); > + } > +UnloadImage: > + gBS->UnloadImage (KernelImageHandle); > + > + return Status; > +} > + > +/** > + Transfer control to a kernel image loaded with QemuLoadKernelImage () > + > + @param[in,out] ImageHandle Handle of image to be started. May ass= ume a > + different value on return if the image= was > + reloaded. > + > + @retval EFI_INVALID_PARAMETER ImageHandle is either an invalid image= handle > + or the image has already been initiali= zed with > + StartImage > + @retval EFI_SECURITY_VIOLATION The current platform policy specifies = that the > + image should not be started. > + > + @return Error codes returned by the started im= age > +**/ > +EFI_STATUS > +EFIAPI > +QemuStartKernelImage ( > + IN OUT EFI_HANDLE *ImageHandle > + ) > +{ > + return gBS->StartImage ( > + *ImageHandle, > + NULL, // ExitDataSize > + NULL // ExitData > + ); > +} > + > +/** > + Unloads an image loaded with QemuLoadKernelImage (). > + > + @param ImageHandle Handle that identifies the image to be > + unloaded. > + > + @retval EFI_SUCCESS The image has been unloaded. > + @retval EFI_UNSUPPORTED The image has been started, and does n= ot > + support unload. > + @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handl= e. > + > + @return Exit code from the image=E2=80=99s unl= oad function. > +**/ > +EFI_STATUS > +EFIAPI > +QemuUnloadKernelImage ( > + IN EFI_HANDLE ImageHandle > + ) > +{ > + EFI_LOADED_IMAGE_PROTOCOL *KernelLoadedImage; > + EFI_STATUS Status; > + > + Status =3D gBS->OpenProtocol ( > + ImageHandle, > + &gEfiLoadedImageProtocolGuid, > + (VOID **)&KernelLoadedImage, > + gImageHandle, // AgentHandle > + NULL, // ControllerHandle > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + if (EFI_ERROR (Status)) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (KernelLoadedImage->LoadOptions !=3D NULL) { > + FreePool (KernelLoadedImage->LoadOptions); > + KernelLoadedImage->LoadOptions =3D NULL; > + } > + KernelLoadedImage->LoadOptionsSize =3D 0; > + > + return gBS->UnloadImage (ImageHandle); > +} > diff --git a/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImage= Lib.inf b/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.i= nf > new file mode 100644 > index 000000000000..b262cb926a4d > --- /dev/null > +++ b/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf > @@ -0,0 +1,38 @@ > +## @file > +# Generic implementation of QemuLoadImageLib library class interface. > +# > +# Copyright (c) 2020, ARM Ltd. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION =3D 1.27 > + BASE_NAME =3D GenericQemuLoadImageLib > + FILE_GUID =3D 9e3e28da-c7b5-4f85-841a-84e6a9a1f1a= 0 > + MODULE_TYPE =3D BASE > + VERSION_STRING =3D 1.0 > + LIBRARY_CLASS =3D QemuLoadImageLib|DXE_DRIVER > + > +[Sources] > + GenericQemuLoadImageLib.c > + > +[Packages] > + MdeModulePkg/MdeModulePkg.dec > + MdePkg/MdePkg.dec > + OvmfPkg/OvmfPkg.dec > + > +[LibraryClasses] > + DebugLib > + MemoryAllocationLib > + PrintLib > + QemuFwCfgLib > + UefiBootServicesTableLib > + > +[Protocols] > + gEfiDevicePathProtocolGuid > + gEfiLoadedImageProtocolGuid > + > +[Guids] > + gQemuKernelLoaderFsMediaGuid >=20