From cf203024745fb654a6816f83e091a165c02294b4 Mon Sep 17 00:00:00 2001 From: Dov Murik Date: Mon, 28 Jun 2021 10:51:09 +0000 Subject: OvmfPkg/GenericQemuLoadImageLib: Read cmdline from QemuKernelLoaderFs Remove the QemuFwCfgLib interface used to read the QEMU cmdline (-append argument) and the initrd size. Instead, use the synthetic filesystem QemuKernelLoaderFs which has three files: "kernel", "initrd", and "cmdline". Cc: Laszlo Ersek Cc: Ard Biesheuvel Cc: Jordan Justen Cc: James Bottomley Cc: Tobin Feldman-Fitzthum Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3457 Signed-off-by: Dov Murik Message-Id: <20210628105110.379951-5-dovmurik@linux.ibm.com> Reviewed-by: Laszlo Ersek Tested-by: Laszlo Ersek --- .../GenericQemuLoadImageLib.c | 151 +++++++++++++++++++-- .../GenericQemuLoadImageLib.inf | 3 +- 2 files changed, 139 insertions(+), 15 deletions(-) (limited to 'OvmfPkg/Library/GenericQemuLoadImageLib') diff --git a/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.c b/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.c index 8a29976ae1..66e029397b 100644 --- a/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.c +++ b/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.c @@ -11,13 +11,14 @@ #include #include #include +#include #include #include -#include #include #include #include #include +#include #pragma pack (1) typedef struct { @@ -30,6 +31,11 @@ typedef struct { KERNEL_FILE_DEVPATH FileNode; EFI_DEVICE_PATH_PROTOCOL EndNode; } KERNEL_VENMEDIA_FILE_DEVPATH; + +typedef struct { + VENDOR_DEVICE_PATH VenMediaNode; + EFI_DEVICE_PATH_PROTOCOL EndNode; +} SINGLE_VENMEDIA_NODE_DEVPATH; #pragma pack () STATIC CONST KERNEL_VENMEDIA_FILE_DEVPATH mKernelDevicePath = { @@ -51,6 +57,82 @@ STATIC CONST KERNEL_VENMEDIA_FILE_DEVPATH mKernelDevicePath = { } }; +STATIC CONST SINGLE_VENMEDIA_NODE_DEVPATH mQemuKernelLoaderFsDevicePath = { + { + { + MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, + { sizeof (VENDOR_DEVICE_PATH) } + }, + QEMU_KERNEL_LOADER_FS_MEDIA_GUID + }, { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + { sizeof (EFI_DEVICE_PATH_PROTOCOL) } + } +}; + +STATIC +EFI_STATUS +GetQemuKernelLoaderBlobSize ( + IN EFI_FILE_HANDLE Root, + IN CHAR16 *FileName, + OUT UINTN *Size + ) +{ + EFI_STATUS Status; + EFI_FILE_HANDLE FileHandle; + UINT64 FileSize; + + Status = Root->Open (Root, &FileHandle, FileName, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR (Status)) { + return Status; + } + Status = FileHandleGetSize (FileHandle, &FileSize); + if (EFI_ERROR (Status)) { + goto CloseFile; + } + if (FileSize > MAX_UINTN) { + Status = EFI_UNSUPPORTED; + goto CloseFile; + } + *Size = (UINTN)FileSize; + Status = EFI_SUCCESS; +CloseFile: + FileHandle->Close (FileHandle); + return Status; +} + +STATIC +EFI_STATUS +ReadWholeQemuKernelLoaderBlob ( + IN EFI_FILE_HANDLE Root, + IN CHAR16 *FileName, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + EFI_FILE_HANDLE FileHandle; + UINTN ReadSize; + + Status = Root->Open (Root, &FileHandle, FileName, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR (Status)) { + return Status; + } + ReadSize = Size; + Status = FileHandle->Read (FileHandle, &ReadSize, Buffer); + if (EFI_ERROR (Status)) { + goto CloseFile; + } + if (ReadSize != Size) { + Status = EFI_PROTOCOL_ERROR; + goto CloseFile; + } + Status = EFI_SUCCESS; +CloseFile: + FileHandle->Close (FileHandle); + return Status; +} + /** 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 load @@ -76,12 +158,16 @@ QemuLoadKernelImage ( OUT EFI_HANDLE *ImageHandle ) { - EFI_STATUS Status; - EFI_HANDLE KernelImageHandle; - EFI_LOADED_IMAGE_PROTOCOL *KernelLoadedImage; - UINTN CommandLineSize; - CHAR8 *CommandLine; - UINTN InitrdSize; + EFI_STATUS Status; + EFI_HANDLE KernelImageHandle; + EFI_LOADED_IMAGE_PROTOCOL *KernelLoadedImage; + EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; + EFI_HANDLE FsVolumeHandle; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FsProtocol; + EFI_FILE_HANDLE Root; + UINTN CommandLineSize; + CHAR8 *CommandLine; + UINTN InitrdSize; // // Load the image. This should call back into the QEMU EFI loader file system. @@ -124,8 +210,38 @@ QemuLoadKernelImage ( ); ASSERT_EFI_ERROR (Status); - QemuFwCfgSelectItem (QemuFwCfgItemCommandLineSize); - CommandLineSize = (UINTN)QemuFwCfgRead32 (); + // + // Open the Qemu Kernel Loader abstract filesystem (volume) which will be + // used to query the "initrd" and to read the "cmdline" synthetic files. + // + DevicePathNode = (EFI_DEVICE_PATH_PROTOCOL *)&mQemuKernelLoaderFsDevicePath; + Status = gBS->LocateDevicePath ( + &gEfiSimpleFileSystemProtocolGuid, + &DevicePathNode, + &FsVolumeHandle + ); + if (EFI_ERROR (Status)) { + goto UnloadImage; + } + + Status = gBS->HandleProtocol ( + FsVolumeHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID **)&FsProtocol + ); + if (EFI_ERROR (Status)) { + goto UnloadImage; + } + + Status = FsProtocol->OpenVolume (FsVolumeHandle, &Root); + if (EFI_ERROR (Status)) { + goto UnloadImage; + } + + Status = GetQemuKernelLoaderBlobSize (Root, L"cmdline", &CommandLineSize); + if (EFI_ERROR (Status)) { + goto CloseRoot; + } if (CommandLineSize == 0) { KernelLoadedImage->LoadOptionsSize = 0; @@ -133,11 +249,14 @@ QemuLoadKernelImage ( CommandLine = AllocatePool (CommandLineSize); if (CommandLine == NULL) { Status = EFI_OUT_OF_RESOURCES; - goto UnloadImage; + goto CloseRoot; } - QemuFwCfgSelectItem (QemuFwCfgItemCommandLineData); - QemuFwCfgReadBytes (CommandLineSize, CommandLine); + Status = ReadWholeQemuKernelLoaderBlob (Root, L"cmdline", CommandLineSize, + CommandLine); + if (EFI_ERROR (Status)) { + goto FreeCommandLine; + } // // Verify NUL-termination of the command line. @@ -155,8 +274,10 @@ QemuLoadKernelImage ( KernelLoadedImage->LoadOptionsSize = (UINT32)((CommandLineSize - 1) * 2); } - QemuFwCfgSelectItem (QemuFwCfgItemInitrdSize); - InitrdSize = (UINTN)QemuFwCfgRead32 (); + Status = GetQemuKernelLoaderBlobSize (Root, L"initrd", &InitrdSize); + if (EFI_ERROR (Status)) { + goto FreeCommandLine; + } if (InitrdSize > 0) { // @@ -199,6 +320,8 @@ FreeCommandLine: if (CommandLineSize > 0) { FreePool (CommandLine); } +CloseRoot: + Root->Close (Root); UnloadImage: if (EFI_ERROR (Status)) { gBS->UnloadImage (KernelImageHandle); diff --git a/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf b/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf index b262cb926a..9c9e35b1c5 100644 --- a/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf +++ b/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf @@ -25,14 +25,15 @@ [LibraryClasses] DebugLib + FileHandleLib MemoryAllocationLib PrintLib - QemuFwCfgLib UefiBootServicesTableLib [Protocols] gEfiDevicePathProtocolGuid gEfiLoadedImageProtocolGuid + gEfiSimpleFileSystemProtocolGuid [Guids] gQemuKernelLoaderFsMediaGuid -- cgit v1.2.3